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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 60dc0a56479aabb76308bf50c684b33dee34295a
4
- data.tar.gz: 146f1c057188c53d530776232b992bc6f8de0042
3
+ metadata.gz: cb0e4ef73520d0841eea1ca26cc32ccf9da59198
4
+ data.tar.gz: 2cc20bd449fe8fc1771bc643099cdfc744493751
5
5
  SHA512:
6
- metadata.gz: 138bc132c80fb43568cce386271ac3f8f9a331a80a861bc155e88b10e11bdf697bfd03becf96598a433d09b50be67519c4c93d0bac96608abab5aa0c223790b7
7
- data.tar.gz: 33f6b72f5db4aeba9cd01b045b30eee2d904226111709cf20c7cb8b120be9900d2518bf0f65b3da1395ff48222e57bb78471f937cb9f5421fdbc8e3d2880d219
6
+ metadata.gz: 9c216a8a5f5b8cb848b39d4c880832a62320450d038419b04bd4083392244fde819ced6650a9d0d139b359b3506a06d149af706165fe9f157eb1613d687fc0c6
7
+ data.tar.gz: 96c66092a67f0f9a9974d741ec103d94eac1dd30e395be4fa611f60d41ff1bc6a7965596f531c4578b4819d9b24597d2a8bfca1de3b336750291a7099073e505
@@ -5,6 +5,7 @@ rvm:
5
5
  - 2.1
6
6
  - 2.2
7
7
  - 2.3.0
8
+ - ruby-head
8
9
  env:
9
10
  - CALC_VERSION=2.12.5.0 # latest stable (12-Oct-2014)
10
11
  - CALC_VERSION=2.12.5.4 # latest unstable (22-Feb-2016)
@@ -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/timpeters/ruby-calc.svg?branch=master)](https://travis-ci.org/timpeters/ruby-calc)
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/timpeters/ruby-calc.git'
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/timpeters/ruby-calc/fork )
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
@@ -2,6 +2,9 @@
2
2
  set -euo pipefail
3
3
  IFS=$'\n\t'
4
4
 
5
+ if ! command -v bundle >/dev/null ; then
6
+ gem install bundler --no-document
7
+ fi
5
8
  bundle install
6
9
 
7
10
  # Do any other automated setup that you need to do here
@@ -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
- fix_methods = 1.methods - exclude
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 & fix_methods) - q_methods).sort.each do |m|
352
- puts "Calc::Q needs method #{ m } for Rational and Fixnum compatibility"
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 - fix_methods - q_methods).sort.each do |m|
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
- (fix_methods - rat_methods - q_methods).sort.each do |m|
360
- puts "Calc::Q needs method #{ m } for Fixnum compatibility"
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
- ["Fixnum compatibility", (fix_methods & q_methods).size, fix_methods.size.to_f],
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
@@ -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 (Fixnum, Bignum, Rational, Float,
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 (TYPE(re) == T_COMPLEX) {
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 (Fixnum, Bignum, Calc::Q,
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 (TYPE(other) == T_COMPLEX) {
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 (TYPE(other) == T_FIXNUM || TYPE(other) == T_BIGNUM || TYPE(other) == T_RATIONAL ||
271
- TYPE(other) == T_FLOAT || CALC_Q_P(other)) {
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);
@@ -77,10 +77,10 @@ value_to_nametype_long(VALUE v, nametype2 * set)
77
77
  VALUE tmp;
78
78
  char *str;
79
79
 
80
- if (TYPE(v) == T_STRING) {
80
+ if (RB_TYPE_P(v, T_STRING)) {
81
81
  str = StringValueCStr(v);
82
82
  }
83
- else if (TYPE(v) == T_SYMBOL) {
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
  }
@@ -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
- * - Fixnum
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 (TYPE(arg) == T_FIXNUM) {
68
+ if (FIXNUM_P(arg)) {
70
69
  qresult = itoq(NUM2LONG(arg));
71
70
  }
72
- else if (TYPE(arg) == T_BIGNUM) {
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 (TYPE(arg) == T_RATIONAL) {
78
+ else if (RB_TYPE_P(arg, T_RATIONAL)) {
80
79
  qresult = rational_to_number(arg);
81
80
  }
82
- else if (TYPE(arg) == T_FLOAT) {
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 && TYPE(arg) == T_STRING) {
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 (TYPE(arg) == T_COMPLEX) {
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) || TYPE(arg) == T_BIGNUM || TYPE(arg) == T_RATIONAL
128
- || TYPE(arg) == T_FLOAT) {
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 {
@@ -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) || TYPE(other) == T_COMPLEX) {
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) || TYPE(other) == T_COMPLEX) {
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);
@@ -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
- * * Fixnum
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 && TYPE(other) == T_FIXNUM) {
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 (TYPE(other) == T_FIXNUM || TYPE(other) == T_BIGNUM || TYPE(other) == T_FLOAT
160
- || TYPE(other) == T_RATIONAL) {
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 (TYPE(other) == T_COMPLEX) {
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 [Fixnum,nil]
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 (TYPE(other) == T_FIXNUM) {
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 (TYPE(other) == T_FIXNUM || TYPE(other) == T_BIGNUM || TYPE(other) == T_FLOAT
455
- || TYPE(other) == T_RATIONAL) {
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 (TYPE(other) == T_COMPLEX) {
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) || TYPE(arg) == T_COMPLEX || qisneg(qself)) {
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 (TYPE(arg) == T_STRING) {
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 Fixnum#size, except that is works on fractions
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
- * Fixnum#size.
2438
+ * Integer#size.
2436
2439
  *
2437
2440
  * @return [Calc::Q]
2438
2441
  * @example
2439
- * Calc::Q(1).size #=> Calc;:Q(4)
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 integer (Fixnum or Bignum).
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 Fixnum or Bignum. If you want to
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 [Fixnum,Bignum]
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
- math_divertio();
2581
- if (args == 0) {
2582
- qprintnum(qself, MODE_DEFAULT);
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
- qprintnum(qself, (int) value_to_mode(mode));
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
  }
@@ -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 Fixnum or Bignum. If you want to
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 [Fixnum,Bugnum]
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
@@ -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(1, 1)
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 Fixnum#fdiv will
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(1, 0)
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 Fixnum or Bignum. If you want to
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 [Fixnum,Bignum]
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
@@ -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 Fixnum#bit_length. Libcalc
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 Fixnum/Rational compatibility
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 Fixnum/Rational compatibility
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 Fixnum/Integer compatibility.
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 Fixnum/Integer compatibility.
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 Fixnum/Bignum/Rational
651
+ # aliases for compatibility with ruby Integer/Rational
624
652
  alias imag im
625
653
  alias integer? int?
626
654
  alias real re
@@ -1,3 +1,3 @@
1
1
  module Calc
2
- VERSION = "0.1.0".freeze
2
+ VERSION = "0.2.0".freeze
3
3
  end
@@ -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/timpeters/ruby-calc"
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.1.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-05-28 00:00:00.000000000 Z
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/timpeters/ruby-calc
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
  - - ">="