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 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
  - - ">="