2 Copyright (C) 2003-2010, Parrot 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 "pmc/pmc_bigint.h"
24 /* HEADERIZER HFILE: none */
25 /* HEADERIZER BEGIN: static */
26 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
28 static void maybe_throw_overflow_error(PARROT_INTERP)
29 __attribute__nonnull__(1);
31 PARROT_IGNORABLE_RESULT
32 PARROT_CANNOT_RETURN_NULL
33 static PMC* upgrade_self_to_bignum(PARROT_INTERP, ARGMOD(PMC *self))
34 __attribute__nonnull__(1)
35 __attribute__nonnull__(2)
38 #define ASSERT_ARGS_maybe_throw_overflow_error __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
39 PARROT_ASSERT_ARG(interp))
40 #define ASSERT_ARGS_upgrade_self_to_bignum __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
41 PARROT_ASSERT_ARG(interp) \
42 , PARROT_ASSERT_ARG(self))
43 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
44 /* HEADERIZER END: static */
48 =item C<static void maybe_throw_overflow_error(PARROT_INTERP)>
50 Checks to see if the interpreter is set to throw an exception on overflow.
52 If so, throw the exception, otherwise ignore.
59 maybe_throw_overflow_error(PARROT_INTERP)
61 ASSERT_ARGS(maybe_throw_overflow_error)
63 /* check to see what the behavior is. If the interpreter is set
64 to throw an exception on overflow. If so, throw the exception,
65 otherwise, chill out it's no big deal. */
66 if (PARROT_ERRORS_test(interp, PARROT_ERRORS_OVERFLOW_FLAG))
67 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_ERR_OVERFLOW,
73 =item C<static PMC* upgrade_self_to_bignum(PARROT_INTERP, PMC *self)>
75 Returns a pointer of *self upgraded to a bignum
81 PARROT_IGNORABLE_RESULT
82 PARROT_CANNOT_RETURN_NULL
84 upgrade_self_to_bignum(PARROT_INTERP, ARGMOD(PMC *self))
86 ASSERT_ARGS(upgrade_self_to_bignum)
88 /* Do an in-place upgrade to a Bignum of SELF and return a pointer
89 to it (which is probably redundant, but whatever). */
90 const INTVAL a = VTABLE_get_integer(interp, self);
91 Parrot_pmc_reuse(interp, self, enum_class_BigInt, 0);
92 VTABLE_set_integer_native(interp, self, a);
96 pmclass Integer extends scalar provides integer provides scalar auto_attrs {
97 ATTR INTVAL iv; /* the value of this Integer */
101 =item C<PMC init_pmc(PMC *init)>
103 Create a new Integer with arguments passed according to pdd03.
107 Initializes the integer with a default value of C<0>.
114 Parrot_Integer_attributes * const attrs =
115 (Parrot_Integer_attributes *)PMC_data(SELF);
120 VTABLE void init_pmc(PMC *init) {
121 Parrot_Integer_attributes * const attrs =
122 (Parrot_Integer_attributes *)PMC_data(SELF);
124 attrs->iv = VTABLE_get_integer(INTERP, init);
127 VTABLE void init_int(INTVAL init) {
128 Parrot_Integer_attributes * const attrs =
129 (Parrot_Integer_attributes *)PMC_data(SELF);
136 =item C<PMC *clone()>
138 Creates an exact duplicate of this PMC.
143 VTABLE PMC *clone() {
144 return Parrot_pmc_new_init_int(INTERP, SELF->vtable->base_type,
150 =item C<void set_pmc(PMC *value)>
152 Sets the value of the integer to the value in C<*value>.
158 VTABLE void set_pmc(PMC *value) {
159 SELF.set_integer_native(VTABLE_get_integer(INTERP, value));
165 =item C<void share()>
167 Sets this PMC as shared and read-only.
173 VTABLE void share() {
175 * assume that the access to a long is atomic.
176 * integers are most often (1) equal to C longs,
177 * not C ints, and this makes a difference in 64-bit
178 * platforms where longs are 64-bit but ints are 32-bit.
179 * (1) Not equal when integers have been configured
180 * to be software-emulated long longs.
182 if (sizeof (INTVAL) != sizeof (long))
189 =item C<INTVAL get_integer()>
191 Returns the integer value of the Integer.
197 VTABLE INTVAL get_integer() {
199 GET_ATTR_iv(INTERP, SELF, iv);
206 =item C<INTVAL get_bool()>
208 Returns the boolean value of the Integer.
213 VTABLE INTVAL get_bool() {
215 GET_ATTR_iv(INTERP, SELF, iv);
222 =item C<FLOATVAL get_number()>
224 Returns the floating-point value of the integer.
229 VTABLE FLOATVAL get_number() {
231 GET_ATTR_iv(INTERP, SELF, iv);
238 =item C<STRING *get_string()>
240 =item C<STRING *get_repr()>
242 Returns the string value of the integer.
247 VTABLE STRING *get_string() {
248 return Parrot_str_from_int(INTERP, SELF.get_integer());
251 VTABLE STRING *get_repr() {
252 return Parrot_str_from_int(INTERP, SELF.get_integer());
258 =item C<void set_integer_native(INTVAL value)>
260 Sets the value of the integer to the value of the C<Integer> C<*value>.
266 VTABLE void set_integer_native(INTVAL value) {
267 SET_ATTR_iv(INTERP, SELF, value);
272 =item C<void set_number_native(FLOATVAL value)>
274 Morphs the integer to a C<Float> and sets the value from C<value>.
276 =item C<void set_bool(INTVAL value)>
278 Morphs the integer to a C<Boolean> and sets the value from C<value>.
280 =item C<void set_string_native(STRING *value)>
282 Morphs the integer to a C<String> and sets the value from C<value>.
288 VTABLE void set_number_native(FLOATVAL value) {
289 Parrot_pmc_reuse(INTERP, SELF, enum_class_Float, 0);
290 SELF.set_number_native(value);
294 VTABLE void set_bool(INTVAL value) {
295 Parrot_pmc_reuse(INTERP, SELF, enum_class_Boolean, 0);
296 SELF.set_bool(value);
301 VTABLE void set_string_native(STRING *value) {
302 Parrot_pmc_reuse(INTERP, SELF, enum_class_String, 0);
303 SELF.set_string_native(value);
308 =item C<PMC *add(PMC *value, PMC *dest)>
310 =item C<PMC *add_int(INTVAL value, PMC *dest)>
312 Adds C<value> to the integer and returns the result in C<*dest>.
318 MULTI PMC *add(Integer value, PMC *dest) {
319 const INTVAL a = SELF.get_integer();
320 const INTVAL b = VTABLE_get_integer(INTERP, value);
321 const INTVAL c = a + b;
323 if ((c^a) >= 0 || (c^b) >= 0)
324 return Parrot_pmc_new_init_int(INTERP,
325 VTABLE_type(INTERP, SELF), c);
328 maybe_throw_overflow_error(INTERP);
329 temp = Parrot_pmc_new_init_int(INTERP, enum_class_BigInt, a);
330 return VTABLE_add(INTERP, temp, value, dest);
335 MULTI PMC *add(Complex value, PMC *dest) {
336 const INTVAL a = SELF.get_integer();
337 dest = Parrot_pmc_new_init_int(INTERP,
338 VTABLE_type(INTERP, value),
339 a + VTABLE_get_number_keyed_int(INTERP, value, 0));
340 VTABLE_set_number_keyed_int(INTERP, dest, 1,
341 VTABLE_get_number_keyed_int(INTERP, value, 1));
347 MULTI PMC *add(BigInt value, PMC *dest) {
349 maybe_throw_overflow_error(INTERP);
350 temp = Parrot_pmc_new_init_int(INTERP, enum_class_BigInt,
352 return VTABLE_add(INTERP, temp, value, dest);
356 MULTI PMC *add(DEFAULT value, PMC *dest) {
357 dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, value));
358 VTABLE_set_number_native(INTERP, dest,
359 SELF.get_integer() + VTABLE_get_number(interp, value));
364 VTABLE PMC *add_int(INTVAL b, PMC *dest) {
365 const INTVAL a = VTABLE_get_integer(INTERP, SELF);
366 const INTVAL c = a + b;
368 if ((c^a) >= 0 || (c^b) >= 0)
369 return Parrot_pmc_new_init_int(INTERP,
370 VTABLE_type(INTERP, SELF), c);
373 maybe_throw_overflow_error(INTERP);
374 temp = Parrot_pmc_new_init_int(INTERP, enum_class_BigInt, a);
375 return VTABLE_add_int(INTERP, temp, b, dest);
382 =item C<void i_add(PMC *value)>
384 =item C<void i_add(INTVAL value)>
386 =item C<void i_add(FLOATVAL value)>
388 Adds C<value> to C<SELF> inplace.
394 MULTI void i_add(Integer value) {
395 STATICSELF.i_add_int(VTABLE_get_integer(INTERP, value));
399 MULTI void i_add(Complex value) {
400 const INTVAL a = SELF.get_integer();
403 Parrot_pmc_reuse(INTERP, SELF, enum_class_Complex, 0);
404 VTABLE_set_number_native(INTERP, SELF,
405 SELF.get_integer() + VTABLE_get_number(INTERP, value));
409 MULTI void i_add(DEFAULT value) {
410 VTABLE_set_number_native(INTERP, SELF,
411 SELF.get_integer() + VTABLE_get_number(INTERP, value));
415 VTABLE void i_add_int(INTVAL b) {
416 const INTVAL a = SELF.get_integer();
417 const INTVAL c = a + b;
419 if ((c^a) >= 0 || (c^b) >= 0)
420 VTABLE_set_integer_native(INTERP, SELF, c);
422 maybe_throw_overflow_error(INTERP);
423 SELF = upgrade_self_to_bignum(INTERP, SELF);
424 VTABLE_i_add_int(INTERP, SELF, b);
429 VTABLE void i_add_float(FLOATVAL value) {
430 const INTVAL a = SELF.get_integer();
431 VTABLE_set_number_native(INTERP, SELF, a + value);
437 =item C<PMC *subtract(PMC *value, PMC *dest)>
439 Subtracts C<*value> from the integer and returns the result in C<*dest>. If
440 C<dest> is NULL, a PMC of this type.
442 Please note: as C<SELF> or C<value> maybe be subclassed, we have to call
443 C<get_integer> and C<set_integer_native> always.
449 MULTI PMC *subtract(Integer value, PMC *dest) {
450 const INTVAL a = SELF.get_integer();
451 const INTVAL b = VTABLE_get_integer(INTERP, value);
452 const INTVAL c = a - b;
454 if ((c^a) >= 0 || (c^~b) >= 0)
455 return Parrot_pmc_new_init_int(INTERP,
456 VTABLE_type(INTERP, SELF), c);
459 maybe_throw_overflow_error(INTERP);
460 temp = Parrot_pmc_new_init_int(INTERP, enum_class_BigInt, a);
461 return VTABLE_subtract(INTERP, temp, value, dest);
466 MULTI PMC *subtract(Complex value, PMC *dest) {
467 const INTVAL a = SELF.get_integer();
468 dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, value));
470 VTABLE_set_number_native(INTERP, dest,
471 a - VTABLE_get_number_keyed_int(INTERP, value, 0));
472 VTABLE_set_number_keyed_int(INTERP, dest, 1,
473 -VTABLE_get_number_keyed_int(INTERP, value, 1));
479 MULTI PMC *subtract(BigInt value, PMC *dest) {
481 maybe_throw_overflow_error(INTERP);
482 temp = Parrot_pmc_new_init_int(INTERP, enum_class_BigInt,
484 return VTABLE_subtract(INTERP, temp, value, dest);
488 MULTI PMC *subtract(DEFAULT value, PMC *dest) {
489 dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, value));
491 VTABLE_set_number_native(INTERP, dest,
492 SELF.get_integer() - VTABLE_get_number(INTERP, value));
499 =item C<PMC *subtract_int(INTVAL value, PMC *dest)>
501 Subtracts C<value> from the integer and returns the result in C<*dest>.
507 VTABLE PMC *subtract_int(INTVAL b, PMC *dest) {
508 const INTVAL a = SELF.get_integer();
509 const INTVAL c = a - b;
511 if ((c^a) >= 0 || (c^~b) >= 0)
512 return Parrot_pmc_new_init_int(INTERP,
513 VTABLE_type(INTERP, SELF), c);
516 maybe_throw_overflow_error(INTERP);
517 temp = Parrot_pmc_new_init_int(INTERP, enum_class_BigInt, a);
518 return VTABLE_subtract_int(INTERP, temp, b, dest);
525 =item C<void i_subtract(PMC *value)>
527 =item C<void i_subtract_int(INTVAL value)>
529 =item C<void i_subtract_float(FLOATVAL value)>
531 Subtracts C<value> from C<SELF> inplace.
537 MULTI void i_subtract(Integer value) {
538 const INTVAL a = SELF.get_integer();
539 const INTVAL b = VTABLE_get_integer(INTERP, value);
540 const INTVAL c = a - b;
542 if ((c^a) >= 0 || (c^~b) >= 0)
543 VTABLE_set_integer_native(INTERP, SELF, c);
545 maybe_throw_overflow_error(INTERP);
546 SELF = upgrade_self_to_bignum(INTERP, SELF);
547 VTABLE_i_subtract(INTERP, SELF, value);
552 MULTI void i_subtract(Complex value) {
553 const INTVAL a = SELF.get_integer();
555 Parrot_pmc_reuse(INTERP, SELF, enum_class_Complex, 0);
556 VTABLE_set_number_native(INTERP, SELF,
557 (FLOATVAL)a - VTABLE_get_number_keyed_int(INTERP, value, 0));
558 VTABLE_set_number_keyed_int(INTERP, SELF, 1,
559 -VTABLE_get_number_keyed_int(INTERP, value, 1));
563 MULTI void i_subtract(DEFAULT value) {
564 VTABLE_set_number_native(INTERP, SELF,
565 SELF.get_integer() - VTABLE_get_number(INTERP, value));
569 VTABLE void i_subtract_int(INTVAL b) {
570 const INTVAL a = SELF.get_integer();
571 const INTVAL c = a - b;
573 if ((c^a) >= 0 || (c^~b) >= 0)
574 VTABLE_set_integer_native(INTERP, SELF, c);
576 maybe_throw_overflow_error(INTERP);
577 SELF = upgrade_self_to_bignum(INTERP, SELF);
578 VTABLE_i_subtract_int(INTERP, SELF, b);
583 VTABLE void i_subtract_float(FLOATVAL value) {
584 const INTVAL a = SELF.get_integer();
585 VTABLE_set_number_native(INTERP, SELF, a - value);
591 =item C<PMC *multiply(PMC *value, PMC *dest)>
593 =item C<PMC *multiply_int(INTVAL value, PMC *dest)>
595 Multiplies the integer by C<*value> and returns the result in C<*dest>.
601 MULTI PMC *multiply(Integer value, PMC *dest) {
602 const INTVAL a = VTABLE_get_integer(INTERP, SELF);
603 const INTVAL b = VTABLE_get_integer(INTERP, value);
604 const INTVAL c = a * b;
605 const double cf = (double)a * (double)b;
607 if ((double) c == cf)
608 return Parrot_pmc_new_init_int(INTERP,
609 VTABLE_type(INTERP, SELF), c);
612 maybe_throw_overflow_error(INTERP);
613 temp = Parrot_pmc_new_init_int(INTERP, enum_class_BigInt, a);
614 return VTABLE_multiply(INTERP, temp, value, dest);
619 MULTI PMC *multiply(Complex value, PMC *dest) {
620 return VTABLE_multiply(INTERP, value, SELF, dest);
624 MULTI PMC *multiply(BigInt value, PMC *dest) {
625 return VTABLE_multiply_int(INTERP, value, SELF.get_integer(), dest);
629 MULTI PMC *multiply(String value, PMC *dest) {
630 return Parrot_Integer_multi_multiply_Integer_PMC(INTERP, SELF, value, dest);
634 MULTI PMC *multiply(DEFAULT value, PMC *dest) {
635 const FLOATVAL valf = VTABLE_get_number(INTERP, value);
636 return Parrot_pmc_new_init_int(INTERP, VTABLE_type(INTERP, SELF),
637 SELF.get_number() * valf);
641 VTABLE PMC *multiply_int(INTVAL b, PMC *dest) {
642 const INTVAL a = SELF.get_integer();
643 const INTVAL c = a * b;
644 const double cf = (double)a * (double)b;
646 if ((double) c == cf)
647 return Parrot_pmc_new_init_int(INTERP,
648 VTABLE_type(INTERP, SELF), c);
651 maybe_throw_overflow_error(INTERP);
652 temp = Parrot_pmc_new_init_int(INTERP, enum_class_BigInt, a);
653 return VTABLE_multiply_int(INTERP, temp, b, dest);
659 =item C<void i_multiply(PMC *value)>
661 =item C<void i_multiply_int(INTVAL value)>
663 =item C<void i_multiply_float(FLOATVAL value)>
665 Multiply C<value> with C<SELF> inplace.
671 MULTI void i_multiply(Integer value) {
672 STATICSELF.i_multiply_int(VTABLE_get_integer(INTERP, value));
676 MULTI void i_multiply(BigInt value) {
677 INTERP->vtables[enum_class_BigInt]->multiply_int(INTERP, value, SELF.get_integer(), SELF);
681 MULTI void i_multiply(Complex value) {
682 VTABLE_multiply(INTERP, value, SELF, SELF);
686 MULTI void i_multiply(DEFAULT value) {
687 VTABLE_set_number_native(INTERP, SELF,
688 SELF.get_integer() * VTABLE_get_number(INTERP, value));
692 VTABLE void i_multiply_int(INTVAL b) {
693 const INTVAL a = SELF.get_integer();
694 const INTVAL c = a * b;
695 const double cf = (double)a * (double)b;
697 if ((double) c == cf)
698 SELF.set_integer_native(c);
700 maybe_throw_overflow_error(INTERP);
701 upgrade_self_to_bignum(INTERP, SELF);
702 VTABLE_i_multiply_int(INTERP, SELF, b);
707 VTABLE void i_multiply_float(FLOATVAL value) {
708 const INTVAL a = SELF.get_integer();
709 VTABLE_set_number_native(INTERP, SELF, a * value);
715 =item C<PMC *divide(PMC *value, PMC *dest)>
717 =item C<PMC *divide_int(INTVAL value, PMC *dest)>
719 =item C<PMC *divide_float(FLOATVAL value, PMC *dest)>
721 Divides the number by C<value> and returns the result in C<*dest>.
723 =item C<void i_divide(PMC *value)>
725 =item C<void i_divide_int(INTVAL value)>
727 =item C<void i_divide_float(FLOATVAL value)>
729 Divides C<SELF> by C<value> inplace.
735 MULTI PMC *divide(BigInt value, PMC *dest) {
737 maybe_throw_overflow_error(INTERP);
738 temp = Parrot_pmc_new_init_int(INTERP, enum_class_BigInt,
740 return VTABLE_divide(INTERP, temp, value, dest);
743 MULTI PMC *divide(DEFAULT value, PMC *dest) {
744 const FLOATVAL d = VTABLE_get_number(INTERP, value);
746 if (FLOAT_IS_ZERO(d))
747 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
748 "float division by zero");
750 return Parrot_pmc_new_init_int(INTERP, VTABLE_type(INTERP, SELF),
751 SELF.get_number() / d);
755 MULTI void i_divide(BigInt value) {
756 maybe_throw_overflow_error(INTERP);
757 SELF = upgrade_self_to_bignum(INTERP, SELF);
758 VTABLE_i_divide(INTERP, SELF, value);
762 MULTI void i_divide(DEFAULT value) {
763 const FLOATVAL d = VTABLE_get_number(INTERP, value);
765 if (FLOAT_IS_ZERO(d))
766 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
767 "float division by zero");
769 VTABLE_set_number_native(INTERP, SELF, SELF.get_number() / d);
775 =item C<PMC *floor_divide(PMC *value, PMC *dest)>
777 =item C<PMC *floor_divide_int(INTVAL value, PMC *dest)>
779 =item C<PMC *floor_divide_float(FLOATVAL value, PMC *dest)>
781 Divides the number by C<value> and returns the result in C<*dest>.
783 =item C<void i_floor_divide(PMC *value)>
785 =item C<void i_floor_divide_int(INTVAL value)>
787 =item C<void i_floor_divide_float(FLOATVAL value)>
789 Divides C<SELF> by C<value> inplace.
795 MULTI PMC *floor_divide(BigInt value, PMC *dest) {
797 maybe_throw_overflow_error(INTERP);
798 temp = Parrot_pmc_new_init_int(INTERP, enum_class_BigInt,
800 return VTABLE_floor_divide(INTERP, temp, value, dest);
804 MULTI PMC *floor_divide(DEFAULT value, PMC *dest) {
805 const FLOATVAL d = VTABLE_get_number(INTERP, value);
808 if (FLOAT_IS_ZERO(d))
809 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
810 "float division by zero");
812 f = floor(SELF.get_number() / d);
813 return Parrot_pmc_new_init_int(INTERP, VTABLE_type(INTERP, SELF),
818 VTABLE PMC *floor_divide_int(INTVAL value, PMC *dest) {
822 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
823 "float division by zero");
825 f = floor(SELF.get_number() / value);
826 return Parrot_pmc_new_init_int(INTERP,
827 VTABLE_type(INTERP, SELF), (INTVAL)f);
830 VTABLE PMC *floor_divide_float(FLOATVAL value, PMC *dest) {
833 if (FLOAT_IS_ZERO(value))
834 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
835 "float division by zero");
837 f = floor(SELF.get_number() / value);
838 return Parrot_pmc_new_init_int(INTERP,
839 VTABLE_type(INTERP, SELF), (INTVAL)f);
842 MULTI void i_floor_divide(BigInt value) {
843 maybe_throw_overflow_error(INTERP);
844 SELF = upgrade_self_to_bignum(INTERP, SELF);
845 VTABLE_i_floor_divide(INTERP, SELF, value);
848 MULTI void i_floor_divide(DEFAULT value) {
849 const FLOATVAL d = VTABLE_get_number(INTERP, value);
852 if (FLOAT_IS_ZERO(d))
853 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
854 "float division by zero");
856 f = floor(SELF.get_number() / d);
857 VTABLE_set_integer_native(INTERP, SELF, (INTVAL)f);
861 VTABLE void i_floor_divide_int(INTVAL value) {
865 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
866 "float division by zero");
868 f = floor(SELF.get_number() / value);
869 VTABLE_set_integer_native(INTERP, SELF, (INTVAL)f);
873 VTABLE void i_floor_divide_float(FLOATVAL value) {
876 if (FLOAT_IS_ZERO(value))
877 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
878 "float division by zero");
880 f = floor(SELF.get_number() / value);
881 VTABLE_set_integer_native(INTERP, SELF, (INTVAL)f);
887 =item C<PMC *modulus(PMC *value, PMC *dest)>
889 =item C<PMC *modulus(INTVAL value, PMC *dest)>
891 =item C<PMC *modulus(FLOATVAL value, PMC *dest)>
893 Calculates the value of corrected C<mod> C<value> and returns
894 the result in C<dest>. See also ops/math.ops.
896 =item C<void i_modulus(PMC *value)>
898 =item C<void i_modulus(INTVAL value)>
900 =item C<void i_modulus(FLOATVAL value)>
902 Calculates modulus in place.
909 MULTI PMC *modulus(BigInt value, PMC *dest) {
911 maybe_throw_overflow_error(INTERP);
912 temp = Parrot_pmc_new_init_int(INTERP, enum_class_BigInt,
914 return VTABLE_modulus(INTERP, temp, value, dest);
918 MULTI PMC *modulus(DEFAULT value, PMC *dest) {
919 const INTVAL d = VTABLE_get_integer(INTERP, value);
922 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
923 "int modulus by zero");
925 return Parrot_pmc_new_init_int(INTERP, VTABLE_type(INTERP, SELF),
926 intval_mod(SELF.get_integer(), d));
930 VTABLE PMC *modulus_int(INTVAL value, PMC *dest) {
932 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
933 "int modulus by zero");
935 return Parrot_pmc_new_init_int(INTERP, VTABLE_type(INTERP, SELF),
936 intval_mod(SELF.get_integer(), value));
940 VTABLE PMC *modulus_float(FLOATVAL value, PMC *dest) {
941 if (FLOAT_IS_ZERO(value))
942 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
943 "int modulus by zero");
945 return Parrot_pmc_new_init_int(INTERP, VTABLE_type(INTERP, SELF),
946 intval_mod(SELF.get_integer(), (INTVAL)value));
950 MULTI void i_modulus(BigInt value) {
951 maybe_throw_overflow_error(INTERP);
952 SELF = upgrade_self_to_bignum(INTERP, SELF);
953 VTABLE_i_modulus(INTERP, SELF, value);
957 MULTI void i_modulus(DEFAULT value) {
958 const INTVAL d = VTABLE_get_integer(INTERP, value);
961 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
962 "int modulus by zero");
964 VTABLE_set_integer_native(INTERP, SELF,
965 intval_mod(SELF.get_integer(), d));
969 VTABLE void i_modulus_int(INTVAL value) {
971 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
972 "int modulus by zero");
974 VTABLE_set_integer_native(INTERP, SELF,
975 intval_mod(SELF.get_integer() , value));
979 VTABLE void i_modulus_float(FLOATVAL value) {
980 if (FLOAT_IS_ZERO(value))
981 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_DIV_BY_ZERO,
982 "int modulus by zero");
984 VTABLE_set_integer_native(INTERP, SELF,
985 intval_mod(SELF.get_integer() , (INTVAL)value));
990 =item C<INTVAL is_equal(PMC *value)>
998 VTABLE INTVAL is_equal(PMC *value) {
1001 switch (value->vtable->base_type) {
1002 case enum_class_BigInt:
1004 PMC const *temp = Parrot_pmc_new_init_int(INTERP, enum_class_BigInt,
1005 SELF.get_integer());
1006 Parrot_mmd_multi_dispatch_from_c_args(INTERP,
1007 "is_equal", "PP->I", temp, value, &retval);
1012 return (VTABLE_get_integer(INTERP, SELF)
1013 == VTABLE_get_integer(INTERP, value));
1021 =item C<INTVAL cmp(PMC *value)>
1023 Returns the result of comparing the integer with C<*value>.
1029 MULTI INTVAL cmp(String value) {
1031 GET_ATTR_iv(INTERP, SELF, iv);
1033 const FLOATVAL fdiff =
1034 (FLOATVAL)iv - VTABLE_get_number(INTERP, value);
1036 if (FLOAT_IS_ZERO(fdiff)) {
1037 const INTVAL idiff =
1038 SELF.get_integer() - VTABLE_get_integer(INTERP, value);
1039 return idiff > 0 ? 1 : idiff < 0 ? -1 : 0;
1042 return fdiff > 0 ? 1 : -1;
1047 MULTI INTVAL cmp(Float value) {
1049 GET_ATTR_iv(INTERP, SELF, iv);
1052 const FLOATVAL diff = (FLOATVAL)iv - VTABLE_get_number(INTERP, value);
1053 return diff > 0 ? 1 : diff < 0 ? -1 : 0;
1058 MULTI INTVAL cmp(DEFAULT value) {
1061 GET_ATTR_iv(INTERP, SELF, selfint);
1063 const INTVAL valueint = VTABLE_get_integer(INTERP, value);
1064 return selfint > valueint ? 1 : selfint < valueint ? -1 : 0;
1071 =item C<INTVAL cmp_num(PMC *value)>
1073 Returns the result of numerically comparing the integer with C<*value>.
1079 MULTI INTVAL cmp_num(String value) {
1080 const FLOATVAL fdiff = SELF.get_number() - VTABLE_get_number(INTERP, value);
1082 if (FLOAT_IS_ZERO(fdiff)) {
1083 const INTVAL idiff =
1084 SELF.get_integer() - VTABLE_get_integer(INTERP, value);
1085 return idiff > 0 ? 1 : idiff < 0 ? -1 : 0;
1088 return fdiff > 0 ? 1 : -1;
1092 MULTI INTVAL cmp_num(Float value) {
1093 const FLOATVAL diff = SELF.get_number() - VTABLE_get_number(INTERP, value);
1094 return diff > 0 ? 1 : diff < 0 ? -1 : 0;
1098 MULTI INTVAL cmp_num(DEFAULT value) {
1100 const INTVAL diff = SELF.get_integer() - VTABLE_get_integer(INTERP, value);
1101 return diff > 0 ? 1 : diff < 0 ? -1 : 0;
1107 =item C<void increment()>
1109 Increments the integer.
1115 VTABLE void increment() {
1117 GET_ATTR_iv(INTERP, SELF, a);
1120 /* did not overflow */
1121 if ((c^a) >= 0 || (c^1) >= 0)
1122 SET_ATTR_iv(INTERP, SELF, c);
1124 Parrot_pmc_reuse(INTERP, SELF, enum_class_BigInt, 0);
1125 VTABLE_set_integer_native(INTERP, SELF, a);
1126 VTABLE_increment(INTERP, SELF);
1133 =item C<void decrement()>
1135 Decrements the integer.
1141 VTABLE void decrement() {
1142 const INTVAL a = SELF.get_integer();
1143 const INTVAL c = a - 1;
1145 if ((c^a) >= 0 || (c^~1) >= 0)
1146 VTABLE_set_integer_native(INTERP, SELF, c);
1148 Parrot_pmc_reuse(INTERP, SELF, enum_class_BigInt, 0);
1149 VTABLE_set_integer_native(INTERP, SELF, a);
1150 VTABLE_decrement(INTERP, SELF);
1157 =item C<PMC *absolute(PMC *dest)>
1159 =item C<void absolute()>
1161 Sets C<dest> to the absolute value of SELF.
1167 VTABLE PMC *absolute(PMC *dest) {
1168 const INTVAL a = abs(SELF.get_integer());
1170 /* TT # 1245 overflow for -maxint */
1171 return Parrot_pmc_new_init_int(INTERP, VTABLE_type(INTERP, SELF), a);
1175 VTABLE void i_absolute() {
1176 const INTVAL a = abs(SELF.get_integer());
1177 VTABLE_set_integer_native(INTERP, SELF, a);
1183 =item C<STRING *get_as_base(INTVAL base)>
1185 Converts and returns the integer in base C<base>. C<base> must be between 2
1192 METHOD get_as_base(INTVAL base) {
1196 if ((base < 2) || (base > 36))
1197 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
1198 "get_as_base: base out of bounds");
1200 result = Parrot_str_from_int_base(INTERP, buf,
1201 (HUGEINTVAL)VTABLE_get_integer(INTERP, SELF),
1202 (unsigned int)base);
1204 RETURN(STRING *result);
1210 =item C<void freeze(PMC *info)>
1212 Used to archive the integer.
1217 VTABLE void freeze(PMC *info) {
1219 VTABLE_push_integer(INTERP, info, SELF.get_integer());
1225 =item C<void thaw(PMC *info)>
1227 Used to unarchive the integer.
1232 VTABLE void thaw(PMC *info) {
1234 SELF.set_integer_native(VTABLE_shift_integer(INTERP, info));
1248 * c-file-style: "parrot"
1250 * vim: expandtab shiftwidth=4: