ruby-calc 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,2755 @@
1
+ #include "calc.h"
2
+
3
+ /* Document-class: Calc::Q
4
+ *
5
+ * Calc rational number (fraction).
6
+ *
7
+ * A rational number consists of an arbitrarily large numerator and
8
+ * denominator. The numerator and denominator are always in lowest terms, and
9
+ * the sign of the number is contained in the numerator.
10
+ *
11
+ * Wraps the libcalc C type NUMBER*.
12
+ */
13
+ VALUE cQ;
14
+
15
+ /*****************************************************************************
16
+ * functions related to memory allocation and object initialization *
17
+ *****************************************************************************/
18
+
19
+ static ID id_add;
20
+ static ID id_and;
21
+ static ID id_coerce;
22
+ static ID id_divide;
23
+ static ID id_multiply;
24
+ static ID id_new;
25
+ static ID id_or;
26
+ static ID id_spaceship;
27
+ static ID id_subtract;
28
+ static ID id_xor;
29
+
30
+ void
31
+ cq_free(void *p)
32
+ {
33
+ qfree((NUMBER *) p);
34
+ }
35
+
36
+ const rb_data_type_t calc_q_type = {
37
+ "Calc::Q",
38
+ {0, cq_free, 0}, /* TODO: 3rd param is optional dsize */
39
+ 0, 0
40
+ #ifdef RUBY_TYPED_FREE_IMMEDATELY
41
+ , RUBY_TYPED_FREE_IMMEDIATELY /* flags is in 2.1+ */
42
+ #endif
43
+ };
44
+
45
+ /* because the true type of rationals in calc is (NUMBER*), we don't do any
46
+ * additional memory allocation in cq_alloc. the 'data' elemnt of underlying
47
+ * RTypedData struct is accessed directly via the DATA_PTR macro.
48
+ *
49
+ * DATA_PTR isn't documented, but it is used by some built in ruby ext libs.
50
+ *
51
+ * the data element can be replaced by assining to the DATA_PTR macro. be
52
+ * careful to free any existing value before replacing (most qmath.c functions
53
+ * actually allocate a new NUMBER and return a pointer to it).
54
+ */
55
+
56
+ /* no additional allocation beyond normal ruby alloc is required */
57
+ VALUE
58
+ cq_alloc(VALUE klass)
59
+ {
60
+ return TypedData_Wrap_Struct(klass, &calc_q_type, 0);
61
+ }
62
+
63
+ /* Creates a new rational number.
64
+ *
65
+ * Arguments are either a numerator/denominator pair, or a single numerator.
66
+ * With a single parameter, a denominator of 1 is implied. Valid types are:
67
+ * * Fixnum
68
+ * * Bignum
69
+ * * Rational
70
+ * * Calc::Q
71
+ * * String
72
+ * * Float
73
+ *
74
+ * Strings can be in rational, floating point, exponential, hex or octal, eg:
75
+ * Calc::Q("3/10") #=> Calc::Q(0.3)
76
+ * Calc::Q("0.5") #=> Calc::Q(0.5)
77
+ * Calc::Q("1e10") #=> Calc::Q(10000000000)
78
+ * Calc::Q("1e-10") #=> Calc::Q(0.0000000001)
79
+ * Calc::Q("0x2a") #=> Calc::Q(42)
80
+ * Calc::Q("052") #=> Calc::Q(42)
81
+ *
82
+ * Note that a Float cannot precisely equal many values; it will be converted
83
+ * the the closest rational number which may not be what you expect, eg:
84
+ * Calc::Q(0.3) #=> Calc::Q(~0.29999999999999998890)
85
+ * for this reason, it is best to avoid Floats. Libcalc's string parsing will
86
+ * work better:
87
+ * Calc::Q("0.3") #=> Calc::Q(0.3)
88
+ *
89
+ * @param num [Numeric,Calc::Q,String]
90
+ * @param den [Numeric,Calc::Q,String] (optional)
91
+ * @return [Calc::Q]
92
+ * @raise [ZeroDivisionError] if denominator of new number is zero
93
+ */
94
+ static VALUE
95
+ cq_initialize(int argc, VALUE * argv, VALUE self)
96
+ {
97
+ NUMBER *qself, *qnum, *qden;
98
+ VALUE num, den;
99
+ setup_math_error();
100
+
101
+ if (rb_scan_args(argc, argv, "11", &num, &den) == 1) {
102
+ /* single param */
103
+ qself = value_to_number(num, 1);
104
+ }
105
+ else {
106
+ /* 2 params. divide first by second. */
107
+ qden = value_to_number(den, 1);
108
+ if (qiszero(qden)) {
109
+ qfree(qden);
110
+ rb_raise(rb_eZeroDivError, "division by zero");
111
+ }
112
+ qnum = value_to_number(num, 1);
113
+ qself = qqdiv(qnum, qden);
114
+ qfree(qden);
115
+ qfree(qnum);
116
+ }
117
+ DATA_PTR(self) = qself;
118
+
119
+ return self;
120
+ }
121
+
122
+ static VALUE
123
+ cq_initialize_copy(VALUE obj, VALUE orig)
124
+ {
125
+ NUMBER *qorig, *qobj;
126
+
127
+ if (obj == orig) {
128
+ return obj;
129
+ }
130
+ if (!CALC_Q_P(orig)) {
131
+ rb_raise(rb_eTypeError, "wrong argument type");
132
+ }
133
+
134
+ qorig = DATA_PTR(orig);
135
+ qobj = qlink(qorig);
136
+ DATA_PTR(obj) = qobj;
137
+
138
+ return obj;
139
+ }
140
+
141
+ /*****************************************************************************
142
+ * private functions used by instance methods *
143
+ *****************************************************************************/
144
+
145
+ static VALUE
146
+ numeric_op(VALUE self, VALUE other,
147
+ NUMBER * (*fqq) (NUMBER *, NUMBER *), NUMBER * (*fql) (NUMBER *, long), ID func)
148
+ {
149
+ NUMBER *qother, *qresult;
150
+ VALUE ary;
151
+ setup_math_error();
152
+
153
+ if (fql && TYPE(other) == T_FIXNUM) {
154
+ qresult = (*fql) (DATA_PTR(self), NUM2LONG(other));
155
+ }
156
+ else if (CALC_Q_P(other)) {
157
+ qresult = (*fqq) (DATA_PTR(self), DATA_PTR(other));
158
+ }
159
+ else if (TYPE(other) == T_FIXNUM || TYPE(other) == T_BIGNUM || TYPE(other) == T_FLOAT
160
+ || TYPE(other) == T_RATIONAL) {
161
+ qother = value_to_number(other, 0);
162
+ qresult = (*fqq) (DATA_PTR(self), qother);
163
+ qfree(qother);
164
+ }
165
+ else if (rb_respond_to(other, id_coerce)) {
166
+ if (TYPE(other) == T_COMPLEX) {
167
+ other = rb_funcall(cC, id_new, 1, other);
168
+ }
169
+ ary = rb_funcall(other, id_coerce, 1, self);
170
+ if (!RB_TYPE_P(ary, T_ARRAY) || RARRAY_LEN(ary) != 2) {
171
+ rb_raise(rb_eTypeError, "coerce must return [x, y]");
172
+ }
173
+ return rb_funcall(RARRAY_AREF(ary, 0), func, 1, RARRAY_AREF(ary, 1));
174
+ }
175
+ else {
176
+ rb_raise(rb_eTypeError,
177
+ "%" PRIsVALUE " (%" PRIsVALUE ") can't be coerced into %" PRIsVALUE, other,
178
+ rb_obj_class(other), rb_obj_class(self));
179
+ }
180
+ return wrap_number(qresult);
181
+ }
182
+
183
+ static VALUE
184
+ trans_function(int argc, VALUE * argv, VALUE self, NUMBER * (*f) (NUMBER *, NUMBER *),
185
+ COMPLEX * (*fcomplex) (COMPLEX *, NUMBER *))
186
+ {
187
+ NUMBER *qepsilon, *qresult;
188
+ COMPLEX *cself, *cresult;
189
+ VALUE epsilon, result;
190
+ setup_math_error();
191
+
192
+ if (rb_scan_args(argc, argv, "01", &epsilon) == 0) {
193
+ qepsilon = NULL;
194
+ }
195
+ else {
196
+ qepsilon = value_to_number(epsilon, 1);
197
+ }
198
+ qresult = (*f) (DATA_PTR(self), qepsilon ? qepsilon : conf->epsilon);
199
+ if (qresult) {
200
+ result = wrap_number(qresult);
201
+ }
202
+ else if (fcomplex) {
203
+ /* non-real result, call complex version. see calc's func.c */
204
+ cself = comalloc();
205
+ qfree(cself->real);
206
+ cself->real = qlink((NUMBER *) DATA_PTR(self));
207
+ cresult = (*fcomplex) (cself, qepsilon ? qepsilon : conf->epsilon);
208
+ comfree(cself);
209
+ if (cresult) {
210
+ result = wrap_complex(cresult);
211
+ }
212
+ else {
213
+ /* Can this happen? */
214
+ rb_raise(e_MathError,
215
+ "Unhandled NULL from complex version of transcendental function");
216
+ }
217
+ }
218
+ else {
219
+ if (qepsilon) {
220
+ qfree(qepsilon);
221
+ }
222
+ rb_raise(e_MathError, "Unhandled NULL from transcendental function");
223
+ }
224
+ if (qepsilon) {
225
+ qfree(qepsilon);
226
+ }
227
+ return result;
228
+ }
229
+
230
+ /* same as trans_function(), except for functions where there are 2 NUMBER*
231
+ * arguments, eg atan2. the first param is the receiver (self). */
232
+ static VALUE
233
+ trans_function2(int argc, VALUE * argv, VALUE self,
234
+ NUMBER * (*f) (NUMBER *, NUMBER *, NUMBER *))
235
+ {
236
+ NUMBER *qarg, *qepsilon, *qresult;
237
+ VALUE arg, epsilon;
238
+ setup_math_error();
239
+
240
+ if (rb_scan_args(argc, argv, "11", &arg, &epsilon) == 1) {
241
+ qarg = value_to_number(arg, 0);
242
+ qresult = (*f) (DATA_PTR(self), qarg, conf->epsilon);
243
+ qfree(qarg);
244
+ }
245
+ else {
246
+ qarg = value_to_number(arg, 0);
247
+ qepsilon = value_to_number(epsilon, 1);
248
+ qresult = (*f) (DATA_PTR(self), qarg, qepsilon);
249
+ qfree(qarg);
250
+ qfree(qepsilon);
251
+ }
252
+ if (!qresult) {
253
+ rb_raise(e_MathError, "Transcendental function returned NULL");
254
+ }
255
+ return wrap_number(qresult);
256
+ }
257
+
258
+ static VALUE
259
+ rounding_function(int argc, VALUE * argv, VALUE self, NUMBER * (f) (NUMBER *, long, long))
260
+ {
261
+ VALUE places, rnd;
262
+ long n, p, r;
263
+ setup_math_error();
264
+
265
+ n = rb_scan_args(argc, argv, "02", &places, &rnd);
266
+ p = (n >= 1) ? value_to_long(places) : 0;
267
+ r = (n == 2) ? value_to_long(rnd) : conf->round;
268
+ return wrap_number((*f) (DATA_PTR(self), p, r));
269
+ }
270
+
271
+ static VALUE
272
+ cand_navigation(int argc, VALUE * argv, VALUE self,
273
+ BOOL(f) (ZVALUE, long, ZVALUE, ZVALUE, ZVALUE, ZVALUE *))
274
+ {
275
+ VALUE count, skip, residue, modulus;
276
+ NUMBER *qself, *qcount, *qskip, *qresidue, *qmodulus, *qresult;
277
+ ZVALUE tmp;
278
+ int n;
279
+ const char *error = NULL;
280
+ setup_math_error();
281
+
282
+ n = rb_scan_args(argc, argv, "04", &count, &skip, &residue, &modulus);
283
+ qself = DATA_PTR(self);
284
+ qcount = (n >= 1) ? value_to_number(count, 1) : qlink(&_qone_);
285
+ qskip = (n >= 2) ? value_to_number(skip, 1) : qlink(&_qone_);
286
+ qresidue = (n >= 3) ? value_to_number(residue, 1) : qlink(&_qzero_);
287
+ qmodulus = (n >= 4) ? value_to_number(modulus, 1) : qlink(&_qone_);
288
+ qresult = NULL;
289
+
290
+ if (!qisint(qself) || !qisint(qcount) || !qisint(qskip) || !qisint(qresidue)
291
+ || !qisint(qmodulus)) {
292
+ error = "receiver and all arguments must be integers";
293
+ }
294
+ else if (zge24b(qcount->num)) {
295
+ error = "count must be < 2^24";
296
+ }
297
+ else {
298
+ if ((*f)
299
+ (qself->num, ztoi(qcount->num), qskip->num, qresidue->num, qmodulus->num, &tmp)) {
300
+ qresult = qalloc();
301
+ qresult->num = tmp;
302
+ }
303
+ }
304
+
305
+ qfree(qcount);
306
+ qfree(qskip);
307
+ qfree(qresidue);
308
+ qfree(qmodulus);
309
+
310
+ if (error) {
311
+ rb_raise(e_MathError, "%s", error);
312
+ }
313
+ else if (qresult) {
314
+ return wrap_number(qresult);
315
+ }
316
+ return Qnil;
317
+ }
318
+
319
+ static VALUE
320
+ trunc_function(int argc, VALUE * argv, VALUE self, NUMBER * (f) (NUMBER *, NUMBER *))
321
+ {
322
+ VALUE places;
323
+ NUMBER *qplaces, *qresult;
324
+ setup_math_error();
325
+
326
+ if (rb_scan_args(argc, argv, "01", &places) == 1) {
327
+ qplaces = value_to_number(places, 0);
328
+ qresult = (*f) (DATA_PTR(self), qplaces);
329
+ qfree(qplaces);
330
+ }
331
+ else {
332
+ qresult = (*f) (DATA_PTR(self), &_qzero_);
333
+ }
334
+ return wrap_number(qresult);
335
+ }
336
+
337
+ /*****************************************************************************
338
+ * instance method implementations *
339
+ *****************************************************************************/
340
+
341
+ /* Bitwise AND
342
+ *
343
+ * @param y [Integer]
344
+ * @return [Calc::Q]
345
+ * @example
346
+ * Calc::Q(18) & 20 #=> Calc::Q(16)
347
+ */
348
+ static VALUE
349
+ cq_and(VALUE x, VALUE y)
350
+ {
351
+ return numeric_op(x, y, &qand, NULL, id_and);
352
+ }
353
+
354
+ /* Performs multiplication.
355
+ *
356
+ * @param y [Numeric,Calc::Q]
357
+ * @return [Calc::Q]
358
+ * @example:
359
+ * Calc::Q(2) * 3 #=> Calc::Q(6)
360
+ */
361
+ static VALUE
362
+ cq_multiply(VALUE x, VALUE y)
363
+ {
364
+ return numeric_op(x, y, &qmul, &qmuli, id_multiply);
365
+ }
366
+
367
+ /* Performs addition.
368
+ *
369
+ * @param y [Numeric,Calc::Q]
370
+ * @return [Calc::Q]
371
+ * @example
372
+ * Calc::Q(1) + 2 #=> Calc::Q(3)
373
+ */
374
+ static VALUE
375
+ cq_add(VALUE x, VALUE y)
376
+ {
377
+ /* fourth arg was &qaddi, but this segfaults with ruby 2.1.x */
378
+ return numeric_op(x, y, &qqadd, NULL, id_add);
379
+ }
380
+
381
+ /* Performs subtraction.
382
+ *
383
+ * @param y [Numeric,Calc::Q]
384
+ * @return [Calc::Q]
385
+ * @example:
386
+ * Calc::Q(1) - 2 #=> Calc::Q(-1)
387
+ */
388
+ static VALUE
389
+ cq_subtract(VALUE x, VALUE y)
390
+ {
391
+ return numeric_op(x, y, &qsub, NULL, id_subtract);
392
+ }
393
+
394
+ /* Unary minus. Returns the receiver's value, negated.
395
+ *
396
+ * @return [Calc::Q]
397
+ * @example
398
+ * -Calc::Q(1) #=> Calc::Q(-1)
399
+ */
400
+ static VALUE
401
+ cq_uminus(VALUE self)
402
+ {
403
+ setup_math_error();
404
+ return wrap_number(qsub(&_qzero_, DATA_PTR(self)));
405
+ }
406
+
407
+ /* Performs division.
408
+ *
409
+ * @param y [Numeric,Calc::Q]
410
+ * @return [Calc::Q]
411
+ * @raise [Calc::MathError] if other is zero
412
+ * @example:
413
+ * Calc::Q(2) / 4 #=> Calc::Q(0.5)
414
+ */
415
+ static VALUE
416
+ cq_divide(VALUE x, VALUE y)
417
+ {
418
+ return numeric_op(x, y, &qqdiv, &qdivi, id_divide);
419
+ }
420
+
421
+ /* Comparison - Returns -1, 0, +1 or nil depending on whether `y` is less than,
422
+ * equal to, or greater than `x`.
423
+ *
424
+ * This is used by the `Comparable` module to implement `==`, `!=`, `<`, `<=`,
425
+ * `>` and `>=`.
426
+ *
427
+ * nil is returned if the two values are incomparable.
428
+ *
429
+ * @param other [Numeric,Calc::Q]
430
+ * @return [Fixnum,nil]
431
+ * @example:
432
+ * Calc::Q(5) <=> 4 #=> 1
433
+ * Calc::Q(5) <=> 5.1 #=> -1
434
+ * Calc::Q(5) <=> 5 #=> 0
435
+ * Calc::Q(5) <=> "cat" #=> nil
436
+ */
437
+ static VALUE
438
+ cq_spaceship(VALUE self, VALUE other)
439
+ {
440
+ VALUE ary;
441
+ NUMBER *qself, *qother;
442
+ int result;
443
+ setup_math_error();
444
+
445
+ qself = DATA_PTR(self);
446
+ /* qreli returns incorrect results if self > 0 and other == 0
447
+ if (TYPE(other) == T_FIXNUM) {
448
+ result = qreli(qself, NUM2LONG(other));
449
+ }
450
+ */
451
+ if (CALC_Q_P(other)) {
452
+ result = qrel(qself, DATA_PTR(other));
453
+ }
454
+ else if (TYPE(other) == T_FIXNUM || TYPE(other) == T_BIGNUM || TYPE(other) == T_FLOAT
455
+ || TYPE(other) == T_RATIONAL) {
456
+ qother = value_to_number(other, 0);
457
+ result = qrel(qself, qother);
458
+ qfree(qother);
459
+ }
460
+ else if (rb_respond_to(other, id_coerce)) {
461
+ if (TYPE(other) == T_COMPLEX) {
462
+ other = rb_funcall(cC, id_new, 1, other);
463
+ }
464
+ ary = rb_funcall(other, id_coerce, 1, self);
465
+ if (!RB_TYPE_P(ary, T_ARRAY) || RARRAY_LEN(ary) != 2) {
466
+ rb_raise(rb_eTypeError, "coerce must return [x, y]");
467
+ }
468
+ return rb_funcall(RARRAY_AREF(ary, 0), id_spaceship, 1, RARRAY_AREF(ary, 1));
469
+ }
470
+ else {
471
+ return Qnil;
472
+ }
473
+
474
+ return INT2FIX(result);
475
+ }
476
+
477
+ /* Bitwise exclusive or (xor)
478
+ *
479
+ * Note that for ruby compatibility, ^ is an xor operator, unlike in calc
480
+ * where it is a power operator.
481
+ *
482
+ * @return [Calc::Q]
483
+ * @example
484
+ * Calc::Q(5).xor(3) #=> Calc::Q(6)
485
+ */
486
+ static VALUE
487
+ cq_xor(VALUE x, VALUE y)
488
+ {
489
+ return numeric_op(x, y, &qxor, NULL, id_xor);
490
+ }
491
+
492
+ /* Bitwise OR
493
+ *
494
+ * @param y [Integer]
495
+ * @return [Calc::Q]
496
+ * @example
497
+ * Calc::Q(18) | 20 #=> Calc::Q(22)
498
+ */
499
+ static VALUE
500
+ cq_or(VALUE x, VALUE y)
501
+ {
502
+ return numeric_op(x, y, &qor, NULL, id_or);
503
+ }
504
+
505
+ /* Bitwise NOT (complement)
506
+ *
507
+ * This is `-self - 1` if self is an integer, `-self` otherwise.
508
+ *
509
+ * @example
510
+ * ~Calc::Q(7) #=> Calc::Q(-8)
511
+ * ~Calc::Q(0.5) #=> Calc::Q(-0.5)
512
+ */
513
+ static VALUE
514
+ cq_comp(VALUE self)
515
+ {
516
+ setup_math_error();
517
+ return wrap_number(qcomp(DATA_PTR(self)));
518
+ }
519
+
520
+ /* Absolute value
521
+ *
522
+ * @return [Calc::Q]
523
+ * @example
524
+ * Calc::Q(1).abs #=> Calc::Q(1)
525
+ * Calc::Q(-1).abs #=> Calc::Q(1)
526
+ */
527
+ static VALUE
528
+ cq_abs(VALUE self)
529
+ {
530
+ setup_math_error();
531
+ return wrap_number(qqabs(DATA_PTR(self)));
532
+ }
533
+
534
+ /* Inverse trigonometric cosine
535
+ *
536
+ * @param eps [Numeric,Calc::Q] (optional) calculation accuracy
537
+ * @return [Calc::Q,Calc::C]
538
+ * @example
539
+ * Calc::Q(0.5).acos #=> Calc::Q(1.04719755119659774615)
540
+ * Calc::Q(2.0).acos #=> Calc::C(1.31695789692481670863i)
541
+ */
542
+ static VALUE
543
+ cq_acos(int argc, VALUE * argv, VALUE self)
544
+ {
545
+ return trans_function(argc, argv, self, &qacos, &c_acos);
546
+ }
547
+
548
+ /* Inverse hyperbolic cosine
549
+ *
550
+ * @param eps [Numeric,Calc::Q] (optional) calculation accuracy
551
+ * @return [Calc::Q,Calc::C]
552
+ * @example
553
+ * Calc::Q(2).acosh #=> Calc::Q(1.31695789692481670862)
554
+ * Calc::Q(0).acosh #=> Calc::C(1.57079632679489661923i)
555
+ */
556
+ static VALUE
557
+ cq_acosh(int argc, VALUE * argv, VALUE self)
558
+ {
559
+ return trans_function(argc, argv, self, &qacosh, &c_acosh);
560
+ }
561
+
562
+ /* Inverse trigonometric cotangent
563
+ *
564
+ * @param eps [Numeric,Calc::Q] (optional) calculation accuracy
565
+ * @return [Calc::Q]
566
+ * @example
567
+ * Calc::Q(2).acot #=> Calc::Q(0.46364760900080611621)
568
+ */
569
+ static VALUE
570
+ cq_acot(int argc, VALUE * argv, VALUE self)
571
+ {
572
+ return trans_function(argc, argv, self, &qacot, NULL);
573
+ }
574
+
575
+ /* Inverse hyperbolic cotangent
576
+ *
577
+ * @param eps [Numeric,Calc::Q] (optional) calculation accuracy
578
+ * @return [Calc::Q,Calc::C]
579
+ * @example
580
+ * Calc::Q(2).acoth #=> Calc::Q(0.5493061443340548457)
581
+ * Calc::Q(0.5).acoth #=> Calc::C(0.5493061443340548457+1.57079632679489661923i)
582
+ */
583
+ static VALUE
584
+ cq_acoth(int argc, VALUE * argv, VALUE self)
585
+ {
586
+ return trans_function(argc, argv, self, &qacoth, &c_acoth);
587
+ }
588
+
589
+ /* Inverse trigonometric cosecant
590
+ *
591
+ * @param eps [Numeric,Calc::Q] (optional) calculation accuracy
592
+ * @return [Calc::Q,Calc::C]
593
+ * @example
594
+ * Calc::Q(2).acsc #=> Calc::Q(0.52359877559829887308)
595
+ * Calc::Q(0.5).acsc #=> Calc::C(1.57079632679489661923-1.31695789692481670863i)
596
+ */
597
+ static VALUE
598
+ cq_acsc(int argc, VALUE * argv, VALUE self)
599
+ {
600
+ return trans_function(argc, argv, self, &qacsc, &c_acsc);
601
+ }
602
+
603
+ /* Inverse hyperbolic cosecant
604
+ *
605
+ * @param eps [Numeric,Calc::Q] (optional) calculation accuracy
606
+ * @return [Calc::Q]
607
+ * @raise [Calc::MathError] if self is zero
608
+ * @example
609
+ * Calc::Q(2).acsch #=> Calc::Q(0.4812118250596034475)
610
+ */
611
+ static VALUE
612
+ cq_acsch(int argc, VALUE * argv, VALUE self)
613
+ {
614
+ return trans_function(argc, argv, self, &qacsch, &c_acsch);
615
+ }
616
+
617
+ /* Approximate numbers by multiples of a specified number
618
+ *
619
+ * Returns the approximate value of self as specified by an error (defaults to
620
+ * Calc.config(:epsilon)) and rounding mode (defaults to Calc.config(:appr)).
621
+ *
622
+ * Type "help appr" in calc for a description of the rounding modes.
623
+ *
624
+ * @param y [Numeric,Calc::Q] (optional) error
625
+ * @param z [Interger] (optional) rounding mode
626
+ * @example
627
+ * Calc::Q("5.44").appr("0.1",0) #=> Calc::Q(5.4)
628
+ */
629
+ static VALUE
630
+ cq_appr(int argc, VALUE * argv, VALUE self)
631
+ {
632
+ VALUE result, epsilon, rounding;
633
+ NUMBER *qepsilon, *qrounding;
634
+ long R = 0;
635
+ int n;
636
+ setup_math_error();
637
+
638
+ n = rb_scan_args(argc, argv, "02", &epsilon, &rounding);
639
+ if (n == 2) {
640
+ if (FIXNUM_P(rounding)) {
641
+ R = FIX2LONG(rounding);
642
+ }
643
+ else {
644
+ qrounding = value_to_number(rounding, 1);
645
+ if (qisfrac(qrounding)) {
646
+ rb_raise(e_MathError, "fractional rounding for appr");
647
+ }
648
+ R = qtoi(DATA_PTR(qrounding));
649
+ qfree(qrounding);
650
+ }
651
+ }
652
+ else {
653
+ R = conf->appr;
654
+ }
655
+ if (n >= 1) {
656
+ qepsilon = value_to_number(epsilon, 1);
657
+ }
658
+ else {
659
+ qepsilon = NULL;
660
+ }
661
+ result = wrap_number(qmappr(DATA_PTR(self), qepsilon ? qepsilon : conf->epsilon, R));
662
+ if (qepsilon) {
663
+ qfree(qepsilon);
664
+ }
665
+ return result;
666
+ }
667
+
668
+ /* Inverse trigonometric secant
669
+ *
670
+ * @param eps [Numeric,Calc::Q] (optional) calculation accuracy
671
+ * @return [Calc::Q,Calc::C]
672
+ * @example
673
+ * Calc::Q(2).asec #=> Calc::Q(1.04719755119659774615)
674
+ */
675
+ static VALUE
676
+ cq_asec(int argc, VALUE * argv, VALUE self)
677
+ {
678
+ return trans_function(argc, argv, self, &qasec, &c_asec);
679
+ }
680
+
681
+ /* Inverse hyperbolic secant
682
+ *
683
+ * @param eps [Numeric,Calc::Q] (optional) calculation accuracy
684
+ * @return [Calc::Q,Calc::C]
685
+ * @raise [Calc::MathError] if self is zero
686
+ * @example
687
+ * Calc::Q(0.5).asech #=> Calc::Q(1.31695789692481670862)
688
+ */
689
+ static VALUE
690
+ cq_asech(int argc, VALUE * argv, VALUE self)
691
+ {
692
+ return trans_function(argc, argv, self, &qasech, &c_asech);
693
+ }
694
+
695
+ /* Inverse trigonometric sine
696
+ *
697
+ * @param eps [Numeric,Calc::Q] (optional) calculation accuracy
698
+ * @return [Calc::Q,Calc::C]
699
+ * @example
700
+ * Calc::Q(0.5).asin #=> Calc::Q(0.52359877559829887308)
701
+ */
702
+ static VALUE
703
+ cq_asin(int argc, VALUE * argv, VALUE self)
704
+ {
705
+ return trans_function(argc, argv, self, &qasin, &c_asin);
706
+ }
707
+
708
+ /* Inverse hyperbolic sine
709
+ *
710
+ * @param eps [Numeric,Calc::Q] (optional) calculation accuracy
711
+ * @return [Calc::Q]
712
+ * @example
713
+ * Calc::Q(2).asinh #=> Calc::Q(1.44363547517881034249)
714
+ */
715
+ static VALUE
716
+ cq_asinh(int argc, VALUE * argv, VALUE self)
717
+ {
718
+ return trans_function(argc, argv, self, &qasinh, NULL);
719
+ }
720
+
721
+ /* Inverse trigonometric tangent
722
+ *
723
+ * @param eps [Numeric,Calc::Q] (optional) calculation accuracy
724
+ * @return [Calc::Q]
725
+ * @example
726
+ * Calc::Q(2).atan #=> Calc::Q(1.10714871779409050302)
727
+ */
728
+ static VALUE
729
+ cq_atan(int argc, VALUE * argv, VALUE self)
730
+ {
731
+ return trans_function(argc, argv, self, &qatan, NULL);
732
+ }
733
+
734
+ /* Angle to point (arctangent with 2 arguments)
735
+ *
736
+ * To match normal calling conventions, `y.atan2(x)` is equivalent to
737
+ * `Math.atan2(y,x)`. To avoid confusion, the class method may be
738
+ * preferrable: `Calc::Q.atan2(y,x)`.
739
+ *
740
+ * @param eps [Numeric,Calc::Q] (optional) calculation accuracy
741
+ * @return [Calc::Q]
742
+ * @example
743
+ * Calc::Q(0).atan2(0) #=> Calc::Q(0)
744
+ * Calc::Q(17).atan2(52) #=> Calc::Q(0.31597027195298044266)
745
+ */
746
+ static VALUE
747
+ cq_atan2(int argc, VALUE * argv, VALUE self)
748
+ {
749
+ return trans_function2(argc, argv, self, &qatan2);
750
+ }
751
+
752
+ /* Inverse hyperbolic tangent
753
+ *
754
+ * @param eps [Numeric,Calc::Q] (optional) calculation accuracy
755
+ * @return [Calc::Q,Calc::C]
756
+ * @example
757
+ * Calc::Q(0.5).atanh #=> Calc::Q(0.87758256189037271612)
758
+ */
759
+ static VALUE
760
+ cq_atanh(int argc, VALUE * argv, VALUE self)
761
+ {
762
+ return trans_function(argc, argv, self, &qatanh, &c_atanh);
763
+ }
764
+
765
+ /* Returns the bernoulli number with index self. Self must be an integer,
766
+ * and < 2^31 if even.
767
+ *
768
+ * @return [Calc::Q]
769
+ * @raise [Calc::MathError] if self is fractional or even and >= 2^31
770
+ * @example
771
+ * Calc::Q(20).bernoulli.to_s(:frac) #=> "-174611/330"
772
+ */
773
+ static VALUE
774
+ cq_bernoulli(VALUE self)
775
+ {
776
+ NUMBER *qself, *qresult;
777
+ setup_math_error();
778
+
779
+ qself = DATA_PTR(self);
780
+ if (qisfrac(qself)) {
781
+ rb_raise(e_MathError, "Non-integer argument for bernoulli");
782
+ }
783
+ qresult = qbern(qself->num);
784
+ if (!qresult) {
785
+ rb_raise(e_MathError, "Bad argument for bern");
786
+ }
787
+ return wrap_number(qresult);
788
+ }
789
+
790
+ /* Returns true if binary bit y is set in self, otherwise false.
791
+ *
792
+ * @param y [Numeric] bit position
793
+ * @return [Boolean]
794
+ * @example
795
+ * Calc::Q(9).bit?(0) #=> true
796
+ * Calc::Q(9).bit?(1) #=> false
797
+ * @see bit
798
+ */
799
+ static VALUE
800
+ cq_bitp(VALUE self, VALUE y)
801
+ {
802
+ /* this is an "opcode" in calc rather than a builtin ("help bit" is
803
+ * wrong!). this is based on calc's opcodes.c#o_bit() */
804
+ NUMBER *qself, *qy;
805
+ long index;
806
+ int r;
807
+ setup_math_error();
808
+
809
+ qself = DATA_PTR(self);
810
+ qy = value_to_number(y, 0);
811
+ if (qisfrac(qy)) {
812
+ qfree(qy);
813
+ rb_raise(e_MathError, "Bad argument type for bit"); /* E_BIT1 */
814
+ }
815
+ if (zge31b(qy->num)) {
816
+ qfree(qy);
817
+ rb_raise(e_MathError, "Index too large for bit"); /* E_BIT2 */
818
+ }
819
+ index = qtoi(qy);
820
+ qfree(qy);
821
+ r = qisset(qself, index);
822
+ return r ? Qtrue : Qfalse;
823
+ }
824
+
825
+ /* Round to a specified number of binary digits
826
+ *
827
+ * Rounds self rounded to the specified number of significant binary digits.
828
+ * For the meanings of the rounding flags, see "help bround".
829
+ *
830
+ * @return [Calc::Q]
831
+ * @param places [Integer] number of binary digits to round to (default 0)
832
+ * @param rnd [Integer] rounding flags (default Calc.config(:round)
833
+ * @example
834
+ * Calc::Q(7,32).bround(3) #=> Calc::Q(0.25)
835
+ */
836
+ static VALUE
837
+ cq_bround(int argc, VALUE * argv, VALUE self)
838
+ {
839
+ return rounding_function(argc, argv, self, &qbround);
840
+ }
841
+
842
+ /* Truncate to a number of binary places
843
+ *
844
+ * Truncates to j binary places. If j is omitted, 0 places is assumed.
845
+ * Truncation of a non-integer prouces values nearer to zero.
846
+ *
847
+ * @param j [Integer]
848
+ * @return [Calc::Q]
849
+ * @example
850
+ * Calc.pi.btrunc #=> Calc::Q(3)
851
+ * Calc.pi.btrunc(5) #=> Calc::Q(3.125)
852
+ */
853
+ static VALUE
854
+ cq_btrunc(int argc, VALUE * argv, VALUE self)
855
+ {
856
+ return trunc_function(argc, argv, self, &qbtrunc);
857
+ }
858
+
859
+ /* Returns the Catalan number for index self. If self is negative, zero is
860
+ * returned.
861
+ *
862
+ * @return [Calc::Q]
863
+ * @raise [Calc::MathError] if self is not an integer or >= 2^31
864
+ * @example
865
+ * Calc::Q(2).catalan #=> Calc::Q(2)
866
+ * Calc::Q(5).catalan #=> Calc::Q(42)
867
+ * Calc::Q(20).catalan #=> Calc::Q(6564120420)
868
+ */
869
+ static VALUE
870
+ cq_catalan(VALUE self)
871
+ {
872
+ NUMBER *qself, *qresult;
873
+ setup_math_error();
874
+
875
+ qself = DATA_PTR(self);
876
+ if (qisfrac(qself)) {
877
+ rb_raise(e_MathError, "Non-integer value for catalan");
878
+ }
879
+ else if (zge31b(qself->num)) {
880
+ rb_raise(e_MathError, "Value too large for catalan");
881
+ }
882
+ qresult = qcatalan(qself);
883
+ if (!qresult) {
884
+ rb_raise(e_MathError, "qcatalan() returned NULL");
885
+ }
886
+ return wrap_number(qresult);
887
+ }
888
+
889
+ /* Approximation using continued fractions
890
+ *
891
+ * If self is an integer or eps is zero, returns x.
892
+ *
893
+ * If abs(eps) < 1, returns the smallest denominator number in one of the three
894
+ * intervals [self, self+abs(eps)], [self-abs(eps), self], [self-abs(eps)/2,
895
+ * self+abs(eps)/2].
896
+ *
897
+ * If eps >= 1 and den(self) > n, returns the nearest above, below or
898
+ * approximation with denominatior less than or equal to n.
899
+ *
900
+ * If den(self) <= eps, returns self.
901
+ *
902
+ * When the result is not self, the rounding is controlled by the final
903
+ * parameter; see "help cfappr" for details.
904
+ *
905
+ * @return [Calc::Q]
906
+ * @param eps [Numeric] epsilon or upper limit of denominator (default: Calc.config("epsilon"))
907
+ * @param rnd [Integer] rounding flags (default: Calc.config("cfappr"))
908
+ * @example
909
+ * Calc.pi.cfappr(1).to_s(:frac) #=> "3"
910
+ * Calc.pi.cfappr(10).to_s(:frac) #=> "25/8"
911
+ * Calc.pi.cfappr(50).to_s(:frac) #=> "157/50"
912
+ * Calc.pi.cfappr(100).to_s(:frac) #=> "311/99"
913
+ */
914
+ static VALUE
915
+ cq_cfappr(int argc, VALUE * argv, VALUE self)
916
+ {
917
+ VALUE eps, rnd, result;
918
+ NUMBER *q;
919
+ long n, R;
920
+ setup_math_error();
921
+
922
+ n = rb_scan_args(argc, argv, "02", &eps, &rnd);
923
+ q = (n >= 1) ? value_to_number(eps, 1) : conf->epsilon;
924
+ R = (n == 2) ? value_to_long(rnd) : conf->cfappr;
925
+ result = wrap_number(qcfappr(DATA_PTR(self), q, R));
926
+ if (n >= 1) {
927
+ qfree(q);
928
+ }
929
+ return result;
930
+ }
931
+
932
+ /* Simplify using continued fractions
933
+ *
934
+ * If self is not an integer, returns either the nearest above or below number
935
+ * with denominator less than self.den.
936
+ *
937
+ * Rounding is controlled by rnd (default: Calc.config(:cfsim)).
938
+ *
939
+ * See "help cfsim" for details of rounding values.
940
+ *
941
+ * Repeated calls to cfsim give a sequence of good approximations with
942
+ * decreasing denominators and correspondinlgy decreasing accuracy.
943
+ *
944
+ * @return [Calc::Q]
945
+ * @param rnd [Integer] rounding flags (default: Calc.config(:cfsim))
946
+ * @example
947
+ * x = Calc.pi; while (!x.int?) do; x = x.cfsim; puts x.to_s(:frac) if x.den < 1e6; end
948
+ * 1146408/364913
949
+ * 312689/99532
950
+ * 104348/33215
951
+ * 355/113
952
+ * 22/7
953
+ * 3
954
+ */
955
+ static VALUE
956
+ cq_cfsim(int argc, VALUE * argv, VALUE self)
957
+ {
958
+ VALUE rnd;
959
+ long n, R;
960
+ setup_math_error();
961
+
962
+ n = rb_scan_args(argc, argv, "01", &rnd);
963
+ R = (n >= 1) ? value_to_long(rnd) : conf->cfsim;
964
+ return wrap_number(qcfsim(DATA_PTR(self), R));
965
+ }
966
+
967
+ /* Cosine
968
+ *
969
+ * @param eps [Numeric,Calc::Q] (optional) calculation accuracy
970
+ * @return [Calc::Q]
971
+ * @example
972
+ * Calc::Q(1).cos #=> Calc::Q(0.5403023058681397174)
973
+ */
974
+ static VALUE
975
+ cq_cos(int argc, VALUE * argv, VALUE self)
976
+ {
977
+ return trans_function(argc, argv, self, &qcos, NULL);
978
+ }
979
+
980
+ /* Hyperbolic cosine
981
+ *
982
+ * @param eps [Numeric,Calc::Q] (optional) calculation accuracy
983
+ * @return [Calc::Q]
984
+ * @example
985
+ * Calc::Q(1).cosh #=> Calc::Q(1.54308063481524377848)
986
+ */
987
+ static VALUE
988
+ cq_cosh(int argc, VALUE * argv, VALUE self)
989
+ {
990
+ return trans_function(argc, argv, self, &qcosh, NULL);
991
+ }
992
+
993
+ /* Trigonometric cotangent
994
+ *
995
+ * @param eps [Numeric,Calc::Q] (optional) calculation accuracy
996
+ * @return [Calc::Q]
997
+ * @raise [Calc::MathError] if self is zero
998
+ * @example
999
+ * Calc::Q(1).cot #=> Calc::Q(0.64209261593433070301)
1000
+ */
1001
+ static VALUE
1002
+ cq_cot(int argc, VALUE * argv, VALUE self)
1003
+ {
1004
+ return trans_function(argc, argv, self, &qcot, NULL);
1005
+ }
1006
+
1007
+ /* Hyperbolic cotangent
1008
+ *
1009
+ * @param eps [Numeric,Calc::Q] (optional) calculation accuracy
1010
+ * @return [Calc::Q]
1011
+ * @raise [Calc::MathError] if self is zero
1012
+ * @example
1013
+ * Calc::Q(1).coth #=> Calc::Q(1.31303528549933130364)
1014
+ */
1015
+ static VALUE
1016
+ cq_coth(int argc, VALUE * argv, VALUE self)
1017
+ {
1018
+ return trans_function(argc, argv, self, &qcoth, NULL);
1019
+ }
1020
+
1021
+ /* Trigonometric cosecant
1022
+ *
1023
+ * @param eps [Numeric,Calc::Q] (optional) calculation accuracy
1024
+ * @return [Calc::Q]
1025
+ * @example
1026
+ * Calc::Q(1).csc #=> Calc::Q(1.18839510577812121626)
1027
+ */
1028
+ static VALUE
1029
+ cq_csc(int argc, VALUE * argv, VALUE self)
1030
+ {
1031
+ return trans_function(argc, argv, self, &qcsc, NULL);
1032
+ }
1033
+
1034
+ /* Hyperbolic cosecant
1035
+ *
1036
+ * @param eps [Numeric,Calc::Q] (optional) calculation accuracy
1037
+ * @return [Calc::Q]
1038
+ * @raise [Calc::MathError] if self is zero
1039
+ * @example
1040
+ * Calc::Q(1).csch #=> Calc::Q(0.85091812823932154513)
1041
+ */
1042
+ static VALUE
1043
+ cq_csch(int argc, VALUE * argv, VALUE self)
1044
+ {
1045
+ return trans_function(argc, argv, self, &qcsch, NULL);
1046
+ }
1047
+
1048
+ /* Returns the denominator. Always positive.
1049
+ *
1050
+ * @return [Calc::Q]
1051
+ * @example:
1052
+ * Calc::Q(1,3).den #=> Calc::Q(3)
1053
+ * Calc::Q(-1,3).den #=> Calc::Q(3)
1054
+ */
1055
+ static VALUE
1056
+ cq_den(VALUE self)
1057
+ {
1058
+ setup_math_error();
1059
+ return wrap_number(qden(DATA_PTR(self)));
1060
+ }
1061
+
1062
+ /* Returns the digit at the specified position on decimal or any other base.
1063
+ *
1064
+ * @return [Calc::Q]
1065
+ * @param n [Integer] index. negative indices are to the right of any decimal point
1066
+ * @param b [Integer] (optional) base >= 2 (default 10)
1067
+ * @example
1068
+ * Calc::Q("123456.789").digit(3) #=> Calc::Q(3)
1069
+ * Calc::Q("123456.789").digit(-3) #=> Calc::Q(9)
1070
+ */
1071
+ static VALUE
1072
+ cq_digit(int argc, VALUE * argv, VALUE self)
1073
+ {
1074
+ VALUE pos, base;
1075
+ NUMBER *qpos, *qbase, *qresult;
1076
+ long n;
1077
+ setup_math_error();
1078
+
1079
+ n = rb_scan_args(argc, argv, "11", &pos, &base);
1080
+ qpos = value_to_number(pos, 1);
1081
+ if (qisfrac(qpos)) {
1082
+ qfree(qpos);
1083
+ rb_raise(e_MathError, "non-integer position for digit");
1084
+ }
1085
+ if (n >= 2) {
1086
+ qbase = value_to_number(base, 1);
1087
+ if (qisfrac(qbase)) {
1088
+ qfree(qpos);
1089
+ qfree(qbase);
1090
+ rb_raise(e_MathError, "non-integer base for digit");
1091
+ }
1092
+ }
1093
+ else {
1094
+ qbase = NULL;
1095
+ }
1096
+ qresult = qdigit(DATA_PTR(self), qpos->num, qbase ? qbase->num : _ten_);
1097
+ qfree(qpos);
1098
+ if (qbase)
1099
+ qfree(qbase);
1100
+ if (qresult == NULL) {
1101
+ rb_raise(e_MathError, "Invalid arguments for digit");
1102
+ }
1103
+ return wrap_number(qresult);
1104
+ }
1105
+
1106
+ /* Returns the number of digits of the integral part of self in decimal or another base
1107
+ *
1108
+ * @return [Calc::Q]
1109
+ * @param b [Integer] (optional) base >= 2 (default 10)
1110
+ * @example
1111
+ * Calc::Q("12.3456").digits #=> Calc::Q(2)
1112
+ * Calc::Q(-1234).digits #=> Calc::Q(4)
1113
+ * Calc::Q(0).digits #=> Calc::Q(1)
1114
+ * Calc::Q("-0.123").digits #=> Calc::Q(1)
1115
+ */
1116
+ static VALUE
1117
+ cq_digits(int argc, VALUE * argv, VALUE self)
1118
+ {
1119
+ VALUE base;
1120
+ NUMBER *qbase, *qresult;
1121
+ long n;
1122
+ setup_math_error();
1123
+
1124
+ n = rb_scan_args(argc, argv, "01", &base);
1125
+ if (n >= 1) {
1126
+ qbase = value_to_number(base, 1);
1127
+ if (qisfrac(qbase) || qiszero(qbase) || qisunit(qbase)) {
1128
+ qfree(qbase);
1129
+ rb_raise(e_MathError, "base must be integer greater than 1 for digits");
1130
+ }
1131
+ }
1132
+ qresult = itoq(qdigits(DATA_PTR(self), n >= 1 ? qbase->num : _ten_));
1133
+ if (n >= 1)
1134
+ qfree(qbase);
1135
+ return wrap_number(qresult);
1136
+ }
1137
+
1138
+ /* Euler number
1139
+ *
1140
+ * Returns the euler number of a specified index.
1141
+ *
1142
+ * Considerable runtime and memory are required for calculating the euler
1143
+ * number for large even indices. Calculated values are stored in a table so
1144
+ * that later calls are executed quickly. This memory can be freed with
1145
+ * `Calc.freeeuler`.
1146
+ *
1147
+ * @example
1148
+ * Calc::Q(18).euler #=> Calc::Q(-2404879675441)
1149
+ * Calc::Q(19).euler #=> Calc::Q(0)
1150
+ * Calc::Q(20).euler #=> Calc::Q(370371188237525)
1151
+ */
1152
+ static VALUE
1153
+ cq_euler(VALUE self)
1154
+ {
1155
+ NUMBER *qself, *qresult;
1156
+ setup_math_error();
1157
+
1158
+ qself = DATA_PTR(self);
1159
+ if (qisfrac(qself)) {
1160
+ rb_raise(e_MathError, "non-integer value for euler");
1161
+ }
1162
+ qresult = qeuler(qself->num);
1163
+ if (qresult == NULL) {
1164
+ rb_raise(e_MathError, "number too big or out of memory for euler");
1165
+ }
1166
+ return wrap_number(qresult);
1167
+ }
1168
+
1169
+ /* Returns true if the number is an even integer
1170
+ *
1171
+ * @return [Boolean]
1172
+ * @example
1173
+ * Calc::Q(1).even? #=> false
1174
+ * Calc::Q(2).even? #=> true
1175
+ */
1176
+ static VALUE
1177
+ cq_evenp(VALUE self)
1178
+ {
1179
+ return qiseven((NUMBER *) DATA_PTR(self)) ? Qtrue : Qfalse;
1180
+ }
1181
+
1182
+ /* Exponential function
1183
+ *
1184
+ * @param eps [Numeric,Calc::Q] (optional) calculation accuracy
1185
+ * @return [Calc::Q]
1186
+ * @example
1187
+ * Calc::Q(1).exp #=> Calc::Q(2.71828182845904523536)
1188
+ * Calc::Q(2).exp #=> Calc::Q(7.38905609893065022723)
1189
+ */
1190
+ static VALUE
1191
+ cq_exp(int argc, VALUE * argv, VALUE self)
1192
+ {
1193
+ return trans_function(argc, argv, self, &qexp, NULL);
1194
+ }
1195
+
1196
+ /* Returns the factorial of a number.
1197
+ *
1198
+ * @return [Calc::Q]
1199
+ * @raise [Calc::MathError] if self is negative or not an integer
1200
+ * @raise [Calc::MathError] if abs(self) >= 2^31
1201
+ * @example:
1202
+ * Calc::Q(10).fact #=> Calc::Q(3628800)
1203
+ */
1204
+ static VALUE
1205
+ cq_fact(VALUE self)
1206
+ {
1207
+ setup_math_error();
1208
+ return wrap_number(qfact(DATA_PTR(self)));
1209
+ }
1210
+
1211
+ /* Smallest prime factor not exceeding specified limit
1212
+ *
1213
+ * Ignoring signs of self and limit; if self has a prime factor less than or
1214
+ * equal to limit, then returns the smallest such factor.
1215
+ *
1216
+ * @param limit [Numeric] (optional) limit, defaults to 2^32-1
1217
+ * @return [Calc::Q]
1218
+ * @raise [Calc::MathError] if self or limit are not integers
1219
+ * @raise [Calc::MathError] if limit is >= 2^32
1220
+ * @example
1221
+ * Calc::Q(2).power(32).+(1).factor #=> Calc::Q(641)
1222
+ */
1223
+ static VALUE
1224
+ cq_factor(int argc, VALUE * argv, VALUE self)
1225
+ {
1226
+ VALUE limit;
1227
+ NUMBER *qself, *qlimit, *qfactor;
1228
+ ZVALUE zlimit;
1229
+ long a;
1230
+ int res;
1231
+ setup_math_error();
1232
+
1233
+ a = rb_scan_args(argc, argv, "01", &limit);
1234
+ if (a >= 1) {
1235
+ qlimit = value_to_number(limit, 0);
1236
+ if (qisfrac(qlimit)) {
1237
+ qfree(qlimit);
1238
+ rb_raise(e_MathError, "non-integer limit for factor");
1239
+ }
1240
+ zcopy(qlimit->num, &zlimit);
1241
+ qfree(qlimit);
1242
+ }
1243
+ else {
1244
+ /* default limit is 2^32-1 */
1245
+ utoz((FULL) 0xffffffff, &zlimit);
1246
+ }
1247
+ qself = DATA_PTR(self);
1248
+ if (qisfrac(qself)) {
1249
+ zfree(zlimit);
1250
+ rb_raise(e_MathError, "non-integer for factor");
1251
+ }
1252
+
1253
+ qfactor = qalloc();
1254
+ res = zfactor(qself->num, zlimit, &(qfactor->num));
1255
+ if (res < 0) {
1256
+ qfree(qfactor);
1257
+ zfree(zlimit);
1258
+ rb_raise(e_MathError, "limit >= 2^32 for factor");
1259
+ }
1260
+ zfree(zlimit);
1261
+ return wrap_number(qfactor);
1262
+ }
1263
+
1264
+ /* Count number of times an integer divides self.
1265
+ *
1266
+ * Returns the greatest non-negative n for which y^n is a divisor of self.
1267
+ * Zero is returns if self is not divisible by y.
1268
+ *
1269
+ * @return [Calc::Q]
1270
+ * @raise [Calc::MathError] if self or y is non-integer
1271
+ * @param y [Integer]
1272
+ * @example
1273
+ * Calc::Q(24).fcnt(4) #=> Calc::Q(1)
1274
+ * Calc::Q(48).fcnt(4) #=> Calc::Q(2)
1275
+ */
1276
+ static VALUE
1277
+ cq_fcnt(VALUE self, VALUE y)
1278
+ {
1279
+ VALUE result;
1280
+ NUMBER *qself, *qy;
1281
+ setup_math_error();
1282
+
1283
+ qself = DATA_PTR(self);
1284
+ qy = value_to_number(y, 0);
1285
+ if (qisfrac(qself) || qisfrac(qy)) {
1286
+ qfree(qy);
1287
+ rb_raise(e_MathError, "non-integral argument for fcnt");
1288
+ }
1289
+ result = wrap_number(itoq(zdivcount(qself->num, qy->num)));
1290
+ qfree(qy);
1291
+ return result;
1292
+ }
1293
+
1294
+ /* Return the fractional part of self
1295
+ *
1296
+ * @return [Calc::Q]
1297
+ * @example
1298
+ * Calc::Q(22,7).frac.to_s(:frac) #=> "1/7"
1299
+ */
1300
+ static VALUE
1301
+ cq_frac(VALUE self)
1302
+ {
1303
+ NUMBER *qself;
1304
+ setup_math_error();
1305
+
1306
+ qself = DATA_PTR(self);
1307
+ if (qisint(qself)) {
1308
+ return wrap_number(qlink(&_qzero_));
1309
+ }
1310
+ else {
1311
+ return wrap_number(qfrac(qself));
1312
+ }
1313
+ }
1314
+
1315
+ /* Remove specified integer factors from self.
1316
+ *
1317
+ * @return [Calc::Q]
1318
+ * @raise [Calc::MathError] if self or y is non-integer
1319
+ * @param y [Integer]
1320
+ * @example
1321
+ * Calc::Q(7).frem(4) #=> 7
1322
+ * Calc::Q(24).frem(4) #=> 6
1323
+ * Calc::Q(48).frem(4) #=> 3
1324
+ * Calc::Q(-48).frem(4) #=> 3
1325
+ */
1326
+ static VALUE
1327
+ cq_frem(VALUE self, VALUE y)
1328
+ {
1329
+ VALUE result;
1330
+ NUMBER *qy;
1331
+
1332
+ qy = value_to_number(y, 0);
1333
+ result = wrap_number(qfacrem(DATA_PTR(self), qy));
1334
+ qfree(qy);
1335
+ return result;
1336
+ }
1337
+
1338
+ /* Returns the Fibonacci number with index self.
1339
+ *
1340
+ * @return [Calc::Q]
1341
+ * @raise [Calc::MathError] if self is not an integer
1342
+ * @raise [Calc::MathError] if abs(self) >= 2^31
1343
+ * @example
1344
+ * Calc::Q(10).fib #=> Calc::Q(55)
1345
+ */
1346
+ static VALUE
1347
+ cq_fib(VALUE self)
1348
+ {
1349
+ setup_math_error();
1350
+ return wrap_number(qfib(DATA_PTR(self)));
1351
+ }
1352
+
1353
+ /* Greatest common divisor
1354
+ *
1355
+ * Returns the greatest common divisor of self and all arguments. If no
1356
+ * arguments, returns self.
1357
+ *
1358
+ * @return [Calc::Q]
1359
+ * @example
1360
+ * Calc::Q(12).gcd(8) #=> Calc::Q(4)
1361
+ * Calc::Q(12).gcd(8, 6) #=> Calc::Q(2)
1362
+ * Calc.gcd("9/10", "11/5", "4/25") #=> Calc::Q(0.02)
1363
+ */
1364
+ static VALUE
1365
+ cq_gcd(int argc, VALUE * argv, VALUE self)
1366
+ {
1367
+ NUMBER *qresult, *qarg, *qtmp;
1368
+ int i;
1369
+ setup_math_error();
1370
+
1371
+ qresult = qqabs(DATA_PTR(self));
1372
+ for (i = 0; i < argc; i++) {
1373
+ qarg = value_to_number(argv[i], 1);
1374
+ qtmp = qgcd(qresult, qarg);
1375
+ qfree(qarg);
1376
+ qfree(qresult);
1377
+ qresult = qtmp;
1378
+ }
1379
+ return wrap_number(qresult);
1380
+ }
1381
+
1382
+ /* Returns greatest integer divisor of self relatively prime to other
1383
+ *
1384
+ * @return [Calc::Q]
1385
+ * @example
1386
+ * Calc::Q(6).gcdrem(15) #=> Calc::Q(2)
1387
+ * Calc::Q(15).gcdrem(6) #=> Calc::Q(5)
1388
+ */
1389
+ static VALUE
1390
+ cq_gcdrem(VALUE self, VALUE other)
1391
+ {
1392
+ NUMBER *qother, *qresult;
1393
+ setup_math_error();
1394
+
1395
+ qother = value_to_number(other, 0);
1396
+ qresult = qgcdrem(DATA_PTR(self), qother);
1397
+ qfree(qother);
1398
+ return wrap_number(qresult);
1399
+ }
1400
+
1401
+ /* Returns index of highest bit in binary representation of self
1402
+ *
1403
+ * If self is a non-zero integer, higbit returns the index of the highest bit
1404
+ * in the binary representation of abs(self). Equivalently, x.highbit = n
1405
+ * if 2^n <= abs(x) < 2^(n+1); the binary representation of x then has n + 1
1406
+ * digits.
1407
+ *
1408
+ * @return [Calc::Q]
1409
+ * @example
1410
+ * Calc::Q(4).highbit #=> Calc::Q(2)
1411
+ * Calc::Q(2).**(27).highbit #=> Calc::Q(27)
1412
+ */
1413
+ static VALUE
1414
+ cq_highbit(VALUE self)
1415
+ {
1416
+ NUMBER *qself;
1417
+ setup_math_error();
1418
+
1419
+ qself = DATA_PTR(self);
1420
+ if (qisfrac(qself)) {
1421
+ rb_raise(e_MathError, "non-integer argument for highbit");
1422
+ }
1423
+ if (qiszero(qself)) {
1424
+ return wrap_number(qlink(&_qnegone_));
1425
+ }
1426
+ else {
1427
+ return wrap_number(itoq(zhighbit(qself->num)));
1428
+ }
1429
+ }
1430
+
1431
+ /* Returns the hypotenuse of a right-angled triangle given the other sides
1432
+ *
1433
+ * @param y [Numeric,Calc::Numeric] other side
1434
+ * @return [Calc::Q]
1435
+ * @example:
1436
+ * Calc::Q(3).hypot(4) #=> Calc::Q(5)
1437
+ * Calc::Q(2).hypot(-3) #=> Calc::Q(3.60555127546398929312)
1438
+ */
1439
+ static VALUE
1440
+ cq_hypot(int argc, VALUE * argv, VALUE self)
1441
+ {
1442
+ return trans_function2(argc, argv, self, &qhypot);
1443
+ }
1444
+
1445
+ /* Integer part of the number
1446
+ *
1447
+ * @return [Calc::Q]
1448
+ * @example
1449
+ * Calc::Q(3).int #=> Calc::Q(3)
1450
+ * Calc::Q("30/7").int #=> Calc::Q(4)
1451
+ * Calc::Q(-3.125).int #=> Calc::Q(-3)
1452
+ */
1453
+ static VALUE
1454
+ cq_int(VALUE self)
1455
+ {
1456
+ NUMBER *qself;
1457
+ setup_math_error();
1458
+
1459
+ qself = DATA_PTR(self);
1460
+ if (qisint(qself)) {
1461
+ return self;
1462
+ }
1463
+ return wrap_number(qint(qself));
1464
+ }
1465
+
1466
+ /* Returns true if the number is an integer.
1467
+ *
1468
+ * @return [Boolean]
1469
+ * @example
1470
+ * Calc::Q(2).int? #=> true
1471
+ * Calc::Q(0.1).int? #=> false
1472
+ */
1473
+ static VALUE
1474
+ cq_intp(VALUE self)
1475
+ {
1476
+ return qisint((NUMBER *) DATA_PTR(self)) ? Qtrue : Qfalse;
1477
+ }
1478
+
1479
+ /* Inverse of a real number
1480
+ *
1481
+ * @return [Calc::Q]
1482
+ * @raise [Calc::MathError] if self is zero
1483
+ * @example:
1484
+ * Calc::Q(3).inverse #=> Calc::Q(0.25)
1485
+ */
1486
+ static VALUE
1487
+ cq_inverse(VALUE self)
1488
+ {
1489
+ setup_math_error();
1490
+ return wrap_number(qinv(DATA_PTR(self)));
1491
+ }
1492
+
1493
+ /* Integer part of specified root
1494
+ *
1495
+ * x.iroot(n) returns the greatest integer v for which v^n <= x.
1496
+ *
1497
+ * @param n [Integer]
1498
+ * @return [Calc::Q]
1499
+ * @raise [Calc::MathError] if n is not a positive integer
1500
+ * @example
1501
+ * Calc::Q(100).iroot(3) #=> Calc::Q(4)
1502
+ */
1503
+ static VALUE
1504
+ cq_iroot(VALUE self, VALUE other)
1505
+ {
1506
+ NUMBER *qother, *qresult;
1507
+ setup_math_error();
1508
+
1509
+ qother = value_to_number(other, 0);
1510
+ qresult = qiroot(DATA_PTR(self), qother);
1511
+ qfree(qother);
1512
+ return wrap_number(qresult);
1513
+ }
1514
+
1515
+ /* Integer part of square root
1516
+ *
1517
+ * x.isqrt returns the greatest integer n for which n^2 <= x.
1518
+ *
1519
+ * @return [Calc::Q]
1520
+ * @raise [Calc::MathError] if self is negative
1521
+ * @example
1522
+ * Calc::Q("8.5").isqrt #=> Calc::Q(2)
1523
+ * Calc::Q(200).isqrt #=> Calc::Q(14)
1524
+ * Calc::Q("2e6").isqrt #=> Calc::Q(1414)
1525
+ */
1526
+ static VALUE
1527
+ cq_isqrt(VALUE self)
1528
+ {
1529
+ setup_math_error();
1530
+ return wrap_number(qisqrt(DATA_PTR(self)));
1531
+ }
1532
+
1533
+ /* Compute the Jacobi function (x = self / y)
1534
+ *
1535
+ * Returns:
1536
+ * -1 if x is not quadratic residue mod y
1537
+ * 1 if y is composite, or x is a quadratic residue of y]
1538
+ * 0 if y is even or y is < 0
1539
+ *
1540
+ * @param y [Integer]
1541
+ * @return [Calc::Q]
1542
+ * @raise [Calc::MathError] if either value is not an integer
1543
+ * @example
1544
+ * Calc::Q(2).jacobi(5) #=> Calc::Q(-1)
1545
+ * Calc::Q(2).jacobi(15) #=> Calc::Q(1)
1546
+ */
1547
+ static VALUE
1548
+ cq_jacobi(VALUE self, VALUE y)
1549
+ {
1550
+ NUMBER *qy, *qresult;
1551
+ setup_math_error();
1552
+
1553
+ qy = value_to_number(y, 0);
1554
+ qresult = qjacobi(DATA_PTR(self), qy);
1555
+ qfree(qy);
1556
+ return wrap_number(qresult);
1557
+ }
1558
+
1559
+ /* Least common multiple
1560
+ *
1561
+ * If no value is zero, lcm returns the least positive number which is a
1562
+ * multiple of all values. If at least one value is zero, the lcm is zero.
1563
+ *
1564
+ * @param v [Numeric] zero or more values
1565
+ * @return [Calc::Q]
1566
+ * @example
1567
+ * Calc::Q(12).lcm(24, 30) #=> Calc::Q(120)
1568
+ */
1569
+ static VALUE
1570
+ cq_lcm(int argc, VALUE * argv, VALUE self)
1571
+ {
1572
+ NUMBER *qresult, *qarg, *qtmp;
1573
+ int i;
1574
+ setup_math_error();
1575
+
1576
+ qresult = qqabs(DATA_PTR(self));
1577
+ for (i = 0; i < argc; i++) {
1578
+ qarg = value_to_number(argv[i], 1);
1579
+ qtmp = qlcm(qresult, qarg);
1580
+ qfree(qarg);
1581
+ qfree(qresult);
1582
+ qresult = qtmp;
1583
+ if (qiszero(qresult))
1584
+ break;
1585
+ }
1586
+ return wrap_number(qresult);
1587
+ }
1588
+
1589
+ /* Least common multiple of positive integers up to specified integer
1590
+ *
1591
+ * Retrurns the lcm of the integers 1, 2, ..., self
1592
+ *
1593
+ * @return [Calc::Q]
1594
+ * @example
1595
+ * Calc::Q(6).lcmfact #=> Calc::Q(60)
1596
+ * Calc::Q(7).lcmfact #=> Calc::Q(420)
1597
+ */
1598
+ static VALUE
1599
+ cq_lcmfact(VALUE self)
1600
+ {
1601
+ setup_math_error();
1602
+ return wrap_number(qlcmfact(DATA_PTR(self)));
1603
+ }
1604
+
1605
+ /* Smallest prime factor in first specified number of primes
1606
+ *
1607
+ * If n is nonzero and abs(n) has a prime factor in the first m primes (2, 3,
1608
+ * 5, ...), then n.lfactor(m) returns the smallest such factor. Otherwise it
1609
+ * returns 1.
1610
+ *
1611
+ * @param m [Numeric]
1612
+ * @return [Calc::Q]
1613
+ * @example
1614
+ * Calc::Q(2**32 + 1).lfactor(116) #=> Calc::Q(641)
1615
+ */
1616
+ static VALUE
1617
+ cq_lfactor(VALUE self, VALUE other)
1618
+ {
1619
+ NUMBER *qother, *qresult;
1620
+ setup_math_error();
1621
+
1622
+ qother = value_to_number(other, 1);
1623
+ qresult = qlowfactor(DATA_PTR(self), qother);
1624
+ qfree(qother);
1625
+ return wrap_number(qresult);
1626
+ }
1627
+
1628
+ /* Index of lowest nonzero bit in binary representation
1629
+ *
1630
+ * Returns the index of the lowest nonzero bit in the binary representation of
1631
+ * abs(self). If self is zero, returns -1.
1632
+ *
1633
+ * @return [Calc::Q]
1634
+ * @raise [Calc::MathError] if self is not an integer
1635
+ * @example
1636
+ * Calc::Q(2).lowbit #=> Calc::Q(1)
1637
+ * Calc::Q(2**27).lowbit #=> Calc::Q(27)
1638
+ */
1639
+ static VALUE
1640
+ cq_lowbit(VALUE self)
1641
+ {
1642
+ NUMBER *qself;
1643
+ long index;
1644
+ setup_math_error();
1645
+
1646
+ qself = DATA_PTR(self);
1647
+ if (qiszero(qself)) {
1648
+ index = -1;
1649
+ }
1650
+ else if (qisfrac(qself)) {
1651
+ rb_raise(e_MathError, "non-integer argument for lowbit");
1652
+ }
1653
+ else {
1654
+ index = zlowbit(qself->num);
1655
+ }
1656
+ return wrap_number(itoq(index));
1657
+ }
1658
+
1659
+ /* leg-to-leg - third side of a right angled triangle
1660
+ *
1661
+ * Returns the third side of a right-angled triangle with unit hypotenuse,
1662
+ * given one other side. x.ltol is equivalent to sqrt(1 - x**2). Result
1663
+ * is to nearest multiple of eps which defaults to Calc.config(:epsilon).
1664
+ *
1665
+ * @param eps [Numeric] (optional) calculation accuracy
1666
+ * @return [Calc::Q]
1667
+ * @raise [Calc::MathError] if self it too large
1668
+ * @example
1669
+ * Calc::Q("0.5").ltol #=> Calc::Q(0.86602540378443864676)
1670
+ */
1671
+ static VALUE
1672
+ cq_ltol(int argc, VALUE * argv, VALUE self)
1673
+ {
1674
+ VALUE epsilon;
1675
+ NUMBER *qresult, *qepsilon;
1676
+ setup_math_error();
1677
+
1678
+ if (rb_scan_args(argc, argv, "01", &epsilon) == 0) {
1679
+ qresult = qlegtoleg(DATA_PTR(self), conf->epsilon, FALSE);
1680
+ }
1681
+ else {
1682
+ qepsilon = value_to_number(epsilon, 1);
1683
+ qresult = qlegtoleg(DATA_PTR(self), qepsilon, FALSE);
1684
+ qfree(qepsilon);
1685
+ }
1686
+ return wrap_number(qresult);
1687
+ }
1688
+
1689
+ /* test for equality modulo a specific number
1690
+ *
1691
+ * Returns true if self is congruent to y modulo md.
1692
+ *
1693
+ * @param y [Numeric]
1694
+ * @param md [Numeric]
1695
+ * @return [Boolean]
1696
+ * @example
1697
+ * Calc::Q(5).meq?(33, 7) #=> true
1698
+ * Calc::Q(5).meq?(32, 7) #=> false
1699
+ * @see Calc::Q#meq
1700
+ */
1701
+ static VALUE
1702
+ cq_meqp(VALUE self, VALUE y, VALUE md)
1703
+ {
1704
+ VALUE result;
1705
+ NUMBER *qy, *qmd, *qtmp;
1706
+ setup_math_error();
1707
+
1708
+ qy = value_to_number(y, 1);
1709
+ qmd = value_to_number(md, 1);
1710
+ qtmp = qsub(DATA_PTR(self), qy);
1711
+ result = qdivides(qtmp, qmd) ? Qtrue : Qfalse;
1712
+ qfree(qtmp);
1713
+ qfree(qmd);
1714
+ qfree(qy);
1715
+ return result;
1716
+ }
1717
+
1718
+ /* Inverse of an integer modulo a specified integer
1719
+ *
1720
+ * Finds x such that:
1721
+ * self * x = 1 (mod md)
1722
+ * If self and md are not relatively prime, zero is returned.
1723
+ *
1724
+ * The canonical residues modulo md are determined by Calc.config(:mod)
1725
+ * (run "help minv" in calc for details).
1726
+ *
1727
+ * @param md [Integer]
1728
+ * @return [Calc::Q]
1729
+ * @raise [Calc::MathError] if self or md are non-integers
1730
+ * @example
1731
+ * Calc::Q(3).minv(10) #=> Calc::Q(7)
1732
+ * Calc::Q(-3).minv(10) #=> Calc::Q(3)
1733
+ */
1734
+ static VALUE
1735
+ cq_minv(VALUE self, VALUE md)
1736
+ {
1737
+ NUMBER *qmd, *qresult;
1738
+ setup_math_error();
1739
+
1740
+ qmd = value_to_number(md, 1);
1741
+ qresult = qminv(DATA_PTR(self), qmd);
1742
+ qfree(qmd);
1743
+ return wrap_number(qresult);
1744
+ }
1745
+
1746
+ /* Computes the remainder for an integer quotient
1747
+ *
1748
+ * @param y [Numeric,Calc::Q]
1749
+ * @param rnd [Integer] rounding flags (default Calc.config(:mod))
1750
+ * @return [Calc::Q]
1751
+ * @example:
1752
+ * Calc::Q(11).mod(5) #=> Calc::Q(1)
1753
+ */
1754
+ static VALUE
1755
+ cq_mod(int argc, VALUE * argv, VALUE self)
1756
+ {
1757
+ VALUE other, rnd;
1758
+ NUMBER *qother, *qresult;
1759
+ long n;
1760
+ setup_math_error();
1761
+
1762
+ n = rb_scan_args(argc, argv, "11", &other, &rnd);
1763
+ qother = value_to_number(other, 0);
1764
+ if (qiszero(qother)) {
1765
+ qfree(qother);
1766
+ rb_raise(rb_eZeroDivError, "division by zero in mod");
1767
+ }
1768
+ qresult = qmod(DATA_PTR(self), qother, (n == 2) ? value_to_long(rnd) : conf->mod);
1769
+ qfree(qother);
1770
+ return wrap_number(qresult);
1771
+ }
1772
+
1773
+ /* Returns true if self exactly divides y, otherwise return false.
1774
+ *
1775
+ * @return [Boolean]
1776
+ * @example
1777
+ * Calc::Q(6).mult?(2) #=> true
1778
+ * Calc::Q(2).mult?(6) #=> false
1779
+ * @see Calc::Q#ismult
1780
+ */
1781
+ static VALUE
1782
+ cq_multp(VALUE self, VALUE other)
1783
+ {
1784
+ VALUE result;
1785
+ NUMBER *qother;
1786
+ setup_math_error();
1787
+
1788
+ qother = value_to_number(other, 0);
1789
+ result = qdivides(DATA_PTR(self), qother) ? Qtrue : Qfalse;
1790
+ qfree(qother);
1791
+ return result;
1792
+ }
1793
+
1794
+ /* Compare nearness of two numbers with a standard
1795
+ *
1796
+ * Returns:
1797
+ * -1 if abs(self - other) < abs(eps)
1798
+ * 0 if abs(self - other) = abs(eps)
1799
+ * 1 if abs(self - other) > abs(eps)
1800
+ *
1801
+ * @param other [Numeric]
1802
+ * @param eps [Numeric] (optional) defaults to Calc.config(:epsilon)
1803
+ * @return [Calc::Q]
1804
+ * @example
1805
+ * Calc::Q("22/7").near("3.15", ".01") #=> Calc::Q(-1)
1806
+ * Calc::Q("22/7").near("3.15", ".005") #=> Calc::Q(1)
1807
+ */
1808
+ static VALUE
1809
+ cq_near(int argc, VALUE * argv, VALUE self)
1810
+ {
1811
+ VALUE other, epsilon;
1812
+ NUMBER *qother, *qepsilon, *qresult;
1813
+ int n;
1814
+ setup_math_error();
1815
+
1816
+ n = rb_scan_args(argc, argv, "11", &other, &epsilon);
1817
+ qother = value_to_number(other, 1);
1818
+ qepsilon = (n == 2) ? value_to_number(epsilon, 1) : conf->epsilon;
1819
+ qresult = itoq((long) qnear(DATA_PTR(self), qother, qepsilon));
1820
+ qfree(qother);
1821
+ if (n == 2)
1822
+ qfree(qepsilon);
1823
+ return wrap_number(qresult);
1824
+ }
1825
+
1826
+ /* Next candidate for primeness
1827
+ *
1828
+ * Returns the least positive integer i greater than abs(self) expressible as
1829
+ * residue + k * modulus, where k is an integer, for which i.ptest?(count, skip)
1830
+ * is true, or if there is no such integer i, nil.
1831
+ *
1832
+ * See `ptest?` for a description of `count` and `skip`. For basic purposes,
1833
+ * use default values and count > 1. Higher counts increase the probability
1834
+ * that the returned value is prime.
1835
+ *
1836
+ * @param count [Integer] number of tests for ptest (default 1)
1837
+ * @param skip [Integer] base selection mode for ptest (default 1)
1838
+ * @param residue [Integer] (default 0)
1839
+ * @param modulus [Integer] (default 1)
1840
+ * @return [Calc::Q]
1841
+ * @raise [Calc::MathError] if self or any parameter is not an integer
1842
+ * @example
1843
+ * Calc::Q(100).nextcand(10) #=> Calc::Q(101)
1844
+ * Calc::Q(5000000000).nextcand(10) #=> Calc::Q(5000000029)
1845
+ */
1846
+ static VALUE
1847
+ cq_nextcand(int argc, VALUE * argv, VALUE self)
1848
+ {
1849
+ return cand_navigation(argc, argv, self, &znextcand);
1850
+ }
1851
+
1852
+ /* libcalc constant for 2^32+15 - can't include prime.h for this */
1853
+ extern NUMBER _nxtprime_;
1854
+
1855
+ /* Next prime number
1856
+ *
1857
+ * If self is >= 2**32, raises an exception. Otherwise returns the next prime
1858
+ * number.
1859
+ *
1860
+ * @return [Calc::Q]
1861
+ * @raise [Calc::MathError] if self is >= 2**32
1862
+ * @example
1863
+ * Calc::Q(2).nextprime #=> Calc::Q(3)
1864
+ * Calc::Q(10).nextprime #=> Calc::Q(11)
1865
+ * Calc::Q(100).nextprime #=> Calc::Q(101)
1866
+ * Calc::Q("1e6").nextprime #=> Calc::Q(1000003)
1867
+ * Calc::Q(2**32 - 1).nextprime #=> Calc::Q(4294967311)
1868
+ */
1869
+ static VALUE
1870
+ cq_nextprime(VALUE self)
1871
+ {
1872
+ NUMBER *qself;
1873
+ FULL next_prime;
1874
+ setup_math_error();
1875
+
1876
+ qself = DATA_PTR(self);
1877
+ if (qisfrac(qself)) {
1878
+ rb_raise(e_MathError, "non-integral for nextprime");
1879
+ }
1880
+ next_prime = znprime(qself->num);
1881
+ if (next_prime == 0) {
1882
+ /* return 2^32+15 */
1883
+ return wrap_number(qlink(&_nxtprime_));
1884
+ }
1885
+ else if (next_prime == 1) {
1886
+ rb_raise(e_MathError, "nextprime arg is >= 2^32");
1887
+ }
1888
+ return wrap_number(utoq(next_prime));
1889
+ }
1890
+
1891
+ /* Norm of a value
1892
+ *
1893
+ * For real values, norm is the square of the absolute value.
1894
+ *
1895
+ * @return [Calc::Q]
1896
+ * @example
1897
+ * Calc::Q("3.4").norm #=> Calc::Q(11.56)
1898
+ * Calc::Q("-3.4").norm #=> Calc::Q(11.56)
1899
+ */
1900
+ static VALUE
1901
+ cq_norm(VALUE self)
1902
+ {
1903
+ setup_math_error();
1904
+ return wrap_number(qsquare(DATA_PTR(self)));
1905
+ }
1906
+
1907
+ /* Returns the numerator. Return value has the same sign as self.
1908
+ *
1909
+ * @return [Calc::Q]
1910
+ * @example:
1911
+ * Calc::Q(1,3).num #=> Calc::Q(1)
1912
+ * Calc::Q(-1,3).num #=> Calc::Q(-1)
1913
+ */
1914
+ static VALUE
1915
+ cq_num(VALUE self)
1916
+ {
1917
+ setup_math_error();
1918
+ return wrap_number(qnum(DATA_PTR(self)));
1919
+ }
1920
+
1921
+ /* Returns true if the number is an odd integer
1922
+ *
1923
+ * @return [Boolean]
1924
+ * @example
1925
+ * Calc::Q(1).odd? #=> true
1926
+ * Calc::Q(2).odd? #=> false
1927
+ */
1928
+ static VALUE
1929
+ cq_oddp(VALUE self)
1930
+ {
1931
+ return qisodd((NUMBER *) DATA_PTR(self)) ? Qtrue : Qfalse;
1932
+ }
1933
+
1934
+ /* Permutation number
1935
+ *
1936
+ * Returns the number of permutations in which `other` things may be chosen
1937
+ * from `self` items where order in which they are chosen matters.
1938
+ *
1939
+ * @return [Calc::Q]
1940
+ * @param other [Integer]
1941
+ * @example
1942
+ * Calc::Q(7).perm(3) #=> Calc::Q(210)
1943
+ */
1944
+ static VALUE
1945
+ cq_perm(VALUE self, VALUE other)
1946
+ {
1947
+ NUMBER *qresult, *qother;
1948
+ setup_math_error();
1949
+
1950
+ qother = value_to_number(other, 0);
1951
+ qresult = qperm(DATA_PTR(self), qother);
1952
+ qfree(qother);
1953
+ return wrap_number(qresult);
1954
+ }
1955
+
1956
+ /* Product of primes up to specified integer
1957
+ *
1958
+ * @return [Calc::Q]
1959
+ * @raise [Calc::MathError] if self is not a positive integer
1960
+ * @example
1961
+ * Calc::Q(2).pfact #=> Calc::Q(2)
1962
+ * Calc::Q(10).pfact #=> Calc::Q(210)
1963
+ * Calc::Q(100).pfact #=> Calc::Q(2305567963945518424753102147331756070)
1964
+ */
1965
+ static VALUE
1966
+ cq_pfact(VALUE self)
1967
+ {
1968
+ setup_math_error();
1969
+ return wrap_number(qpfact(DATA_PTR(self)));
1970
+ }
1971
+
1972
+ /* Number of primes not exceeded specified number
1973
+ *
1974
+ * @return [Calc::Q]
1975
+ * @raise [Calc::MathError] if self is >= 2**32
1976
+ * @example
1977
+ * Calc::Q(10).pix #=> Calc::Q(4)
1978
+ * Calc::Q(100).pix #=> Calc::Q(25)
1979
+ * Calc::Q(10**9).pix #=> Calc::Q(50847534)
1980
+ */
1981
+ static VALUE
1982
+ cq_pix(VALUE self)
1983
+ {
1984
+ NUMBER *qself;
1985
+ long value;
1986
+ setup_math_error();
1987
+
1988
+ qself = DATA_PTR(self);
1989
+ if (qisfrac(qself)) {
1990
+ rb_raise(e_MathError, "non-integer value for pix");
1991
+ }
1992
+ value = zpix(qself->num);
1993
+ if (value >= 0) {
1994
+ return wrap_number(utoq(value));
1995
+ }
1996
+ rb_raise(e_MathError, "pix arg is >= 2^32");
1997
+ }
1998
+
1999
+ /* Number of decimal (or other) places in fractional part
2000
+ *
2001
+ * Returns the number of digits needed to express the fractional part of this
2002
+ * number in base b. If self is an integer, returns 0. If the expansion in
2003
+ * base b is infinite, returns nil.
2004
+ *
2005
+ * @param b [Integer] base (default 10)
2006
+ * @return [Calc::Q]
2007
+ * @raise [Calc::MathError] if base is invalid
2008
+ * @example
2009
+ * Calc::Q(3).places #=> Calc::Q(0)
2010
+ * Calc::Q("0.0123").places #=> Calc::Q(4)
2011
+ * Calc::Q("0.0123").places(2) #=> nil
2012
+ * Calc::Q(".625").places(2) #=> Calc::Q(3)
2013
+ */
2014
+ static VALUE
2015
+ cq_places(int argc, VALUE * argv, VALUE self)
2016
+ {
2017
+ VALUE base;
2018
+ NUMBER *qbase;
2019
+ long places;
2020
+ setup_math_error();
2021
+
2022
+ if (rb_scan_args(argc, argv, "01", &base) == 0) {
2023
+ places = qdecplaces(DATA_PTR(self));
2024
+ }
2025
+ else {
2026
+ qbase = value_to_number(base, 0);
2027
+ if (qisfrac(qbase)) {
2028
+ qfree(qbase);
2029
+ rb_raise(e_MathError, "non-integer base for places");
2030
+ }
2031
+ places = qplaces(DATA_PTR(self), qbase->num);
2032
+ qfree(qbase);
2033
+ if (places == -2) {
2034
+ rb_raise(e_MathError, "invalid base for places");
2035
+ }
2036
+ }
2037
+ if (places == -1) {
2038
+ return Qnil;
2039
+ }
2040
+ return wrap_number(itoq(places));
2041
+ }
2042
+
2043
+ /* Integral power of an interger modulo a specified integer
2044
+ *
2045
+ * x.pmod(n, md) returns the integer value of the canonical reidue of
2046
+ * x^n modulo md. The canonical residue is determined by Calc.config(:mod).
2047
+ * See "help pmod" for full details.
2048
+ *
2049
+ * @param n [Integer]
2050
+ * @param md [Integer]
2051
+ * @return [Calc::Q]
2052
+ * @example
2053
+ * Calc::Q(2).pmod(3, 10) #=> Calc::Q(8)
2054
+ * Calc::Q(2).pmod(5, 10) #=> Calc::Q(2)
2055
+ */
2056
+ static VALUE
2057
+ cq_pmod(VALUE self, VALUE n, VALUE md)
2058
+ {
2059
+ NUMBER *qn, *qmd, *qresult;
2060
+ setup_math_error();
2061
+
2062
+ qn = value_to_number(n, 0);
2063
+ qmd = value_to_number(md, 0);
2064
+ qresult = qpowermod(DATA_PTR(self), qn, qmd);
2065
+ qfree(qn);
2066
+ qfree(qmd);
2067
+ return wrap_number(qresult);
2068
+ }
2069
+
2070
+ /* Number of bits that match 0 or 1
2071
+ *
2072
+ * Counts of number of bits in abs(self) that match bitval (1 or 0, default 1)
2073
+ *
2074
+ * @param bitval [Integer] 0 or 1 (default 1)
2075
+ * @return [Calc::Q]
2076
+ * @example
2077
+ * Calc::Q(32767).popcnt #=> Calc::Q(15)
2078
+ * Calc::Q(32767).popcnt(0) #=> Calc::Q(0)
2079
+ */
2080
+ static VALUE
2081
+ cq_popcnt(int argc, VALUE * argv, VALUE self)
2082
+ {
2083
+ VALUE bitval;
2084
+ NUMBER *qself, *qbitval, *qresult;
2085
+ int b = 1;
2086
+ setup_math_error();
2087
+
2088
+ if (rb_scan_args(argc, argv, "01", &bitval) == 1) {
2089
+ qbitval = value_to_number(bitval, 0);
2090
+ if (qiszero(qbitval)) {
2091
+ b = 0;
2092
+ }
2093
+ qfree(qbitval);
2094
+ }
2095
+ qself = DATA_PTR(self);
2096
+ if (qisint(qself)) {
2097
+ qresult = itoq(zpopcnt(qself->num, b));
2098
+ }
2099
+ else {
2100
+ qresult = itoq(zpopcnt(qself->num, b) + zpopcnt(qself->den, b));
2101
+ }
2102
+ return wrap_number(qresult);
2103
+ }
2104
+
2105
+ /* Evaluates a numeric power
2106
+ *
2107
+ * @param y [Numeric] power to raise by
2108
+ * @param eps [Numeric,Calc::Q] (optional) calculation accuracy
2109
+ * @return [Calc::Q,Calc::C]
2110
+ * @raise [Calc::MathError] if raising to a VERY large power
2111
+ * @example
2112
+ * Calc::Q("1.2345").power(10) #=> Calc::Q(8.2207405646327461795)
2113
+ * Calc::Q(-1).power("0.1") #=> Calc::C(0.95105651629515357212+0.3090169943749474241i)
2114
+ */
2115
+ static VALUE
2116
+ cq_power(int argc, VALUE * argv, VALUE self)
2117
+ {
2118
+ /* ref: powervalue() in calc value.c. handle cases NUM,NUM and NUM,COM */
2119
+ VALUE arg, epsilon, result;
2120
+ NUMBER *qself, *qarg, *qepsilon;
2121
+ COMPLEX *cself, *carg;
2122
+ setup_math_error();
2123
+
2124
+ if (rb_scan_args(argc, argv, "11", &arg, &epsilon) == 1) {
2125
+ qepsilon = NULL;
2126
+ }
2127
+ else {
2128
+ qepsilon = value_to_number(epsilon, 1);
2129
+ }
2130
+ qself = DATA_PTR(self);
2131
+ if (CALC_C_P(arg) || TYPE(arg) == T_COMPLEX || qisneg(qself)) {
2132
+ cself = comalloc();
2133
+ qfree(cself->real);
2134
+ cself->real = qlink(qself);
2135
+ if (TYPE(arg) == T_STRING) {
2136
+ carg = comalloc();
2137
+ qfree(carg->real);
2138
+ carg->real = value_to_number(arg, 1);
2139
+ }
2140
+ else {
2141
+ carg = value_to_complex(arg);
2142
+ }
2143
+ result = wrap_complex(c_power(cself, carg, qepsilon ? qepsilon : conf->epsilon));
2144
+ comfree(cself);
2145
+ comfree(carg);
2146
+ }
2147
+ else {
2148
+ qarg = value_to_number(arg, 1);
2149
+ result = wrap_number(qpower(qself, qarg, qepsilon ? qepsilon : conf->epsilon));
2150
+ qfree(qarg)
2151
+ }
2152
+ if (qepsilon) {
2153
+ qfree(qepsilon);
2154
+ }
2155
+ return result;
2156
+ }
2157
+
2158
+ /* Previous candidate for primeness
2159
+ *
2160
+ * Returns the greatest positive integer i less than abs(self) expressible as
2161
+ * residue + k * modulus, where k is an integer, for which ptest?(count, skip)
2162
+ * is true, or if there is no such integer i, nil.
2163
+ *
2164
+ * See `ptest?` for a description of `count` and `skip`. For basic purposes,
2165
+ * use default values and count > 1. Higher counts increase the probability
2166
+ * that the returned value is prime.
2167
+ *
2168
+ * @param count [Integer] number of tests for ptest (default 1)
2169
+ * @param skip [Integer] base selection mode for ptest (default 1)
2170
+ * @param residue [Integer] (default 0)
2171
+ * @param modulus [Integer] (default 1)
2172
+ * @return [Calc::Q]
2173
+ * @raise [Calc::MathError] if self or any parameter is not an integer
2174
+ * @example
2175
+ * Calc::Q(100).prevcand(10) #=> Calc::Q(97)
2176
+ * Calc::Q(5000000000).prevcand(10) #=> Calc::Q(4999999937)
2177
+ */
2178
+ static VALUE
2179
+ cq_prevcand(int argc, VALUE * argv, VALUE self)
2180
+ {
2181
+ return cand_navigation(argc, argv, self, &zprevcand);
2182
+ }
2183
+
2184
+ /* Previous prime number
2185
+ *
2186
+ * If self <= 2, returns nil. If self is >= 2**32, raises an exception.
2187
+ * Otherwise returns the previous prime number.
2188
+ *
2189
+ * @return [Calc::Q]
2190
+ * @raise [Calc::MathError] if self is >= 2**32
2191
+ * @example
2192
+ * Calc::Q(2).prevprime #=> nil
2193
+ * Calc::Q(10).prevprime #=> Calc::Q(7)
2194
+ * Calc::Q(100).prevprime #=> Calc::Q(97)
2195
+ * Calc::Q("1e6").prevprime #=> Calc::Q(999983)
2196
+ * Calc::Q(2**32 - 1).prevprime #=> Calc::Q(4294967291)
2197
+ */
2198
+ static VALUE
2199
+ cq_prevprime(VALUE self)
2200
+ {
2201
+ NUMBER *qself;
2202
+ FULL prev_prime;
2203
+ setup_math_error();
2204
+
2205
+ qself = DATA_PTR(self);
2206
+ if (qisfrac(qself)) {
2207
+ rb_raise(e_MathError, "non-integral for prevprime");
2208
+ }
2209
+ prev_prime = zpprime(qself->num);
2210
+ if (prev_prime == 0) {
2211
+ return Qnil;
2212
+ }
2213
+ else if (prev_prime == 1) {
2214
+ rb_raise(e_MathError, "prevprime arg is >= 2^32");
2215
+ }
2216
+ return wrap_number(utoq(prev_prime));
2217
+ }
2218
+
2219
+ /* Small integer prime test
2220
+ *
2221
+ * Returns true if self is prime, false if it is not prime.
2222
+ * This function can't be used for odd numbers > 2^32.
2223
+ *
2224
+ * @return [Boolean]
2225
+ * @raise [Calc::MathError] if self is odd and > 2^32.
2226
+ * @example
2227
+ * Calc::Q(2**31 - 9).prime? #=> false
2228
+ * Calc::Q(2**31 - 1).prime? #=> true
2229
+ * @see Calc::Q#isprime
2230
+ */
2231
+ static VALUE
2232
+ cq_primep(VALUE self)
2233
+ {
2234
+ NUMBER *qself;
2235
+ setup_math_error();
2236
+
2237
+ qself = DATA_PTR(self);
2238
+ if (qisfrac(qself)) {
2239
+ rb_raise(e_MathError, "non-integral for prime?");
2240
+ }
2241
+ switch (zisprime(qself->num)) {
2242
+ case 0:
2243
+ return Qfalse;
2244
+ case 1:
2245
+ return Qtrue;
2246
+ default:
2247
+ rb_raise(e_MathError, "prime? argument is an odd value > 2^32");
2248
+ }
2249
+ }
2250
+
2251
+ /* Probabilistic test of primality
2252
+ *
2253
+ * Returns false if self is definitely not a prime. Returns true if self is
2254
+ * probably prime.
2255
+ *
2256
+ * If self is < 2**32, essentially calles prime? and returns true only if self
2257
+ * is prime.
2258
+ *
2259
+ * If self is > 2**32 and is divisible by a prime <= 101, returns false.
2260
+ *
2261
+ * In other cases, performs abs(count) tests of bases of possible primality.
2262
+ *
2263
+ * `skip` specifies how to select bases for testing:
2264
+ * 0: random in [2, self-2]
2265
+ * 1: successive primes [2, 3, 5, ...] not exceeding min(self, 65536)
2266
+ * otherwise: integers starting from `skip`
2267
+ *
2268
+ * For a full explanation of the tests, see "help ptest".
2269
+ *
2270
+ * Returning true from this function means self is either prime or a strong
2271
+ * psuedoprime. The probability that a composite number returns true is less
2272
+ * than (1/4)**count. For example, ptest(10) incorrectly returns true less
2273
+ * than once in a million numbers; ptest(20) incorrectly returns true less
2274
+ * than once in a quadrillion numbers.
2275
+ *
2276
+ * @param count [Integer] (optional: default 1)
2277
+ * @param skip [Integer] (optional: default 1)
2278
+ * @return [Boolean]
2279
+ * @example
2280
+ * Calc::Q(4294967291).ptest?(10) #=> true
2281
+ */
2282
+ static VALUE
2283
+ cq_ptestp(int argc, VALUE * argv, VALUE self)
2284
+ {
2285
+ VALUE count, skip, result;
2286
+ NUMBER *qcount, *qskip;
2287
+ int n;
2288
+ setup_math_error();
2289
+
2290
+ n = rb_scan_args(argc, argv, "02", &count, &skip);
2291
+ qcount = (n >= 1) ? value_to_number(count, 0) : qlink(&_qone_);
2292
+ qskip = (n >= 2) ? value_to_number(skip, 0) : qlink(&_qone_);
2293
+ result = qprimetest(DATA_PTR(self), qcount, qskip) ? Qtrue : Qfalse;
2294
+ qfree(qcount);
2295
+ qfree(qskip);
2296
+ return result;
2297
+ }
2298
+
2299
+ /* Returns the quotient and remainder from division
2300
+ *
2301
+ * @param y [Numeric,Calc::Q] number to divide by
2302
+ * @param rnd [Integer] optional rounding mode, default Calc.config(:quomod)
2303
+ * @return [Array<Calc::Q>] Array containing quotient and remainder
2304
+ * @todo add parameter to control rounding
2305
+ * @example
2306
+ * Calc::Q(13).quomod(5) #=> [Calc::Q(2), Calc::Q(3)]
2307
+ */
2308
+ static VALUE
2309
+ cq_quomod(int argc, VALUE * argv, VALUE self)
2310
+ {
2311
+ VALUE other, rnd;
2312
+ NUMBER *qother, *qquo, *qmod;
2313
+ long r;
2314
+ setup_math_error();
2315
+
2316
+ if (rb_scan_args(argc, argv, "11", &other, &rnd) == 2) {
2317
+ r = value_to_long(rnd);
2318
+ }
2319
+ else {
2320
+ r = conf->quomod;
2321
+ }
2322
+ qother = value_to_number(other, 0);
2323
+ if (qiszero(qother)) {
2324
+ qfree(qother);
2325
+ rb_raise(rb_eZeroDivError, "division by zero in quomod");
2326
+ }
2327
+ qquomod(DATA_PTR(self), qother, &qquo, &qmod, r);
2328
+ qfree(qother);
2329
+ return rb_assoc_new(wrap_number(qquo), wrap_number(qmod));
2330
+ }
2331
+
2332
+ /* Returns true if both values are relatively prime
2333
+ *
2334
+ * @param other [Integer]
2335
+ * @return [Boolean]
2336
+ * @raise [Calc::MathError] if either values are non-integers
2337
+ * @example
2338
+ * Calc::Q(6).rel?(5) #=> true
2339
+ * Calc::Q(6).rel?(2) #=> false
2340
+ * @see Calc::Q#isrel
2341
+ */
2342
+ static VALUE
2343
+ cq_relp(VALUE self, VALUE other)
2344
+ {
2345
+ VALUE result;
2346
+ NUMBER *qself, *qother;
2347
+ setup_math_error();
2348
+
2349
+ qself = DATA_PTR(self);
2350
+ qother = value_to_number(other, 0);
2351
+ if (qisfrac(qself) || qisfrac(qother)) {
2352
+ qfree(qother);
2353
+ rb_raise(e_MathError, "non-integer for rel?");
2354
+ }
2355
+ result = zrelprime(qself->num, qother->num) ? Qtrue : Qfalse;
2356
+ qfree(qother);
2357
+ return result;
2358
+ }
2359
+
2360
+ /* Round to a specified number of decimal places
2361
+ *
2362
+ * Rounds self rounded to the specified number of significant binary digits.
2363
+ * For the meanings of the rounding flags, see "help round".
2364
+ *
2365
+ * @return [Calc::Q]
2366
+ * @param places [Integer] number of decimal digits to round to (default 0)
2367
+ * @param rnd [Integer] rounding flags (default Calc.config(:round))
2368
+ * @example
2369
+ * Calc::Q(7,32).round(3) #=> Calc::Q(0.219)
2370
+ */
2371
+ static VALUE
2372
+ cq_round(int argc, VALUE * argv, VALUE self)
2373
+ {
2374
+ return rounding_function(argc, argv, self, &qround);
2375
+ }
2376
+
2377
+ /* Trigonometric secant
2378
+ *
2379
+ * @param eps [Numeric,Calc::Q] (optional) calculation accuracy
2380
+ * @return [Calc::Q]
2381
+ * @example
2382
+ * Calc::Q(1).sec #=> Calc::Q(1.85081571768092561791)
2383
+ */
2384
+ static VALUE
2385
+ cq_sec(int argc, VALUE * argv, VALUE self)
2386
+ {
2387
+ return trans_function(argc, argv, self, &qsec, NULL);
2388
+ }
2389
+
2390
+ /* Hyperbolic secant
2391
+ *
2392
+ * @param eps [Numeric,Calc::Q] (optional) calculation accuracy
2393
+ * @return [Calc::Q]
2394
+ * @example
2395
+ * Calc::Q(1).sech #=> Calc::Q(0.64805427366388539958)
2396
+ */
2397
+ static VALUE
2398
+ cq_sech(int argc, VALUE * argv, VALUE self)
2399
+ {
2400
+ return trans_function(argc, argv, self, &qsech, NULL);
2401
+ }
2402
+
2403
+ /* Trigonometric sine
2404
+ *
2405
+ * @param eps [Numeric,Calc::Q] (optional) calculation accuracy
2406
+ * @return [Calc::Q]
2407
+ * @example
2408
+ * Calc::Q(1).sin #=> Calc::Q(0.84147098480789650665)
2409
+ */
2410
+ static VALUE
2411
+ cq_sin(int argc, VALUE * argv, VALUE self)
2412
+ {
2413
+ return trans_function(argc, argv, self, &qsin, NULL);
2414
+ }
2415
+
2416
+ /* Hyperbolic sine
2417
+ *
2418
+ * @param eps [Numeric,Calc::Q] (optional) calculation accuracy
2419
+ * @return [Calc::Q]
2420
+ * @example
2421
+ * Calc::Q(1).sin #=> Calc::Q(1.17520119364380145688)
2422
+ */
2423
+ static VALUE
2424
+ cq_sinh(int argc, VALUE * argv, VALUE self)
2425
+ {
2426
+ return trans_function(argc, argv, self, &qsinh, NULL);
2427
+ }
2428
+
2429
+ /* Returns the number of bytes in the machine representation of `self`
2430
+ *
2431
+ * This method acts like ruby's Fixnum#size, except that is works on fractions
2432
+ * in which case the result is the number of bytes for both the numerator and
2433
+ * denominator. As the internal representation of numbers differs between
2434
+ * ruby and libcalc, it wil not necessary return the same values as
2435
+ * Fixnum#size.
2436
+ *
2437
+ * @return [Calc::Q]
2438
+ * @example
2439
+ * Calc::Q(1).size #=> Calc;:Q(4)
2440
+ * Calc::Q(2**32).size #=> Calc::Q(8)
2441
+ * Calc::Q("1/3").size #=> Calc::Q(8)
2442
+ */
2443
+ static VALUE
2444
+ cq_size(VALUE self)
2445
+ {
2446
+ NUMBER *qself;
2447
+ size_t s;
2448
+ setup_math_error();
2449
+
2450
+ qself = DATA_PTR(self);
2451
+ if (qisint(qself)) {
2452
+ s = qself->num.len * sizeof(HALF);
2453
+ }
2454
+ else {
2455
+ s = (qself->num.len + qself->den.len) * sizeof(HALF);
2456
+ }
2457
+ return wrap_number(itoq(s));
2458
+ }
2459
+
2460
+ /* Return true if this value is a square
2461
+ *
2462
+ * Returns true if there exists integers, b such that:
2463
+ * self == a^2 / b^2 (b != 0)
2464
+ *
2465
+ * Note that this function works on rationals, so:
2466
+ * Calc::Q(25, 15).sq? #=> true
2467
+ *
2468
+ * If you want to test for perfect square integers, you need to exclude
2469
+ * non-integer values before you test.
2470
+ *
2471
+ * @return [Boolean]
2472
+ * @example
2473
+ * Calc::Q(25).sq? #=> true
2474
+ * Calc::Q(3).sq? #=> false
2475
+ * Calc::Q("4/25").sq? #=> true
2476
+ * @see Calc::Q#issq
2477
+ */
2478
+ static VALUE
2479
+ cq_sqp(VALUE self)
2480
+ {
2481
+ setup_math_error();
2482
+ return qissquare(DATA_PTR(self)) ? Qtrue : Qfalse;
2483
+ }
2484
+
2485
+ /* Trigonometric tangent
2486
+ *
2487
+ * @param eps [Numeric,Calc::Q] (optional) calculation accuracy
2488
+ * @return [Calc::Q]
2489
+ * @example
2490
+ * Calc::Q(1).tan #=> Calc::Q(1.55740772465490223051)
2491
+ */
2492
+ static VALUE
2493
+ cq_tan(int argc, VALUE * argv, VALUE self)
2494
+ {
2495
+ return trans_function(argc, argv, self, &qtan, NULL);
2496
+ }
2497
+
2498
+ /* Hyperbolic tangent
2499
+ *
2500
+ * @param eps [Numeric,Calc::Q] (optional) calculation accuracy
2501
+ * @return [Calc::Q]
2502
+ * @example
2503
+ * Calc::Q(1).tanh #=> Calc::Q(0.76159415595576488812)
2504
+ */
2505
+ static VALUE
2506
+ cq_tanh(int argc, VALUE * argv, VALUE self)
2507
+ {
2508
+ return trans_function(argc, argv, self, &qtanh, NULL);
2509
+ }
2510
+
2511
+ /* Converts this number to a core ruby integer (Fixnum or Bignum).
2512
+ *
2513
+ * If self is a fraction, the fractional part is truncated.
2514
+ *
2515
+ * Note that the return value is a ruby Fixnum or Bignum. If you want to
2516
+ * convert to an integer but have the result be a `Calc::Q` object, use
2517
+ * `trunc` or `round`.
2518
+ *
2519
+ * @return [Fixnum,Bignum]
2520
+ * @example
2521
+ * Calc::Q(42).to_i #=> 42
2522
+ * Calc::Q("1e19").to_i #=> 10000000000000000000
2523
+ * Calc::Q(1,2).to_i #=> 0
2524
+ */
2525
+ static VALUE
2526
+ cq_to_i(VALUE self)
2527
+ {
2528
+ NUMBER *qself;
2529
+ ZVALUE ztmp;
2530
+ VALUE string, result;
2531
+ char *s;
2532
+ setup_math_error();
2533
+
2534
+ qself = DATA_PTR(self);
2535
+ if (qisint(qself)) {
2536
+ zcopy(qself->num, &ztmp);
2537
+ }
2538
+ else {
2539
+ zquo(qself->num, qself->den, &ztmp, 0);
2540
+ }
2541
+ if (zgtmaxlong(ztmp)) {
2542
+ /* too big to fit in a long, ztoi would return MAXLONG. use a string
2543
+ * intermediary */
2544
+ math_divertio();
2545
+ zprintval(ztmp, 0, 0);
2546
+ s = math_getdivertedio();
2547
+ string = rb_str_new2(s);
2548
+ free(s);
2549
+ result = rb_funcall(string, rb_intern("to_i"), 0);
2550
+ }
2551
+ else {
2552
+ result = LONG2NUM(ztoi(ztmp));
2553
+ }
2554
+ zfree(ztmp);
2555
+ return result;
2556
+ }
2557
+
2558
+ /* Converts this number to a string.
2559
+ *
2560
+ * Format depends on the configuration parameters "mode" and "display. The
2561
+ * mode can be overridden for individual calls.
2562
+ *
2563
+ * @param mode [String,Symbol] (optional) output mode, see [Calc::Config]
2564
+ * @return [String]
2565
+ * @example
2566
+ * Calc::Q(1,2).to_s #=> "0.5"
2567
+ * Calc::Q(1,2).to_s(:frac) #=> "1/2"
2568
+ * Calc::Q(42).to_s(:hex) #=> "0x2a"
2569
+ */
2570
+ static VALUE
2571
+ cq_to_s(int argc, VALUE * argv, VALUE self)
2572
+ {
2573
+ NUMBER *qself = DATA_PTR(self);
2574
+ char *s;
2575
+ int args;
2576
+ VALUE rs, mode;
2577
+ setup_math_error();
2578
+
2579
+ args = rb_scan_args(argc, argv, "01", &mode);
2580
+ math_divertio();
2581
+ if (args == 0) {
2582
+ qprintnum(qself, MODE_DEFAULT);
2583
+ }
2584
+ else {
2585
+ qprintnum(qself, (int) value_to_mode(mode));
2586
+ }
2587
+ s = math_getdivertedio();
2588
+ rs = rb_str_new2(s);
2589
+ free(s);
2590
+
2591
+ return rs;
2592
+ }
2593
+
2594
+ /* Truncate to a number of decimal places
2595
+ *
2596
+ * Truncates to j decimal places. If j is omitted, 0 places is assumed.
2597
+ * Truncation of a non-integer prouces values nearer to zero.
2598
+ *
2599
+ * @param j [Integer]
2600
+ * @return [Calc::Q]
2601
+ * @example
2602
+ * Calc.pi.trunc #=> Calc::Q(3)
2603
+ * Calc.pi.trunc(5) #=> Calc::Q(3.14159)
2604
+ */
2605
+ static VALUE
2606
+ cq_trunc(int argc, VALUE * argv, VALUE self)
2607
+ {
2608
+ return trunc_function(argc, argv, self, &qtrunc);
2609
+ }
2610
+
2611
+ /* Returns true if self is zero
2612
+ *
2613
+ * @param eps [Numeric,Calc::Q] (optional) calculation accuracy
2614
+ * @return [Calc::Q]
2615
+ * @example
2616
+ * Calc::Q(0).zero? #=> true
2617
+ * Calc::Q(1).zero? #=> false
2618
+ */
2619
+ static VALUE
2620
+ cq_zerop(VALUE self)
2621
+ {
2622
+ return qiszero((NUMBER *) DATA_PTR(self)) ? Qtrue : Qfalse;
2623
+ }
2624
+
2625
+ /*****************************************************************************
2626
+ * class definition, called once from Init_calc when library is loaded *
2627
+ *****************************************************************************/
2628
+ void
2629
+ define_calc_q(VALUE m)
2630
+ {
2631
+ cQ = rb_define_class_under(m, "Q", cNumeric);
2632
+ rb_define_alloc_func(cQ, cq_alloc);
2633
+ rb_define_method(cQ, "initialize", cq_initialize, -1);
2634
+ rb_define_method(cQ, "initialize_copy", cq_initialize_copy, 1);
2635
+
2636
+ rb_define_method(cQ, "&", cq_and, 1);
2637
+ rb_define_method(cQ, "*", cq_multiply, 1);
2638
+ rb_define_method(cQ, "+", cq_add, 1);
2639
+ rb_define_method(cQ, "-", cq_subtract, 1);
2640
+ rb_define_method(cQ, "-@", cq_uminus, 0);
2641
+ rb_define_method(cQ, "/", cq_divide, 1);
2642
+ rb_define_method(cQ, "<=>", cq_spaceship, 1);
2643
+ rb_define_method(cQ, "^", cq_xor, 1);
2644
+ rb_define_method(cQ, "|", cq_or, 1);
2645
+ rb_define_method(cQ, "~", cq_comp, 0);
2646
+ rb_define_method(cQ, "abs", cq_abs, 0);
2647
+ rb_define_method(cQ, "acos", cq_acos, -1);
2648
+ rb_define_method(cQ, "acosh", cq_acosh, -1);
2649
+ rb_define_method(cQ, "acot", cq_acot, -1);
2650
+ rb_define_method(cQ, "acoth", cq_acoth, -1);
2651
+ rb_define_method(cQ, "acsc", cq_acsc, -1);
2652
+ rb_define_method(cQ, "acsch", cq_acsch, -1);
2653
+ rb_define_method(cQ, "appr", cq_appr, -1);
2654
+ rb_define_method(cQ, "asec", cq_asec, -1);
2655
+ rb_define_method(cQ, "asech", cq_asech, -1);
2656
+ rb_define_method(cQ, "asin", cq_asin, -1);
2657
+ rb_define_method(cQ, "asinh", cq_asinh, -1);
2658
+ rb_define_method(cQ, "atan", cq_atan, -1);
2659
+ rb_define_method(cQ, "atan2", cq_atan2, -1);
2660
+ rb_define_method(cQ, "atanh", cq_atanh, -1);
2661
+ rb_define_method(cQ, "bernoulli", cq_bernoulli, 0);
2662
+ rb_define_method(cQ, "bit?", cq_bitp, 1);
2663
+ rb_define_method(cQ, "bround", cq_bround, -1);
2664
+ rb_define_method(cQ, "btrunc", cq_btrunc, -1);
2665
+ rb_define_method(cQ, "catalan", cq_catalan, 0);
2666
+ rb_define_method(cQ, "cfappr", cq_cfappr, -1);
2667
+ rb_define_method(cQ, "cfsim", cq_cfsim, -1);
2668
+ rb_define_method(cQ, "cos", cq_cos, -1);
2669
+ rb_define_method(cQ, "cosh", cq_cosh, -1);
2670
+ rb_define_method(cQ, "cot", cq_cot, -1);
2671
+ rb_define_method(cQ, "coth", cq_coth, -1);
2672
+ rb_define_method(cQ, "csc", cq_csc, -1);
2673
+ rb_define_method(cQ, "csch", cq_csch, -1);
2674
+ rb_define_method(cQ, "den", cq_den, 0);
2675
+ rb_define_method(cQ, "digit", cq_digit, -1);
2676
+ rb_define_method(cQ, "digits", cq_digits, -1);
2677
+ rb_define_method(cQ, "euler", cq_euler, 0);
2678
+ rb_define_method(cQ, "even?", cq_evenp, 0);
2679
+ rb_define_method(cQ, "exp", cq_exp, -1);
2680
+ rb_define_method(cQ, "fact", cq_fact, 0);
2681
+ rb_define_method(cQ, "factor", cq_factor, -1);
2682
+ rb_define_method(cQ, "fcnt", cq_fcnt, 1);
2683
+ rb_define_method(cQ, "frac", cq_frac, 0);
2684
+ rb_define_method(cQ, "frem", cq_frem, 1);
2685
+ rb_define_method(cQ, "fib", cq_fib, 0);
2686
+ rb_define_method(cQ, "gcd", cq_gcd, -1);
2687
+ rb_define_method(cQ, "gcdrem", cq_gcdrem, 1);
2688
+ rb_define_method(cQ, "highbit", cq_highbit, 0);
2689
+ rb_define_method(cQ, "hypot", cq_hypot, -1);
2690
+ rb_define_method(cQ, "int", cq_int, 0);
2691
+ rb_define_method(cQ, "int?", cq_intp, 0);
2692
+ rb_define_method(cQ, "inverse", cq_inverse, 0);
2693
+ rb_define_method(cQ, "iroot", cq_iroot, 1);
2694
+ rb_define_method(cQ, "isqrt", cq_isqrt, 0);
2695
+ rb_define_method(cQ, "jacobi", cq_jacobi, 1);
2696
+ rb_define_method(cQ, "lcm", cq_lcm, -1);
2697
+ rb_define_method(cQ, "lcmfact", cq_lcmfact, 0);
2698
+ rb_define_method(cQ, "lfactor", cq_lfactor, 1);
2699
+ rb_define_method(cQ, "lowbit", cq_lowbit, 0);
2700
+ rb_define_method(cQ, "ltol", cq_ltol, -1);
2701
+ rb_define_method(cQ, "meq?", cq_meqp, 2);
2702
+ rb_define_method(cQ, "minv", cq_minv, 1);
2703
+ rb_define_method(cQ, "mod", cq_mod, -1);
2704
+ rb_define_method(cQ, "mult?", cq_multp, 1);
2705
+ rb_define_method(cQ, "near", cq_near, -1);
2706
+ rb_define_method(cQ, "nextcand", cq_nextcand, -1);
2707
+ rb_define_method(cQ, "nextprime", cq_nextprime, 0);
2708
+ rb_define_method(cQ, "norm", cq_norm, 0);
2709
+ rb_define_method(cQ, "num", cq_num, 0);
2710
+ rb_define_method(cQ, "odd?", cq_oddp, 0);
2711
+ rb_define_method(cQ, "perm", cq_perm, 1);
2712
+ rb_define_method(cQ, "pfact", cq_pfact, 0);
2713
+ rb_define_method(cQ, "pix", cq_pix, 0);
2714
+ rb_define_method(cQ, "places", cq_places, -1);
2715
+ rb_define_method(cQ, "pmod", cq_pmod, 2);
2716
+ rb_define_method(cQ, "popcnt", cq_popcnt, -1);
2717
+ rb_define_method(cQ, "power", cq_power, -1);
2718
+ rb_define_method(cQ, "prevcand", cq_prevcand, -1);
2719
+ rb_define_method(cQ, "prevprime", cq_prevprime, 0);
2720
+ rb_define_method(cQ, "prime?", cq_primep, 0);
2721
+ rb_define_method(cQ, "ptest?", cq_ptestp, -1);
2722
+ rb_define_method(cQ, "quomod", cq_quomod, -1);
2723
+ rb_define_method(cQ, "rel?", cq_relp, 1);
2724
+ rb_define_method(cQ, "round", cq_round, -1);
2725
+ rb_define_method(cQ, "sec", cq_sec, -1);
2726
+ rb_define_method(cQ, "sech", cq_sech, -1);
2727
+ rb_define_method(cQ, "sin", cq_sin, -1);
2728
+ rb_define_method(cQ, "sinh", cq_sinh, -1);
2729
+ rb_define_method(cQ, "size", cq_size, 0);
2730
+ rb_define_method(cQ, "sq?", cq_sqp, 0);
2731
+ rb_define_method(cQ, "tan", cq_tan, -1);
2732
+ rb_define_method(cQ, "tanh", cq_tanh, -1);
2733
+ rb_define_method(cQ, "to_i", cq_to_i, 0);
2734
+ rb_define_method(cQ, "to_s", cq_to_s, -1);
2735
+ rb_define_method(cQ, "trunc", cq_trunc, -1);
2736
+ rb_define_method(cQ, "zero?", cq_zerop, 0);
2737
+
2738
+ /* include Comparable */
2739
+ rb_include_module(cQ, rb_mComparable);
2740
+
2741
+ rb_define_alias(cQ, "denominator", "den");
2742
+ rb_define_alias(cQ, "magnitude", "abs");
2743
+ rb_define_alias(cQ, "numerator", "num");
2744
+
2745
+ id_add = rb_intern("+");
2746
+ id_and = rb_intern("&");
2747
+ id_coerce = rb_intern("coerce");
2748
+ id_divide = rb_intern("/");
2749
+ id_multiply = rb_intern("*");
2750
+ id_new = rb_intern("new");
2751
+ id_or = rb_intern("|");
2752
+ id_spaceship = rb_intern("<=>");
2753
+ id_subtract = rb_intern("-");
2754
+ id_xor = rb_intern("^");
2755
+ }