fix codetest failure - parentheses should not have space immediately
[parrot.git] / src / pmc / integer.pmc
blobe0b95c066f09f68783ad2ab9c059cccf2f97b266
1 /*
2 Copyright (C) 2003-2010, Parrot 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 "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)
36         FUNC_MODIFIES(*self);
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.
54 =cut
58 static void
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,
68             "Integer overflow");
73 =item C<static PMC* upgrade_self_to_bignum(PARROT_INTERP, PMC *self)>
75 Returns a pointer of *self upgraded to a bignum
77 =cut
81 PARROT_IGNORABLE_RESULT
82 PARROT_CANNOT_RETURN_NULL
83 static PMC*
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);
93     return self;
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.
105 =item C<void init()>
107 Initializes the integer with a default value of C<0>.
109 =cut
113     VTABLE void init() {
114         Parrot_Integer_attributes * const attrs =
115             (Parrot_Integer_attributes *)PMC_data(SELF);
117         attrs->iv      = 0;
118     }
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);
125     }
127     VTABLE void init_int(INTVAL init) {
128         Parrot_Integer_attributes * const attrs =
129             (Parrot_Integer_attributes *)PMC_data(SELF);
131         attrs->iv = init;
132     }
136 =item C<PMC *clone()>
138 Creates an exact duplicate of this PMC.
140 =cut
143     VTABLE PMC *clone() {
144         return Parrot_pmc_new_init_int(INTERP, SELF->vtable->base_type,
145             SELF.get_integer());
146     }
150 =item C<void set_pmc(PMC *value)>
152 Sets the value of the integer to the value in C<*value>.
154 =cut
158     VTABLE void set_pmc(PMC *value) {
159         SELF.set_integer_native(VTABLE_get_integer(INTERP, value));
160     }
165 =item C<void share()>
167 Sets this PMC as shared and read-only.
169 =cut
173     VTABLE void share() {
174         /*
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.
181          */
182         if (sizeof (INTVAL) != sizeof (long))
183             SUPER();
184     }
189 =item C<INTVAL get_integer()>
191 Returns the integer value of the Integer.
193 =cut
197     VTABLE INTVAL get_integer() {
198         INTVAL iv;
199         GET_ATTR_iv(INTERP, SELF, iv);
200         return iv;
201     }
206 =item C<INTVAL get_bool()>
208 Returns the boolean value of the Integer.
210 =cut
213     VTABLE INTVAL get_bool() {
214         INTVAL iv;
215         GET_ATTR_iv(INTERP, SELF, iv);
216         return iv ? 1 : 0;
217     }
222 =item C<FLOATVAL get_number()>
224 Returns the floating-point value of the integer.
226 =cut
229     VTABLE FLOATVAL get_number() {
230         INTVAL iv;
231         GET_ATTR_iv(INTERP, SELF, iv);
232         return (FLOATVAL)iv;
233     }
238 =item C<STRING *get_string()>
240 =item C<STRING *get_repr()>
242 Returns the string value of the integer.
244 =cut
247     VTABLE STRING *get_string() {
248         return Parrot_str_from_int(INTERP, SELF.get_integer());
249     }
251     VTABLE STRING *get_repr() {
252         return Parrot_str_from_int(INTERP, SELF.get_integer());
253     }
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>.
262 =cut
266     VTABLE void set_integer_native(INTVAL value) {
267         SET_ATTR_iv(INTERP, SELF, value);
268     }
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>.
284 =cut
288     VTABLE void set_number_native(FLOATVAL value) {
289         Parrot_pmc_reuse(INTERP, SELF, enum_class_Float, 0);
290         SELF.set_number_native(value);
291     }
294     VTABLE void set_bool(INTVAL value) {
295         Parrot_pmc_reuse(INTERP, SELF, enum_class_Boolean, 0);
296         SELF.set_bool(value);
297     }
301     VTABLE void set_string_native(STRING *value) {
302         Parrot_pmc_reuse(INTERP, SELF, enum_class_String, 0);
303         SELF.set_string_native(value);
304     }
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>.
314 =cut
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);
326         else {
327             PMC *temp;
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);
331         }
332     }
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));
343         return dest;
344     }
347     MULTI PMC *add(BigInt value, PMC *dest) {
348         PMC *temp;
349         maybe_throw_overflow_error(INTERP);
350         temp = Parrot_pmc_new_init_int(INTERP, enum_class_BigInt,
351                 SELF.get_integer());
352         return VTABLE_add(INTERP, temp, value, dest);
353     }
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));
360         return dest;
361     }
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);
371         else {
372             PMC *temp;
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);
376         }
377     }
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.
390 =cut
394     MULTI void i_add(Integer value) {
395         STATICSELF.i_add_int(VTABLE_get_integer(INTERP, value));
396     }
399     MULTI void i_add(Complex value) {
400         const INTVAL a = SELF.get_integer();
401         UNUSED(a);
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));
406     }
409     MULTI void i_add(DEFAULT value) {
410         VTABLE_set_number_native(INTERP, SELF,
411                 SELF.get_integer() + VTABLE_get_number(INTERP, value));
412     }
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);
421         else {
422             maybe_throw_overflow_error(INTERP);
423             SELF = upgrade_self_to_bignum(INTERP, SELF);
424             VTABLE_i_add_int(INTERP, SELF, b);
425         }
426     }
429     VTABLE void i_add_float(FLOATVAL value) {
430         const INTVAL a = SELF.get_integer();
431         VTABLE_set_number_native(INTERP, SELF, a + value);
432     }
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.
445 =cut
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);
457         else {
458             PMC *temp;
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);
462         }
463     }
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));
475         return dest;
476     }
479     MULTI PMC *subtract(BigInt value, PMC *dest) {
480         PMC *temp;
481         maybe_throw_overflow_error(INTERP);
482         temp = Parrot_pmc_new_init_int(INTERP, enum_class_BigInt,
483                  SELF.get_integer());
484         return VTABLE_subtract(INTERP, temp, value, dest);
485     }
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));
493         return dest;
494     }
499 =item C<PMC *subtract_int(INTVAL value, PMC *dest)>
501 Subtracts C<value> from the integer and returns the result in C<*dest>.
503 =cut
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);
514         else {
515             PMC *temp;
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);
519         }
520     }
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.
533 =cut
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);
544         else {
545             maybe_throw_overflow_error(INTERP);
546             SELF = upgrade_self_to_bignum(INTERP, SELF);
547             VTABLE_i_subtract(INTERP, SELF, value);
548         }
549     }
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));
560     }
563     MULTI void i_subtract(DEFAULT value) {
564         VTABLE_set_number_native(INTERP, SELF,
565                 SELF.get_integer() - VTABLE_get_number(INTERP, value));
566     }
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);
575         else {
576             maybe_throw_overflow_error(INTERP);
577             SELF = upgrade_self_to_bignum(INTERP, SELF);
578             VTABLE_i_subtract_int(INTERP, SELF, b);
579         }
580     }
583     VTABLE void i_subtract_float(FLOATVAL value) {
584         const INTVAL a = SELF.get_integer();
585         VTABLE_set_number_native(INTERP, SELF, a - value);
586     }
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>.
597 =cut
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);
610         else {
611             PMC *temp;
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);
615         }
616     }
619     MULTI PMC *multiply(Complex value, PMC *dest) {
620         return VTABLE_multiply(INTERP, value, SELF, dest);
621     }
624     MULTI PMC *multiply(BigInt value, PMC *dest) {
625         return VTABLE_multiply_int(INTERP, value, SELF.get_integer(), dest);
626     }
629     MULTI PMC *multiply(String value, PMC *dest) {
630         return Parrot_Integer_multi_multiply_Integer_PMC(INTERP, SELF, value, dest);
631     }
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);
638     }
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);
649         else {
650             PMC *temp;
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);
654         }
655     }
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.
667 =cut
671     MULTI void i_multiply(Integer value) {
672         STATICSELF.i_multiply_int(VTABLE_get_integer(INTERP, value));
673     }
676     MULTI void i_multiply(BigInt value) {
677         INTERP->vtables[enum_class_BigInt]->multiply_int(INTERP, value, SELF.get_integer(), SELF);
678     }
681     MULTI void i_multiply(Complex value) {
682         VTABLE_multiply(INTERP, value, SELF, SELF);
683     }
686     MULTI void i_multiply(DEFAULT value) {
687         VTABLE_set_number_native(INTERP, SELF,
688                 SELF.get_integer() * VTABLE_get_number(INTERP, value));
689     }
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);
699         else {
700             maybe_throw_overflow_error(INTERP);
701             upgrade_self_to_bignum(INTERP, SELF);
702             VTABLE_i_multiply_int(INTERP, SELF, b);
703         }
704     }
707     VTABLE void i_multiply_float(FLOATVAL value) {
708         const INTVAL a = SELF.get_integer();
709         VTABLE_set_number_native(INTERP, SELF, a * value);
710     }
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.
731 =cut
735     MULTI PMC *divide(BigInt value, PMC *dest) {
736         PMC *temp;
737         maybe_throw_overflow_error(INTERP);
738         temp = Parrot_pmc_new_init_int(INTERP, enum_class_BigInt,
739             SELF.get_integer());
740         return VTABLE_divide(INTERP, temp, value, dest);
741     }
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);
752     }
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);
759     }
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);
770     }
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.
791 =cut
795     MULTI PMC *floor_divide(BigInt value, PMC *dest) {
796         PMC *temp;
797         maybe_throw_overflow_error(INTERP);
798         temp = Parrot_pmc_new_init_int(INTERP, enum_class_BigInt,
799                 SELF.get_integer());
800         return VTABLE_floor_divide(INTERP, temp, value, dest);
801     }
804     MULTI PMC *floor_divide(DEFAULT value, PMC *dest) {
805         const FLOATVAL d = VTABLE_get_number(INTERP, value);
806         FLOATVAL f;
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),
814             (INTVAL)f);
815     }
818     VTABLE PMC *floor_divide_int(INTVAL value, PMC *dest) {
819         FLOATVAL f;
821         if (value == 0)
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);
828     }
830     VTABLE PMC *floor_divide_float(FLOATVAL value, PMC *dest) {
831         FLOATVAL f;
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);
840     }
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);
846     }
848     MULTI void i_floor_divide(DEFAULT value) {
849         const FLOATVAL d = VTABLE_get_number(INTERP, value);
850         FLOATVAL f;
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);
858     }
861     VTABLE void i_floor_divide_int(INTVAL value) {
862         FLOATVAL f;
864         if (value == 0)
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);
870     }
873     VTABLE void i_floor_divide_float(FLOATVAL value) {
874         FLOATVAL f;
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);
882     }
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.
904 =cut
909     MULTI PMC *modulus(BigInt value, PMC *dest) {
910         PMC *temp;
911         maybe_throw_overflow_error(INTERP);
912         temp = Parrot_pmc_new_init_int(INTERP, enum_class_BigInt,
913              SELF.get_integer());
914         return VTABLE_modulus(INTERP, temp, value, dest);
915     }
918     MULTI PMC *modulus(DEFAULT value, PMC *dest) {
919         const INTVAL d = VTABLE_get_integer(INTERP, value);
921         if (d == 0)
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));
927     }
930     VTABLE PMC *modulus_int(INTVAL value, PMC *dest) {
931         if (value == 0)
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));
937     }
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));
947     }
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);
954     }
957     MULTI void i_modulus(DEFAULT value) {
958         const INTVAL d = VTABLE_get_integer(INTERP, value);
960         if (d == 0)
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));
966     }
969     VTABLE void i_modulus_int(INTVAL value) {
970         if (value == 0)
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));
976     }
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));
986     }
990 =item C<INTVAL is_equal(PMC *value)>
992 The C<==> operation.
994 =cut
998     VTABLE INTVAL is_equal(PMC *value) {
999         INTVAL retval;
1001         switch (value->vtable->base_type) {
1002           case enum_class_BigInt:
1003           {
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);
1008             return retval;
1009           }
1010             break;
1011           default:
1012             return (VTABLE_get_integer(INTERP, SELF)
1013                 ==  VTABLE_get_integer(INTERP, value));
1014             break;
1015         }
1016     }
1021 =item C<INTVAL cmp(PMC *value)>
1023 Returns the result of comparing the integer with C<*value>.
1025 =cut
1029     MULTI INTVAL cmp(String value) {
1030         INTVAL iv;
1031         GET_ATTR_iv(INTERP, SELF, iv);
1032         {
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;
1040             }
1042             return fdiff > 0 ? 1 : -1;
1043         }
1044     }
1047     MULTI INTVAL cmp(Float value) {
1048         INTVAL iv;
1049         GET_ATTR_iv(INTERP, SELF, iv);
1051         {
1052             const FLOATVAL diff = (FLOATVAL)iv - VTABLE_get_number(INTERP, value);
1053             return diff > 0 ? 1 : diff < 0 ? -1 : 0;
1054         }
1055     }
1058     MULTI INTVAL cmp(DEFAULT value) {
1059         /* int or undef */
1060         INTVAL selfint;
1061         GET_ATTR_iv(INTERP, SELF, selfint);
1062         {
1063             const INTVAL valueint = VTABLE_get_integer(INTERP, value);
1064             return selfint > valueint ? 1 : selfint < valueint ? -1 : 0;
1065         }
1066     }
1071 =item C<INTVAL cmp_num(PMC *value)>
1073 Returns the result of numerically comparing the integer with C<*value>.
1075 =cut
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;
1086         }
1088         return fdiff > 0 ? 1 : -1;
1089     }
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;
1095     }
1098     MULTI INTVAL cmp_num(DEFAULT value) {
1099         /* int or undef */
1100         const INTVAL diff = SELF.get_integer() - VTABLE_get_integer(INTERP, value);
1101         return diff > 0 ? 1 : diff < 0 ? -1 : 0;
1102     }
1107 =item C<void increment()>
1109 Increments the integer.
1111 =cut
1115     VTABLE void increment() {
1116         INTVAL a, c;
1117         GET_ATTR_iv(INTERP, SELF, a);
1118         c = a + 1;
1120         /* did not overflow */
1121         if ((c^a) >= 0 || (c^1) >= 0)
1122             SET_ATTR_iv(INTERP, SELF, c);
1123         else {
1124             Parrot_pmc_reuse(INTERP, SELF, enum_class_BigInt, 0);
1125             VTABLE_set_integer_native(INTERP, SELF, a);
1126             VTABLE_increment(INTERP, SELF);
1127         }
1128     }
1133 =item C<void decrement()>
1135 Decrements the integer.
1137 =cut
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);
1147         else {
1148             Parrot_pmc_reuse(INTERP, SELF, enum_class_BigInt, 0);
1149             VTABLE_set_integer_native(INTERP, SELF, a);
1150             VTABLE_decrement(INTERP, SELF);
1151         }
1152     }
1157 =item C<PMC *absolute(PMC *dest)>
1159 =item C<void absolute()>
1161 Sets C<dest> to the absolute value of SELF.
1163 =cut
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);
1172     }
1175     VTABLE void i_absolute() {
1176         const INTVAL a = abs(SELF.get_integer());
1177         VTABLE_set_integer_native(INTERP, SELF, a);
1178     }
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
1186 and 36, inclusive.
1188 =cut
1192     METHOD get_as_base(INTVAL base) {
1193         char buf[128];
1194         STRING *result;
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);
1205     }
1210 =item C<void freeze(PMC *info)>
1212 Used to archive the integer.
1214 =cut
1217     VTABLE void freeze(PMC *info) {
1218         SUPER(info);
1219         VTABLE_push_integer(INTERP, info, SELF.get_integer());
1220     }
1225 =item C<void thaw(PMC *info)>
1227 Used to unarchive the integer.
1229 =cut
1232     VTABLE void thaw(PMC *info) {
1233         SUPER(info);
1234         SELF.set_integer_native(VTABLE_shift_integer(INTERP, info));
1235     }
1240 =back
1242 =cut
1247  * Local variables:
1248  *   c-file-style: "parrot"
1249  * End:
1250  * vim: expandtab shiftwidth=4:
1251  */