Ruby 2.1.5p273(2014-11-13revision48405)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

complex.c
Go to the documentation of this file.
1 /*
2 complex.c: Coded by Tadayoshi Funaba 2008-2012
3
4 This implementation is based on Keiju Ishitsuka's Complex library
5 which is written in ruby.
6 */
7
8 #include "ruby.h"
9 #include "internal.h"
10 #include <math.h>
11
12 #define NDEBUG
13 #include <assert.h>
14
15 #define ZERO INT2FIX(0)
16 #define ONE INT2FIX(1)
17 #define TWO INT2FIX(2)
18
19 VALUE rb_cComplex;
20
21 static ID id_abs, id_arg, id_convert,
22 id_denominator, id_eqeq_p, id_expt, id_fdiv,
23 id_inspect, id_negate, id_numerator, id_quo,
24 id_real_p, id_to_f, id_to_i, id_to_r, id_to_s,
25 id_i_real, id_i_imag;
26
27 #define f_boolcast(x) ((x) ? Qtrue : Qfalse)
28
29 #define binop(n,op) \
30 inline static VALUE \
31 f_##n(VALUE x, VALUE y)\
32 {\
33 return rb_funcall(x, (op), 1, y);\
34 }
35
36 #define fun1(n) \
37 inline static VALUE \
38 f_##n(VALUE x)\
39 {\
40 return rb_funcall(x, id_##n, 0);\
41 }
42
43 #define fun2(n) \
44 inline static VALUE \
45 f_##n(VALUE x, VALUE y)\
46 {\
47 return rb_funcall(x, id_##n, 1, y);\
48 }
49
50 #define math1(n) \
51 inline static VALUE \
52 m_##n(VALUE x)\
53 {\
54 return rb_funcall(rb_mMath, id_##n, 1, x);\
55 }
56
57 #define math2(n) \
58 inline static VALUE \
59 m_##n(VALUE x, VALUE y)\
60 {\
61 return rb_funcall(rb_mMath, id_##n, 2, x, y);\
62 }
63
64 #define PRESERVE_SIGNEDZERO
65
66 inline static VALUE
67 f_add(VALUE x, VALUE y)
68 {
69 #ifndef PRESERVE_SIGNEDZERO
70 if (FIXNUM_P(y) && FIX2LONG(y) == 0)
71 return x;
72 else if (FIXNUM_P(x) && FIX2LONG(x) == 0)
73 return y;
74 #endif
75 return rb_funcall(x, '+', 1, y);
76 }
77
78 inline static VALUE
79 f_div(VALUE x, VALUE y)
80 {
81 if (FIXNUM_P(y) && FIX2LONG(y) == 1)
82 return x;
83 return rb_funcall(x, '/', 1, y);
84 }
85
86 inline static VALUE
87 f_gt_p(VALUE x, VALUE y)
88 {
89 if (FIXNUM_P(x) && FIXNUM_P(y))
90 return f_boolcast(FIX2LONG(x) > FIX2LONG(y));
91 return rb_funcall(x, '>', 1, y);
92 }
93
94 inline static VALUE
95 f_mul(VALUE x, VALUE y)
96 {
97 #ifndef PRESERVE_SIGNEDZERO
98 if (FIXNUM_P(y)) {
99 long iy = FIX2LONG(y);
100 if (iy == 0) {
101 if (FIXNUM_P(x) || RB_TYPE_P(x, T_BIGNUM))
102 return ZERO;
103 }
104 else if (iy == 1)
105 return x;
106 }
107 else if (FIXNUM_P(x)) {
108 long ix = FIX2LONG(x);
109 if (ix == 0) {
110 if (FIXNUM_P(y) || RB_TYPE_P(y, T_BIGNUM))
111 return ZERO;
112 }
113 else if (ix == 1)
114 return y;
115 }
116 #endif
117 return rb_funcall(x, '*', 1, y);
118 }
119
120 inline static VALUE
121 f_sub(VALUE x, VALUE y)
122 {
123 #ifndef PRESERVE_SIGNEDZERO
124 if (FIXNUM_P(y) && FIX2LONG(y) == 0)
125 return x;
126 #endif
127 return rb_funcall(x, '-', 1, y);
128 }
129
130 fun1(abs)
131 fun1(arg)
132 fun1(denominator)
133 fun1(inspect)
134 fun1(negate)
135 fun1(numerator)
136 fun1(real_p)
137
138 inline static VALUE
139 f_to_i(VALUE x)
140 {
141 if (RB_TYPE_P(x, T_STRING))
142 return rb_str_to_inum(x, 10, 0);
143 return rb_funcall(x, id_to_i, 0);
144 }
145 inline static VALUE
146 f_to_f(VALUE x)
147 {
148 if (RB_TYPE_P(x, T_STRING))
149 return DBL2NUM(rb_str_to_dbl(x, 0));
150 return rb_funcall(x, id_to_f, 0);
151 }
152
153 fun1(to_r)
154 fun1(to_s)
155
156 inline static VALUE
157 f_eqeq_p(VALUE x, VALUE y)
158 {
159 if (FIXNUM_P(x) && FIXNUM_P(y))
160 return f_boolcast(FIX2LONG(x) == FIX2LONG(y));
161 return rb_funcall(x, id_eqeq_p, 1, y);
162 }
163
164 fun2(expt)
165 fun2(fdiv)
166 fun2(quo)
167
168 inline static VALUE
169 f_negative_p(VALUE x)
170 {
171 if (FIXNUM_P(x))
172 return f_boolcast(FIX2LONG(x) < 0);
173 return rb_funcall(x, '<', 1, ZERO);
174 }
175
176 #define f_positive_p(x) (!f_negative_p(x))
177
178 inline static VALUE
179 f_zero_p(VALUE x)
180 {
181 if (RB_TYPE_P(x, T_FIXNUM)) {
182 return f_boolcast(FIX2LONG(x) == 0);
183 }
184 else if (RB_TYPE_P(x, T_BIGNUM)) {
185 return Qfalse;
186 }
187 else if (RB_TYPE_P(x, T_RATIONAL)) {
188 VALUE num = RRATIONAL(x)->num;
189
190 return f_boolcast(FIXNUM_P(num) && FIX2LONG(num) == 0);
191 }
192 return rb_funcall(x, id_eqeq_p, 1, ZERO);
193 }
194
195 #define f_nonzero_p(x) (!f_zero_p(x))
196
197 inline static VALUE
198 f_one_p(VALUE x)
199 {
200 if (RB_TYPE_P(x, T_FIXNUM)) {
201 return f_boolcast(FIX2LONG(x) == 1);
202 }
203 else if (RB_TYPE_P(x, T_BIGNUM)) {
204 return Qfalse;
205 }
206 else if (RB_TYPE_P(x, T_RATIONAL)) {
207 VALUE num = RRATIONAL(x)->num;
208 VALUE den = RRATIONAL(x)->den;
209
210 return f_boolcast(FIXNUM_P(num) && FIX2LONG(num) == 1 &&
211 FIXNUM_P(den) && FIX2LONG(den) == 1);
212 }
213 return rb_funcall(x, id_eqeq_p, 1, ONE);
214 }
215
216 inline static VALUE
217 f_kind_of_p(VALUE x, VALUE c)
218 {
219 return rb_obj_is_kind_of(x, c);
220 }
221
222 inline static VALUE
223 k_numeric_p(VALUE x)
224 {
225 return f_kind_of_p(x, rb_cNumeric);
226 }
227
228 inline static VALUE
229 k_fixnum_p(VALUE x)
230 {
231 return f_kind_of_p(x, rb_cFixnum);
232 }
233
234 inline static VALUE
235 k_bignum_p(VALUE x)
236 {
237 return f_kind_of_p(x, rb_cBignum);
238 }
239
240 inline static VALUE
241 k_float_p(VALUE x)
242 {
243 return f_kind_of_p(x, rb_cFloat);
244 }
245
246 inline static VALUE
247 k_rational_p(VALUE x)
248 {
249 return f_kind_of_p(x, rb_cRational);
250 }
251
252 inline static VALUE
253 k_complex_p(VALUE x)
254 {
255 return f_kind_of_p(x, rb_cComplex);
256 }
257
258 #define k_exact_p(x) (!k_float_p(x))
259 #define k_inexact_p(x) k_float_p(x)
260
261 #define k_exact_zero_p(x) (k_exact_p(x) && f_zero_p(x))
262 #define k_exact_one_p(x) (k_exact_p(x) && f_one_p(x))
263
264 #define get_dat1(x) \
265 struct RComplex *dat;\
266 dat = ((struct RComplex *)(x))
267
268 #define get_dat2(x,y) \
269 struct RComplex *adat, *bdat;\
270 adat = ((struct RComplex *)(x));\
271 bdat = ((struct RComplex *)(y))
272
273 inline static VALUE
274 nucomp_s_new_internal(VALUE klass, VALUE real, VALUE imag)
275 {
276 NEWOBJ_OF(obj, struct RComplex, klass, T_COMPLEX | (RGENGC_WB_PROTECTED_COMPLEX ? FL_WB_PROTECTED : 0));
277
278 RCOMPLEX_SET_REAL(obj, real);
279 RCOMPLEX_SET_IMAG(obj, imag);
280
281 return (VALUE)obj;
282 }
283
284 static VALUE
285 nucomp_s_alloc(VALUE klass)
286 {
287 return nucomp_s_new_internal(klass, ZERO, ZERO);
288 }
289
290 #if 0
291 static VALUE
292 nucomp_s_new_bang(int argc, VALUE *argv, VALUE klass)
293 {
294 VALUE real, imag;
295
296 switch (rb_scan_args(argc, argv, "11", &real, &imag)) {
297 case 1:
298 if (!k_numeric_p(real))
299 real = f_to_i(real);
300 imag = ZERO;
301 break;
302 default:
303 if (!k_numeric_p(real))
304 real = f_to_i(real);
305 if (!k_numeric_p(imag))
306 imag = f_to_i(imag);
307 break;
308 }
309
310 return nucomp_s_new_internal(klass, real, imag);
311 }
312 #endif
313
314 inline static VALUE
315 f_complex_new_bang1(VALUE klass, VALUE x)
316 {
317 assert(!k_complex_p(x));
318 return nucomp_s_new_internal(klass, x, ZERO);
319 }
320
321 inline static VALUE
322 f_complex_new_bang2(VALUE klass, VALUE x, VALUE y)
323 {
324 assert(!k_complex_p(x));
325 assert(!k_complex_p(y));
326 return nucomp_s_new_internal(klass, x, y);
327 }
328
329 #ifdef CANONICALIZATION_FOR_MATHN
330 #define CANON
331 #endif
332
333 #ifdef CANON
334 static int canonicalization = 0;
335
336 RUBY_FUNC_EXPORTED void
337 nucomp_canonicalization(int f)
338 {
339 canonicalization = f;
340 }
341 #endif
342
343 inline static void
344 nucomp_real_check(VALUE num)
345 {
346 if (!RB_TYPE_P(num, T_FIXNUM) &&
347 !RB_TYPE_P(num, T_BIGNUM) &&
348 !RB_TYPE_P(num, T_FLOAT) &&
349 !RB_TYPE_P(num, T_RATIONAL)) {
350 if (!k_numeric_p(num) || !f_real_p(num))
351 rb_raise(rb_eTypeError, "not a real");
352 }
353 }
354
355 inline static VALUE
356 nucomp_s_canonicalize_internal(VALUE klass, VALUE real, VALUE imag)
357 {
358 #ifdef CANON
359 #define CL_CANON
360 #ifdef CL_CANON
361 if (k_exact_zero_p(imag) && canonicalization)
362 return real;
363 #else
364 if (f_zero_p(imag) && canonicalization)
365 return real;
366 #endif
367 #endif
368 if (f_real_p(real) && f_real_p(imag))
369 return nucomp_s_new_internal(klass, real, imag);
370 else if (f_real_p(real)) {
371 get_dat1(imag);
372
373 return nucomp_s_new_internal(klass,
374 f_sub(real, dat->imag),
375 f_add(ZERO, dat->real));
376 }
377 else if (f_real_p(imag)) {
378 get_dat1(real);
379
380 return nucomp_s_new_internal(klass,
381 dat->real,
382 f_add(dat->imag, imag));
383 }
384 else {
385 get_dat2(real, imag);
386
387 return nucomp_s_new_internal(klass,
388 f_sub(adat->real, bdat->imag),
389 f_add(adat->imag, bdat->real));
390 }
391 }
392
393 /*
394 * call-seq:
395 * Complex.rect(real[, imag]) -> complex
396 * Complex.rectangular(real[, imag]) -> complex
397 *
398 * Returns a complex object which denotes the given rectangular form.
399 *
400 * Complex.rectangular(1, 2) #=> (1+2i)
401 */
402 static VALUE
403 nucomp_s_new(int argc, VALUE *argv, VALUE klass)
404 {
405 VALUE real, imag;
406
407 switch (rb_scan_args(argc, argv, "11", &real, &imag)) {
408 case 1:
409 nucomp_real_check(real);
410 imag = ZERO;
411 break;
412 default:
413 nucomp_real_check(real);
414 nucomp_real_check(imag);
415 break;
416 }
417
418 return nucomp_s_canonicalize_internal(klass, real, imag);
419 }
420
421 inline static VALUE
422 f_complex_new2(VALUE klass, VALUE x, VALUE y)
423 {
424 assert(!k_complex_p(x));
425 return nucomp_s_canonicalize_internal(klass, x, y);
426 }
427
428 /*
429 * call-seq:
430 * Complex(x[, y]) -> numeric
431 *
432 * Returns x+i*y;
433 *
434 * Complex(1, 2) #=> (1+2i)
435 * Complex('1+2i') #=> (1+2i)
436 *
437 * Syntax of string form:
438 *
439 * string form = extra spaces , complex , extra spaces ;
440 * complex = real part | [ sign ] , imaginary part
441 * | real part , sign , imaginary part
442 * | rational , "@" , rational ;
443 * real part = rational ;
444 * imaginary part = imaginary unit | unsigned rational , imaginary unit ;
445 * rational = [ sign ] , unsigned rational ;
446 * unsigned rational = numerator | numerator , "/" , denominator ;
447 * numerator = integer part | fractional part | integer part , fractional part ;
448 * denominator = digits ;
449 * integer part = digits ;
450 * fractional part = "." , digits , [ ( "e" | "E" ) , [ sign ] , digits ] ;
451 * imaginary unit = "i" | "I" | "j" | "J" ;
452 * sign = "-" | "+" ;
453 * digits = digit , { digit | "_" , digit };
454 * digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
455 * extra spaces = ? \s* ? ;
456 *
457 * See String#to_c.
458 */
459 static VALUE
460 nucomp_f_complex(int argc, VALUE *argv, VALUE klass)
461 {
462 return rb_funcall2(rb_cComplex, id_convert, argc, argv);
463 }
464
465 #define imp1(n) \
466 inline static VALUE \
467 m_##n##_bang(VALUE x)\
468 {\
469 return rb_math_##n(x);\
470 }
471
472 #define imp2(n) \
473 inline static VALUE \
474 m_##n##_bang(VALUE x, VALUE y)\
475 {\
476 return rb_math_##n(x, y);\
477 }
478
479 imp2(atan2)
480 imp1(cos)
481 imp1(cosh)
482 imp1(exp)
483 imp2(hypot)
484
485 #define m_hypot(x,y) m_hypot_bang((x),(y))
486
487 static VALUE
488 m_log_bang(VALUE x)
489 {
490 return rb_math_log(1, &x);
491 }
492
493 imp1(sin)
494 imp1(sinh)
495
496 static VALUE
497 m_cos(VALUE x)
498 {
499 if (f_real_p(x))
500 return m_cos_bang(x);
501 {
502 get_dat1(x);
503 return f_complex_new2(rb_cComplex,
504 f_mul(m_cos_bang(dat->real),
505 m_cosh_bang(dat->imag)),
506 f_mul(f_negate(m_sin_bang(dat->real)),
507 m_sinh_bang(dat->imag)));
508 }
509 }
510
511 static VALUE
512 m_sin(VALUE x)
513 {
514 if (f_real_p(x))
515 return m_sin_bang(x);
516 {
517 get_dat1(x);
518 return f_complex_new2(rb_cComplex,
519 f_mul(m_sin_bang(dat->real),
520 m_cosh_bang(dat->imag)),
521 f_mul(m_cos_bang(dat->real),
522 m_sinh_bang(dat->imag)));
523 }
524 }
525
526 #if 0
527 imp1(sqrt)
528
529 static VALUE
530 m_sqrt(VALUE x)
531 {
532 if (f_real_p(x)) {
533 if (f_positive_p(x))
534 return m_sqrt_bang(x);
535 return f_complex_new2(rb_cComplex, ZERO, m_sqrt_bang(f_negate(x)));
536 }
537 else {
538 get_dat1(x);
539
540 if (f_negative_p(dat->imag))
541 return f_conj(m_sqrt(f_conj(x)));
542 else {
543 VALUE a = f_abs(x);
544 return f_complex_new2(rb_cComplex,
545 m_sqrt_bang(f_div(f_add(a, dat->real), TWO)),
546 m_sqrt_bang(f_div(f_sub(a, dat->real), TWO)));
547 }
548 }
549 }
550 #endif
551
552 inline static VALUE
553 f_complex_polar(VALUE klass, VALUE x, VALUE y)
554 {
555 assert(!k_complex_p(x));
556 assert(!k_complex_p(y));
557 return nucomp_s_canonicalize_internal(klass,
558 f_mul(x, m_cos(y)),
559 f_mul(x, m_sin(y)));
560 }
561
562 /*
563 * call-seq:
564 * Complex.polar(abs[, arg]) -> complex
565 *
566 * Returns a complex object which denotes the given polar form.
567 *
568 * Complex.polar(3, 0) #=> (3.0+0.0i)
569 * Complex.polar(3, Math::PI/2) #=> (1.836909530733566e-16+3.0i)
570 * Complex.polar(3, Math::PI) #=> (-3.0+3.673819061467132e-16i)
571 * Complex.polar(3, -Math::PI/2) #=> (1.836909530733566e-16-3.0i)
572 */
573 static VALUE
574 nucomp_s_polar(int argc, VALUE *argv, VALUE klass)
575 {
576 VALUE abs, arg;
577
578 switch (rb_scan_args(argc, argv, "11", &abs, &arg)) {
579 case 1:
580 nucomp_real_check(abs);
581 arg = ZERO;
582 break;
583 default:
584 nucomp_real_check(abs);
585 nucomp_real_check(arg);
586 break;
587 }
588 return f_complex_polar(klass, abs, arg);
589 }
590
591 /*
592 * call-seq:
593 * cmp.real -> real
594 *
595 * Returns the real part.
596 *
597 * Complex(7).real #=> 7
598 * Complex(9, -4).real #=> 9
599 */
600 static VALUE
601 nucomp_real(VALUE self)
602 {
603 get_dat1(self);
604 return dat->real;
605 }
606
607 /*
608 * call-seq:
609 * cmp.imag -> real
610 * cmp.imaginary -> real
611 *
612 * Returns the imaginary part.
613 *
614 * Complex(7).imaginary #=> 0
615 * Complex(9, -4).imaginary #=> -4
616 */
617 static VALUE
618 nucomp_imag(VALUE self)
619 {
620 get_dat1(self);
621 return dat->imag;
622 }
623
624 /*
625 * call-seq:
626 * -cmp -> complex
627 *
628 * Returns negation of the value.
629 *
630 * -Complex(1, 2) #=> (-1-2i)
631 */
632 static VALUE
633 nucomp_negate(VALUE self)
634 {
635 get_dat1(self);
636 return f_complex_new2(CLASS_OF(self),
637 f_negate(dat->real), f_negate(dat->imag));
638 }
639
640 inline static VALUE
641 f_addsub(VALUE self, VALUE other,
642 VALUE (*func)(VALUE, VALUE), ID id)
643 {
644 if (k_complex_p(other)) {
645 VALUE real, imag;
646
647 get_dat2(self, other);
648
649 real = (*func)(adat->real, bdat->real);
650 imag = (*func)(adat->imag, bdat->imag);
651
652 return f_complex_new2(CLASS_OF(self), real, imag);
653 }
654 if (k_numeric_p(other) && f_real_p(other)) {
655 get_dat1(self);
656
657 return f_complex_new2(CLASS_OF(self),
658 (*func)(dat->real, other), dat->imag);
659 }
660 return rb_num_coerce_bin(self, other, id);
661 }
662
663 /*
664 * call-seq:
665 * cmp + numeric -> complex
666 *
667 * Performs addition.
668 *
669 * Complex(2, 3) + Complex(2, 3) #=> (4+6i)
670 * Complex(900) + Complex(1) #=> (901+0i)
671 * Complex(-2, 9) + Complex(-9, 2) #=> (-11+11i)
672 * Complex(9, 8) + 4 #=> (13+8i)
673 * Complex(20, 9) + 9.8 #=> (29.8+9i)
674 */
675 static VALUE
676 nucomp_add(VALUE self, VALUE other)
677 {
678 return f_addsub(self, other, f_add, '+');
679 }
680
681 /*
682 * call-seq:
683 * cmp - numeric -> complex
684 *
685 * Performs subtraction.
686 *
687 * Complex(2, 3) - Complex(2, 3) #=> (0+0i)
688 * Complex(900) - Complex(1) #=> (899+0i)
689 * Complex(-2, 9) - Complex(-9, 2) #=> (7+7i)
690 * Complex(9, 8) - 4 #=> (5+8i)
691 * Complex(20, 9) - 9.8 #=> (10.2+9i)
692 */
693 static VALUE
694 nucomp_sub(VALUE self, VALUE other)
695 {
696 return f_addsub(self, other, f_sub, '-');
697 }
698
699 /*
700 * call-seq:
701 * cmp * numeric -> complex
702 *
703 * Performs multiplication.
704 *
705 * Complex(2, 3) * Complex(2, 3) #=> (-5+12i)
706 * Complex(900) * Complex(1) #=> (900+0i)
707 * Complex(-2, 9) * Complex(-9, 2) #=> (0-85i)
708 * Complex(9, 8) * 4 #=> (36+32i)
709 * Complex(20, 9) * 9.8 #=> (196.0+88.2i)
710 */
711 static VALUE
712 nucomp_mul(VALUE self, VALUE other)
713 {
714 if (k_complex_p(other)) {
715 VALUE real, imag;
716
717 get_dat2(self, other);
718
719 real = f_sub(f_mul(adat->real, bdat->real),
720 f_mul(adat->imag, bdat->imag));
721 imag = f_add(f_mul(adat->real, bdat->imag),
722 f_mul(adat->imag, bdat->real));
723
724 return f_complex_new2(CLASS_OF(self), real, imag);
725 }
726 if (k_numeric_p(other) && f_real_p(other)) {
727 get_dat1(self);
728
729 return f_complex_new2(CLASS_OF(self),
730 f_mul(dat->real, other),
731 f_mul(dat->imag, other));
732 }
733 return rb_num_coerce_bin(self, other, '*');
734 }
735
736 inline static VALUE
737 f_divide(VALUE self, VALUE other,
738 VALUE (*func)(VALUE, VALUE), ID id)
739 {
740 if (k_complex_p(other)) {
741 int flo;
742 get_dat2(self, other);
743
744 flo = (k_float_p(adat->real) || k_float_p(adat->imag) ||
745 k_float_p(bdat->real) || k_float_p(bdat->imag));
746
747 if (f_gt_p(f_abs(bdat->real), f_abs(bdat->imag))) {
748 VALUE r, n;
749
750 r = (*func)(bdat->imag, bdat->real);
751 n = f_mul(bdat->real, f_add(ONE, f_mul(r, r)));
752 if (flo)
753 return f_complex_new2(CLASS_OF(self),
754 (*func)(self, n),
755 (*func)(f_negate(f_mul(self, r)), n));
756 return f_complex_new2(CLASS_OF(self),
757 (*func)(f_add(adat->real,
758 f_mul(adat->imag, r)), n),
759 (*func)(f_sub(adat->imag,
760 f_mul(adat->real, r)), n));
761 }
762 else {
763 VALUE r, n;
764
765 r = (*func)(bdat->real, bdat->imag);
766 n = f_mul(bdat->imag, f_add(ONE, f_mul(r, r)));
767 if (flo)
768 return f_complex_new2(CLASS_OF(self),
769 (*func)(f_mul(self, r), n),
770 (*func)(f_negate(self), n));
771 return f_complex_new2(CLASS_OF(self),
772 (*func)(f_add(f_mul(adat->real, r),
773 adat->imag), n),
774 (*func)(f_sub(f_mul(adat->imag, r),
775 adat->real), n));
776 }
777 }
778 if (k_numeric_p(other) && f_real_p(other)) {
779 get_dat1(self);
780
781 return f_complex_new2(CLASS_OF(self),
782 (*func)(dat->real, other),
783 (*func)(dat->imag, other));
784 }
785 return rb_num_coerce_bin(self, other, id);
786 }
787
788 #define rb_raise_zerodiv() rb_raise(rb_eZeroDivError, "divided by 0")
789
790 /*
791 * call-seq:
792 * cmp / numeric -> complex
793 * cmp.quo(numeric) -> complex
794 *
795 * Performs division.
796 *
797 * Complex(2, 3) / Complex(2, 3) #=> ((1/1)+(0/1)*i)
798 * Complex(900) / Complex(1) #=> ((900/1)+(0/1)*i)
799 * Complex(-2, 9) / Complex(-9, 2) #=> ((36/85)-(77/85)*i)
800 * Complex(9, 8) / 4 #=> ((9/4)+(2/1)*i)
801 * Complex(20, 9) / 9.8 #=> (2.0408163265306123+0.9183673469387754i)
802 */
803 static VALUE
804 nucomp_div(VALUE self, VALUE other)
805 {
806 return f_divide(self, other, f_quo, id_quo);
807 }
808
809 #define nucomp_quo nucomp_div
810
811 /*
812 * call-seq:
813 * cmp.fdiv(numeric) -> complex
814 *
815 * Performs division as each part is a float, never returns a float.
816 *
817 * Complex(11, 22).fdiv(3) #=> (3.6666666666666665+7.333333333333333i)
818 */
819 static VALUE
820 nucomp_fdiv(VALUE self, VALUE other)
821 {
822 return f_divide(self, other, f_fdiv, id_fdiv);
823 }
824
825 inline static VALUE
826 f_reciprocal(VALUE x)
827 {
828 return f_quo(ONE, x);
829 }
830
831 /*
832 * call-seq:
833 * cmp ** numeric -> complex
834 *
835 * Performs exponentiation.
836 *
837 * Complex('i') ** 2 #=> (-1+0i)
838 * Complex(-8) ** Rational(1, 3) #=> (1.0000000000000002+1.7320508075688772i)
839 */
840 static VALUE
841 nucomp_expt(VALUE self, VALUE other)
842 {
843 if (k_numeric_p(other) && k_exact_zero_p(other))
844 return f_complex_new_bang1(CLASS_OF(self), ONE);
845
846 if (k_rational_p(other) && f_one_p(f_denominator(other)))
847 other = f_numerator(other); /* c14n */
848
849 if (k_complex_p(other)) {
850 get_dat1(other);
851
852 if (k_exact_zero_p(dat->imag))
853 other = dat->real; /* c14n */
854 }
855
856 if (k_complex_p(other)) {
857 VALUE r, theta, nr, ntheta;
858
859 get_dat1(other);
860
861 r = f_abs(self);
862 theta = f_arg(self);
863
864 nr = m_exp_bang(f_sub(f_mul(dat->real, m_log_bang(r)),
865 f_mul(dat->imag, theta)));
866 ntheta = f_add(f_mul(theta, dat->real),
867 f_mul(dat->imag, m_log_bang(r)));
868 return f_complex_polar(CLASS_OF(self), nr, ntheta);
869 }
870 if (k_fixnum_p(other)) {
871 if (f_gt_p(other, ZERO)) {
872 VALUE x, z;
873 long n;
874
875 x = self;
876 z = x;
877 n = FIX2LONG(other) - 1;
878
879 while (n) {
880 long q, r;
881
882 while (1) {
883 get_dat1(x);
884
885 q = n / 2;
886 r = n % 2;
887
888 if (r)
889 break;
890
891 x = nucomp_s_new_internal(CLASS_OF(self),
892 f_sub(f_mul(dat->real, dat->real),
893 f_mul(dat->imag, dat->imag)),
894 f_mul(f_mul(TWO, dat->real), dat->imag));
895 n = q;
896 }
897 z = f_mul(z, x);
898 n--;
899 }
900 return z;
901 }
902 return f_expt(f_reciprocal(self), f_negate(other));
903 }
904 if (k_numeric_p(other) && f_real_p(other)) {
905 VALUE r, theta;
906
907 if (k_bignum_p(other))
908 rb_warn("in a**b, b may be too big");
909
910 r = f_abs(self);
911 theta = f_arg(self);
912
913 return f_complex_polar(CLASS_OF(self), f_expt(r, other),
914 f_mul(theta, other));
915 }
916 return rb_num_coerce_bin(self, other, id_expt);
917 }
918
919 /*
920 * call-seq:
921 * cmp == object -> true or false
922 *
923 * Returns true if cmp equals object numerically.
924 *
925 * Complex(2, 3) == Complex(2, 3) #=> true
926 * Complex(5) == 5 #=> true
927 * Complex(0) == 0.0 #=> true
928 * Complex('1/3') == 0.33 #=> false
929 * Complex('1/2') == '1/2' #=> false
930 */
931 static VALUE
932 nucomp_eqeq_p(VALUE self, VALUE other)
933 {
934 if (k_complex_p(other)) {
935 get_dat2(self, other);
936
937 return f_boolcast(f_eqeq_p(adat->real, bdat->real) &&
938 f_eqeq_p(adat->imag, bdat->imag));
939 }
940 if (k_numeric_p(other) && f_real_p(other)) {
941 get_dat1(self);
942
943 return f_boolcast(f_eqeq_p(dat->real, other) && f_zero_p(dat->imag));
944 }
945 return f_eqeq_p(other, self);
946 }
947
948 /* :nodoc: */
949 static VALUE
950 nucomp_coerce(VALUE self, VALUE other)
951 {
952 if (k_numeric_p(other) && f_real_p(other))
953 return rb_assoc_new(f_complex_new_bang1(CLASS_OF(self), other), self);
954 if (RB_TYPE_P(other, T_COMPLEX))
955 return rb_assoc_new(other, self);
956
957 rb_raise(rb_eTypeError, "%s can't be coerced into %s",
958 rb_obj_classname(other), rb_obj_classname(self));
959 return Qnil;
960 }
961
962 /*
963 * call-seq:
964 * cmp.abs -> real
965 * cmp.magnitude -> real
966 *
967 * Returns the absolute part of its polar form.
968 *
969 * Complex(-1).abs #=> 1
970 * Complex(3.0, -4.0).abs #=> 5.0
971 */
972 static VALUE
973 nucomp_abs(VALUE self)
974 {
975 get_dat1(self);
976
977 if (f_zero_p(dat->real)) {
978 VALUE a = f_abs(dat->imag);
979 if (k_float_p(dat->real) && !k_float_p(dat->imag))
980 a = f_to_f(a);
981 return a;
982 }
983 if (f_zero_p(dat->imag)) {
984 VALUE a = f_abs(dat->real);
985 if (!k_float_p(dat->real) && k_float_p(dat->imag))
986 a = f_to_f(a);
987 return a;
988 }
989 return m_hypot(dat->real, dat->imag);
990 }
991
992 /*
993 * call-seq:
994 * cmp.abs2 -> real
995 *
996 * Returns square of the absolute value.
997 *
998 * Complex(-1).abs2 #=> 1
999 * Complex(3.0, -4.0).abs2 #=> 25.0
1000 */
1001 static VALUE
1002 nucomp_abs2(VALUE self)
1003 {
1004 get_dat1(self);
1005 return f_add(f_mul(dat->real, dat->real),
1006 f_mul(dat->imag, dat->imag));
1007 }
1008
1009 /*
1010 * call-seq:
1011 * cmp.arg -> float
1012 * cmp.angle -> float
1013 * cmp.phase -> float
1014 *
1015 * Returns the angle part of its polar form.
1016 *
1017 * Complex.polar(3, Math::PI/2).arg #=> 1.5707963267948966
1018 */
1019 static VALUE
1020 nucomp_arg(VALUE self)
1021 {
1022 get_dat1(self);
1023 return m_atan2_bang(dat->imag, dat->real);
1024 }
1025
1026 /*
1027 * call-seq:
1028 * cmp.rect -> array
1029 * cmp.rectangular -> array
1030 *
1031 * Returns an array; [cmp.real, cmp.imag].
1032 *
1033 * Complex(1, 2).rectangular #=> [1, 2]
1034 */
1035 static VALUE
1036 nucomp_rect(VALUE self)
1037 {
1038 get_dat1(self);
1039 return rb_assoc_new(dat->real, dat->imag);
1040 }
1041
1042 /*
1043 * call-seq:
1044 * cmp.polar -> array
1045 *
1046 * Returns an array; [cmp.abs, cmp.arg].
1047 *
1048 * Complex(1, 2).polar #=> [2.23606797749979, 1.1071487177940904]
1049 */
1050 static VALUE
1051 nucomp_polar(VALUE self)
1052 {
1053 return rb_assoc_new(f_abs(self), f_arg(self));
1054 }
1055
1056 /*
1057 * call-seq:
1058 * cmp.conj -> complex
1059 * cmp.conjugate -> complex
1060 *
1061 * Returns the complex conjugate.
1062 *
1063 * Complex(1, 2).conjugate #=> (1-2i)
1064 */
1065 static VALUE
1066 nucomp_conj(VALUE self)
1067 {
1068 get_dat1(self);
1069 return f_complex_new2(CLASS_OF(self), dat->real, f_negate(dat->imag));
1070 }
1071
1072 #if 0
1073 /* :nodoc: */
1074 static VALUE
1075 nucomp_true(VALUE self)
1076 {
1077 return Qtrue;
1078 }
1079 #endif
1080
1081 /*
1082 * call-seq:
1083 * cmp.real? -> false
1084 *
1085 * Returns false.
1086 */
1087 static VALUE
1088 nucomp_false(VALUE self)
1089 {
1090 return Qfalse;
1091 }
1092
1093 #if 0
1094 /* :nodoc: */
1095 static VALUE
1096 nucomp_exact_p(VALUE self)
1097 {
1098 get_dat1(self);
1099 return f_boolcast(k_exact_p(dat->real) && k_exact_p(dat->imag));
1100 }
1101
1102 /* :nodoc: */
1103 static VALUE
1104 nucomp_inexact_p(VALUE self)
1105 {
1106 return f_boolcast(!nucomp_exact_p(self));
1107 }
1108 #endif
1109
1110 /*
1111 * call-seq:
1112 * cmp.denominator -> integer
1113 *
1114 * Returns the denominator (lcm of both denominator - real and imag).
1115 *
1116 * See numerator.
1117 */
1118 static VALUE
1119 nucomp_denominator(VALUE self)
1120 {
1121 get_dat1(self);
1122 return rb_lcm(f_denominator(dat->real), f_denominator(dat->imag));
1123 }
1124
1125 /*
1126 * call-seq:
1127 * cmp.numerator -> numeric
1128 *
1129 * Returns the numerator.
1130 *
1131 * 1 2 3+4i <- numerator
1132 * - + -i -> ----
1133 * 2 3 6 <- denominator
1134 *
1135 * c = Complex('1/2+2/3i') #=> ((1/2)+(2/3)*i)
1136 * n = c.numerator #=> (3+4i)
1137 * d = c.denominator #=> 6
1138 * n / d #=> ((1/2)+(2/3)*i)
1139 * Complex(Rational(n.real, d), Rational(n.imag, d))
1140 * #=> ((1/2)+(2/3)*i)
1141 * See denominator.
1142 */
1143 static VALUE
1144 nucomp_numerator(VALUE self)
1145 {
1146 VALUE cd;
1147
1148 get_dat1(self);
1149
1150 cd = f_denominator(self);
1151 return f_complex_new2(CLASS_OF(self),
1152 f_mul(f_numerator(dat->real),
1153 f_div(cd, f_denominator(dat->real))),
1154 f_mul(f_numerator(dat->imag),
1155 f_div(cd, f_denominator(dat->imag))));
1156 }
1157
1158 /* :nodoc: */
1159 static VALUE
1160 nucomp_hash(VALUE self)
1161 {
1162 st_index_t v, h[2];
1163 VALUE n;
1164
1165 get_dat1(self);
1166 n = rb_hash(dat->real);
1167 h[0] = NUM2LONG(n);
1168 n = rb_hash(dat->imag);
1169 h[1] = NUM2LONG(n);
1170 v = rb_memhash(h, sizeof(h));
1171 return LONG2FIX(v);
1172 }
1173
1174 /* :nodoc: */
1175 static VALUE
1176 nucomp_eql_p(VALUE self, VALUE other)
1177 {
1178 if (k_complex_p(other)) {
1179 get_dat2(self, other);
1180
1181 return f_boolcast((CLASS_OF(adat->real) == CLASS_OF(bdat->real)) &&
1182 (CLASS_OF(adat->imag) == CLASS_OF(bdat->imag)) &&
1183 f_eqeq_p(self, other));
1184
1185 }
1186 return Qfalse;
1187 }
1188
1189 inline static VALUE
1190 f_signbit(VALUE x)
1191 {
1192 #if defined(HAVE_SIGNBIT) && defined(__GNUC__) && defined(__sun) && \
1193 !defined(signbit)
1194 extern int signbit(double);
1195 #endif
1196 if (RB_TYPE_P(x, T_FLOAT)) {
1197 double f = RFLOAT_VALUE(x);
1198 return f_boolcast(!isnan(f) && signbit(f));
1199 }
1200 return f_negative_p(x);
1201 }
1202
1203 inline static VALUE
1204 f_tpositive_p(VALUE x)
1205 {
1206 return f_boolcast(!f_signbit(x));
1207 }
1208
1209 static VALUE
1210 f_format(VALUE self, VALUE (*func)(VALUE))
1211 {
1212 VALUE s, impos;
1213
1214 get_dat1(self);
1215
1216 impos = f_tpositive_p(dat->imag);
1217
1218 s = (*func)(dat->real);
1219 rb_str_cat2(s, !impos ? "-" : "+");
1220
1221 rb_str_concat(s, (*func)(f_abs(dat->imag)));
1222 if (!rb_isdigit(RSTRING_PTR(s)[RSTRING_LEN(s) - 1]))
1223 rb_str_cat2(s, "*");
1224 rb_str_cat2(s, "i");
1225
1226 return s;
1227 }
1228
1229 /*
1230 * call-seq:
1231 * cmp.to_s -> string
1232 *
1233 * Returns the value as a string.
1234 *
1235 * Complex(2).to_s #=> "2+0i"
1236 * Complex('-8/6').to_s #=> "-4/3+0i"
1237 * Complex('1/2i').to_s #=> "0+1/2i"
1238 * Complex(0, Float::INFINITY).to_s #=> "0+Infinity*i"
1239 * Complex(Float::NAN, Float::NAN).to_s #=> "NaN+NaN*i"
1240 */
1241 static VALUE
1242 nucomp_to_s(VALUE self)
1243 {
1244 return f_format(self, f_to_s);
1245 }
1246
1247 /*
1248 * call-seq:
1249 * cmp.inspect -> string
1250 *
1251 * Returns the value as a string for inspection.
1252 *
1253 * Complex(2).inspect #=> "(2+0i)"
1254 * Complex('-8/6').inspect #=> "((-4/3)+0i)"
1255 * Complex('1/2i').inspect #=> "(0+(1/2)*i)"
1256 * Complex(0, Float::INFINITY).inspect #=> "(0+Infinity*i)"
1257 * Complex(Float::NAN, Float::NAN).inspect #=> "(NaN+NaN*i)"
1258 */
1259 static VALUE
1260 nucomp_inspect(VALUE self)
1261 {
1262 VALUE s;
1263
1264 s = rb_usascii_str_new2("(");
1265 rb_str_concat(s, f_format(self, f_inspect));
1266 rb_str_cat2(s, ")");
1267
1268 return s;
1269 }
1270
1271 /* :nodoc: */
1272 static VALUE
1273 nucomp_dumper(VALUE self)
1274 {
1275 return self;
1276 }
1277
1278 /* :nodoc: */
1279 static VALUE
1280 nucomp_loader(VALUE self, VALUE a)
1281 {
1282 get_dat1(self);
1283
1284 RCOMPLEX_SET_REAL(dat, rb_ivar_get(a, id_i_real));
1285 RCOMPLEX_SET_IMAG(dat, rb_ivar_get(a, id_i_imag));
1286
1287 return self;
1288 }
1289
1290 /* :nodoc: */
1291 static VALUE
1292 nucomp_marshal_dump(VALUE self)
1293 {
1294 VALUE a;
1295 get_dat1(self);
1296
1297 a = rb_assoc_new(dat->real, dat->imag);
1298 rb_copy_generic_ivar(a, self);
1299 return a;
1300 }
1301
1302 /* :nodoc: */
1303 static VALUE
1304 nucomp_marshal_load(VALUE self, VALUE a)
1305 {
1306 Check_Type(a, T_ARRAY);
1307 if (RARRAY_LEN(a) != 2)
1308 rb_raise(rb_eArgError, "marshaled complex must have an array whose length is 2 but %ld", RARRAY_LEN(a));
1309 rb_ivar_set(self, id_i_real, RARRAY_AREF(a, 0));
1310 rb_ivar_set(self, id_i_imag, RARRAY_AREF(a, 1));
1311 return self;
1312 }
1313
1314 /* --- */
1315
1316 VALUE
1317 rb_complex_raw(VALUE x, VALUE y)
1318 {
1319 return nucomp_s_new_internal(rb_cComplex, x, y);
1320 }
1321
1322 VALUE
1323 rb_complex_new(VALUE x, VALUE y)
1324 {
1325 return nucomp_s_canonicalize_internal(rb_cComplex, x, y);
1326 }
1327
1328 VALUE
1329 rb_complex_polar(VALUE x, VALUE y)
1330 {
1331 return f_complex_polar(rb_cComplex, x, y);
1332 }
1333
1334 static VALUE nucomp_s_convert(int argc, VALUE *argv, VALUE klass);
1335
1336 VALUE
1337 rb_Complex(VALUE x, VALUE y)
1338 {
1339 VALUE a[2];
1340 a[0] = x;
1341 a[1] = y;
1342 return nucomp_s_convert(2, a, rb_cComplex);
1343 }
1344
1345 /*
1346 * call-seq:
1347 * cmp.to_i -> integer
1348 *
1349 * Returns the value as an integer if possible (the imaginary part
1350 * should be exactly zero).
1351 *
1352 * Complex(1, 0).to_i #=> 1
1353 * Complex(1, 0.0).to_i # RangeError
1354 * Complex(1, 2).to_i # RangeError
1355 */
1356 static VALUE
1357 nucomp_to_i(VALUE self)
1358 {
1359 get_dat1(self);
1360
1361 if (k_inexact_p(dat->imag) || f_nonzero_p(dat->imag)) {
1362 VALUE s = f_to_s(self);
1363 rb_raise(rb_eRangeError, "can't convert %s into Integer",
1364 StringValuePtr(s));
1365 }
1366 return f_to_i(dat->real);
1367 }
1368
1369 /*
1370 * call-seq:
1371 * cmp.to_f -> float
1372 *
1373 * Returns the value as a float if possible (the imaginary part should
1374 * be exactly zero).
1375 *
1376 * Complex(1, 0).to_f #=> 1.0
1377 * Complex(1, 0.0).to_f # RangeError
1378 * Complex(1, 2).to_f # RangeError
1379 */
1380 static VALUE
1381 nucomp_to_f(VALUE self)
1382 {
1383 get_dat1(self);
1384
1385 if (k_inexact_p(dat->imag) || f_nonzero_p(dat->imag)) {
1386 VALUE s = f_to_s(self);
1387 rb_raise(rb_eRangeError, "can't convert %s into Float",
1388 StringValuePtr(s));
1389 }
1390 return f_to_f(dat->real);
1391 }
1392
1393 /*
1394 * call-seq:
1395 * cmp.to_r -> rational
1396 *
1397 * Returns the value as a rational if possible (the imaginary part
1398 * should be exactly zero).
1399 *
1400 * Complex(1, 0).to_r #=> (1/1)
1401 * Complex(1, 0.0).to_r # RangeError
1402 * Complex(1, 2).to_r # RangeError
1403 *
1404 * See rationalize.
1405 */
1406 static VALUE
1407 nucomp_to_r(VALUE self)
1408 {
1409 get_dat1(self);
1410
1411 if (k_inexact_p(dat->imag) || f_nonzero_p(dat->imag)) {
1412 VALUE s = f_to_s(self);
1413 rb_raise(rb_eRangeError, "can't convert %s into Rational",
1414 StringValuePtr(s));
1415 }
1416 return f_to_r(dat->real);
1417 }
1418
1419 /*
1420 * call-seq:
1421 * cmp.rationalize([eps]) -> rational
1422 *
1423 * Returns the value as a rational if possible (the imaginary part
1424 * should be exactly zero).
1425 *
1426 * Complex(1.0/3, 0).rationalize #=> (1/3)
1427 * Complex(1, 0.0).rationalize # RangeError
1428 * Complex(1, 2).rationalize # RangeError
1429 *
1430 * See to_r.
1431 */
1432 static VALUE
1433 nucomp_rationalize(int argc, VALUE *argv, VALUE self)
1434 {
1435 get_dat1(self);
1436
1437 rb_scan_args(argc, argv, "01", NULL);
1438
1439 if (k_inexact_p(dat->imag) || f_nonzero_p(dat->imag)) {
1440 VALUE s = f_to_s(self);
1441 rb_raise(rb_eRangeError, "can't convert %s into Rational",
1442 StringValuePtr(s));
1443 }
1444 return rb_funcall2(dat->real, rb_intern("rationalize"), argc, argv);
1445 }
1446
1447 /*
1448 * call-seq:
1449 * complex.to_c -> self
1450 *
1451 * Returns self.
1452 *
1453 * Complex(2).to_c #=> (2+0i)
1454 * Complex(-8, 6).to_c #=> (-8+6i)
1455 */
1456 static VALUE
1457 nucomp_to_c(VALUE self)
1458 {
1459 return self;
1460 }
1461
1462 /*
1463 * call-seq:
1464 * nil.to_c -> (0+0i)
1465 *
1466 * Returns zero as a complex.
1467 */
1468 static VALUE
1469 nilclass_to_c(VALUE self)
1470 {
1471 return rb_complex_new1(INT2FIX(0));
1472 }
1473
1474 /*
1475 * call-seq:
1476 * num.to_c -> complex
1477 *
1478 * Returns the value as a complex.
1479 */
1480 static VALUE
1481 numeric_to_c(VALUE self)
1482 {
1483 return rb_complex_new1(self);
1484 }
1485
1486 #include <ctype.h>
1487
1488 inline static int
1489 issign(int c)
1490 {
1491 return (c == '-' || c == '+');
1492 }
1493
1494 static int
1495 read_sign(const char **s,
1496 char **b)
1497 {
1498 int sign = '?';
1499
1500 if (issign(**s)) {
1501 sign = **b = **s;
1502 (*s)++;
1503 (*b)++;
1504 }
1505 return sign;
1506 }
1507
1508 inline static int
1509 isdecimal(int c)
1510 {
1511 return isdigit((unsigned char)c);
1512 }
1513
1514 static int
1515 read_digits(const char **s, int strict,
1516 char **b)
1517 {
1518 int us = 1;
1519
1520 if (!isdecimal(**s))
1521 return 0;
1522
1523 while (isdecimal(**s) || **s == '_') {
1524 if (**s == '_') {
1525 if (strict) {
1526 if (us)
1527 return 0;
1528 }
1529 us = 1;
1530 }
1531 else {
1532 **b = **s;
1533 (*b)++;
1534 us = 0;
1535 }
1536 (*s)++;
1537 }
1538 if (us)
1539 do {
1540 (*s)--;
1541 } while (**s == '_');
1542 return 1;
1543 }
1544
1545 inline static int
1546 islettere(int c)
1547 {
1548 return (c == 'e' || c == 'E');
1549 }
1550
1551 static int
1552 read_num(const char **s, int strict,
1553 char **b)
1554 {
1555 if (**s != '.') {
1556 if (!read_digits(s, strict, b))
1557 return 0;
1558 }
1559
1560 if (**s == '.') {
1561 **b = **s;
1562 (*s)++;
1563 (*b)++;
1564 if (!read_digits(s, strict, b)) {
1565 (*b)--;
1566 return 0;
1567 }
1568 }
1569
1570 if (islettere(**s)) {
1571 **b = **s;
1572 (*s)++;
1573 (*b)++;
1574 read_sign(s, b);
1575 if (!read_digits(s, strict, b)) {
1576 (*b)--;
1577 return 0;
1578 }
1579 }
1580 return 1;
1581 }
1582
1583 inline static int
1584 read_den(const char **s, int strict,
1585 char **b)
1586 {
1587 if (!read_digits(s, strict, b))
1588 return 0;
1589 return 1;
1590 }
1591
1592 static int
1593 read_rat_nos(const char **s, int strict,
1594 char **b)
1595 {
1596 if (!read_num(s, strict, b))
1597 return 0;
1598 if (**s == '/') {
1599 **b = **s;
1600 (*s)++;
1601 (*b)++;
1602 if (!read_den(s, strict, b)) {
1603 (*b)--;
1604 return 0;
1605 }
1606 }
1607 return 1;
1608 }
1609
1610 static int
1611 read_rat(const char **s, int strict,
1612 char **b)
1613 {
1614 read_sign(s, b);
1615 if (!read_rat_nos(s, strict, b))
1616 return 0;
1617 return 1;
1618 }
1619
1620 inline static int
1621 isimagunit(int c)
1622 {
1623 return (c == 'i' || c == 'I' ||
1624 c == 'j' || c == 'J');
1625 }
1626
1627 VALUE rb_cstr_to_rat(const char *, int);
1628
1629 static VALUE
1630 str2num(char *s)
1631 {
1632 if (strchr(s, '/'))
1633 return rb_cstr_to_rat(s, 0);
1634 if (strpbrk(s, ".eE"))
1635 return DBL2NUM(rb_cstr_to_dbl(s, 0));
1636 return rb_cstr_to_inum(s, 10, 0);
1637 }
1638
1639 static int
1640 read_comp(const char **s, int strict,
1641 VALUE *ret, char **b)
1642 {
1643 char *bb;
1644 int sign;
1645 VALUE num, num2;
1646
1647 bb = *b;
1648
1649 sign = read_sign(s, b);
1650
1651 if (isimagunit(**s)) {
1652 (*s)++;
1653 num = INT2FIX((sign == '-') ? -1 : + 1);
1654 *ret = rb_complex_new2(ZERO, num);
1655 return 1; /* e.g. "i" */
1656 }
1657
1658 if (!read_rat_nos(s, strict, b)) {
1659 **b = '\0';
1660 num = str2num(bb);
1661 *ret = rb_complex_new2(num, ZERO);
1662 return 0; /* e.g. "-" */
1663 }
1664 **b = '\0';
1665 num = str2num(bb);
1666
1667 if (isimagunit(**s)) {
1668 (*s)++;
1669 *ret = rb_complex_new2(ZERO, num);
1670 return 1; /* e.g. "3i" */
1671 }
1672
1673 if (**s == '@') {
1674 int st;
1675
1676 (*s)++;
1677 bb = *b;
1678 st = read_rat(s, strict, b);
1679 **b = '\0';
1680 if (strlen(bb) < 1 ||
1681 !isdecimal(*(bb + strlen(bb) - 1))) {
1682 *ret = rb_complex_new2(num, ZERO);
1683 return 0; /* e.g. "1@-" */
1684 }
1685 num2 = str2num(bb);
1686 *ret = rb_complex_polar(num, num2);
1687 if (!st)
1688 return 0; /* e.g. "1@2." */
1689 else
1690 return 1; /* e.g. "1@2" */
1691 }
1692
1693 if (issign(**s)) {
1694 bb = *b;
1695 sign = read_sign(s, b);
1696 if (isimagunit(**s))
1697 num2 = INT2FIX((sign == '-') ? -1 : + 1);
1698 else {
1699 if (!read_rat_nos(s, strict, b)) {
1700 *ret = rb_complex_new2(num, ZERO);
1701 return 0; /* e.g. "1+xi" */
1702 }
1703 **b = '\0';
1704 num2 = str2num(bb);
1705 }
1706 if (!isimagunit(**s)) {
1707 *ret = rb_complex_new2(num, ZERO);
1708 return 0; /* e.g. "1+3x" */
1709 }
1710 (*s)++;
1711 *ret = rb_complex_new2(num, num2);
1712 return 1; /* e.g. "1+2i" */
1713 }
1714 /* !(@, - or +) */
1715 {
1716 *ret = rb_complex_new2(num, ZERO);
1717 return 1; /* e.g. "3" */
1718 }
1719 }
1720
1721 inline static void
1722 skip_ws(const char **s)
1723 {
1724 while (isspace((unsigned char)**s))
1725 (*s)++;
1726 }
1727
1728 static int
1729 parse_comp(const char *s, int strict,
1730 VALUE *num)
1731 {
1732 char *buf, *b;
1733 VALUE tmp;
1734 int ret = 1;
1735
1736 buf = ALLOCV_N(char, tmp, strlen(s) + 1);
1737 b = buf;
1738
1739 skip_ws(&s);
1740 if (!read_comp(&s, strict, num, &b)) {
1741 ret = 0;
1742 }
1743 else {
1744 skip_ws(&s);
1745
1746 if (strict)
1747 if (*s != '\0')
1748 ret = 0;
1749 }
1750 ALLOCV_END(tmp);
1751
1752 return ret;
1753 }
1754
1755 static VALUE
1756 string_to_c_strict(VALUE self)
1757 {
1758 char *s;
1759 VALUE num;
1760
1761 rb_must_asciicompat(self);
1762
1763 s = RSTRING_PTR(self);
1764
1765 if (!s || memchr(s, '\0', RSTRING_LEN(self)))
1766 rb_raise(rb_eArgError, "string contains null byte");
1767
1768 if (s && s[RSTRING_LEN(self)]) {
1769 rb_str_modify(self);
1770 s = RSTRING_PTR(self);
1771 s[RSTRING_LEN(self)] = '\0';
1772 }
1773
1774 if (!s)
1775 s = (char *)"";
1776
1777 if (!parse_comp(s, 1, &num)) {
1778 VALUE ins = f_inspect(self);
1779 rb_raise(rb_eArgError, "invalid value for convert(): %s",
1780 StringValuePtr(ins));
1781 }
1782
1783 return num;
1784 }
1785
1786 /*
1787 * call-seq:
1788 * str.to_c -> complex
1789 *
1790 * Returns a complex which denotes the string form. The parser
1791 * ignores leading whitespaces and trailing garbage. Any digit
1792 * sequences can be separated by an underscore. Returns zero for null
1793 * or garbage string.
1794 *
1795 * '9'.to_c #=> (9+0i)
1796 * '2.5'.to_c #=> (2.5+0i)
1797 * '2.5/1'.to_c #=> ((5/2)+0i)
1798 * '-3/2'.to_c #=> ((-3/2)+0i)
1799 * '-i'.to_c #=> (0-1i)
1800 * '45i'.to_c #=> (0+45i)
1801 * '3-4i'.to_c #=> (3-4i)
1802 * '-4e2-4e-2i'.to_c #=> (-400.0-0.04i)
1803 * '-0.0-0.0i'.to_c #=> (-0.0-0.0i)
1804 * '1/2+3/4i'.to_c #=> ((1/2)+(3/4)*i)
1805 * 'ruby'.to_c #=> (0+0i)
1806 *
1807 * See Kernel.Complex.
1808 */
1809 static VALUE
1810 string_to_c(VALUE self)
1811 {
1812 char *s;
1813 VALUE num;
1814
1815 rb_must_asciicompat(self);
1816
1817 s = RSTRING_PTR(self);
1818
1819 if (s && s[RSTRING_LEN(self)]) {
1820 rb_str_modify(self);
1821 s = RSTRING_PTR(self);
1822 s[RSTRING_LEN(self)] = '\0';
1823 }
1824
1825 if (!s)
1826 s = (char *)"";
1827
1828 (void)parse_comp(s, 0, &num);
1829
1830 return num;
1831 }
1832
1833 static VALUE
1834 nucomp_s_convert(int argc, VALUE *argv, VALUE klass)
1835 {
1836 VALUE a1, a2, backref;
1837
1838 rb_scan_args(argc, argv, "11", &a1, &a2);
1839
1840 if (NIL_P(a1) || (argc == 2 && NIL_P(a2)))
1841 rb_raise(rb_eTypeError, "can't convert nil into Complex");
1842
1843 backref = rb_backref_get();
1844 rb_match_busy(backref);
1845
1846 if (RB_TYPE_P(a1, T_STRING)) {
1847 a1 = string_to_c_strict(a1);
1848 }
1849
1850 if (RB_TYPE_P(a2, T_STRING)) {
1851 a2 = string_to_c_strict(a2);
1852 }
1853
1854 rb_backref_set(backref);
1855
1856 if (RB_TYPE_P(a1, T_COMPLEX)) {
1857 {
1858 get_dat1(a1);
1859
1860 if (k_exact_zero_p(dat->imag))
1861 a1 = dat->real;
1862 }
1863 }
1864
1865 if (RB_TYPE_P(a2, T_COMPLEX)) {
1866 {
1867 get_dat1(a2);
1868
1869 if (k_exact_zero_p(dat->imag))
1870 a2 = dat->real;
1871 }
1872 }
1873
1874 if (RB_TYPE_P(a1, T_COMPLEX)) {
1875 if (argc == 1 || (k_exact_zero_p(a2)))
1876 return a1;
1877 }
1878
1879 if (argc == 1) {
1880 if (k_numeric_p(a1) && !f_real_p(a1))
1881 return a1;
1882 /* should raise exception for consistency */
1883 if (!k_numeric_p(a1))
1884 return rb_convert_type(a1, T_COMPLEX, "Complex", "to_c");
1885 }
1886 else {
1887 if ((k_numeric_p(a1) && k_numeric_p(a2)) &&
1888 (!f_real_p(a1) || !f_real_p(a2)))
1889 return f_add(a1,
1890 f_mul(a2,
1891 f_complex_new_bang2(rb_cComplex, ZERO, ONE)));
1892 }
1893
1894 {
1895 VALUE argv2[2];
1896 argv2[0] = a1;
1897 argv2[1] = a2;
1898 return nucomp_s_new(argc, argv2, klass);
1899 }
1900 }
1901
1902 /* --- */
1903
1904 /*
1905 * call-seq:
1906 * num.real -> self
1907 *
1908 * Returns self.
1909 */
1910 static VALUE
1911 numeric_real(VALUE self)
1912 {
1913 return self;
1914 }
1915
1916 /*
1917 * call-seq:
1918 * num.imag -> 0
1919 * num.imaginary -> 0
1920 *
1921 * Returns zero.
1922 */
1923 static VALUE
1924 numeric_imag(VALUE self)
1925 {
1926 return INT2FIX(0);
1927 }
1928
1929 /*
1930 * call-seq:
1931 * num.abs2 -> real
1932 *
1933 * Returns square of self.
1934 */
1935 static VALUE
1936 numeric_abs2(VALUE self)
1937 {
1938 return f_mul(self, self);
1939 }
1940
1941 #define id_PI rb_intern("PI")
1942
1943 /*
1944 * call-seq:
1945 * num.arg -> 0 or float
1946 * num.angle -> 0 or float
1947 * num.phase -> 0 or float
1948 *
1949 * Returns 0 if the value is positive, pi otherwise.
1950 */
1951 static VALUE
1952 numeric_arg(VALUE self)
1953 {
1954 if (f_positive_p(self))
1955 return INT2FIX(0);
1956 return rb_const_get(rb_mMath, id_PI);
1957 }
1958
1959 /*
1960 * call-seq:
1961 * num.rect -> array
1962 * num.rectangular -> array
1963 *
1964 * Returns an array; [num, 0].
1965 */
1966 static VALUE
1967 numeric_rect(VALUE self)
1968 {
1969 return rb_assoc_new(self, INT2FIX(0));
1970 }
1971
1972 /*
1973 * call-seq:
1974 * num.polar -> array
1975 *
1976 * Returns an array; [num.abs, num.arg].
1977 */
1978 static VALUE
1979 numeric_polar(VALUE self)
1980 {
1981 return rb_assoc_new(f_abs(self), f_arg(self));
1982 }
1983
1984 /*
1985 * call-seq:
1986 * num.conj -> self
1987 * num.conjugate -> self
1988 *
1989 * Returns self.
1990 */
1991 static VALUE
1992 numeric_conj(VALUE self)
1993 {
1994 return self;
1995 }
1996
1997 /*
1998 * call-seq:
1999 * flo.arg -> 0 or float
2000 * flo.angle -> 0 or float
2001 * flo.phase -> 0 or float
2002 *
2003 * Returns 0 if the value is positive, pi otherwise.
2004 */
2005 static VALUE
2006 float_arg(VALUE self)
2007 {
2008 if (isnan(RFLOAT_VALUE(self)))
2009 return self;
2010 if (f_tpositive_p(self))
2011 return INT2FIX(0);
2012 return rb_const_get(rb_mMath, id_PI);
2013 }
2014
2015 /*
2016 * A complex number can be represented as a paired real number with
2017 * imaginary unit; a+bi. Where a is real part, b is imaginary part
2018 * and i is imaginary unit. Real a equals complex a+0i
2019 * mathematically.
2020 *
2021 * In ruby, you can create complex object with Complex, Complex::rect,
2022 * Complex::polar or to_c method.
2023 *
2024 * Complex(1) #=> (1+0i)
2025 * Complex(2, 3) #=> (2+3i)
2026 * Complex.polar(2, 3) #=> (-1.9799849932008908+0.2822400161197344i)
2027 * 3.to_c #=> (3+0i)
2028 *
2029 * You can also create complex object from floating-point numbers or
2030 * strings.
2031 *
2032 * Complex(0.3) #=> (0.3+0i)
2033 * Complex('0.3-0.5i') #=> (0.3-0.5i)
2034 * Complex('2/3+3/4i') #=> ((2/3)+(3/4)*i)
2035 * Complex('1@2') #=> (-0.4161468365471424+0.9092974268256817i)
2036 *
2037 * 0.3.to_c #=> (0.3+0i)
2038 * '0.3-0.5i'.to_c #=> (0.3-0.5i)
2039 * '2/3+3/4i'.to_c #=> ((2/3)+(3/4)*i)
2040 * '1@2'.to_c #=> (-0.4161468365471424+0.9092974268256817i)
2041 *
2042 * A complex object is either an exact or an inexact number.
2043 *
2044 * Complex(1, 1) / 2 #=> ((1/2)+(1/2)*i)
2045 * Complex(1, 1) / 2.0 #=> (0.5+0.5i)
2046 */
2047 void
2048 Init_Complex(void)
2049 {
2050 VALUE compat;
2051 #undef rb_intern
2052 #define rb_intern(str) rb_intern_const(str)
2053
2054 assert(fprintf(stderr, "assert() is now active\n"));
2055
2056 id_abs = rb_intern("abs");
2057 id_arg = rb_intern("arg");
2058 id_convert = rb_intern("convert");
2059 id_denominator = rb_intern("denominator");
2060 id_eqeq_p = rb_intern("==");
2061 id_expt = rb_intern("**");
2062 id_fdiv = rb_intern("fdiv");
2063 id_inspect = rb_intern("inspect");
2064 id_negate = rb_intern("-@");
2065 id_numerator = rb_intern("numerator");
2066 id_quo = rb_intern("quo");
2067 id_real_p = rb_intern("real?");
2068 id_to_f = rb_intern("to_f");
2069 id_to_i = rb_intern("to_i");
2070 id_to_r = rb_intern("to_r");
2071 id_to_s = rb_intern("to_s");
2072 id_i_real = rb_intern("@real");
2073 id_i_imag = rb_intern("@image"); /* @image, not @imag */
2074
2075 rb_cComplex = rb_define_class("Complex", rb_cNumeric);
2076
2077 rb_define_alloc_func(rb_cComplex, nucomp_s_alloc);
2078 rb_undef_method(CLASS_OF(rb_cComplex), "allocate");
2079
2080 #if 0
2081 rb_define_private_method(CLASS_OF(rb_cComplex), "new!", nucomp_s_new_bang, -1);
2082 rb_define_private_method(CLASS_OF(rb_cComplex), "new", nucomp_s_new, -1);
2083 #else
2084 rb_undef_method(CLASS_OF(rb_cComplex), "new");
2085 #endif
2086
2087 rb_define_singleton_method(rb_cComplex, "rectangular", nucomp_s_new, -1);
2088 rb_define_singleton_method(rb_cComplex, "rect", nucomp_s_new, -1);
2089 rb_define_singleton_method(rb_cComplex, "polar", nucomp_s_polar, -1);
2090
2091 rb_define_global_function("Complex", nucomp_f_complex, -1);
2092
2093 rb_undef_method(rb_cComplex, "%");
2094 rb_undef_method(rb_cComplex, "<");
2095 rb_undef_method(rb_cComplex, "<=");
2096 rb_undef_method(rb_cComplex, "<=>");
2097 rb_undef_method(rb_cComplex, ">");
2098 rb_undef_method(rb_cComplex, ">=");
2099 rb_undef_method(rb_cComplex, "between?");
2100 rb_undef_method(rb_cComplex, "div");
2101 rb_undef_method(rb_cComplex, "divmod");
2102 rb_undef_method(rb_cComplex, "floor");
2103 rb_undef_method(rb_cComplex, "ceil");
2104 rb_undef_method(rb_cComplex, "modulo");
2105 rb_undef_method(rb_cComplex, "remainder");
2106 rb_undef_method(rb_cComplex, "round");
2107 rb_undef_method(rb_cComplex, "step");
2108 rb_undef_method(rb_cComplex, "truncate");
2109 rb_undef_method(rb_cComplex, "i");
2110
2111 #if 0 /* NUBY */
2112 rb_undef_method(rb_cComplex, "//");
2113 #endif
2114
2115 rb_define_method(rb_cComplex, "real", nucomp_real, 0);
2116 rb_define_method(rb_cComplex, "imaginary", nucomp_imag, 0);
2117 rb_define_method(rb_cComplex, "imag", nucomp_imag, 0);
2118
2119 rb_define_method(rb_cComplex, "-@", nucomp_negate, 0);
2120 rb_define_method(rb_cComplex, "+", nucomp_add, 1);
2121 rb_define_method(rb_cComplex, "-", nucomp_sub, 1);
2122 rb_define_method(rb_cComplex, "*", nucomp_mul, 1);
2123 rb_define_method(rb_cComplex, "/", nucomp_div, 1);
2124 rb_define_method(rb_cComplex, "quo", nucomp_quo, 1);
2125 rb_define_method(rb_cComplex, "fdiv", nucomp_fdiv, 1);
2126 rb_define_method(rb_cComplex, "**", nucomp_expt, 1);
2127
2128 rb_define_method(rb_cComplex, "==", nucomp_eqeq_p, 1);
2129 rb_define_method(rb_cComplex, "coerce", nucomp_coerce, 1);
2130
2131 rb_define_method(rb_cComplex, "abs", nucomp_abs, 0);
2132 rb_define_method(rb_cComplex, "magnitude", nucomp_abs, 0);
2133 rb_define_method(rb_cComplex, "abs2", nucomp_abs2, 0);
2134 rb_define_method(rb_cComplex, "arg", nucomp_arg, 0);
2135 rb_define_method(rb_cComplex, "angle", nucomp_arg, 0);
2136 rb_define_method(rb_cComplex, "phase", nucomp_arg, 0);
2137 rb_define_method(rb_cComplex, "rectangular", nucomp_rect, 0);
2138 rb_define_method(rb_cComplex, "rect", nucomp_rect, 0);
2139 rb_define_method(rb_cComplex, "polar", nucomp_polar, 0);
2140 rb_define_method(rb_cComplex, "conjugate", nucomp_conj, 0);
2141 rb_define_method(rb_cComplex, "conj", nucomp_conj, 0);
2142 #if 0
2143 rb_define_method(rb_cComplex, "~", nucomp_conj, 0); /* gcc */
2144 #endif
2145
2146 rb_define_method(rb_cComplex, "real?", nucomp_false, 0);
2147 #if 0
2148 rb_define_method(rb_cComplex, "complex?", nucomp_true, 0);
2149 rb_define_method(rb_cComplex, "exact?", nucomp_exact_p, 0);
2150 rb_define_method(rb_cComplex, "inexact?", nucomp_inexact_p, 0);
2151 #endif
2152
2153 rb_define_method(rb_cComplex, "numerator", nucomp_numerator, 0);
2154 rb_define_method(rb_cComplex, "denominator", nucomp_denominator, 0);
2155
2156 rb_define_method(rb_cComplex, "hash", nucomp_hash, 0);
2157 rb_define_method(rb_cComplex, "eql?", nucomp_eql_p, 1);
2158
2159 rb_define_method(rb_cComplex, "to_s", nucomp_to_s, 0);
2160 rb_define_method(rb_cComplex, "inspect", nucomp_inspect, 0);
2161
2162 rb_define_private_method(rb_cComplex, "marshal_dump", nucomp_marshal_dump, 0);
2163 compat = rb_define_class_under(rb_cComplex, "compatible", rb_cObject);
2164 rb_define_private_method(compat, "marshal_load", nucomp_marshal_load, 1);
2165 rb_marshal_define_compat(rb_cComplex, compat, nucomp_dumper, nucomp_loader);
2166
2167 /* --- */
2168
2169 rb_define_method(rb_cComplex, "to_i", nucomp_to_i, 0);
2170 rb_define_method(rb_cComplex, "to_f", nucomp_to_f, 0);
2171 rb_define_method(rb_cComplex, "to_r", nucomp_to_r, 0);
2172 rb_define_method(rb_cComplex, "rationalize", nucomp_rationalize, -1);
2173 rb_define_method(rb_cComplex, "to_c", nucomp_to_c, 0);
2174 rb_define_method(rb_cNilClass, "to_c", nilclass_to_c, 0);
2175 rb_define_method(rb_cNumeric, "to_c", numeric_to_c, 0);
2176
2177 rb_define_method(rb_cString, "to_c", string_to_c, 0);
2178
2179 rb_define_private_method(CLASS_OF(rb_cComplex), "convert", nucomp_s_convert, -1);
2180
2181 /* --- */
2182
2183 rb_define_method(rb_cNumeric, "real", numeric_real, 0);
2184 rb_define_method(rb_cNumeric, "imaginary", numeric_imag, 0);
2185 rb_define_method(rb_cNumeric, "imag", numeric_imag, 0);
2186 rb_define_method(rb_cNumeric, "abs2", numeric_abs2, 0);
2187 rb_define_method(rb_cNumeric, "arg", numeric_arg, 0);
2188 rb_define_method(rb_cNumeric, "angle", numeric_arg, 0);
2189 rb_define_method(rb_cNumeric, "phase", numeric_arg, 0);
2190 rb_define_method(rb_cNumeric, "rectangular", numeric_rect, 0);
2191 rb_define_method(rb_cNumeric, "rect", numeric_rect, 0);
2192 rb_define_method(rb_cNumeric, "polar", numeric_polar, 0);
2193 rb_define_method(rb_cNumeric, "conjugate", numeric_conj, 0);
2194 rb_define_method(rb_cNumeric, "conj", numeric_conj, 0);
2195
2196 rb_define_method(rb_cFloat, "arg", float_arg, 0);
2197 rb_define_method(rb_cFloat, "angle", float_arg, 0);
2198 rb_define_method(rb_cFloat, "phase", float_arg, 0);
2199
2200 /*
2201 * The imaginary unit.
2202 */
2203 rb_define_const(rb_cComplex, "I",
2204 f_complex_new_bang2(rb_cComplex, ZERO, ONE));
2205 }
2206
2207 /*
2208 Local variables:
2209 c-file-style: "ruby"
2210 End:
2211 */
read_rat_nos
static int read_rat_nos(const char **s, int strict, char **b)
Definition: complex.c:1593
rb_cString
RUBY_EXTERN VALUE rb_cString
Definition: ruby.h:1583
nucomp_expt
static VALUE nucomp_expt(VALUE self, VALUE other)
Definition: complex.c:841
ZERO
#define ZERO
Definition: complex.c:15
islettere
static int islettere(int c)
Definition: complex.c:1546
rb_hash
VALUE rb_hash(VALUE obj)
Definition: hash.c:106
f_mul
static VALUE f_mul(VALUE x, VALUE y)
Definition: complex.c:95
nucomp_rationalize
static VALUE nucomp_rationalize(int argc, VALUE *argv, VALUE self)
Definition: complex.c:1433
rb_cFloat
RUBY_EXTERN VALUE rb_cFloat
Definition: ruby.h:1566
RARRAY_LEN
#define RARRAY_LEN(a)
Definition: ruby.h:878
rb_num_coerce_bin
VALUE rb_num_coerce_bin(VALUE, VALUE, ID)
Definition: numeric.c:280
sinh
double sinh(double x)
Definition: math.c:253
fun1
#define fun1(n)
Definition: complex.c:36
strlen
size_t strlen(const char *)
rb_backref_set
void rb_backref_set(VALUE)
Definition: vm.c:953
T_FIXNUM
#define T_FIXNUM
Definition: ruby.h:489
nucomp_to_f
static VALUE nucomp_to_f(VALUE self)
Definition: complex.c:1381
nucomp_denominator
static VALUE nucomp_denominator(VALUE self)
Definition: complex.c:1119
nucomp_quo
#define nucomp_quo
Definition: complex.c:809
signbit
RUBY_EXTERN int signbit(double x)
Definition: signbit.c:5
rb_define_singleton_method
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1655
k_inexact_p
#define k_inexact_p(x)
Definition: complex.c:259
nilclass_to_c
static VALUE nilclass_to_c(VALUE self)
Definition: complex.c:1469
id_to_r
static ID id_to_r
Definition: complex.c:21
nucomp_sub
static VALUE nucomp_sub(VALUE self, VALUE other)
Definition: complex.c:694
rb_usascii_str_new2
#define rb_usascii_str_new2
Definition: intern.h:846
CLASS_OF
#define CLASS_OF(v)
Definition: ruby.h:440
nucomp_imag
static VALUE nucomp_imag(VALUE self)
Definition: complex.c:618
Qtrue
#define Qtrue
Definition: ruby.h:426
fun2
#define fun2(n)
Definition: complex.c:43
f_complex_new2
static VALUE f_complex_new2(VALUE klass, VALUE x, VALUE y)
Definition: complex.c:422
f_signbit
static VALUE f_signbit(VALUE x)
Definition: complex.c:1190
rb_complex_polar
VALUE rb_complex_polar(VALUE x, VALUE y)
Definition: complex.c:1329
ruby.h
isimagunit
static int isimagunit(int c)
Definition: complex.c:1621
k_numeric_p
static VALUE k_numeric_p(VALUE x)
Definition: complex.c:223
rb_define_private_method
void rb_define_private_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1500
nucomp_s_new
static VALUE nucomp_s_new(int argc, VALUE *argv, VALUE klass)
Definition: complex.c:403
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:548
rb_must_asciicompat
void rb_must_asciicompat(VALUE)
Definition: string.c:1580
T_RATIONAL
#define T_RATIONAL
Definition: ruby.h:495
read_rat
static int read_rat(const char **s, int strict, char **b)
Definition: complex.c:1611
rb_str_concat
VALUE rb_str_concat(VALUE, VALUE)
Definition: string.c:2340
rb_memhash
st_index_t rb_memhash(const void *ptr, long len)
Definition: random.c:1302
id_PI
#define id_PI
Definition: complex.c:1941
nucomp_add
static VALUE nucomp_add(VALUE self, VALUE other)
Definition: complex.c:676
rb_lcm
VALUE rb_lcm(VALUE x, VALUE y)
Definition: rational.c:1730
rb_funcall
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:775
string_to_c_strict
static VALUE string_to_c_strict(VALUE self)
Definition: complex.c:1756
k_bignum_p
static VALUE k_bignum_p(VALUE x)
Definition: complex.c:235
id_to_i
static ID id_to_i
Definition: complex.c:21
nucomp_to_s
static VALUE nucomp_to_s(VALUE self)
Definition: complex.c:1242
rb_backref_get
VALUE rb_backref_get(void)
Definition: vm.c:947
rb_define_class_under
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:676
Check_Type
#define Check_Type(v, t)
Definition: ruby.h:532
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1857
rb_ivar_get
VALUE rb_ivar_get(VALUE, ID)
Definition: variable.c:1115
rb_convert_type
VALUE rb_convert_type(VALUE, int, const char *, const char *)
Definition: object.c:2616
f_complex_polar
static VALUE f_complex_polar(VALUE klass, VALUE x, VALUE y)
Definition: complex.c:553
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
rb_obj_is_kind_of
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Definition: object.c:652
Init_Complex
void Init_Complex(void)
Definition: complex.c:2048
nucomp_abs
static VALUE nucomp_abs(VALUE self)
Definition: complex.c:973
nucomp_negate
static VALUE nucomp_negate(VALUE self)
Definition: complex.c:633
nucomp_mul
static VALUE nucomp_mul(VALUE self, VALUE other)
Definition: complex.c:712
T_ARRAY
#define T_ARRAY
Definition: ruby.h:484
st_index_t
st_data_t st_index_t
Definition: st.h:48
cosh
double cosh(double x)
Definition: math.c:224
rb_str_to_dbl
double rb_str_to_dbl(VALUE, int)
Definition: object.c:2867
rb_define_global_function
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
Definition: class.c:1684
rb_mMath
RUBY_EXTERN VALUE rb_mMath
Definition: ruby.h:1547
rb_isdigit
int rb_isdigit(int c)
Definition: encoding.c:1925
RCOMPLEX_SET_IMAG
#define RCOMPLEX_SET_IMAG(cmp, i)
Definition: ruby.h:955
m_sin
static VALUE m_sin(VALUE x)
Definition: complex.c:512
nucomp_to_c
static VALUE nucomp_to_c(VALUE self)
Definition: complex.c:1457
FIXNUM_P
#define FIXNUM_P(f)
Definition: ruby.h:347
f_negative_p
static VALUE f_negative_p(VALUE x)
Definition: date_core.c:127
nucomp_arg
static VALUE nucomp_arg(VALUE self)
Definition: complex.c:1020
rb_undef_method
void rb_undef_method(VALUE klass, const char *name)
Definition: class.c:1506
nucomp_inspect
static VALUE nucomp_inspect(VALUE self)
Definition: complex.c:1260
RComplex
Definition: ruby.h:948
id_denominator
static ID id_denominator
Definition: complex.c:21
k_float_p
static VALUE k_float_p(VALUE x)
Definition: complex.c:241
rb_complex_new1
#define rb_complex_new1(x)
Definition: intern.h:182
m_hypot
#define m_hypot(x, y)
k_complex_p
static VALUE k_complex_p(VALUE x)
Definition: complex.c:253
rb_eRangeError
VALUE rb_eRangeError
Definition: error.c:552
rb_obj_classname
const char * rb_obj_classname(VALUE)
Definition: variable.c:406
f_add
static VALUE f_add(VALUE x, VALUE y)
Definition: complex.c:67
str2num
static VALUE str2num(char *s)
Definition: complex.c:1630
numeric_rect
static VALUE numeric_rect(VALUE self)
Definition: complex.c:1967
NEWOBJ_OF
#define NEWOBJ_OF(obj, type, klass, flags)
Definition: ruby.h:694
rb_cstr_to_rat
VALUE rb_cstr_to_rat(const char *, int)
Definition: rational.c:2374
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:1664
nucomp_eqeq_p
static VALUE nucomp_eqeq_p(VALUE self, VALUE other)
Definition: complex.c:932
k_exact_p
#define k_exact_p(x)
Definition: complex.c:258
id_inspect
static ID id_inspect
Definition: complex.c:21
RRATIONAL
#define RRATIONAL(obj)
Definition: ruby.h:1130
rb_math_log
VALUE rb_math_log(int argc, VALUE *argv)
numeric_abs2
static VALUE numeric_abs2(VALUE self)
Definition: complex.c:1936
id_quo
static ID id_quo
Definition: complex.c:21
nucomp_eql_p
static VALUE nucomp_eql_p(VALUE self, VALUE other)
Definition: complex.c:1176
get_dat1
#define get_dat1(x)
Definition: complex.c:264
f_to_i
#define f_to_i(x)
Definition: date_core.c:45
f_complex_new_bang1
static VALUE f_complex_new_bang1(VALUE klass, VALUE x)
Definition: complex.c:315
id_convert
static ID id_convert
Definition: complex.c:21
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1553
rb_str_to_inum
VALUE rb_str_to_inum(VALUE str, int base, int badcheck)
Definition: bignum.c:4129
nucomp_f_complex
static VALUE nucomp_f_complex(int argc, VALUE *argv, VALUE klass)
Definition: complex.c:460
rb_str_cat2
VALUE rb_str_cat2(VALUE, const char *)
Definition: string.c:2159
parse_comp
static int parse_comp(const char *s, int strict, VALUE *num)
Definition: complex.c:1729
nucomp_real
static VALUE nucomp_real(VALUE self)
Definition: complex.c:601
string_to_c
static VALUE string_to_c(VALUE self)
Definition: complex.c:1810
NIL_P
#define NIL_P(v)
Definition: ruby.h:438
numeric_conj
static VALUE numeric_conj(VALUE self)
Definition: complex.c:1992
rb_define_class
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:630
nucomp_s_alloc
static VALUE nucomp_s_alloc(VALUE klass)
Definition: complex.c:285
rb_define_const
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2225
k_exact_zero_p
#define k_exact_zero_p(x)
Definition: complex.c:261
float_arg
static VALUE float_arg(VALUE self)
Definition: complex.c:2006
T_FLOAT
#define T_FLOAT
Definition: ruby.h:481
f_tpositive_p
static VALUE f_tpositive_p(VALUE x)
Definition: complex.c:1204
read_den
static int read_den(const char **s, int strict, char **b)
Definition: complex.c:1584
id_expt
static ID id_expt
Definition: complex.c:21
argc
int argc
Definition: ruby.c:131
Qfalse
#define Qfalse
Definition: ruby.h:425
id_i_real
static ID id_i_real
Definition: complex.c:21
ALLOCV_N
#define ALLOCV_N(type, v, n)
Definition: ruby.h:1348
f_sub
static VALUE f_sub(VALUE x, VALUE y)
Definition: complex.c:121
T_BIGNUM
#define T_BIGNUM
Definition: ruby.h:487
RUBY_FUNC_EXPORTED
#define RUBY_FUNC_EXPORTED
Definition: defines.h:246
id_numerator
static ID id_numerator
Definition: complex.c:21
T_COMPLEX
#define T_COMPLEX
Definition: ruby.h:496
read_comp
static int read_comp(const char **s, int strict, VALUE *ret, char **b)
Definition: complex.c:1640
ALLOCV_END
#define ALLOCV_END(v)
Definition: ruby.h:1349
nucomp_fdiv
static VALUE nucomp_fdiv(VALUE self, VALUE other)
Definition: complex.c:820
f_denominator
#define f_denominator(x)
Definition: rational.c:1780
f_positive_p
#define f_positive_p(x)
Definition: complex.c:176
rb_const_get
VALUE rb_const_get(VALUE, ID)
Definition: variable.c:1880
f_inspect
#define f_inspect(x)
Definition: date_core.c:48
imp1
#define imp1(n)
Definition: complex.c:465
RSTRING_LEN
#define RSTRING_LEN(str)
Definition: ruby.h:841
func
SSL_METHOD *(* func)(void)
Definition: ossl_ssl.c:113
rb_complex_new2
#define rb_complex_new2(x, y)
Definition: intern.h:183
numeric_arg
static VALUE numeric_arg(VALUE self)
Definition: complex.c:1952
f_addsub
static VALUE f_addsub(VALUE self, VALUE other, VALUE(*func)(VALUE, VALUE), ID id)
Definition: complex.c:641
f_to_s
#define f_to_s(x)
Definition: date_core.c:47
nucomp_to_r
static VALUE nucomp_to_r(VALUE self)
Definition: complex.c:1407
f_zero_p
static VALUE f_zero_p(VALUE x)
Definition: complex.c:179
f_to_f
static VALUE f_to_f(VALUE x)
Definition: complex.c:146
id_arg
static ID id_arg
Definition: complex.c:21
hypot
RUBY_EXTERN double hypot(double, double)
Definition: hypot.c:6
rb_scan_args
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1728
f_div
static VALUE f_div(VALUE x, VALUE y)
Definition: complex.c:79
rb_ivar_set
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1133
buf
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4308
rb_assoc_new
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:616
internal.h
ID
unsigned long ID
Definition: ruby.h:89
Qnil
#define Qnil
Definition: ruby.h:427
VALUE
unsigned long VALUE
Definition: ruby.h:88
rb_funcall2
#define rb_funcall2
Definition: ruby.h:1456
RGENGC_WB_PROTECTED_COMPLEX
#define RGENGC_WB_PROTECTED_COMPLEX
Definition: ruby.h:735
strchr
char * strchr(char *, char)
rb_match_busy
void rb_match_busy(VALUE)
Definition: re.c:1214
rb_Complex
VALUE rb_Complex(VALUE x, VALUE y)
Definition: complex.c:1337
isnan
#define isnan(x)
Definition: win32.h:376
nucomp_s_polar
static VALUE nucomp_s_polar(int argc, VALUE *argv, VALUE klass)
Definition: complex.c:574
rb_cNumeric
RUBY_EXTERN VALUE rb_cNumeric
Definition: ruby.h:1575
rb_complex_new
VALUE rb_complex_new(VALUE x, VALUE y)
Definition: complex.c:1323
nucomp_real_check
static void nucomp_real_check(VALUE num)
Definition: complex.c:344
numeric_to_c
static VALUE numeric_to_c(VALUE self)
Definition: complex.c:1481
ONE
#define ONE
Definition: complex.c:16
skip_ws
static void skip_ws(const char **s)
Definition: complex.c:1722
nucomp_numerator
static VALUE nucomp_numerator(VALUE self)
Definition: complex.c:1144
RSTRING_PTR
#define RSTRING_PTR(str)
Definition: ruby.h:845
rb_str_modify
void rb_str_modify(VALUE)
Definition: string.c:1484
nucomp_s_canonicalize_internal
static VALUE nucomp_s_canonicalize_internal(VALUE klass, VALUE real, VALUE imag)
Definition: complex.c:356
RFLOAT_VALUE
#define RFLOAT_VALUE(v)
Definition: ruby.h:814
quo
#define quo(x, y)
Definition: date_strftime.c:26
nucomp_canonicalization
void nucomp_canonicalization(int)
nucomp_abs2
static VALUE nucomp_abs2(VALUE self)
Definition: complex.c:1002
f
#define f
id_eqeq_p
static ID id_eqeq_p
Definition: complex.c:21
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:231
rb_cBignum
VALUE rb_cBignum
Definition: bignum.c:35
f_quo
#define f_quo(x, y)
Definition: date_core.c:35
f_kind_of_p
static VALUE f_kind_of_p(VALUE x, VALUE c)
Definition: complex.c:217
nucomp_to_i
static VALUE nucomp_to_i(VALUE self)
Definition: complex.c:1357
RARRAY_AREF
#define RARRAY_AREF(a, i)
Definition: ruby.h:901
k_fixnum_p
static VALUE k_fixnum_p(VALUE x)
Definition: complex.c:229
rb_intern
#define rb_intern(str)
f_expt
#define f_expt(x, y)
Definition: date_core.c:39
id_fdiv
static ID id_fdiv
Definition: complex.c:21
rb_complex_raw
VALUE rb_complex_raw(VALUE x, VALUE y)
Definition: complex.c:1317
id_negate
static ID id_negate
Definition: complex.c:21
FL_WB_PROTECTED
#define FL_WB_PROTECTED
Definition: ruby.h:1134
LONG2FIX
#define LONG2FIX(i)
Definition: ruby.h:232
nucomp_dumper
static VALUE nucomp_dumper(VALUE self)
Definition: complex.c:1273
rb_marshal_define_compat
void rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE(*dumper)(VALUE), VALUE(*loader)(VALUE, VALUE))
Definition: marshal.c:113
T_STRING
#define T_STRING
Definition: ruby.h:482
f_boolcast
#define f_boolcast(x)
Definition: complex.c:27
f_eqeq_p
static VALUE f_eqeq_p(VALUE x, VALUE y)
Definition: date_core.c:100
issign
static int issign(int c)
Definition: complex.c:1489
get_dat2
#define get_dat2(x, y)
Definition: complex.c:268
f_nonzero_p
#define f_nonzero_p(x)
Definition: complex.c:195
k_rational_p
static VALUE k_rational_p(VALUE x)
Definition: complex.c:247
nucomp_rect
static VALUE nucomp_rect(VALUE self)
Definition: complex.c:1036
nucomp_marshal_load
static VALUE nucomp_marshal_load(VALUE self, VALUE a)
Definition: complex.c:1304
f_divide
static VALUE f_divide(VALUE self, VALUE other, VALUE(*func)(VALUE, VALUE), ID id)
Definition: complex.c:737
nucomp_s_new_internal
static VALUE nucomp_s_new_internal(VALUE klass, VALUE real, VALUE imag)
Definition: complex.c:274
TWO
#define TWO
Definition: complex.c:17
read_sign
static int read_sign(const char **s, char **b)
Definition: complex.c:1495
numeric_imag
static VALUE numeric_imag(VALUE self)
Definition: complex.c:1924
nucomp_loader
static VALUE nucomp_loader(VALUE self, VALUE a)
Definition: complex.c:1280
nucomp_hash
static VALUE nucomp_hash(VALUE self)
Definition: complex.c:1160
nucomp_conj
static VALUE nucomp_conj(VALUE self)
Definition: complex.c:1066
nucomp_s_convert
static VALUE nucomp_s_convert(int argc, VALUE *argv, VALUE klass)
Definition: complex.c:1834
rb_cRational
RUBY_EXTERN VALUE rb_cRational
Definition: ruby.h:1579
assert
#define assert(condition)
Definition: ossl.h:45
f_complex_new_bang2
static VALUE f_complex_new_bang2(VALUE klass, VALUE x, VALUE y)
Definition: complex.c:322
StringValuePtr
#define StringValuePtr(v)
Definition: ruby.h:540
id_to_f
static ID id_to_f
Definition: complex.c:21
nucomp_coerce
static VALUE nucomp_coerce(VALUE self, VALUE other)
Definition: complex.c:950
f_numerator
#define f_numerator(x)
Definition: rational.c:1777
read_digits
static int read_digits(const char **s, int strict, char **b)
Definition: complex.c:1515
RCOMPLEX_SET_REAL
#define RCOMPLEX_SET_REAL(cmp, r)
Definition: ruby.h:954
imp2
#define imp2(n)
Definition: complex.c:472
f_to_r
#define f_to_r(x)
Definition: date_core.c:46
id_i_imag
static ID id_i_imag
Definition: complex.c:21
numeric_polar
static VALUE numeric_polar(VALUE self)
Definition: complex.c:1979
rb_copy_generic_ivar
void rb_copy_generic_ivar(VALUE, VALUE)
Definition: variable.c:1049
f_abs
#define f_abs(x)
Definition: date_core.c:29
nucomp_marshal_dump
static VALUE nucomp_marshal_dump(VALUE self)
Definition: complex.c:1292
f_negate
#define f_negate(x)
Definition: date_core.c:30
rb_cstr_to_inum
VALUE rb_cstr_to_inum(const char *str, int base, int badcheck)
Definition: bignum.c:3963
f_reciprocal
static VALUE f_reciprocal(VALUE x)
Definition: complex.c:826
f_gt_p
static VALUE f_gt_p(VALUE x, VALUE y)
Definition: complex.c:87
NULL
#define NULL
Definition: _sdbm.c:103
FIX2LONG
#define FIX2LONG(x)
Definition: ruby.h:345
id_to_s
static ID id_to_s
Definition: complex.c:21
rb_cFixnum
RUBY_EXTERN VALUE rb_cFixnum
Definition: ruby.h:1565
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1488
rb_warn
void rb_warn(const char *fmt,...)
Definition: error.c:223
isdecimal
static int isdecimal(int c)
Definition: complex.c:1509
rb_cNilClass
RUBY_EXTERN VALUE rb_cNilClass
Definition: ruby.h:1574
rb_cstr_to_dbl
double rb_cstr_to_dbl(const char *, int)
Definition: object.c:2783
id_abs
static ID id_abs
Definition: complex.c:21
rb_eArgError
VALUE rb_eArgError
Definition: error.c:549
nucomp_false
static VALUE nucomp_false(VALUE self)
Definition: complex.c:1088
numeric_real
static VALUE numeric_real(VALUE self)
Definition: complex.c:1911
nucomp_div
static VALUE nucomp_div(VALUE self, VALUE other)
Definition: complex.c:804
NUM2LONG
#define NUM2LONG(x)
Definition: ruby.h:600
nucomp_polar
static VALUE nucomp_polar(VALUE self)
Definition: complex.c:1051
argv
char ** argv
Definition: ruby.c:132
DBL2NUM
#define DBL2NUM(dbl)
Definition: ruby.h:815
f_one_p
static VALUE f_one_p(VALUE x)
Definition: complex.c:198
rb_cComplex
VALUE rb_cComplex
Definition: complex.c:19
f_format
static VALUE f_format(VALUE self, VALUE(*func)(VALUE))
Definition: complex.c:1210
read_num
static int read_num(const char **s, int strict, char **b)
Definition: complex.c:1552
id_real_p
static ID id_real_p
Definition: complex.c:21