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.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.rubocop.yml +52 -0
- data/.rubocop_todo.yml +11 -0
- data/.travis.yml +15 -0
- data/.yardopts +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +497 -0
- data/Rakefile +23 -0
- data/bin/console +10 -0
- data/bin/install_calc.sh +18 -0
- data/bin/makefile.patch +48 -0
- data/bin/setup +7 -0
- data/bin/todo.rb +374 -0
- data/ext/calc/c.c +775 -0
- data/ext/calc/calc.c +192 -0
- data/ext/calc/calc.h +71 -0
- data/ext/calc/config.c +239 -0
- data/ext/calc/convert.c +193 -0
- data/ext/calc/extconf.rb +29 -0
- data/ext/calc/math_error.c +72 -0
- data/ext/calc/numeric.c +623 -0
- data/ext/calc/q.c +2755 -0
- data/lib/calc.rb +214 -0
- data/lib/calc/c.rb +371 -0
- data/lib/calc/import.rb +6 -0
- data/lib/calc/numeric.rb +208 -0
- data/lib/calc/q.rb +628 -0
- data/lib/calc/version.rb +3 -0
- data/ruby-calc.gemspec +29 -0
- metadata +167 -0
data/ext/calc/q.c
ADDED
@@ -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
|
+
}
|