ruby-calc 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 [![Build Status](https://travis-ci.org/
|
1
|
+
# ruby-calc [![Build Status](https://travis-ci.org/timocp/ruby-calc.svg?branch=master)](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
|
- - ">="
|