tagged release 0.7.1
[parrot.git] / src / dynpmc / rational.pmc
blob173653fae268b032945be49b2510285c9c7cb0c6
1 /*
2 Copyright (C) 2008, The Perl Foundation.
3 $Id$
5 =pod
7 =head1 NAME
9 src/dynpmc/rational.pmc - Rational numbers PMC
11 =head1 DESCRIPTION
13 Rational is currently going to get implemented. It uses the GNU Multiple Precision (GMP) library,
14 like BigInt, because implementation with integers would be too unstable and inaccurate.
16 'LispRational' will subclass this.
18 You may use Rational with any of parrot's basic data types as well as with String-, Integer- and
19 Float-PMCs.
21 =head1 Functions
23 Currently C<rational.pmc> only has some C<static> functions for code sharing.
25 =over 4
27 =cut
31 #include "parrot/has_header.h"
33 #ifdef PARROT_HAS_GMP
34 #  include <gmp.h>
35    typedef struct RATIONAL {
36       mpq_t q;
37    } RATIONAL;
38 #  define RT(x)         ((RATIONAL*) PMC_struct_val(x))->q
39 #else
40 #  define RT(x)
41 #endif
43 #define RAISE_EXCEPTION   Parrot_ex_throw_from_c_args(interp, NULL, \
44     EXCEPTION_LIBRARY_NOT_LOADED, "GNU Multiple Precision library not found.");
48 =item * static STRING *rat_get_string_to_base(PARROT_INTERP, PMC *self, int base)
50 Returns a string representation of a Rational-PMC to a certain base.
52 =cut
55 static STRING *rat_get_string_to_base(PARROT_INTERP, PMC *self, int base) {
56   #ifdef PARROT_HAS_GMP
57     STRING *pstr;
58     char *cstr = mpq_get_str(NULL, (int) base, RT(self));
59     pstr = string_from_cstring(interp, cstr, 0);
60     string_cstring_free(cstr);
61     return pstr;
62   #else
63     RAISE_EXCEPTION
64   #endif
69 =item * static void rat_add_integer(PARROT_INTERP, PMC *self, int value, PMC *dest)
71 Adds an integer "value" to a Rational-PMC and stores the result in (another) Rational-PMC.
73 =cut
76 static void rat_add_integer(PARROT_INTERP, PMC *self, int value, PMC *dest) {
77   #ifdef PARROT_HAS_GMP
78     mpq_t t;
80     if (dest) {
81         if (self != dest)
82             VTABLE_morph(interp, dest, self->vtable->base_type);
83     }
84     else {
85         dest = pmc_new(interp, self->vtable->base_type);
86     }
88     mpq_init(t);
89     mpq_set_si(t, (int) value, 1);
90     mpq_add(RT(dest), RT(self), t);
91     mpq_clear(t);
92   #else
93     RAISE_EXCEPTION
94   #endif
99 =item * static void rat_add_float(PARROT_INTERP, PMC *self, double value, PMC *dest)
101 Adds a float "value" to a Rational-PMC and stores the result in (another) Rational-PMC. "value" is
102 first conveted to a rational using GMPs mpq_set_d-function. This is meant to be exact.
104 =cut
107 static void rat_add_float(PARROT_INTERP, PMC *self, double value, PMC *dest) {
108   #ifdef PARROT_HAS_GMP
109     mpq_t t;
111     if (dest)
112         VTABLE_morph(interp, dest, self->vtable->base_type);
113     else
114         dest = pmc_new(interp, self->vtable->base_type);
116     mpq_init(t);
117     mpq_set_d(t, (double) value);
118     mpq_add(RT(dest), RT(self), t);
119     mpq_clear(t);
120   #else
121     RAISE_EXCEPTION
122   #endif
127 =item * static void rat_multiply_integer(PARROT_INTERP, PMC *self, int value, PMC *dest)
129 Multiplys a Rational-PMC with an integer "value" and stores the result in (another) Rational-PMC.
131 =cut
134 static void rat_multiply_integer(PARROT_INTERP, PMC *self, int value, PMC *dest) {
135   #ifdef PARROT_HAS_GMP
136     if (dest)
137         VTABLE_morph(interp, dest, self->vtable->base_type);
138     else
139         dest = pmc_new(interp, self->vtable->base_type);
141     mpz_mul_ui(mpq_numref(RT(dest)), mpq_numref(RT(self)), (unsigned int) value);
142     mpq_set_den(RT(dest), mpq_denref(RT(self)));
143   #else
144     RAISE_EXCEPTION
145   #endif
150 =item * static void rat_multiply_float(PARROT_INTERP, PMC *self, double value, PMC *dest)
152 Multiplies a Rational-PMC with a float "value" and stores the result in (another) Rational-PMC.
154 =cut
157 static void rat_multiply_float(PARROT_INTERP, PMC *self, double value, PMC *dest) {
158   #ifdef PARROT_HAS_GMP
159     mpq_t t;
161     if (dest)
162         VTABLE_morph(interp, dest, self->vtable->base_type);
163     else
164         dest = pmc_new(interp, self->vtable->base_type);
166     mpq_init(t);
167     mpq_set_d(t, (double) value);
168     mpq_mul(RT(dest), RT(self), t);
169     mpq_clear(t);
170   #else
171     RAISE_EXCEPTION
172   #endif
177 =item * static void rat_divide_integer(PARROT_INTERP, PMC *self, int value, PMC *dest)
179 Divides a Rational-PMC through an integer "value" and stores the result in (another) Rational-PMC.
181 =cut
184 static void rat_divide_integer(PARROT_INTERP, PMC *self, int value, PMC *dest) {
185   #ifdef PARROT_HAS_GMP
186     mpq_t t;
188     if (dest)
189         VTABLE_morph(interp, dest, self->vtable->base_type);
190     else
191         dest = pmc_new(interp, self->vtable->base_type);
193     mpq_init(t);
194     mpq_set_si(t, (int) value, 1);
195     mpq_div(RT(dest), RT(self), t);
196     mpq_clear(t);
197   #else
198     RAISE_EXCEPTION
199   #endif
204 =item * static void rat_divide_float(PARROT_INTERP, PMC *self, double value, PMC *dest)
206 Divides a Rational-PMC through a float "value" and stores the result in (another) Rational-PMC.
208 =cut
211 static void rat_divide_float(PARROT_INTERP, PMC *self, double value, PMC *dest) {
212   #ifdef PARROT_HAS_GMP
213     mpq_t t;
215     if (dest)
216         VTABLE_morph(interp, dest, self->vtable->base_type);
217     else
218         dest = pmc_new(interp, self->vtable->base_type);
220     mpq_init(t);
221     mpq_set_d(t, (double) value);
222     mpq_div(RT(dest), RT(self), t);
223     mpq_clear(t);
224   #else
225     RAISE_EXCEPTION
226   #endif
231 =item * static void rat_power_int(PARROT_INTERP, PMC *self, int value, PMC *dest)
233 Calculates the power of a Rational-PMC to an exponent value and stores the result in (another)
234 Rational-PMC.
236 =cut
239 static void rat_power_int(PARROT_INTERP, PMC *self, int value, PMC *dest) {
240   #ifdef PARROT_HAS_GMP
241     mpz_t t;
243     if (dest)
244         VTABLE_morph(interp, dest, self->vtable->base_type);
245     else
246         dest = pmc_new(interp, self->vtable->base_type);
248     mpq_get_num(t, RT(self));
249     mpz_pow_ui(t, t, (unsigned int) value);
250     mpq_set_num(RT(dest), t);
251     mpz_clear(t);
253     mpq_get_den(t, RT(self));
254     mpz_pow_ui(t, t, (unsigned int) value);
255     mpq_set_den(RT(dest), t);
256     mpz_clear(t);
257   #else
258     RAISE_EXCEPTION
259   #endif
264 =back
266 =cut
270 pmclass Rational dynpmc provides scalar {
273 =head2 Methods
275 The DynPMC Rational has the following methods. Note, that all methods depend on GMP. If GMP is not
276 available, an exception is thrown in almost all cases. The only exception is the version-method.
278 =over 4
280 =item C<METHOD version()>
282 Returns the version of GNU Multiple Precision library. Returns 0.0.0, if GMP is not available.
284 =cut
287     METHOD version() {
288         STRING *version;
289       #ifdef PARROT_HAS_GMP
290         version = string_from_cstring(INTERP, gmp_version, 0);
291       #else
292         version = string_from_cstring(INTERP, "0.0.0", 0);
293       #endif
294         RETURN(STRING *version);
295     }
299 =item C<void init()>
301 =cut
304     VTABLE void init() {
305       #ifdef PARROT_HAS_GMP
306         PMC_struct_val(SELF) = malloc(sizeof (RATIONAL));
307         mpq_init(RT(SELF));
308         PObj_active_destroy_SET(SELF);
309       #else
310         PMC_struct_val(SELF) = NULL;
311       #endif
312     }
316 =item C<void clone()>
318 =cut
321     VTABLE PMC *clone() {
322       #ifdef PARROT_HAS_GMP
323         mpz_t num, den;
324         PMC *ret = pmc_new(INTERP, SELF->vtable->base_type);
325         mpq_get_num(num, RT(SELF));
326         mpq_get_den(den, RT(SELF));
327         mpq_set_num(RT(ret), num);
328         mpq_set_den(RT(ret), den);
329         mpz_clear(num);
330         mpz_clear(den);
331         return ret;
332       #else
333         RAISE_EXCEPTION
334       #endif
335     }
339 =item C<void destroy()>
341 =cut
344     VTABLE void destroy() {
345       #ifdef PARROT_HAS_GMP
346         mpq_clear(RT(SELF));
347         mem_sys_free(PMC_struct_val(SELF));
348       #else
349         RAISE_EXCEPTION
350       #endif
351     }
355 =item C<void set_integer_native(INTVAL)>
357 =cut
360     VTABLE void set_integer_native(INTVAL value) {
361       #ifdef PARROT_HAS_GMP
362         mpq_set_si(RT(SELF), (signed int) value, 1);
363         mpq_canonicalize(RT(SELF));
364       #else
365         RAISE_EXCEPTION
366       #endif
367     }
371 =item C<void set_number_native(FLOATVAL)>
373 =cut
376     VTABLE void set_number_native(FLOATVAL value) {
377       #ifdef PARROT_HAS_GMP
378         mpq_set_d(RT(SELF), (double) value);
379         mpq_canonicalize(RT(SELF));
380       #else
381         RAISE_EXCEPTION
382       #endif
383     }
387 =item C<void set_string_native(STRING*)>
389 =cut
392     VTABLE void set_string_native(STRING *value) {
393       #ifdef PARROT_HAS_GMP
394         char *cstr = string_to_cstring(INTERP, value);
395         mpq_set_str(RT(SELF), cstr, 0);
396         mpq_canonicalize(RT(SELF));
397         string_cstring_free(cstr);
398       #else
399         RAISE_EXCEPTION
400       #endif
401     }
405 =item C<void set_string_keyed_int(INTVAL base, STRING *value)>
407 =cut
410     VTABLE void set_string_keyed_int(INTVAL base, STRING *value) {
411       #ifdef PARROT_HAS_GMP
412         char *cstr = string_to_cstring(INTERP, value);
413         mpq_set_str(RT(SELF), cstr, (int) base);
414         mpq_canonicalize(RT(SELF));
415         string_cstring_free(cstr);
416       #else
417         RAISE_EXCEPTION
418       #endif
419     }
424 =item C<INTVAL get_integer()>
426 =cut
429     VTABLE INTVAL get_integer() {
430       #ifdef PARROT_HAS_GMP
431         mpz_t q;
432         mpz_init(q);
433         mpz_tdiv_q(q, mpq_numref(RT(SELF)), mpq_denref(RT(SELF)));
434         if (mpz_fits_slong_p(q)) {
435             INTVAL ret = (INTVAL) mpz_get_si(q);
436             mpz_clear(q);
437             return ret;
438         }
439         else {
440             mpz_clear(q);
441             Parrot_ex_throw_from_c_args(INTERP, NULL, 1,
442                 "Rational, get_integer(): Number is too big.");
443         }
444       #else
445         RAISE_EXCEPTION
446       #endif
447     }
451 =item C<get_number()>
453 =cut
456     VTABLE FLOATVAL get_number() {
457       #ifdef PARROT_HAS_GMP
458         double d;
459         d = mpq_get_d(RT(SELF));
460         return (FLOATVAL) d;
461       #else
462         RAISE_EXCEPTION
463       #endif
464     }
468 =item C<get_bool()>
470 =cut
473     VTABLE INTVAL get_bool() {
474       #ifdef PARROT_HAS_GMP
475         if (mpq_cmp_si(RT(SELF), 0, 0))
476             return 0;
477         else
478             return 1;
479       #else
480         RAISE_EXCEPTION
481       #endif
482     }
485 =item C<STRING *get_string()>
487 =cut
490     VTABLE STRING *get_string() {
491       #ifdef PARROT_HAS_GMP
492         return rat_get_string_to_base(INTERP, SELF, 10);
493       #else
494         RAISE_EXCEPTION
495       #endif
496     }
500 =item C<STRING *get_string_keyed_int(INTVAL base)>
502 =cut
505     VTABLE STRING *get_string_keyed_int(INTVAL base) {
506       #ifdef PARROT_HAS_GMP
507         return rat_get_string_to_base(INTERP, SELF, (int) base);
508       #else
509         RAISE_EXCEPTION
510       #endif
511     }
515 =item C<void increment()>
517 =cut
520     VTABLE void increment() {
521       #ifdef PARROT_HAS_GMP
522         mpz_add(mpq_numref(RT(SELF)), mpq_numref(RT(SELF)), mpq_denref(RT(SELF)));
523         mpq_canonicalize(RT(SELF));
524       #else
525         RAISE_EXCEPTION
526       #endif
527     }
531 =item C<void decrement()>
533 =cut
536     VTABLE void decrement() {
537       #ifdef PARROT_HAS_GMP
538         mpz_sub(mpq_numref(RT(SELF)), mpq_numref(RT(SELF)), mpq_denref(RT(SELF)));
539         mpq_canonicalize(RT(SELF));
540       #else
541         RAISE_EXCEPTION
542       #endif
543     }
547 =item C<PMC *add(PMC* value, PMC* dest)>
549 Adds Integer-, Float- or Rational-PMCs to SELF and stores them in dest.
551 =cut
554     VTABLE PMC *add(PMC* value, PMC* dest) {
555 MMD_Integer: {
556         rat_add_integer(INTERP, SELF, PMC_int_val(value), dest);
557         return dest;
558         }
559 MMD_Float: {
560         rat_add_float(INTERP, SELF, PMC_num_val(value), dest);
561         return dest;
562         }
563 MMD_Rational: {
564       #ifdef PARROT_HAS_GMP
565         if (dest)
566             VTABLE_morph(INTERP, dest, SELF->vtable->base_type);
567         else
568             dest = pmc_new(INTERP, SELF->vtable->base_type);
570         mpq_add(RT(dest), RT(SELF), RT(value));
571         return dest;
572       #else
573         RAISE_EXCEPTION
574       #endif
575         }
576 MMD_DEFAULT: {
577     Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_UNIMPLEMENTED,
578         "Rational, add: Not implemented (yet).");
579         }
580     }
584 =item C<void i_add(PMC *value)>
586 =cut
589     VTABLE void i_add(PMC *value) {
590 MMD_Integer: {
591         rat_add_integer(INTERP, SELF, (int) PMC_int_val(value), SELF);
592         }
593 MMD_Float: {
594         rat_add_float(INTERP, SELF, (double) PMC_num_val(value), SELF);
595         }
596 MMD_Rational: {
597       #ifdef PARROT_HAS_GMP
598         mpq_add(RT(SELF), RT(SELF), RT(value));
599       #else
600         RAISE_EXCEPTION
601       #endif
602         }
603 MMD_DEFAULT: {
604     Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_UNIMPLEMENTED,
605         "Rational, i_add: Not implemented (yet).");
606         }
607     }
611 =item C<PMC *add_int(INTVAL value, PMC* dest)>
613 =cut
616     VTABLE PMC *add_int(INTVAL value, PMC* dest) {
617         rat_add_integer(INTERP, SELF, (int) value, dest);
618         return dest;
619     }
623 =item C<void i_add_int(INTVAL value)>
625 =cut
628     VTABLE void i_add_int(INTVAL value) {
629         rat_add_integer(INTERP, SELF, (int) value, SELF);
630     }
634 =item C<PMC *add_float(FLOATVAL value, PMC* dest)>
636 =cut
639     VTABLE PMC *add_float(FLOATVAL value, PMC* dest) {
640         rat_add_float(INTERP, SELF, (double) value, dest);
641         return dest;
642     }
646 =item C<void i_add_float(FLOATVAL value)>
648 =cut
651     VTABLE void i_add_float(FLOATVAL value) {
652         rat_add_float(INTERP, SELF, (double) value, SELF);
653     }
657 =item C<PMC *subtract(PMC* value, PMC* dest)>
659 =cut
662     VTABLE PMC *subtract(PMC* value, PMC* dest) {
663 MMD_Integer: {
664         rat_add_integer(INTERP, SELF, -((int) PMC_int_val(value)), dest);
665         return dest;
666         }
667 MMD_Float: {
668         rat_add_float(INTERP, SELF, - ((double) PMC_num_val(value)), dest);
669         return dest;
670         }
671 MMD_Rational: {
672       #ifdef PARROT_HAS_GMP
673         if (dest)
674             VTABLE_morph(INTERP, dest, SELF->vtable->base_type);
675         else
676             dest = pmc_new(INTERP, SELF->vtable->base_type);
678         mpq_sub(RT(dest), RT(SELF), RT(value));
679         return dest;
680       #else
681         RAISE_EXCEPTION
682       #endif
683         }
684 MMD_DEFAULT: {
685     Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_UNIMPLEMENTED,
686         "Rational, subtract: Not implemented (yet).");
687         }
688     }
692 =item C<void i_subtract(PMC *value)>
694 =cut
697     VTABLE void i_subtract(PMC *value) {
698 MMD_Integer: {
699         rat_add_integer(INTERP, SELF, -((int) PMC_int_val(value)), SELF);
700         }
701 MMD_Float: {
702         rat_add_float(INTERP, SELF, - ((double) PMC_num_val(value)), SELF);
703         }
704 MMD_Rational: {
705       #ifdef PARROT_HAS_GMP
706         mpq_sub(RT(SELF), RT(SELF), RT(value));
707       #else
708         RAISE_EXCEPTION
709       #endif
710         }
711 MMD_DEFAULT: {
712     Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_UNIMPLEMENTED,
713         "Rational, i_subtract: Not implemented (yet).");
714         }
715     }
719 =item C<PMC *subtract_int(INTVAL value, PMC* dest)>
721 =cut
724     VTABLE PMC *subtract_int(INTVAL value, PMC* dest) {
725         rat_add_integer(INTERP, SELF, -((int) value), dest);
726         return dest;
727     }
731 =item C<void i_subtract_int(INTVAL value)>
733 =cut
736     VTABLE void i_subtract_int(INTVAL value) {
737         rat_add_integer(INTERP, SELF, -((int) value), SELF);
738     }
742 =item C<PMC *subtract_float(FLOATVAL value, PMC* dest)>
744 =cut
747     VTABLE PMC *subtract_float(FLOATVAL value, PMC* dest) {
748         rat_add_float(INTERP, SELF, -((double) value), dest);
749         return dest;
750     }
754 =item C<void i_subtract_float(FLOATVAL value)>
756 =cut
759     VTABLE void i_subtract_float(FLOATVAL value) {
760         rat_add_float(INTERP, SELF, -((double) value), SELF);
761     }
765 =item C<PMC *multiply(PMC* value, PMC* dest)>
767 =cut
770     VTABLE PMC *multiply(PMC* value, PMC* dest) {
771 MMD_Integer: {
772         rat_multiply_integer(INTERP, SELF, (int) PMC_int_val(value), dest);
773         return dest;
774         }
775 MMD_Float: {
776         rat_multiply_float(INTERP, SELF, (double) PMC_num_val(value), dest);
777         return dest;
778         }
779 MMD_Rational: {
780       #ifdef PARROT_HAS_GMP
781         if (dest)
782             VTABLE_morph(INTERP, dest, SELF->vtable->base_type);
783         else
784             dest = pmc_new(INTERP, SELF->vtable->base_type);
786         mpq_mul(RT(dest), RT(SELF), RT(value));
787         return dest;
788       #else
789         RAISE_EXCEPTION
790       #endif
791         }
792 MMD_DEFAULT: {
793         Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_UNIMPLEMENTED,
794             "Rational, multiply: Not implemented (yet).");
795         }
796     }
800 =item C<void i_multiply(PMC *value)>
802 =cut
805     VTABLE void i_multiply(PMC *value) {
806 MMD_Integer: {
807         rat_multiply_integer(INTERP, SELF, (int) PMC_int_val(value), SELF);
808         }
809 MMD_Float: {
810         rat_multiply_float(INTERP, SELF, (double) PMC_num_val(value), SELF);
811         }
812 MMD_Rational: {
813       #ifdef PARROT_HAS_GMP
814         mpq_mul(RT(SELF), RT(SELF), RT(value));
815       #else
816         RAISE_EXCEPTION
817       #endif
818         }
819 MMD_DEFAULT: {
820         Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_UNIMPLEMENTED,
821             "Rational, i_multiply: Not implemented (yet).");
822         }
823     }
827 =item C<PMC *multiply_int(INTVAL value, PMC* dest)>
829 =cut
832     VTABLE PMC *multiply_int(INTVAL value, PMC* dest) {
833         rat_multiply_integer(INTERP, SELF, (int) value, dest);
834         return dest;
835     }
839 =item C<void i_multiply_int(INTVAL value)>
841 =cut
844     VTABLE void i_multiply_int(INTVAL value) {
845         rat_multiply_integer(INTERP, SELF, (int) value, SELF);
846     }
850 =item C<PMC *multiply_float(FLOATVAL value, PMC* dest)>
852 =cut
855     VTABLE PMC *multiply_float(FLOATVAL value, PMC* dest) {
856         rat_multiply_float(INTERP, SELF, (double) value, dest);
857         return dest;
858     }
862 =item C<void i_multiply_float(FLOATVAL value)>
864 =cut
867     VTABLE void i_multiply_float(FLOATVAL value) {
868         rat_multiply_float(INTERP, SELF, (double) value, SELF);
869     }
873 =item C<PMC *divide(PMC* value, PMC* dest)>
875 =cut
878     VTABLE PMC *divide(PMC* value, PMC* dest) {
879 MMD_Integer: {
880         rat_divide_integer(INTERP, SELF, (int) PMC_int_val(value), dest);
881         return dest;
882         }
883 MMD_Float: {
884         rat_divide_float(INTERP, SELF, (double) PMC_num_val(value), dest);
885         return dest;
886         }
887 MMD_Rational: {
888       #ifdef PARROT_HAS_GMP
889         if (dest)
890             VTABLE_morph(INTERP, dest, SELF->vtable->base_type);
891         else
892             dest = pmc_new(INTERP, SELF->vtable->base_type);
894         mpq_div(RT(dest), RT(SELF), RT(value));
895         return dest;
896       #else
897         RAISE_EXCEPTION
898       #endif
899         }
900 MMD_DEFAULT: {
901         Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_UNIMPLEMENTED,
902             "Rational, divide: Not implemented (yet).");
903         }
904     }
908 =item C<void i_divide(PMC *value)>
910 =cut
913     VTABLE void i_divide(PMC *value) {
914 MMD_Integer: {
915         rat_divide_integer(INTERP, SELF, (int) PMC_int_val(value), SELF);
916         }
917 MMD_Float: {
918         rat_divide_float(INTERP, SELF, (double) PMC_num_val(value), SELF);
919         }
920 MMD_Rational: {
921       #ifdef PARROT_HAS_GMP
922         mpq_div(RT(SELF), RT(SELF), RT(value));
923       #else
924         RAISE_EXCEPTION
925       #endif
926         }
927 MMD_DEFAULT: {
928         Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_UNIMPLEMENTED,
929             "Rational, i_divide: Not implemented (yet).");
930         }
931     }
935 =item C<PMC *divide_int(INTVAL value, PMC* dest)>
937 =cut
940     VTABLE PMC *divide_int(INTVAL value, PMC* dest) {
941         rat_divide_integer(INTERP, SELF, (int) value, dest);
942         return dest;
943     }
947 =item C<void i_divide_int(INTVAL value)>
949 =cut
952     VTABLE void i_divide_int(INTVAL value) {
953         rat_divide_integer(INTERP, SELF, (int) value, SELF);
954     }
958 =item C<PMC *divide_float(FLOATVAL value, PMC* dest)>
960 =cut
963     VTABLE PMC *divide_float(FLOATVAL value, PMC* dest) {
964         rat_divide_float(INTERP, SELF, (double) value, dest);
965         return dest;
966     }
970 =item C<void i_divide_float(FLOATVAL value)>
972 =cut
975     VTABLE void i_divide_float(FLOATVAL value) {
976         rat_divide_float(INTERP, SELF, (double) value, SELF);
977     }
981 =item C<PMC *negate(PMC* dest)>
983 =cut
986     VTABLE PMC *neg(PMC* dest) {
987       #ifdef PARROT_HAS_GMP
988         if (dest)
989             VTABLE_morph(INTERP, dest, SELF->vtable->base_type);
990         else
991             dest = pmc_new(INTERP, SELF->vtable->base_type);
993         mpq_neg(RT(dest), RT(SELF));
994         return dest;
995       #else
996         RAISE_EXCEPTION
997       #endif
998     }
1002 =item C<void i_negate()>
1004 =cut
1007     VTABLE void i_neg() {
1008       #ifdef PARROT_HAS_GMP
1009         mpq_neg(RT(SELF), RT(SELF));
1010       #else
1011         RAISE_EXCEPTION
1012       #endif
1013     }
1017 =item C<PMC *absolute(PMC* dest)>
1019 =cut
1022     VTABLE PMC *absolute(PMC* dest) {
1023       #ifdef PARROT_HAS_GMP
1024         if (dest)
1025             VTABLE_morph(INTERP, dest, SELF->vtable->base_type);
1026         else
1027             dest = pmc_new(INTERP, SELF->vtable->base_type);
1029         mpq_abs(RT(dest), RT(SELF));
1030         return dest;
1031       #else
1032         RAISE_EXCEPTION
1033       #endif
1034     }
1038 =item C<void i_absolute()>
1040 =cut
1043     VTABLE void i_absolute() {
1044       #ifdef PARROT_HAS_GMP
1045         mpq_abs(RT(SELF), RT(SELF));
1046       #else
1047         RAISE_EXCEPTION
1048       #endif
1049     }
1053 =item C<INTVAL cmp(PMC *value)>
1055 =cut
1058     VTABLE INTVAL cmp(PMC *value) {
1059 MMD_Integer: {
1060       #ifdef PARROT_HAS_GMP
1061         return (INTVAL) mpq_cmp_si(RT(SELF), PMC_int_val(value), 1);
1062       #else
1063         RAISE_EXCEPTION
1064       #endif
1065       }
1066 MMD_Float: {
1067       #ifdef PARROT_HAS_GMP
1068         Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_UNIMPLEMENTED,
1069             "This is going to get implemented soon.");
1070       #else
1071         RAISE_EXCEPTION
1072       #endif
1073       }
1074 MMD_Rational: {
1075       #ifdef PARROT_HAS_GMP
1076         return (INTVAL) mpq_cmp(RT(SELF), RT(value));
1077       #else
1078         RAISE_EXCEPTION
1079       #endif
1080       }
1081 MMD_DEFAULT: {
1082         Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_UNIMPLEMENTED,
1083             "cmp not implemented (yet).");
1084       }
1085     }
1089 =item C<INTVAL is_equal(PMC *value)>
1091 =cut
1094     VTABLE INTVAL is_equal(PMC *value) {
1095 MMD_Integer: {
1096       #ifdef PARROT_HAS_GMP
1097         INTVAL eq = 0;
1098         mpq_t t;
1099         mpq_init(t);
1100         mpq_set_ui(t, PMC_int_val(value), 1);
1102         eq = (INTVAL) mpq_equal(RT(SELF), RT(value));
1103         mpq_clear(t);
1105         return eq;
1106       #else
1107         RAISE_EXCEPTION
1108       #endif
1109       }
1110 MMD_Float: {
1111         Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_UNIMPLEMENTED,
1112             "Equality to floats can not be checked because of limited machine "
1113             "accuracy.\nApproximate the rational and check whether the "
1114             "difference to a value is lower\nthan an epsilon.");
1115       }
1116 MMD_Rational: {
1117       #ifdef PARROT_HAS_GMP
1118         return (INTVAL) mpq_equal(RT(SELF), RT(value));
1119       #else
1120         RAISE_EXCEPTION
1121       #endif
1122       }
1123 MMD_DEFAULT: {
1124         Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_UNIMPLEMENTED,
1125             "is_equal not implemented (yet).");
1126       }
1127     }
1131  * Local variables:
1132  *   c-file-style: "parrot"
1133  * End:
1134  * vim: expandtab shiftwidth=4:
1135  */