2 Copyright (C) 2003-2008, The Perl Foundation.
7 src/pmc/integer.pmc - Integer PMC class
11 C<Integer> provides an integer for languages that want a value-restricted
12 integer type without going to an I register.
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) ;
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,
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);
47 PMC * const temp = VTABLE_get_bignum(interp, self);
48 return mmd_dispatch_p_pip(interp, temp, b, dest, mmd);
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,
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);
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.
80 Initializes the integer with a default value of C<0>.
85 VTABLE PMC *instantiate(PMC *sig) {
86 PMC * const ret = new_pmc_header(INTERP, 0);
87 opcode_t *arg_op = interp->current_args;
90 ret->vtable = interp->vtables[SELF->vtable->base_type];
92 if (SIG_ELEMS(sig) == 2) {
93 switch (SIG_ITEM(sig, 1)) {
95 init = REG_INT(interp, arg_op[3]);
101 Parrot_ex_throw_from_c_args(INTERP, NULL, 1,
102 "Integer.instantiate: unhandled initializer");
107 PMC_int_val(ret) = 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>.
124 VTABLE PMC *new_from_string(STRING *rep, INTVAL flags) {
125 const INTVAL type = SELF->vtable->base_type;
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);
138 =item C<void set_pmc(PMC *value)>
140 Sets the value of the integer to the value in C<*value>.
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.
159 VTABLE void share() {
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.
168 if (sizeof (INTVAL) != sizeof (long))
174 =item C<INTVAL get_integer()>
176 Returns the integer value of the Integer.
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.
194 VTABLE INTVAL get_bool() {
195 return SELF.get_integer() ? 1 : 0;
200 =item C<FLOATVAL get_number()>
202 Returns the floating-point value of the integer.
207 VTABLE FLOATVAL get_number() {
208 return SELF.get_integer();
213 =item C<PMC *get_bignum()>
215 Return a new BigInt PMC with the value of C<SELF>.
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);
229 =item C<STRING *get_string()>
231 Returns the string value of the integer.
236 VTABLE STRING *get_string() {
237 return string_from_int(INTERP, SELF.get_integer());
240 VTABLE STRING *get_repr() {
241 return string_from_int(INTERP, SELF.get_integer());
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>.
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>.
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
320 VTABLE PMC *add(PMC *value, PMC *dest) {
323 * SELF and value can both be PMCs that inherit
325 * cl = subclass "Integer", "MyInt"
326 * so we can't used PMC_int_val(SELF) in any of these
330 * check for exact Integer type
331 * e.g. MMD_Integer_EXACT
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) {
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);
347 return overflow(INTERP, SELF, b, dest, MMD_ADD);
350 const INTVAL a = SELF.get_integer();
352 VTABLE_morph(INTERP, dest, VTABLE_type(interp, value));
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));
364 return overflow_p(INTERP, SELF, value, dest, MMD_ADD);
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));
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) {
382 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
384 VTABLE_set_integer_native(INTERP, dest, c);
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.
405 VTABLE void i_add(PMC *value) {
407 STATICSELF.i_add_int(VTABLE_get_integer(INTERP, value));
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));
417 VTABLE_set_number_native(INTERP, SELF,
418 PMC_int_val(SELF) + VTABLE_get_number(INTERP, value));
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);
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.
449 VTABLE PMC *subtract(PMC *value, PMC *dest) {
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) {
457 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
459 VTABLE_set_integer_native(INTERP, dest, c);
463 return overflow(INTERP, SELF, b, dest, MMD_SUBTRACT);
466 const INTVAL a = SELF.get_integer();
468 VTABLE_morph(INTERP, dest, value->vtable->base_type);
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));
480 return overflow_p(INTERP, SELF, value, dest, MMD_SUBTRACT);
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));
494 =item C<PMC *subtract_int(INTVAL value, PMC *dest)>
496 Subtracts C<value> from the integer and returns the result in C<*dest>.
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) {
507 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
509 VTABLE_set_integer_native(INTERP, dest, c);
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.
530 VTABLE void i_subtract(PMC *value) {
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);
539 overflow(INTERP, SELF, b, SELF, MMD_SUBTRACT);
542 const INTVAL a = SELF.get_integer();
544 VTABLE_morph(INTERP, SELF, value->vtable->base_type);
545 VTABLE_set_number_native(INTERP, SELF,
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));
552 VTABLE_set_number_native(INTERP, SELF,
553 SELF.get_integer() - VTABLE_get_number(INTERP, value));
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);
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>.
583 VTABLE PMC *multiply(PMC *value, PMC *dest) {
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) {
592 dest = pmc_new(INTERP, VTABLE_type(interp, SELF));
594 VTABLE_set_integer_native(INTERP, dest, c);
598 return overflow(INTERP, SELF, b, dest, MMD_MULTIPLY);
601 Parrot_ex_throw_from_c_args(INTERP, NULL,
602 EXCEPTION_INTERNAL_NOT_IMPLEMENTED,
603 "RT #46629 mul<Integer, Complex>");
606 return Parrot_BigInt_multiply_int(INTERP, value,
607 SELF.get_integer(), dest);
610 return Parrot_Integer_multiply_Integer(INTERP, SELF, value, dest);
613 const FLOATVAL valf = VTABLE_get_number(INTERP, value);
615 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
617 VTABLE_set_number_native(INTERP, dest, SELF.get_number() * valf);
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) {
629 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
631 VTABLE_set_integer_native(INTERP, dest, c);
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.
652 VTABLE void i_multiply(PMC *value) {
654 STATICSELF.i_multiply_int(VTABLE_get_integer(INTERP, value));
657 Parrot_BigInt_multiply_int(INTERP, value,
658 SELF.get_integer(), SELF);
661 Parrot_ex_throw_from_c_args(INTERP, NULL,
662 EXCEPTION_INTERNAL_NOT_IMPLEMENTED,
663 "RT #46629 i_mul<Integer, Complex>");
666 VTABLE_set_number_native(INTERP, SELF,
667 SELF.get_integer() * VTABLE_get_number(INTERP, value));
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);
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.
709 VTABLE PMC *divide(PMC *value, PMC *dest) {
711 return overflow_p(INTERP, SELF, value, dest, MMD_DIVIDE);
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");
721 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
722 VTABLE_set_number_native(INTERP, dest, SELF.get_number() / d);
727 VTABLE void i_divide(PMC *value) {
729 overflow_p(INTERP, SELF, value, SELF, MMD_DIVIDE);
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);
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.
764 VTABLE PMC *floor_divide(PMC *value, PMC *dest) {
766 return overflow_p(INTERP, SELF, value, dest, MMD_FLOOR_DIVIDE);
769 FLOATVAL d = VTABLE_get_number(INTERP, value);
772 if (FLOAT_IS_ZERO(d))
773 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
774 "float division by zero");
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);
785 VTABLE PMC *floor_divide_int(INTVAL value, PMC *dest) {
789 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
790 "float division by zero");
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);
801 VTABLE PMC *floor_divide_float(FLOATVAL value, PMC *dest) {
804 if (FLOAT_IS_ZERO(value))
805 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
806 "float division by zero");
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);
817 VTABLE void i_floor_divide(PMC *value) {
819 overflow_p(INTERP, SELF, value, SELF, MMD_FLOOR_DIVIDE);
822 FLOATVAL d = VTABLE_get_number(INTERP, value);
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);
834 VTABLE void i_floor_divide_int(INTVAL value) {
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) {
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>.
880 VTABLE PMC *cmodulus(PMC *value, PMC *dest) {
882 return overflow_p(INTERP, SELF, value, dest, MMD_CMOD);
885 INTVAL d = VTABLE_get_integer(INTERP, value);
888 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
889 "int cmodulus by zero");
892 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
894 VTABLE_set_integer_native(INTERP, dest,
895 SELF.get_integer() % d);
900 VTABLE PMC *cmodulus_float(FLOATVAL value, PMC *dest) {
903 if (FLOAT_IS_ZERO(value))
904 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
905 "int cmodulus by zero");
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);
916 VTABLE PMC *cmodulus_int(INTVAL value, PMC *dest) {
918 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
919 "int cmodulus by zero");
922 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
923 VTABLE_set_integer_native(INTERP, dest,
924 SELF.get_integer() % value);
928 VTABLE void i_cmodulus(PMC *value) {
930 overflow_p(INTERP, SELF, value, SELF, MMD_CMOD);
933 const INTVAL d = VTABLE_get_integer(INTERP, value);
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);
944 VTABLE void i_cmodulus_int(INTVAL value) {
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) {
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
987 VTABLE PMC *modulus(PMC *value, PMC *dest) {
989 return overflow_p(INTERP, SELF, value, dest, MMD_MOD);
992 const INTVAL d = VTABLE_get_integer(INTERP, value);
995 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
996 "int modulus by zero");
999 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1001 VTABLE_set_integer_native(INTERP, dest,
1002 intval_mod(SELF.get_integer(), d));
1007 VTABLE PMC *modulus_int(INTVAL value, PMC *dest) {
1009 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
1010 "int modulus by zero");
1013 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1015 VTABLE_set_integer_native(INTERP, dest,
1016 intval_mod(SELF.get_integer(), value));
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");
1026 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1028 VTABLE_set_integer_native(INTERP, dest,
1029 intval_mod(SELF.get_integer(), (INTVAL)value));
1032 VTABLE void i_modulus(PMC *value) {
1034 overflow_p(INTERP, SELF, value, SELF, MMD_MOD);
1037 const INTVAL d = VTABLE_get_integer(INTERP, value);
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));
1048 VTABLE void i_modulus_int(INTVAL value) {
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.
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;
1096 return SUPER(b, dest);
1106 if (r / temp != prev)
1107 return overflow(INTERP, SELF, orig_b, dest, MMD_POW);
1117 if (prev != 0 && temp / prev != prev)
1118 return overflow(INTERP, SELF, orig_b, dest, MMD_POW);
1123 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1125 VTABLE_set_integer_native(INTERP, dest, r);
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.
1147 VTABLE INTVAL is_equal(PMC *value) {
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);
1154 return (VTABLE_get_integer(INTERP, SELF) ==
1155 VTABLE_get_integer(INTERP, value));
1161 =item C<INTVAL cmp(PMC *value)>
1163 Returns the result of comparing the integer with C<*value>.
1168 VTABLE INTVAL cmp(PMC *value) {
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;
1178 return fdiff > 0 ? 1 : -1;
1182 const FLOATVAL diff =
1183 SELF.get_number() - VTABLE_get_number(INTERP, value);
1184 return diff > 0 ? 1 : diff < 0 ? -1 : 0;
1188 const INTVAL diff = SELF.get_integer()
1189 - VTABLE_get_integer(INTERP, value);
1190 return diff > 0 ? 1 : diff < 0 ? -1 : 0;
1196 =item C<INTVAL cmp_num(PMC *value)>
1198 Returns the result of numerically comparing the integer with C<*value>.
1203 VTABLE INTVAL cmp_num(PMC *value) {
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;
1214 return fdiff > 0 ? 1 : -1;
1218 const FLOATVAL diff =
1219 SELF.get_number() - VTABLE_get_number(INTERP, value);
1220 return diff > 0 ? 1 : diff < 0 ? -1 : 0;
1225 SELF.get_integer() - VTABLE_get_integer(INTERP, value);
1226 return diff > 0 ? 1 : diff < 0 ? -1 : 0;
1232 =item C<void increment()>
1234 Increments the integer.
1239 VTABLE void increment() {
1240 /* RT #46633 overflow */
1241 PMC_int_val(SELF) ++;
1246 =item C<void decrement()>
1248 Decrements the integer.
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.
1269 VTABLE PMC *absolute(PMC *dest) {
1270 const INTVAL a = abs(SELF.get_integer());
1272 /* RT #46635 overlflow for -maxint */
1274 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1276 VTABLE_set_integer_native(INTERP, dest, a);
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.
1297 METHOD get_as_base(INTVAL base) {
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);
1312 =item C<void freeze(visit_info *info)>
1314 Used to archive the integer.
1319 VTABLE void freeze(visit_info *info) {
1320 IMAGE_IO * const io = info->image_io;
1322 VTABLE_push_integer(INTERP, io, PMC_int_val(SELF));
1327 =item C<void thaw(visit_info *info)>
1329 Used to unarchive the integer.
1334 VTABLE void thaw(visit_info *info) {
1335 IMAGE_IO * const io = info->image_io;
1337 if (info->extra_flags == EXTRA_IS_NULL)
1338 PMC_int_val(SELF) = VTABLE_shift_integer(INTERP, io);
1352 * c-file-style: "parrot"
1354 * vim: expandtab shiftwidth=4: