ruby-calc 0.1.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.
@@ -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
+ }