tagged release 0.7.1
[parrot.git] / src / pmc / integer.pmc
blobd57d2187e8994537d726c939684a5df21c5a32f0
1 /*
2 Copyright (C) 2003-2008, The Perl Foundation.
3 $Id$
5 =head1 NAME
7 src/pmc/integer.pmc - Integer PMC class
9 =head1 DESCRIPTION
11 C<Integer> provides an integer for languages that want a value-restricted
12 integer type without going to an I register.
14 =head2 Functions
16 =over 4
18 =cut
22 #include "parrot/parrot.h"
24 #include "pmc_bigint.h"
25 /* RT#46619 create MMD headers to in Pmc2c.pm */
27 extern INTVAL Parrot_BigInt_is_equal_BigInt(PARROT_INTERP, PMC*, PMC*);
28 extern PMC *Parrot_BigInt_multiply_int(PARROT_INTERP,
29         PMC *pmc, INTVAL value, PMC *dest) ;
32 static PMC*
33 overflow(PARROT_INTERP, PMC *self, INTVAL b, PMC *dest, int mmd) {
34     const INTVAL a = VTABLE_get_integer(interp, self);
36     if (PARROT_ERRORS_test(interp, PARROT_ERRORS_OVERFLOW_FLAG))
37     Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_ERR_OVERFLOW,
38         "Integer overflow");
40 if (self == dest) {
41     /* RT #46621 preserve type system */
42     VTABLE_morph(interp, self, enum_class_BigInt);
43     VTABLE_set_integer_native(interp, self, a);
44     return mmd_dispatch_p_pip(interp, self, b, dest, mmd);
46 else {
47     PMC * const temp = VTABLE_get_bignum(interp, self);
48     return mmd_dispatch_p_pip(interp, temp, b, dest, mmd);
52 static PMC*
53 overflow_p(PARROT_INTERP, PMC *self, PMC *val, PMC *dest, int mmd) {
54 const INTVAL a = VTABLE_get_integer(interp, self);
56 if (PARROT_ERRORS_test(interp, PARROT_ERRORS_OVERFLOW_FLAG))
57     Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_ERR_OVERFLOW,
58         "Integer overflow");
60 if (self == dest) {
61     VTABLE_morph(interp, self, enum_class_BigInt);
62     VTABLE_set_integer_native(interp, self, a);
63     return mmd_dispatch_p_ppp(interp, self, val, dest, mmd);
65 else {
66     PMC * const temp = VTABLE_get_bignum(interp, self);
67     return mmd_dispatch_p_ppp(interp, temp, val, dest, mmd);
71 pmclass Integer extends scalar provides integer provides scalar {
74 =item C<PMC instantiate(PMC *sig)>
76 Create a new Integer with arguments passed according to pdd03.
78 =item C<void init()>
80 Initializes the integer with a default value of C<0>.
82 =cut
85 VTABLE PMC *instantiate(PMC *sig) {
86     PMC * const ret    = new_pmc_header(INTERP, 0);
87     opcode_t   *arg_op = interp->current_args;
88     INTVAL      init   = 0;
90     ret->vtable        = interp->vtables[SELF->vtable->base_type];
92     if (SIG_ELEMS(sig) == 2) {
93         switch (SIG_ITEM(sig, 1)) {
94             case PARROT_ARG_I:
95                 init = REG_INT(interp, arg_op[3]);
96                 break;
97             case PARROT_ARG_IC:
98                 init = arg_op[3];
99                 break;
100             default:
101                 Parrot_ex_throw_from_c_args(INTERP, NULL, 1,
102                         "Integer.instantiate: unhandled initializer");
103                 break;
104         }
105     }
107     PMC_int_val(ret) = init;
108     return ret;
111 VTABLE void init() {
112     PMC_int_val(SELF) = 0;
117 =item C<PMC new_from_string(STRING *rep)>
119 Class method to construct an Integer from the string representation C<rep>.
121 =cut
124 VTABLE PMC *new_from_string(STRING *rep, INTVAL flags) {
125     const INTVAL type = SELF->vtable->base_type;
126     PMC * const res =
127         (flags & PObj_constant_FLAG)
128             ? constant_pmc_new(INTERP, type)
129             : pmc_new(INTERP, type);
131     /* RT #46623 bigint overflow */
132     PMC_int_val(res) = string_to_int(INTERP, rep);
133     return res;
138 =item C<void set_pmc(PMC *value)>
140 Sets the value of the integer to the value in C<*value>.
142 =cut
146 VTABLE void set_pmc(PMC *value) {
147     PMC_int_val(SELF) = VTABLE_get_integer(INTERP, value);
152 =item C<void share()>
154 Sets this PMC as shared and read-only.
156 =cut
159 VTABLE void share() {
160     /*
161      * assume that the access to a long is atomic.
162      * integers are most often (1) equal to C longs,
163      * not C ints, and this makes a difference in 64-bit
164      * platforms where longs are 64-bit but ints are 32-bit.
165      * (1) Not equal when integers have been configured
166      *     to be software-emulated long longs.
167      */
168     if (sizeof (INTVAL) != sizeof (long))
169         SUPER();
174 =item C<INTVAL get_integer()>
176 Returns the integer value of the Integer.
178 =cut
181 VTABLE INTVAL get_integer() {
182     return PMC_int_val(SELF);
187 =item C<INTVAL get_bool()>
189 Returns the boolean value of the Integer.
191 =cut
194     VTABLE INTVAL get_bool() {
195         return SELF.get_integer() ? 1 : 0;
196     }
200 =item C<FLOATVAL get_number()>
202 Returns the floating-point value of the integer.
204 =cut
207     VTABLE FLOATVAL get_number() {
208         return SELF.get_integer();
209     }
213 =item C<PMC *get_bignum()>
215 Return a new BigInt PMC with the value of C<SELF>.
217 =cut
220 VTABLE PMC *get_bignum() {
221     const INTVAL val = SELF.get_integer();
222     PMC * const  ret = pmc_new(INTERP, enum_class_BigInt);
223     VTABLE_set_integer_native(INTERP, ret, val);
224     return ret;
229 =item C<STRING *get_string()>
231 Returns the string value of the integer.
233 =cut
236     VTABLE STRING *get_string() {
237         return string_from_int(INTERP, SELF.get_integer());
238     }
240     VTABLE STRING *get_repr() {
241         return string_from_int(INTERP, SELF.get_integer());
242     }
246 =item C<void set_integer_same(PMC *value)>
248 =item C<void set_integer_native(INTVAL value)>
250 Sets the value of the integer to the value of the C<Integer> C<*value>.
252 =cut
255 VTABLE void set_integer_same(PMC *value) {
256     PMC_int_val(SELF) = PMC_int_val(value);
259 VTABLE void set_integer_native(INTVAL value) {
260     PMC_int_val(SELF) = value;
265 =item C<void set_number_native(FLOATVAL value)>
267 Morphs the integer to a C<Float> and sets the value from C<value>.
269 =item C<void set_bool(INTVAL value)>
271 Morphs the integer to a C<Boolean> and sets the value from C<value>.
273 =item C<void set_bigint_int(INTVAL value)>
275 Morphs the integer to a C<BigInt> and sets the value from C<value>.
277 =item C<void set_string_native(STRING *value)>
279 Morphs the integer to a C<String> and sets the value from C<value>.
281 =cut
284 VTABLE void set_number_native(FLOATVAL value) {
285     SELF.morph(enum_class_Float);
286     SELF.set_number_native(value);
289 VTABLE void set_bool(INTVAL value) {
290     SELF.morph(enum_class_Boolean);
291     SELF.set_bool(value);
294 VTABLE void set_bignum_int(INTVAL value) {
295     SELF.morph(enum_class_BigInt);
296     SELF.set_integer_native(value);
299 VTABLE void set_string_native(STRING *value) {
300     SELF.morph(enum_class_String);
301     SELF.set_string_native(value);
306 =item C<PMC *add(PMC *value, PMC *dest)>
308 =item C<PMC *add_int(INTVAL value, PMC *dest)>
310 Adds C<value> to the integer and returns the result in C<*dest>.
312 Please note: the label syntax I<MMD_type:> denote the behavior, if
313 the right hand value is of that type. The part inside the braces is
314 converted to a distinct function and gets I<mmd_register>ed for these
315 two types.
317 =cut
320 VTABLE PMC *add(PMC *value, PMC *dest) {
321 MMD_Integer: {
322         /*
323          * SELF and value can both be PMCs that inherit
324          * from Integer:
325          *   cl = subclass "Integer", "MyInt"
326          * so we can't used PMC_int_val(SELF) in any of these
327          * Integer methods
328          *
329          * RT #46627
330          *   check for exact Integer type
331          *   e.g. MMD_Integer_EXACT
332          */
334         const INTVAL a = SELF.get_integer();
335         const INTVAL b = VTABLE_get_integer(INTERP, value);
336         const INTVAL c = a + b;
338         if ((c^a) >= 0 || (c^b) >= 0) {
339             if (!dest)
340                 dest = pmc_new(INTERP, VTABLE_type(interp, SELF));
342             /* need this for e.g. Undef PMC */
343             VTABLE_set_integer_native(INTERP, dest, c);
344             return dest;
345         }
346         else
347             return overflow(INTERP, SELF, b, dest, MMD_ADD);
348     }
349 MMD_Complex: {
350         const INTVAL a = SELF.get_integer();
351         if (dest)
352             VTABLE_morph(INTERP, dest, VTABLE_type(interp, value));
353         else
354             dest = pmc_new(INTERP, VTABLE_type(interp, value));
356         VTABLE_set_number_native(INTERP, dest,
357                 a + VTABLE_get_number_keyed_int(INTERP, value, 0));
358         VTABLE_set_number_keyed_int(INTERP, dest, 1,
359                 VTABLE_get_number_keyed_int(INTERP, value, 1));
361         return dest;
362     }
363 MMD_BigInt: {
364         return overflow_p(INTERP, SELF, value, dest, MMD_ADD);
365     }
366 MMD_DEFAULT: {
367         if (!dest)
368             dest = pmc_new(INTERP, VTABLE_type(interp, value));
370         VTABLE_set_number_native(INTERP, dest,
371             SELF.get_integer() + VTABLE_get_number(INTERP, value));
372         return dest;
373     }
376 VTABLE PMC *add_int(INTVAL b, PMC *dest) {
377     const INTVAL a = VTABLE_get_integer(INTERP, SELF);
378     const INTVAL c = a + b;
380     if ((c^a) >= 0 || (c^b) >= 0) {
381         if (!dest)
382             dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
384         VTABLE_set_integer_native(INTERP, dest, c);
385         return dest;
386     }
387     else
388         return overflow(INTERP, SELF, b, dest, MMD_ADD);
393 =item C<void i_add(PMC *value)>
395 =item C<void i_add(INTVAL value)>
397 =item C<void i_add(FLOATVAL value)>
399 Adds C<value> to C<SELF> inplace.
401 =cut
405 VTABLE void i_add(PMC *value) {
406 MMD_Integer: {
407         STATICSELF.i_add_int(VTABLE_get_integer(INTERP, value));
408     }
409 MMD_Complex: {
410         const INTVAL a = SELF.get_integer();
412         VTABLE_morph(INTERP, SELF, value->vtable->base_type);
413         VTABLE_set_number_native(INTERP, SELF,
414             SELF.get_integer() + VTABLE_get_number(INTERP, value));
415     }
416 MMD_DEFAULT: {
417     VTABLE_set_number_native(INTERP, SELF,
418         PMC_int_val(SELF) + VTABLE_get_number(INTERP, value));
419     }
422 VTABLE void i_add_int(INTVAL b) {
423     const INTVAL a = SELF.get_integer();
424     const INTVAL c = a + b;
426     if ((c^a) >= 0 || (c^b) >= 0)
427         VTABLE_set_integer_native(INTERP, SELF, c);
428     else
429         overflow(INTERP, SELF, b, SELF, MMD_SUBTRACT);
432 VTABLE void i_add_float(FLOATVAL value) {
433     const INTVAL a = SELF.get_integer();
434     VTABLE_set_number_native(INTERP, SELF, a + value);
438 =item C<PMC *subtract(PMC *value, PMC *dest)>
440 Subtracts C<*value> from the integer and returns the result in C<*dest>.
441 If C<dest> is NULL, a new int PMC is created.
443 Please note: as C<SELF> or C<value> maybe be subclassed, we have to
444 call C<get_integer> and C<set_integer_native> always.
446 =cut
449 VTABLE PMC *subtract(PMC *value, PMC *dest) {
450 MMD_Integer: {
451         const INTVAL a = SELF.get_integer();
452         const INTVAL b = VTABLE_get_integer(INTERP, value);
453         const INTVAL c = a - b;
455         if ((c^a) >= 0 || (c^~b) >= 0) {
456             if (!dest)
457                 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
459             VTABLE_set_integer_native(INTERP, dest, c);
460             return dest;
461         }
462         else
463             return overflow(INTERP, SELF, b, dest, MMD_SUBTRACT);
464     }
465 MMD_Complex: {
466         const INTVAL a = SELF.get_integer();
467         if (dest)
468             VTABLE_morph(INTERP, dest, value->vtable->base_type);
469         else
470             dest = pmc_new(INTERP, VTABLE_type(INTERP, value));
472         VTABLE_set_number_native(INTERP, dest,
473                 a - VTABLE_get_number_keyed_int(INTERP, value, 0));
474         VTABLE_set_number_keyed_int(INTERP, dest, 1,
475                 -VTABLE_get_number_keyed_int(INTERP, value, 1));
477         return dest;
478     }
479 MMD_BigInt: {
480         return overflow_p(INTERP, SELF, value, dest, MMD_SUBTRACT);
481     }
482 MMD_DEFAULT: {
483         if (!dest)
484             dest = pmc_new(INTERP, VTABLE_type(INTERP, value));
486         VTABLE_set_number_native(INTERP, dest,
487             SELF.get_integer() - VTABLE_get_number(INTERP, value));
488         return dest;
489     }
494 =item C<PMC *subtract_int(INTVAL value, PMC *dest)>
496 Subtracts C<value> from the integer and returns the result in C<*dest>.
498 =cut
501 VTABLE PMC *subtract_int(INTVAL b, PMC *dest) {
502     const INTVAL a = SELF.get_integer();
503     const INTVAL c = a - b;
505     if ((c^a) >= 0 || (c^~b) >= 0) {
506         if (!dest)
507             dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
509         VTABLE_set_integer_native(INTERP, dest, c);
510         return dest;
511     }
512     else
513         return overflow(INTERP, SELF, b, dest, MMD_SUBTRACT);
518 =item C<void i_subtract(PMC *value)>
520 =item C<void i_subtract_int(INTVAL value)>
522 =item C<void i_subtract_float(FLOATVAL value)>
524 Subtracts C<value> from C<SELF> inplace.
526 =cut
530 VTABLE void i_subtract(PMC *value) {
531 MMD_Integer: {
532         const INTVAL a = SELF.get_integer();
533         const INTVAL b = VTABLE_get_integer(INTERP, value);
534         const INTVAL c = a - b;
536         if ((c^a) >= 0 || (c^~b) >= 0)
537             VTABLE_set_integer_native(INTERP, SELF, c);
538         else
539             overflow(INTERP, SELF, b, SELF, MMD_SUBTRACT);
540     }
541 MMD_Complex: {
542         const INTVAL a = SELF.get_integer();
544         VTABLE_morph(INTERP, SELF, value->vtable->base_type);
545         VTABLE_set_number_native(INTERP, SELF,
546                 (FLOATVAL)a -
547                 VTABLE_get_number_keyed_int(INTERP, value, 0));
548         VTABLE_set_number_keyed_int(INTERP, SELF, 1,
549                 -VTABLE_get_number_keyed_int(INTERP, value, 1));
550     }
551 MMD_DEFAULT: {
552     VTABLE_set_number_native(INTERP, SELF,
553         SELF.get_integer() - VTABLE_get_number(INTERP, value));
554     }
557 VTABLE void i_subtract_int(INTVAL b) {
558     const INTVAL a = SELF.get_integer();
559     const INTVAL c = a - b;
561     if ((c^a) >= 0 || (c^~b) >= 0)
562         VTABLE_set_integer_native(INTERP, SELF, c);
563     else
564         overflow(INTERP, SELF, b, SELF, MMD_SUBTRACT);
567 VTABLE void i_subtract_float(FLOATVAL value) {
568     const INTVAL a = SELF.get_integer();
569     VTABLE_set_number_native(INTERP, SELF, a - value);
574 =item C<PMC *multiply(PMC *value, PMC *dest)>
576 =item C<PMC *multiply_int(INTVAL value, PMC *dest)>
578 Multiplies the integer by C<*value> and returns the result in C<*dest>.
580 =cut
583 VTABLE PMC *multiply(PMC *value, PMC *dest) {
584 MMD_Integer: {
585         const INTVAL a  = VTABLE_get_integer(INTERP, SELF);
586         const INTVAL b  = VTABLE_get_integer(INTERP, value);
587         const double cf = (double)a * (double)b;
588         const INTVAL c  = a * b;
590         if ((double) c == cf) {
591             if (!dest)
592                 dest = pmc_new(INTERP, VTABLE_type(interp, SELF));
594             VTABLE_set_integer_native(INTERP, dest, c);
595             return dest;
596         }
597         else
598             return overflow(INTERP, SELF, b, dest, MMD_MULTIPLY);
599     }
600 MMD_Complex: {
601             Parrot_ex_throw_from_c_args(INTERP, NULL,
602                 EXCEPTION_INTERNAL_NOT_IMPLEMENTED,
603                 "RT #46629 mul<Integer, Complex>");
604         }
605 MMD_BigInt:     {
606         return Parrot_BigInt_multiply_int(INTERP, value,
607                 SELF.get_integer(), dest);
608     }
609 MMD_String: {
610         return Parrot_Integer_multiply_Integer(INTERP, SELF, value, dest);
611     }
612 MMD_DEFAULT: {
613         const FLOATVAL valf = VTABLE_get_number(INTERP, value);
614         if (!dest)
615             dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
617         VTABLE_set_number_native(INTERP, dest, SELF.get_number() * valf);
618         return dest;
619     }
622 VTABLE PMC *multiply_int(INTVAL b, PMC *dest) {
623     const INTVAL a  = SELF.get_integer();
624     const double cf = (double)a * (double)b;
625     const INTVAL c  = a * b;
627     if ((double) c == cf) {
628         if (!dest)
629             dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
631         VTABLE_set_integer_native(INTERP, dest, c);
632         return dest;
633     }
634     else
635         return overflow(INTERP, SELF, b, dest, MMD_MULTIPLY);
640 =item C<void i_multiply(PMC *value)>
642 =item C<void i_multiply_int(INTVAL value)>
644 =item C<void i_multiply_float(FLOATVAL value)>
646 Multiply C<value> with C<SELF> inplace.
648 =cut
652 VTABLE void i_multiply(PMC *value) {
653 MMD_Integer: {
654         STATICSELF.i_multiply_int(VTABLE_get_integer(INTERP, value));
655     }
656 MMD_BigInt: {
657         Parrot_BigInt_multiply_int(INTERP, value,
658                 SELF.get_integer(), SELF);
659     }
660 MMD_Complex: {
661             Parrot_ex_throw_from_c_args(INTERP, NULL,
662                 EXCEPTION_INTERNAL_NOT_IMPLEMENTED,
663                 "RT #46629 i_mul<Integer, Complex>");
664     }
665 MMD_DEFAULT: {
666         VTABLE_set_number_native(INTERP, SELF,
667             SELF.get_integer() * VTABLE_get_number(INTERP, value));
668     }
671 VTABLE void i_multiply_int(INTVAL b) {
672     const INTVAL a  = SELF.get_integer();
673     const double cf = (double)a * (double)b;
674     const INTVAL c  = a * b;
676     if ((double) c == cf)
677         SELF.set_integer_native(c);
678     else
679         overflow(INTERP, SELF, b, SELF, MMD_MULTIPLY);
682 VTABLE void i_multiply_float(FLOATVAL value) {
683     const INTVAL a = SELF.get_integer();
684     VTABLE_set_number_native(INTERP, SELF, a * value);
689 =item C<PMC *divide(PMC *value, PMC *dest)>
691 =item C<PMC *divide_int(INTVAL value, PMC *dest)>
693 =item C<PMC *divide_float(FLOATVAL value, PMC *dest)>
695 Divides the number by C<value> and returns the result in C<*dest>.
697 =item C<void i_divide(PMC *value)>
699 =item C<void i_divide_int(INTVAL value)>
701 =item C<void i_divide_float(FLOATVAL value)>
703 Divides C<SELF> by C<value> inplace.
705 =cut
709 VTABLE PMC *divide(PMC *value, PMC *dest) {
710 MMD_BigInt:     {
711         return overflow_p(INTERP, SELF, value, dest, MMD_DIVIDE);
712     }
713 MMD_DEFAULT: {
714         FLOATVAL d = VTABLE_get_number(INTERP, value);
716         if (FLOAT_IS_ZERO(d))
717             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
718                 "float division by zero");
720         if (!dest)
721             dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
722         VTABLE_set_number_native(INTERP, dest, SELF.get_number() / d);
723         return dest;
724     }
727 VTABLE void i_divide(PMC *value) {
728 MMD_BigInt:     {
729          overflow_p(INTERP, SELF, value, SELF, MMD_DIVIDE);
730     }
731 MMD_DEFAULT: {
732         FLOATVAL d = VTABLE_get_number(INTERP, value);
734         if (FLOAT_IS_ZERO(d))
735             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
736                     "float division by zero");
738         VTABLE_set_number_native(INTERP, SELF, SELF.get_number() / d);
739     }
744 =item C<PMC *floor_divide(PMC *value, PMC *dest)>
746 =item C<PMC *floor_divide_int(INTVAL value, PMC *dest)>
748 =item C<PMC *floor_divide_float(FLOATVAL value, PMC *dest)>
750 Divides the number by C<value> and returns the result in C<*dest>.
752 =item C<void i_floor_divide(PMC *value)>
754 =item C<void i_floor_divide_int(INTVAL value)>
756 =item C<void i_floor_divide_float(FLOATVAL value)>
758 Divides C<SELF> by C<value> inplace.
760 =cut
764 VTABLE PMC *floor_divide(PMC *value, PMC *dest) {
765 MMD_BigInt:     {
766         return overflow_p(INTERP, SELF, value, dest, MMD_FLOOR_DIVIDE);
767     }
768 MMD_DEFAULT: {
769         FLOATVAL d = VTABLE_get_number(INTERP, value);
770         FLOATVAL f;
772         if (FLOAT_IS_ZERO(d))
773             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
774                     "float division by zero");
776         if (!dest)
777             dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
779         f = floor(SELF.get_number() / d);
780         VTABLE_set_integer_native(INTERP, dest, (INTVAL)f);
781         return dest;
782     }
785 VTABLE PMC *floor_divide_int(INTVAL value, PMC *dest) {
786     FLOATVAL f;
788     if (value == 0)
789         Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
790             "float division by zero");
792     if (!dest)
793         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
795     f = floor(SELF.get_number() / value);
796     VTABLE_set_integer_native(INTERP, dest, (INTVAL)f);
798     return dest;
801 VTABLE PMC *floor_divide_float(FLOATVAL value, PMC *dest) {
802     FLOATVAL f;
804     if (FLOAT_IS_ZERO(value))
805         Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
806             "float division by zero");
808     if (!dest)
809         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
811     f = floor(SELF.get_number() / value);
812     VTABLE_set_integer_native(INTERP, dest, (INTVAL)f);
814     return dest;
817 VTABLE void i_floor_divide(PMC *value) {
818 MMD_BigInt:     {
819         overflow_p(INTERP, SELF, value, SELF, MMD_FLOOR_DIVIDE);
820     }
821 MMD_DEFAULT: {
822         FLOATVAL d = VTABLE_get_number(INTERP, value);
823         FLOATVAL f;
825         if (FLOAT_IS_ZERO(d))
826             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
827                 "float division by zero");
829         f = floor(SELF.get_number() / d);
830         VTABLE_set_integer_native(INTERP, SELF, (INTVAL)f);
831     }
834 VTABLE void i_floor_divide_int(INTVAL value) {
835     FLOATVAL f;
837     if (value == 0)
838         Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
839             "float division by zero");
841     f = floor(SELF.get_number() / value);
842     VTABLE_set_integer_native(INTERP, SELF, (INTVAL)f);
845 VTABLE void i_floor_divide_float(FLOATVAL value) {
846     FLOATVAL f;
848     if (FLOAT_IS_ZERO(value))
849         Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
850             "float division by zero");
852     f = floor(SELF.get_number() / value);
853     VTABLE_set_integer_native(INTERP, SELF, (INTVAL)f);
858 =item C<PMC *cmodulus(PMC *value, PMC *dest)>
860 =item C<PMC *cmodulus(INTVAL value, PMC *dest)>
862 =item C<PMC *cmodulus(FLOATVAL value, PMC *dest)>
864 Calculates the value of the number C-style C<mod> C<value> and returns
865 the result in C<dest>.
867 =item C<void i_cmodulus(PMC *value)>
869 =item C<void i_cmodulus(INTVAL value)>
871 =item C<void i_cmodulus(FLOATVAL value)>
873 Calculates the value of the number C-style C<mod> C<value> and returns
874 the result in C<dest>.
876 =cut
880 VTABLE PMC *cmodulus(PMC *value, PMC *dest) {
881 MMD_BigInt: {
882         return overflow_p(INTERP, SELF, value, dest, MMD_CMOD);
883     }
884 MMD_DEFAULT: {
885         INTVAL d = VTABLE_get_integer(INTERP, value);
887         if (d == 0)
888             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
889                 "int cmodulus by zero");
891         if (!dest)
892             dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
894         VTABLE_set_integer_native(INTERP, dest,
895                 SELF.get_integer() % d);
896         return dest;
897     }
900 VTABLE PMC *cmodulus_float(FLOATVAL value, PMC *dest) {
901     FLOATVAL f;
903     if (FLOAT_IS_ZERO(value))
904         Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
905             "int cmodulus by zero");
907     if (!dest)
908         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
910     f = fmod(SELF.get_integer(), value);
911     VTABLE_set_integer_native(INTERP, dest, (INTVAL)f);
913     return dest;
916 VTABLE PMC *cmodulus_int(INTVAL value, PMC *dest) {
917     if (value == 0)
918         Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
919             "int cmodulus by zero");
921     if (!dest)
922         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
923     VTABLE_set_integer_native(INTERP, dest,
924             SELF.get_integer() % value);
925     return dest;
928 VTABLE void i_cmodulus(PMC *value) {
929 MMD_BigInt: {
930          overflow_p(INTERP, SELF, value, SELF, MMD_CMOD);
931     }
932 MMD_DEFAULT: {
933         const INTVAL d = VTABLE_get_integer(INTERP, value);
935         if (d == 0)
936             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
937                 "int cmodulus by zero");
939         VTABLE_set_integer_native(INTERP, SELF,
940                 SELF.get_integer() % d);
941     }
944 VTABLE void i_cmodulus_int(INTVAL value) {
945     if (value == 0)
946         Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
947             "int cmodulus by zero");
949     VTABLE_set_integer_native(INTERP, SELF,
950             SELF.get_integer() % value);
953 VTABLE void i_cmodulus_float(FLOATVAL value) {
954     FLOATVAL f;
956     if (FLOAT_IS_ZERO(value))
957         Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
958             "int cmodulus by zero");
960     f = fmod(SELF.get_integer(), value);
961     VTABLE_set_integer_native(INTERP, SELF, (INTVAL)f);
966 =item C<PMC *modulus(PMC *value, PMC *dest)>
968 =item C<PMC *modulus(INTVAL value, PMC *dest)>
970 =item C<PMC *modulus(FLOATVAL value, PMC *dest)>
972 Calculates the value of corrected C<mod> C<value> and returns
973 the result in C<dest>. See also ops/math.ops.
975 =item C<void i_modulus(PMC *value)>
977 =item C<void i_modulus(INTVAL value)>
979 =item C<void i_modulus(FLOATVAL value)>
981 Calculates modulus inplace
983 =cut
987 VTABLE PMC *modulus(PMC *value, PMC *dest) {
988 MMD_BigInt: {
989         return overflow_p(INTERP, SELF, value, dest, MMD_MOD);
990     }
991 MMD_DEFAULT: {
992         const INTVAL d = VTABLE_get_integer(INTERP, value);
994         if (d == 0)
995             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
996                 "int modulus by zero");
998         if (!dest)
999             dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1001         VTABLE_set_integer_native(INTERP, dest,
1002                 intval_mod(SELF.get_integer(), d));
1003         return dest;
1004     }
1007 VTABLE PMC *modulus_int(INTVAL value, PMC *dest) {
1008     if (value == 0)
1009         Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
1010             "int modulus by zero");
1012     if (!dest)
1013         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1015     VTABLE_set_integer_native(INTERP, dest,
1016             intval_mod(SELF.get_integer(), value));
1017     return dest;
1020 VTABLE PMC *modulus_float(FLOATVAL value, PMC *dest) {
1021     if (FLOAT_IS_ZERO(value))
1022         Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
1023             "int modulus by zero");
1025     if (!dest)
1026         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1028     VTABLE_set_integer_native(INTERP, dest,
1029             intval_mod(SELF.get_integer(), (INTVAL)value));
1030     return dest;
1032 VTABLE void i_modulus(PMC *value) {
1033 MMD_BigInt: {
1034          overflow_p(INTERP, SELF, value, SELF, MMD_MOD);
1035     }
1036 MMD_DEFAULT: {
1037         const INTVAL d = VTABLE_get_integer(INTERP, value);
1039         if (d == 0)
1040             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
1041                 "int modulus by zero");
1043         VTABLE_set_integer_native(INTERP, SELF,
1044                 intval_mod(SELF.get_integer(), d));
1045     }
1048 VTABLE void i_modulus_int(INTVAL value) {
1049     if (value == 0)
1050         Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
1051             "int modulus by zero");
1053     VTABLE_set_integer_native(INTERP, SELF,
1054             intval_mod(SELF.get_integer() , value));
1057 VTABLE void i_modulus_float(FLOATVAL value) {
1058     if (FLOAT_IS_ZERO(value))
1059         Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
1060             "int modulus by zero");
1062     VTABLE_set_integer_native(INTERP, SELF,
1063             intval_mod(SELF.get_integer() , (INTVAL)value));
1068 =item C<PMC *pow(PMC *value, PMC *dest)>
1070 =item C<PMC *pow_int(INTVAL value, PMC *dest)>
1072 Return SELF to the C<value>th power and return result in C<dest>.
1074 =item C<void i_pow(PMC *value)>
1076 =item C<void i_pow_int(INTVAL value)>
1078 Raise SELF to the C<value>th power.
1080 RT #46631 Complex and BigInt rhs.
1082 =cut
1085 VTABLE PMC *pow(PMC *value, PMC *dest) {
1086     const INTVAL v = VTABLE_get_integer(INTERP, value);
1087     return STATICSELF.pow_int(v, dest);
1090 VTABLE PMC *pow_int(INTVAL b, PMC *dest) {
1091     const INTVAL a      = SELF.get_integer();
1092     const INTVAL orig_b = b;
1093     INTVAL       r;
1095     if (b < 0)
1096         return SUPER(b, dest);
1098     r = 1;
1100     if (a) {
1101         INTVAL temp = a;
1102         while (b > 0) {
1103             INTVAL prev = r;
1104             if (b & 1) {
1105                 r *= temp;
1106                 if (r / temp != prev)
1107                     return overflow(INTERP, SELF, orig_b, dest, MMD_POW);
1108             }
1110             b >>= 1;
1111             if (!b)
1112                 break;
1114             prev  = temp;
1115             temp *= temp;
1117             if (prev != 0 && temp / prev != prev)
1118                 return overflow(INTERP, SELF, orig_b, dest, MMD_POW);
1119         }
1120     }
1122     if (!dest)
1123         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1125     VTABLE_set_integer_native(INTERP, dest, r);
1126     return dest;
1130 VTABLE void i_pow(PMC *value) {
1131     STATICSELF.pow(value, SELF);
1134 VTABLE void i_pow_int(INTVAL value) {
1135     STATICSELF.pow_int(value, SELF);
1140 =item C<INTVAL is_equal(PMC *value)>
1142 The C<==> operation.
1144 =cut
1147 VTABLE INTVAL is_equal(PMC *value) {
1148 MMD_BigInt: {
1149         PMC * const temp = pmc_new(INTERP, enum_class_BigInt);
1150         VTABLE_set_integer_native(INTERP, temp, SELF.get_integer());
1151         return Parrot_BigInt_is_equal_BigInt(INTERP, temp, value);
1152     }
1153 MMD_DEFAULT: {
1154     return (VTABLE_get_integer(INTERP, SELF) ==
1155         VTABLE_get_integer(INTERP, value));
1156     }
1161 =item C<INTVAL cmp(PMC *value)>
1163 Returns the result of comparing the integer with C<*value>.
1165 =cut
1168 VTABLE INTVAL cmp(PMC *value) {
1169 MMD_String: {
1170             FLOATVAL fdiff =
1171                 SELF.get_number() - VTABLE_get_number(INTERP, value);
1172             if (FLOAT_IS_ZERO(fdiff)) {
1173                 const INTVAL idiff =
1174                     SELF.get_integer() - VTABLE_get_integer(INTERP, value);
1175                 return idiff > 0 ? 1 : idiff < 0 ? -1 : 0;
1176             }
1177             else {
1178                 return fdiff > 0 ? 1 : -1;
1179             }
1180     }
1181 MMD_Float: {
1182             const FLOATVAL diff =
1183                 SELF.get_number() - VTABLE_get_number(INTERP, value);
1184             return diff > 0 ? 1 : diff < 0 ? -1 : 0;
1185         }
1186 MMD_DEFAULT: {
1187             /* int or undef */
1188             const INTVAL diff = SELF.get_integer()
1189                 - VTABLE_get_integer(INTERP, value);
1190             return diff > 0 ? 1 : diff < 0 ? -1 : 0;
1191         }
1196 =item C<INTVAL cmp_num(PMC *value)>
1198 Returns the result of numerically comparing the integer with C<*value>.
1200 =cut
1203 VTABLE INTVAL cmp_num(PMC *value) {
1204 MMD_String: {
1205             FLOATVAL fdiff =
1206                 SELF.get_number() - VTABLE_get_number(INTERP, value);
1208             if (FLOAT_IS_ZERO(fdiff)) {
1209                 const INTVAL idiff =
1210                     SELF.get_integer() - VTABLE_get_integer(INTERP, value);
1211                 return idiff > 0 ? 1 : idiff < 0 ? -1 : 0;
1212             }
1213             else {
1214                 return fdiff > 0 ? 1 : -1;
1215             }
1216         }
1217 MMD_Float: {
1218             const FLOATVAL diff =
1219                 SELF.get_number() - VTABLE_get_number(INTERP, value);
1220             return diff > 0 ? 1 : diff < 0 ? -1 : 0;
1221         }
1222 MMD_DEFAULT: {
1223             /* int or undef */
1224             const INTVAL diff =
1225                 SELF.get_integer() - VTABLE_get_integer(INTERP, value);
1226             return diff > 0 ? 1 : diff < 0 ? -1 : 0;
1227         }
1232 =item C<void increment()>
1234 Increments the integer.
1236 =cut
1239 VTABLE void increment() {
1240     /* RT #46633 overflow */
1241     PMC_int_val(SELF) ++;
1246 =item C<void decrement()>
1248 Decrements the integer.
1250 =cut
1253 VTABLE void decrement() {
1254     /* RT #46633 overflow */
1255     PMC_int_val(SELF) --;
1259 =item C<PMC *absolute(PMC *dest)>
1261 =item C<void absolute()>
1263 Sets C<dest> to the absolute value of SELF.
1265 =cut
1269 VTABLE PMC *absolute(PMC *dest) {
1270     const INTVAL a = abs(SELF.get_integer());
1272     /* RT #46635 overlflow for -maxint */
1273     if (!dest)
1274         dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1276     VTABLE_set_integer_native(INTERP, dest, a);
1277     return dest;
1281 VTABLE void i_absolute() {
1282     const INTVAL a = abs(SELF.get_integer());
1283     VTABLE_set_integer_native(INTERP, SELF, a);
1288 =item C<STRING *get_as_base(INTVAL base)>
1290 Converts and returns the integer in base C<base>.
1291 C<base> must be between 2 and 36, inclusive.
1293 =cut
1297 METHOD get_as_base(INTVAL base) {
1298     char buf[128];
1299     STRING *result;
1301     if ((base < 2) || (base > 36))
1302         Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_OUT_OF_BOUNDS,
1303             "get_as_base: base out of bounds");
1305         result = int_to_str(interp, buf,
1306                 (HUGEINTVAL)VTABLE_get_integer(INTERP, SELF), (char)base);
1307         RETURN(STRING *result);
1308     }
1312 =item C<void freeze(visit_info *info)>
1314 Used to archive the integer.
1316 =cut
1319     VTABLE void freeze(visit_info *info) {
1320         IMAGE_IO * const io = info->image_io;
1321         SUPER(info);
1322         VTABLE_push_integer(INTERP, io, PMC_int_val(SELF));
1323     }
1327 =item C<void thaw(visit_info *info)>
1329 Used to unarchive the integer.
1331 =cut
1334     VTABLE void thaw(visit_info *info) {
1335         IMAGE_IO * const io = info->image_io;
1336         SUPER(info);
1337         if (info->extra_flags == EXTRA_IS_NULL)
1338             PMC_int_val(SELF) = VTABLE_shift_integer(INTERP, io);
1339     }
1344 =back
1346 =cut
1351  * Local variables:
1352  *   c-file-style: "parrot"
1353  * End:
1354  * vim: expandtab shiftwidth=4:
1355  */