ruby-calc 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/CHANGELOG.md +27 -0
- data/README.md +10 -3
- data/bin/setup +3 -0
- data/bin/todo.rb +7 -7
- data/ext/calc/c.c +6 -6
- data/ext/calc/config.c +2 -2
- data/ext/calc/convert.c +9 -10
- data/ext/calc/numeric.c +2 -2
- data/ext/calc/q.c +41 -27
- data/lib/calc/c.rb +2 -2
- data/lib/calc/numeric.rb +36 -7
- data/lib/calc/q.rb +34 -6
- data/lib/calc/version.rb +1 -1
- data/ruby-calc.gemspec +2 -1
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cb0e4ef73520d0841eea1ca26cc32ccf9da59198
|
4
|
+
data.tar.gz: 2cc20bd449fe8fc1771bc643099cdfc744493751
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9c216a8a5f5b8cb848b39d4c880832a62320450d038419b04bd4083392244fde819ced6650a9d0d139b359b3506a06d149af706165fe9f157eb1613d687fc0c6
|
7
|
+
data.tar.gz: 96c66092a67f0f9a9974d741ec103d94eac1dd30e395be4fa611f60d41ff1bc6a7965596f531c4578b4819d9b24597d2a8bfca1de3b336750291a7099073e505
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# Change Log
|
2
|
+
All notable changes to this project will be documented in this file.
|
3
|
+
|
4
|
+
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
5
|
+
and this project adheres to [Semantic Versioning](http://semver.org/).
|
6
|
+
|
7
|
+
## [Unreleased]
|
8
|
+
|
9
|
+
## [0.2.0] - 2016-12-24
|
10
|
+
### Added
|
11
|
+
- Compatibility with ruby 2.4 `Fixnum`/`Bignum` unification to `Integer`
|
12
|
+
- Parameters for `ceil` and `floor` compatible with ruby 2.4 numeric classes
|
13
|
+
- Methods `finite?` and `infinite?` compatible with ruby 2.4 numeric classes
|
14
|
+
- Method `digits_r` compatible with ruby 2.4 numeric `digits`, as libcalc
|
15
|
+
already provides a `digits` function (requires ruby 2.4)
|
16
|
+
- Method `clamp` returns ruby calc classes in ruby 2.4
|
17
|
+
|
18
|
+
## 0.1.0 - 2016-05-28
|
19
|
+
### Added
|
20
|
+
- Adds `Calc::Q` (rational numbers) and `Calc::C` (complex numbers)
|
21
|
+
- Important (mathematical) libcalc functions as methods
|
22
|
+
- Several libcalc configuration options via `Calc#config`
|
23
|
+
- Conversion to/from libcalc and ruby classes
|
24
|
+
- Compatibility methods with ruby numeric classes
|
25
|
+
|
26
|
+
[Unreleased]: https://github.com/timocp/ruby-calc/compare/v0.2.0...HEAD
|
27
|
+
[0.2.0]: https://github.com/timocp/ruby-calc/compare/v0.1.0...v0.2.0
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# ruby-calc [](https://travis-ci.org/timocp/ruby-calc)
|
2
2
|
|
3
3
|
ruby-calc provides ruby bindings for calc, a c-style arbitrary precision calculator.
|
4
4
|
|
@@ -18,7 +18,7 @@ Manual | Download and install calc yourself by referring to the calc website, or
|
|
18
18
|
Add this line to your application's Gemfile:
|
19
19
|
|
20
20
|
```ruby
|
21
|
-
gem 'ruby-calc', git: 'git://github.com/
|
21
|
+
gem 'ruby-calc', git: 'git://github.com/timocp/ruby-calc.git'
|
22
22
|
```
|
23
23
|
|
24
24
|
And then execute:
|
@@ -349,6 +349,13 @@ Calc::Q(1,20).to_s(:bin) #=> "1/0b10100 base 2 fractions
|
|
349
349
|
|
350
350
|
The default output mode can be set with [Calc::Config]. The output of `inspect` will match whatever the current default is.
|
351
351
|
|
352
|
+
The argument to `to_s` may also be an integer. In this case, it acts like ruby `Fixnum#to_s`, and treats the argument as a base. This only works for integers.
|
353
|
+
|
354
|
+
```ruby
|
355
|
+
Calc::Q(12345).to_s(2) #=> "11000000111001"
|
356
|
+
Calc::Q(12345).to_s(36) #=> "9ix"
|
357
|
+
```
|
358
|
+
|
352
359
|
Note that you can also provide `Calc::Q` objects to the ruby printf method. The format string parameter will coerce the number to the right internal type first (eg %d will display as an integer, %f as a floating point number). The display may have lost precision in this conversion.
|
353
360
|
|
354
361
|
### Configuration
|
@@ -490,7 +497,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
490
497
|
|
491
498
|
## Contributing
|
492
499
|
|
493
|
-
1. Fork it ( https://github.com/
|
500
|
+
1. Fork it ( https://github.com/timocp/ruby-calc/fork )
|
494
501
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
495
502
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
496
503
|
4. Push to the branch (`git push origin my-new-feature`)
|
data/bin/setup
CHANGED
data/bin/todo.rb
CHANGED
@@ -344,20 +344,20 @@ end
|
|
344
344
|
|
345
345
|
rat_methods = Rational(1, 2).methods - exclude
|
346
346
|
com_methods = Complex(1, 2).methods - exclude
|
347
|
-
|
347
|
+
int_methods = 1.methods - exclude
|
348
348
|
q_methods = Calc::Q(1).methods
|
349
349
|
c_methods = Calc::C(1, 1).methods
|
350
350
|
|
351
|
-
((rat_methods &
|
352
|
-
puts "Calc::Q needs method #{ m } for Rational and
|
351
|
+
((rat_methods & int_methods) - q_methods).sort.each do |m|
|
352
|
+
puts "Calc::Q needs method #{ m } for Rational and #{ 1.class } compatibility"
|
353
353
|
end
|
354
354
|
|
355
|
-
(rat_methods -
|
355
|
+
(rat_methods - int_methods - q_methods).sort.each do |m|
|
356
356
|
puts "Calc::Q needs method #{ m } for Rational compatibility"
|
357
357
|
end
|
358
358
|
|
359
|
-
(
|
360
|
-
puts "Calc::Q needs method #{ m } for
|
359
|
+
(int_methods - rat_methods - q_methods).sort.each do |m|
|
360
|
+
puts "Calc::Q needs method #{ m } for #{ 1.class } compatibility"
|
361
361
|
end
|
362
362
|
|
363
363
|
(com_methods - c_methods).sort.each do |m|
|
@@ -367,7 +367,7 @@ end
|
|
367
367
|
[
|
368
368
|
["ruby-calc builtins", builtins_done, builtins],
|
369
369
|
["Rational compatibility", (rat_methods & q_methods).size, rat_methods.size.to_f],
|
370
|
-
["
|
370
|
+
["#{ 1.class } compatibility", (int_methods & q_methods).size, int_methods.size.to_f],
|
371
371
|
["Complex compatibility", (com_methods & c_methods).size, com_methods.size.to_f]
|
372
372
|
].each do |goal, done, total|
|
373
373
|
printf "%25s: %3d/%3d (%3.1f%%)\n", goal, done, total, done / total * 100
|
data/ext/calc/c.c
CHANGED
@@ -37,7 +37,7 @@ cc_alloc(VALUE klass)
|
|
37
37
|
* If a single param of type Complex or Calc::C, returns a new complex number
|
38
38
|
* with the same real and imaginary parts.
|
39
39
|
*
|
40
|
-
* If a single param of other numeric types (
|
40
|
+
* If a single param of other numeric types (Integer, Rational, Float,
|
41
41
|
* Calc::Q), returns a complex number with the specified real part and zero
|
42
42
|
* imaginary part.
|
43
43
|
*
|
@@ -56,7 +56,7 @@ cc_initialize(int argc, VALUE * argv, VALUE self)
|
|
56
56
|
if (CALC_C_P(re)) {
|
57
57
|
cself = clink((COMPLEX *) DATA_PTR(re));
|
58
58
|
}
|
59
|
-
else if (
|
59
|
+
else if (RB_TYPE_P(re, T_COMPLEX)) {
|
60
60
|
cself = value_to_complex(re);
|
61
61
|
}
|
62
62
|
else {
|
@@ -238,7 +238,7 @@ cc_divide(VALUE x, VALUE y)
|
|
238
238
|
* If the other value is complex (Calc::C or Complex), returns true if the
|
239
239
|
* real an imaginary parts of both numbers are the same.
|
240
240
|
*
|
241
|
-
* The other value is some other numberic type (
|
241
|
+
* The other value is some other numberic type (Integer, Calc::Q,
|
242
242
|
* Rational or Float) then returns true if the complex part of this number is
|
243
243
|
* zero and the real part is equal to the other.
|
244
244
|
*
|
@@ -262,13 +262,13 @@ cc_equal(VALUE self, VALUE other)
|
|
262
262
|
if (CALC_C_P(other)) {
|
263
263
|
result = !c_cmp(cself, DATA_PTR(other));
|
264
264
|
}
|
265
|
-
else if (
|
265
|
+
else if (RB_TYPE_P(other, T_COMPLEX)) {
|
266
266
|
cother = value_to_complex(other);
|
267
267
|
result = !c_cmp(cself, cother);
|
268
268
|
comfree(cother);
|
269
269
|
}
|
270
|
-
else if (
|
271
|
-
|
270
|
+
else if (FIXNUM_P(other) || RB_TYPE_P(other, T_BIGNUM) || RB_TYPE_P(other, T_RATIONAL) ||
|
271
|
+
RB_TYPE_P(other, T_FLOAT) || CALC_Q_P(other)) {
|
272
272
|
cother = qqtoc(value_to_number(other, 0), &_qzero_);
|
273
273
|
result = !c_cmp(cself, cother);
|
274
274
|
comfree(cother);
|
data/ext/calc/config.c
CHANGED
@@ -77,10 +77,10 @@ value_to_nametype_long(VALUE v, nametype2 * set)
|
|
77
77
|
VALUE tmp;
|
78
78
|
char *str;
|
79
79
|
|
80
|
-
if (
|
80
|
+
if (RB_TYPE_P(v, T_STRING)) {
|
81
81
|
str = StringValueCStr(v);
|
82
82
|
}
|
83
|
-
else if (
|
83
|
+
else if (RB_TYPE_P(v, T_SYMBOL)) {
|
84
84
|
tmp = rb_funcall(v, rb_intern("to_s"), 0);
|
85
85
|
str = StringValueCStr(tmp);
|
86
86
|
}
|
data/ext/calc/convert.c
CHANGED
@@ -50,8 +50,7 @@ rational_to_number(VALUE arg)
|
|
50
50
|
}
|
51
51
|
|
52
52
|
/* converts a ruby value into a NUMBER*. Allowed types:
|
53
|
-
* -
|
54
|
-
* - Bignum
|
53
|
+
* - Integer
|
55
54
|
* - Calc::Q
|
56
55
|
* - Rational
|
57
56
|
* - String (using libcalc str2q)
|
@@ -66,24 +65,24 @@ value_to_number(VALUE arg, int string_allowed)
|
|
66
65
|
NUMBER *qresult;
|
67
66
|
VALUE num, tmp;
|
68
67
|
|
69
|
-
if (
|
68
|
+
if (FIXNUM_P(arg)) {
|
70
69
|
qresult = itoq(NUM2LONG(arg));
|
71
70
|
}
|
72
|
-
else if (
|
71
|
+
else if (RB_TYPE_P(arg, T_BIGNUM)) {
|
73
72
|
num = bignum_to_calc_q(arg);
|
74
73
|
qresult = qlink((NUMBER *) DATA_PTR(num));
|
75
74
|
}
|
76
75
|
else if (CALC_Q_P(arg)) {
|
77
76
|
qresult = qlink((NUMBER *) DATA_PTR(arg));
|
78
77
|
}
|
79
|
-
else if (
|
78
|
+
else if (RB_TYPE_P(arg, T_RATIONAL)) {
|
80
79
|
qresult = rational_to_number(arg);
|
81
80
|
}
|
82
|
-
else if (
|
81
|
+
else if (RB_TYPE_P(arg, T_FLOAT)) {
|
83
82
|
tmp = rb_funcall(arg, rb_intern("to_r"), 0);
|
84
83
|
qresult = rational_to_number(tmp);
|
85
84
|
}
|
86
|
-
else if (string_allowed &&
|
85
|
+
else if (string_allowed && RB_TYPE_P(arg, T_STRING)) {
|
87
86
|
qresult = str2q(StringValueCStr(arg));
|
88
87
|
/* libcalc str2q allows a 0 denominator */
|
89
88
|
if (ziszero(qresult->den)) {
|
@@ -116,7 +115,7 @@ value_to_complex(VALUE arg)
|
|
116
115
|
if (CALC_C_P(arg)) {
|
117
116
|
cresult = clink((COMPLEX *) DATA_PTR(arg));
|
118
117
|
}
|
119
|
-
else if (
|
118
|
+
else if (RB_TYPE_P(arg, T_COMPLEX)) {
|
120
119
|
real = rb_funcall(arg, rb_intern("real"), 0);
|
121
120
|
imag = rb_funcall(arg, rb_intern("imag"), 0);
|
122
121
|
cresult = qqtoc(value_to_number(real, 0), value_to_number(imag, 0));
|
@@ -124,8 +123,8 @@ value_to_complex(VALUE arg)
|
|
124
123
|
else if (CALC_Q_P(arg)) {
|
125
124
|
cresult = qqtoc(DATA_PTR(arg), &_qzero_);
|
126
125
|
}
|
127
|
-
else if (FIXNUM_P(arg) ||
|
128
|
-
||
|
126
|
+
else if (FIXNUM_P(arg) || RB_TYPE_P(arg, T_BIGNUM) || RB_TYPE_P(arg, T_RATIONAL)
|
127
|
+
|| RB_TYPE_P(arg, T_FLOAT)) {
|
129
128
|
cresult = qqtoc(value_to_number(arg, 0), &_qzero_);
|
130
129
|
}
|
131
130
|
else {
|
data/ext/calc/numeric.c
CHANGED
@@ -146,7 +146,7 @@ cn_cmp(VALUE self, VALUE other)
|
|
146
146
|
|
147
147
|
if (CALC_Q_P(self)) {
|
148
148
|
qself = DATA_PTR(self);
|
149
|
-
if (CALC_C_P(other) ||
|
149
|
+
if (CALC_C_P(other) || RB_TYPE_P(other, T_COMPLEX)) {
|
150
150
|
cother = value_to_complex(other);
|
151
151
|
r = qrel(qself, cother->real);
|
152
152
|
i = qrel(&_qzero_, cother->imag);
|
@@ -161,7 +161,7 @@ cn_cmp(VALUE self, VALUE other)
|
|
161
161
|
}
|
162
162
|
else if (CALC_C_P(self)) {
|
163
163
|
cself = DATA_PTR(self);
|
164
|
-
if (CALC_C_P(other) ||
|
164
|
+
if (CALC_C_P(other) || RB_TYPE_P(other, T_COMPLEX)) {
|
165
165
|
cother = value_to_complex(other);
|
166
166
|
r = qrel(cself->real, cother->real);
|
167
167
|
i = qrel(cself->imag, cother->imag);
|
data/ext/calc/q.c
CHANGED
@@ -64,8 +64,7 @@ cq_alloc(VALUE klass)
|
|
64
64
|
*
|
65
65
|
* Arguments are either a numerator/denominator pair, or a single numerator.
|
66
66
|
* With a single parameter, a denominator of 1 is implied. Valid types are:
|
67
|
-
* *
|
68
|
-
* * Bignum
|
67
|
+
* * Integer
|
69
68
|
* * Rational
|
70
69
|
* * Calc::Q
|
71
70
|
* * String
|
@@ -150,20 +149,21 @@ numeric_op(VALUE self, VALUE other,
|
|
150
149
|
VALUE ary;
|
151
150
|
setup_math_error();
|
152
151
|
|
153
|
-
if (fql &&
|
152
|
+
if (fql && FIXNUM_P(other)) {
|
154
153
|
qresult = (*fql) (DATA_PTR(self), NUM2LONG(other));
|
155
154
|
}
|
156
155
|
else if (CALC_Q_P(other)) {
|
157
156
|
qresult = (*fqq) (DATA_PTR(self), DATA_PTR(other));
|
158
157
|
}
|
159
|
-
else if (
|
160
|
-
||
|
158
|
+
else if (RB_TYPE_P(other, T_FIXNUM) || RB_TYPE_P(other, T_BIGNUM)
|
159
|
+
|| RB_TYPE_P(other, T_FLOAT)
|
160
|
+
|| RB_TYPE_P(other, T_RATIONAL)) {
|
161
161
|
qother = value_to_number(other, 0);
|
162
162
|
qresult = (*fqq) (DATA_PTR(self), qother);
|
163
163
|
qfree(qother);
|
164
164
|
}
|
165
165
|
else if (rb_respond_to(other, id_coerce)) {
|
166
|
-
if (
|
166
|
+
if (RB_TYPE_P(other, T_COMPLEX)) {
|
167
167
|
other = rb_funcall(cC, id_new, 1, other);
|
168
168
|
}
|
169
169
|
ary = rb_funcall(other, id_coerce, 1, self);
|
@@ -427,7 +427,7 @@ cq_divide(VALUE x, VALUE y)
|
|
427
427
|
* nil is returned if the two values are incomparable.
|
428
428
|
*
|
429
429
|
* @param other [Numeric,Calc::Q]
|
430
|
-
* @return [
|
430
|
+
* @return [Integer,nil]
|
431
431
|
* @example:
|
432
432
|
* Calc::Q(5) <=> 4 #=> 1
|
433
433
|
* Calc::Q(5) <=> 5.1 #=> -1
|
@@ -444,21 +444,21 @@ cq_spaceship(VALUE self, VALUE other)
|
|
444
444
|
|
445
445
|
qself = DATA_PTR(self);
|
446
446
|
/* qreli returns incorrect results if self > 0 and other == 0
|
447
|
-
if (
|
447
|
+
if (FIXNUM_P(other)) {
|
448
448
|
result = qreli(qself, NUM2LONG(other));
|
449
449
|
}
|
450
450
|
*/
|
451
451
|
if (CALC_Q_P(other)) {
|
452
452
|
result = qrel(qself, DATA_PTR(other));
|
453
453
|
}
|
454
|
-
else if (
|
455
|
-
||
|
454
|
+
else if (FIXNUM_P(other) || RB_TYPE_P(other, T_BIGNUM) || RB_TYPE_P(other, T_FLOAT)
|
455
|
+
|| RB_TYPE_P(other, T_RATIONAL)) {
|
456
456
|
qother = value_to_number(other, 0);
|
457
457
|
result = qrel(qself, qother);
|
458
458
|
qfree(qother);
|
459
459
|
}
|
460
460
|
else if (rb_respond_to(other, id_coerce)) {
|
461
|
-
if (
|
461
|
+
if (RB_TYPE_P(other, T_COMPLEX)) {
|
462
462
|
other = rb_funcall(cC, id_new, 1, other);
|
463
463
|
}
|
464
464
|
ary = rb_funcall(other, id_coerce, 1, self);
|
@@ -1104,6 +1104,9 @@ cq_digit(int argc, VALUE * argv, VALUE self)
|
|
1104
1104
|
}
|
1105
1105
|
|
1106
1106
|
/* Returns the number of digits of the integral part of self in decimal or another base
|
1107
|
+
*
|
1108
|
+
* Note that this is unlike the ruby's `Integer#digits`. For an equivalent,
|
1109
|
+
* see `Q#digits_r`.
|
1107
1110
|
*
|
1108
1111
|
* @return [Calc::Q]
|
1109
1112
|
* @param b [Integer] (optional) base >= 2 (default 10)
|
@@ -2128,11 +2131,11 @@ cq_power(int argc, VALUE * argv, VALUE self)
|
|
2128
2131
|
qepsilon = value_to_number(epsilon, 1);
|
2129
2132
|
}
|
2130
2133
|
qself = DATA_PTR(self);
|
2131
|
-
if (CALC_C_P(arg) ||
|
2134
|
+
if (CALC_C_P(arg) || RB_TYPE_P(arg, T_COMPLEX) || qisneg(qself)) {
|
2132
2135
|
cself = comalloc();
|
2133
2136
|
qfree(cself->real);
|
2134
2137
|
cself->real = qlink(qself);
|
2135
|
-
if (
|
2138
|
+
if (RB_TYPE_P(arg, T_STRING)) {
|
2136
2139
|
carg = comalloc();
|
2137
2140
|
qfree(carg->real);
|
2138
2141
|
carg->real = value_to_number(arg, 1);
|
@@ -2428,15 +2431,15 @@ cq_sinh(int argc, VALUE * argv, VALUE self)
|
|
2428
2431
|
|
2429
2432
|
/* Returns the number of bytes in the machine representation of `self`
|
2430
2433
|
*
|
2431
|
-
* This method acts like ruby's
|
2434
|
+
* This method acts like ruby's Integer#size, except that is works on fractions
|
2432
2435
|
* in which case the result is the number of bytes for both the numerator and
|
2433
2436
|
* denominator. As the internal representation of numbers differs between
|
2434
2437
|
* ruby and libcalc, it wil not necessary return the same values as
|
2435
|
-
*
|
2438
|
+
* Integer#size.
|
2436
2439
|
*
|
2437
2440
|
* @return [Calc::Q]
|
2438
2441
|
* @example
|
2439
|
-
* Calc::Q(1).size #=> Calc
|
2442
|
+
* Calc::Q(1).size #=> Calc::Q(4)
|
2440
2443
|
* Calc::Q(2**32).size #=> Calc::Q(8)
|
2441
2444
|
* Calc::Q("1/3").size #=> Calc::Q(8)
|
2442
2445
|
*/
|
@@ -2508,15 +2511,15 @@ cq_tanh(int argc, VALUE * argv, VALUE self)
|
|
2508
2511
|
return trans_function(argc, argv, self, &qtanh, NULL);
|
2509
2512
|
}
|
2510
2513
|
|
2511
|
-
/* Converts this number to a core ruby
|
2514
|
+
/* Converts this number to a core ruby Integer.
|
2512
2515
|
*
|
2513
2516
|
* If self is a fraction, the fractional part is truncated.
|
2514
2517
|
*
|
2515
|
-
* Note that the return value is a ruby
|
2518
|
+
* Note that the return value is a ruby Integer. If you want to
|
2516
2519
|
* convert to an integer but have the result be a `Calc::Q` object, use
|
2517
2520
|
* `trunc` or `round`.
|
2518
2521
|
*
|
2519
|
-
* @return [
|
2522
|
+
* @return [Integer]
|
2520
2523
|
* @example
|
2521
2524
|
* Calc::Q(42).to_i #=> 42
|
2522
2525
|
* Calc::Q("1e19").to_i #=> 10000000000000000000
|
@@ -2560,12 +2563,13 @@ cq_to_i(VALUE self)
|
|
2560
2563
|
* Format depends on the configuration parameters "mode" and "display. The
|
2561
2564
|
* mode can be overridden for individual calls.
|
2562
2565
|
*
|
2563
|
-
* @param mode [String,Symbol] (optional) output mode, see [Calc::Config]
|
2566
|
+
* @param mode [String,Symbol,Integer] (optional) output mode, see [Calc::Config]
|
2564
2567
|
* @return [String]
|
2565
2568
|
* @example
|
2566
2569
|
* Calc::Q(1,2).to_s #=> "0.5"
|
2567
2570
|
* Calc::Q(1,2).to_s(:frac) #=> "1/2"
|
2568
2571
|
* Calc::Q(42).to_s(:hex) #=> "0x2a"
|
2572
|
+
* Calc::Q(42).to_s(8) #=> "52"
|
2569
2573
|
*/
|
2570
2574
|
static VALUE
|
2571
2575
|
cq_to_s(int argc, VALUE * argv, VALUE self)
|
@@ -2577,16 +2581,26 @@ cq_to_s(int argc, VALUE * argv, VALUE self)
|
|
2577
2581
|
setup_math_error();
|
2578
2582
|
|
2579
2583
|
args = rb_scan_args(argc, argv, "01", &mode);
|
2580
|
-
|
2581
|
-
|
2582
|
-
|
2584
|
+
if (args == 1 && FIXNUM_P(mode)) {
|
2585
|
+
if (qisint((NUMBER *) DATA_PTR(self))) {
|
2586
|
+
rs = rb_funcall(cq_to_i(self), rb_intern("to_s"), 1, mode);
|
2587
|
+
}
|
2588
|
+
else {
|
2589
|
+
rb_raise(rb_eArgError, "can't convert non-integer to string with base");
|
2590
|
+
}
|
2583
2591
|
}
|
2584
2592
|
else {
|
2585
|
-
|
2593
|
+
math_divertio();
|
2594
|
+
if (args == 0) {
|
2595
|
+
qprintnum(qself, MODE_DEFAULT);
|
2596
|
+
}
|
2597
|
+
else {
|
2598
|
+
qprintnum(qself, (int) value_to_mode(mode));
|
2599
|
+
}
|
2600
|
+
s = math_getdivertedio();
|
2601
|
+
rs = rb_str_new2(s);
|
2602
|
+
free(s);
|
2586
2603
|
}
|
2587
|
-
s = math_getdivertedio();
|
2588
|
-
rs = rb_str_new2(s);
|
2589
|
-
free(s);
|
2590
2604
|
|
2591
2605
|
return rs;
|
2592
2606
|
}
|
data/lib/calc/c.rb
CHANGED
@@ -315,11 +315,11 @@ module Calc
|
|
315
315
|
|
316
316
|
# Convert a wholly real number to an integer.
|
317
317
|
#
|
318
|
-
# Note that the return value is a ruby
|
318
|
+
# Note that the return value is a ruby Integer. If you want to
|
319
319
|
# convert to an integer but have the result be a `Calc::Q` object, use
|
320
320
|
# `trunc` or `round`.
|
321
321
|
#
|
322
|
-
# @return [
|
322
|
+
# @return [Integer]
|
323
323
|
# @raise [RangeError] if imaginary part is non-zero
|
324
324
|
# @example
|
325
325
|
# Calc::C(2, 0).to_i #=> 2
|
data/lib/calc/numeric.rb
CHANGED
@@ -43,17 +43,22 @@ module Calc
|
|
43
43
|
# For complex self, returns a complex number composed of the ceiling
|
44
44
|
# of the real and imaginary parts separately.
|
45
45
|
#
|
46
|
+
# If ndigits is present, the ceiling is calculated at the nth digit instead
|
47
|
+
# of returning an integer.
|
48
|
+
#
|
49
|
+
# @param ndigits [Integer]
|
46
50
|
# @return [Calc::Q,Calc::C]
|
47
51
|
# @example
|
48
52
|
# Calc::Q(1.23).ceil #=> Calc::Q(2)
|
53
|
+
# Calc::Q(1.23).ceil(1) #=> Calc::Q(1.3)
|
49
54
|
# Calc::C(7.8, 9.1).ceil #=> Calc::C(8+10i)
|
50
|
-
def ceil
|
51
|
-
appr(
|
55
|
+
def ceil(ndigits = 0)
|
56
|
+
appr(Q.new(10)**-ndigits, 1)
|
52
57
|
end
|
53
58
|
|
54
59
|
# Division
|
55
60
|
#
|
56
|
-
# This method exists for ruby compatibility. Note that
|
61
|
+
# This method exists for ruby compatibility. Note that Integer#fdiv will
|
57
62
|
# return a Float, however Q#div returns another Q.
|
58
63
|
#
|
59
64
|
# @param y [Numeric]
|
@@ -66,6 +71,16 @@ module Calc
|
|
66
71
|
self / y
|
67
72
|
end
|
68
73
|
|
74
|
+
# Returns true - calc values are always finite
|
75
|
+
#
|
76
|
+
# @return [true]
|
77
|
+
# @example
|
78
|
+
# Calc::Q(1).finite? #=> true
|
79
|
+
# Calc::C(1, 1).finite? #=> true
|
80
|
+
def finite?
|
81
|
+
true
|
82
|
+
end
|
83
|
+
|
69
84
|
# Floor
|
70
85
|
#
|
71
86
|
# For real self, returns the greatest integer not greater than self.
|
@@ -73,12 +88,16 @@ module Calc
|
|
73
88
|
# For complex self, returns a complex number composed of the floor of the
|
74
89
|
# real and imaginary parts separately.
|
75
90
|
#
|
91
|
+
# If ndigits is present, the floor is calculated at the nth digit instead
|
92
|
+
# of returning an integer.
|
93
|
+
#
|
94
|
+
# @param ndigits [Integer]
|
76
95
|
# @return [Calc::Q,Calc::C]
|
77
96
|
# @example
|
78
97
|
# Calc::Q(1.23).floor #=> Calc::Q(1)
|
79
98
|
# Calc::C(7.8, 9.1).floor #=> Calc::C(7+9i)
|
80
|
-
def floor
|
81
|
-
appr(
|
99
|
+
def floor(ndigits = 0)
|
100
|
+
appr(Q.new(10)**-ndigits, 0)
|
82
101
|
end
|
83
102
|
|
84
103
|
# Floor of logarithm to base 10
|
@@ -109,6 +128,16 @@ module Calc
|
|
109
128
|
ilog 2
|
110
129
|
end
|
111
130
|
|
131
|
+
# Returns nil - calc values are never inifinite.
|
132
|
+
#
|
133
|
+
# @return [nil]
|
134
|
+
# @example
|
135
|
+
# Calc::Q(1).infinite? #=> nil
|
136
|
+
# Calc::C(1, 1).infinite? #=> nil
|
137
|
+
def infinite?
|
138
|
+
nil
|
139
|
+
end
|
140
|
+
|
112
141
|
# Returns 1 if self is an integer, otherwise 0.
|
113
142
|
#
|
114
143
|
# @return [Calc::Q]
|
@@ -187,11 +216,11 @@ module Calc
|
|
187
216
|
|
188
217
|
# Invokes the child class's `to_i` method to convert self to an integer.
|
189
218
|
#
|
190
|
-
# Note that the return value is a ruby
|
219
|
+
# Note that the return value is a ruby Integer. If you want to
|
191
220
|
# convert to an integer but have the result be a `Calc::Q` object, use
|
192
221
|
# `trunc` or `round`.
|
193
222
|
#
|
194
|
-
# @return [
|
223
|
+
# @return [Integer]
|
195
224
|
# @raise [RangeError] if self is complex with non-zero imaginary part
|
196
225
|
# @example
|
197
226
|
# Calc::Q("5/2").to_int #=> 2
|
data/lib/calc/q.rb
CHANGED
@@ -56,7 +56,7 @@ module Calc
|
|
56
56
|
|
57
57
|
# Returns the number of bits in the integer part of `self`
|
58
58
|
#
|
59
|
-
# Note that this is compatible with ruby's
|
59
|
+
# Note that this is compatible with ruby's Integer#bit_length. Libcalc
|
60
60
|
# provides a similar function called `highbit` with different semantics.
|
61
61
|
#
|
62
62
|
# This returns the bit position of the highest bit which is different to
|
@@ -102,6 +102,14 @@ module Calc
|
|
102
102
|
to_i.chr(*args)
|
103
103
|
end
|
104
104
|
|
105
|
+
# if clamp has been inherited from <=>, make sure its return value is the
|
106
|
+
# correct class
|
107
|
+
if instance_methods.include?(:clamp)
|
108
|
+
def clamp(min, max)
|
109
|
+
super(Q.new(min), Q.new(max))
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
105
113
|
# Complex conjugate
|
106
114
|
#
|
107
115
|
# As the conjugate of real x is x, this method returns self.
|
@@ -114,6 +122,26 @@ module Calc
|
|
114
122
|
end
|
115
123
|
alias conjugate conj
|
116
124
|
|
125
|
+
if 0.class.instance_methods.include?(:digits)
|
126
|
+
# Returns an array of digits in base b making up self
|
127
|
+
#
|
128
|
+
# This is compatible with ruby's `Integer#digits`. Note that `Q#digits`
|
129
|
+
# implements the libcalc function `digits`, which is different. Any
|
130
|
+
# fractional part of self is truncated.
|
131
|
+
#
|
132
|
+
# Requires ruby 2.4.
|
133
|
+
#
|
134
|
+
# @param b [Integer] (optional) base, default 10
|
135
|
+
# @return [Array]
|
136
|
+
# @example
|
137
|
+
# Calc::Q(1234).digits_r #=> [Calc::Q(4), Calc::Q(3), Calc::Q(2), Calc::Q(1)]
|
138
|
+
# Calc::Q(1234).digits_r(7) #=> [Calc::Q(2), Calc::Q(1), Calc::Q(4), Calc::Q(3)]
|
139
|
+
# Calc::Q(1234).digits_r(100) #=> [Calc::Q(34), Calc::Q(12)]
|
140
|
+
def digits_r(b = 10)
|
141
|
+
to_i.digits(b).map { |d| Q.new(d) }
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
117
145
|
# Ruby compatible integer division
|
118
146
|
#
|
119
147
|
# Calls `quo` to get the quotient of integer division, with rounding mode
|
@@ -363,7 +391,7 @@ module Calc
|
|
363
391
|
|
364
392
|
# Return true if `self` is less than zero.
|
365
393
|
#
|
366
|
-
# This method exists for ruby
|
394
|
+
# This method exists for ruby Integer/Rational compatibility
|
367
395
|
#
|
368
396
|
# @return [Boolean]
|
369
397
|
# @example
|
@@ -385,7 +413,7 @@ module Calc
|
|
385
413
|
|
386
414
|
# Return true if `self` is greater than zero.
|
387
415
|
#
|
388
|
-
# This method exists for ruby
|
416
|
+
# This method exists for ruby Integer/Rational compatibility
|
389
417
|
#
|
390
418
|
# @return [Boolean]
|
391
419
|
# @example
|
@@ -398,7 +426,7 @@ module Calc
|
|
398
426
|
|
399
427
|
# Returns one less than self.
|
400
428
|
#
|
401
|
-
# This method exists for ruby
|
429
|
+
# This method exists for ruby Integer compatibility.
|
402
430
|
#
|
403
431
|
# @return [Calc::Q]
|
404
432
|
# @example
|
@@ -530,7 +558,7 @@ module Calc
|
|
530
558
|
|
531
559
|
# Returns one more than self.
|
532
560
|
#
|
533
|
-
# This method exists for ruby
|
561
|
+
# This method exists for ruby Integer compatibility.
|
534
562
|
#
|
535
563
|
# @return [Calc::Q]
|
536
564
|
# @example
|
@@ -620,7 +648,7 @@ module Calc
|
|
620
648
|
args.inject(self, :^)
|
621
649
|
end
|
622
650
|
|
623
|
-
# aliases for compatibility with ruby
|
651
|
+
# aliases for compatibility with ruby Integer/Rational
|
624
652
|
alias imag im
|
625
653
|
alias integer? int?
|
626
654
|
alias real re
|
data/lib/calc/version.rb
CHANGED
data/ruby-calc.gemspec
CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
|
|
11
11
|
|
12
12
|
spec.summary = "Ruby bindings for calc"
|
13
13
|
spec.description = "Ruby bindings for calc, an arbitrary precision maths library. ruby-calc provides access to a the large number of mathematical functions that come with calc."
|
14
|
-
spec.homepage = "https://github.com/
|
14
|
+
spec.homepage = "https://github.com/timocp/ruby-calc"
|
15
15
|
spec.license = "MIT"
|
16
16
|
|
17
17
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f[/^(test|spec|features)/] }
|
@@ -19,6 +19,7 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
20
|
spec.require_paths = ["lib"]
|
21
21
|
spec.extensions = ["ext/calc/extconf.rb"]
|
22
|
+
spec.required_ruby_version = "~> 2.0"
|
22
23
|
|
23
24
|
spec.add_development_dependency "bundler", "~> 1.8"
|
24
25
|
spec.add_development_dependency "rake", "~> 10.0"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-calc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tim Peters
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-12-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -114,6 +114,7 @@ files:
|
|
114
114
|
- ".rubocop_todo.yml"
|
115
115
|
- ".travis.yml"
|
116
116
|
- ".yardopts"
|
117
|
+
- CHANGELOG.md
|
117
118
|
- Gemfile
|
118
119
|
- LICENSE.txt
|
119
120
|
- README.md
|
@@ -139,7 +140,7 @@ files:
|
|
139
140
|
- lib/calc/q.rb
|
140
141
|
- lib/calc/version.rb
|
141
142
|
- ruby-calc.gemspec
|
142
|
-
homepage: https://github.com/
|
143
|
+
homepage: https://github.com/timocp/ruby-calc
|
143
144
|
licenses:
|
144
145
|
- MIT
|
145
146
|
metadata: {}
|
@@ -149,9 +150,9 @@ require_paths:
|
|
149
150
|
- lib
|
150
151
|
required_ruby_version: !ruby/object:Gem::Requirement
|
151
152
|
requirements:
|
152
|
-
- - "
|
153
|
+
- - "~>"
|
153
154
|
- !ruby/object:Gem::Version
|
154
|
-
version: '0'
|
155
|
+
version: '2.0'
|
155
156
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
156
157
|
requirements:
|
157
158
|
- - ">="
|