Permalink
Find file
Fetching contributors…
Cannot retrieve contributors at this time
1905 lines (1478 sloc) 46.3 KB
/*
Copyright (C) 2004-2014, Parrot Foundation.
=head1 NAME
src/pmc/bigint.pmc - BigInt PMC
=head1 DESCRIPTION
C<BigInt> provides arbitrary precision integer mathematic functions.
=head2 Functions
=over 4
=item C<static void bigint_set_long(PARROT_INTERP, PMC *self, long value)>
Set the value of the BigInt to C<value>.
=item C<static void bigint_set_double(PARROT_INTERP, PMC *self, double value)>
Set the value of the BigInt to C<value>.
=cut
*/
/* TODO split that out into a separate file */
#ifdef S_SPLINT_S
# undef PARROT_HAS_GMP /* splint barfs on the gmp.h header */
#endif /* S_SPLINT_S */
#define NO_MULTIPLE_DISPATCH(name) \
Parrot_ex_throw_from_c_args(interp, NULL, \
EXCEPTION_INTERNAL_NOT_IMPLEMENTED, \
"BigInt: no multiple dispatch variant '%s' for %Ss", \
(name), VTABLE_name(interp, value))
#define NO_MULTIPLE_DISPATCH_FLOAT(name) \
Parrot_ex_throw_from_c_args(interp, NULL, \
EXCEPTION_INTERNAL_NOT_IMPLEMENTED, \
"BigInt: no multiple dispatch variant '%s' for FLOATVAL", \
(name))
#ifdef PARROT_HAS_GMP
# include <gmp.h>
typedef struct BIGINT {
mpz_t b;
} BIGINT;
/* HEADERIZER BEGIN: static */
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
static void bigint_abs(PARROT_INTERP, ARGIN(PMC *self), ARGMOD(PMC *dest))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(3)
FUNC_MODIFIES(*dest);
static void bigint_add_bigint(PARROT_INTERP,
ARGIN(PMC *self),
ARGIN(PMC *value),
ARGMOD(PMC *dest))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(3)
__attribute__nonnull__(4)
FUNC_MODIFIES(*dest);
static void bigint_add_bigint_int(PARROT_INTERP,
ARGIN(PMC *self),
INTVAL value,
ARGMOD(PMC *dest))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(4)
FUNC_MODIFIES(*dest);
static void bigint_check_divide_zero(PARROT_INTERP, ARGIN(PMC *value))
__attribute__nonnull__(1)
__attribute__nonnull__(2);
static void bigint_clear(PARROT_INTERP, ARGIN(PMC *self))
__attribute__nonnull__(1)
__attribute__nonnull__(2);
PARROT_WARN_UNUSED_RESULT
static INTVAL bigint_cmp(PARROT_INTERP, ARGIN(PMC *self), ARGIN(PMC *value))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(3);
PARROT_WARN_UNUSED_RESULT
static INTVAL bigint_cmp_int(PARROT_INTERP, ARGIN(PMC *self), INTVAL value)
__attribute__nonnull__(1)
__attribute__nonnull__(2);
static void bigint_div_bigint(PARROT_INTERP,
ARGIN(PMC *self),
ARGIN(PMC *value),
ARGMOD(PMC *dest))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(3)
__attribute__nonnull__(4)
FUNC_MODIFIES(*dest);
static void bigint_div_bigint_int(PARROT_INTERP,
ARGIN(PMC *self),
INTVAL value,
ARGMOD(PMC *dest))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(4)
FUNC_MODIFIES(*dest);
static void bigint_fdiv_bigint(PARROT_INTERP,
ARGIN(PMC *self),
ARGMOD(PMC *value),
ARGMOD(PMC *dest))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(3)
__attribute__nonnull__(4)
FUNC_MODIFIES(*value)
FUNC_MODIFIES(*dest);
static void bigint_fdiv_bigint_int(PARROT_INTERP,
ARGIN(PMC *self),
INTVAL value,
ARGMOD(PMC *dest))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(4)
FUNC_MODIFIES(*dest);
PARROT_WARN_UNUSED_RESULT
static int bigint_get_bool(PARROT_INTERP, ARGIN(PMC *self))
__attribute__nonnull__(1)
__attribute__nonnull__(2);
PARROT_WARN_UNUSED_RESULT
static double bigint_get_double(PARROT_INTERP, ARGIN(PMC *self))
__attribute__nonnull__(1)
__attribute__nonnull__(2);
PARROT_WARN_UNUSED_RESULT
static long bigint_get_long(PARROT_INTERP, ARGIN(PMC *self))
__attribute__nonnull__(1)
__attribute__nonnull__(2);
PARROT_CANNOT_RETURN_NULL
PARROT_WARN_UNUSED_RESULT
static BIGINT* bigint_get_self(PARROT_INTERP, ARGIN(PMC *self))
__attribute__nonnull__(1)
__attribute__nonnull__(2);
PARROT_WARN_UNUSED_RESULT
PARROT_CANNOT_RETURN_NULL
static char * bigint_get_string(PARROT_INTERP, ARGIN(PMC *self), int base)
__attribute__nonnull__(1)
__attribute__nonnull__(2);
static void bigint_init(PARROT_INTERP, ARGIN(PMC *self))
__attribute__nonnull__(1)
__attribute__nonnull__(2);
static void bigint_mod_bigint(PARROT_INTERP,
ARGIN(PMC *self),
ARGMOD(PMC *value),
ARGMOD(PMC *dest))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(3)
__attribute__nonnull__(4)
FUNC_MODIFIES(*value)
FUNC_MODIFIES(*dest);
static void bigint_mod_bigint_int(PARROT_INTERP,
ARGIN(PMC *self),
INTVAL value,
ARGMOD(PMC *dest))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(4)
FUNC_MODIFIES(*dest);
static void bigint_mul_bigint(PARROT_INTERP,
ARGIN(PMC *self),
ARGIN(PMC *value),
ARGMOD(PMC *dest))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(3)
__attribute__nonnull__(4)
FUNC_MODIFIES(*dest);
static void bigint_mul_bigint_int(PARROT_INTERP,
ARGIN(PMC *self),
INTVAL value,
ARGMOD(PMC *dest))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(4)
FUNC_MODIFIES(*dest);
static void bigint_neg(PARROT_INTERP, ARGIN(PMC *self), ARGMOD(PMC *dest))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(3)
FUNC_MODIFIES(*dest);
static void bigint_pow_bigint_int(PARROT_INTERP,
ARGIN(PMC *self),
INTVAL value,
ARGMOD(PMC *dest))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(4)
FUNC_MODIFIES(*dest);
static void bigint_set(PARROT_INTERP, ARGMOD(PMC *dest), ARGIN(PMC *src))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(3)
FUNC_MODIFIES(*dest);
static void bigint_set_double(PARROT_INTERP,
ARGMOD(PMC *self),
double value)
__attribute__nonnull__(1)
__attribute__nonnull__(2)
FUNC_MODIFIES(*self);
static void bigint_set_long(PARROT_INTERP, ARGMOD(PMC *self), long value)
__attribute__nonnull__(1)
__attribute__nonnull__(2)
FUNC_MODIFIES(*self);
static void bigint_set_self(PARROT_INTERP,
ARGMOD(PMC *self),
ARGIN(BIGINT *value))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(3)
FUNC_MODIFIES(*self);
static void bigint_set_str(PARROT_INTERP,
ARGMOD(PMC *self),
ARGIN(const STRING *value),
int base)
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(3)
FUNC_MODIFIES(*self);
static void bigint_sub_bigint(PARROT_INTERP,
ARGIN(PMC *self),
ARGIN(PMC *value),
ARGMOD(PMC *dest))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(3)
__attribute__nonnull__(4)
FUNC_MODIFIES(*dest);
static void bigint_sub_bigint_int(PARROT_INTERP,
ARGIN(PMC *self),
INTVAL value,
ARGMOD(PMC *dest))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(4)
FUNC_MODIFIES(*dest);
static void int_check_divide_zero(PARROT_INTERP, INTVAL value)
__attribute__nonnull__(1);
#define ASSERT_ARGS_bigint_abs __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(self) \
, PARROT_ASSERT_ARG(dest))
#define ASSERT_ARGS_bigint_add_bigint __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(self) \
, PARROT_ASSERT_ARG(value) \
, PARROT_ASSERT_ARG(dest))
#define ASSERT_ARGS_bigint_add_bigint_int __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(self) \
, PARROT_ASSERT_ARG(dest))
#define ASSERT_ARGS_bigint_check_divide_zero __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(value))
#define ASSERT_ARGS_bigint_clear __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(self))
#define ASSERT_ARGS_bigint_cmp __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(self) \
, PARROT_ASSERT_ARG(value))
#define ASSERT_ARGS_bigint_cmp_int __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(self))
#define ASSERT_ARGS_bigint_div_bigint __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(self) \
, PARROT_ASSERT_ARG(value) \
, PARROT_ASSERT_ARG(dest))
#define ASSERT_ARGS_bigint_div_bigint_int __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(self) \
, PARROT_ASSERT_ARG(dest))
#define ASSERT_ARGS_bigint_fdiv_bigint __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(self) \
, PARROT_ASSERT_ARG(value) \
, PARROT_ASSERT_ARG(dest))
#define ASSERT_ARGS_bigint_fdiv_bigint_int __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(self) \
, PARROT_ASSERT_ARG(dest))
#define ASSERT_ARGS_bigint_get_bool __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(self))
#define ASSERT_ARGS_bigint_get_double __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(self))
#define ASSERT_ARGS_bigint_get_long __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(self))
#define ASSERT_ARGS_bigint_get_self __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(self))
#define ASSERT_ARGS_bigint_get_string __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(self))
#define ASSERT_ARGS_bigint_init __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(self))
#define ASSERT_ARGS_bigint_mod_bigint __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(self) \
, PARROT_ASSERT_ARG(value) \
, PARROT_ASSERT_ARG(dest))
#define ASSERT_ARGS_bigint_mod_bigint_int __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(self) \
, PARROT_ASSERT_ARG(dest))
#define ASSERT_ARGS_bigint_mul_bigint __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(self) \
, PARROT_ASSERT_ARG(value) \
, PARROT_ASSERT_ARG(dest))
#define ASSERT_ARGS_bigint_mul_bigint_int __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(self) \
, PARROT_ASSERT_ARG(dest))
#define ASSERT_ARGS_bigint_neg __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(self) \
, PARROT_ASSERT_ARG(dest))
#define ASSERT_ARGS_bigint_pow_bigint_int __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(self) \
, PARROT_ASSERT_ARG(dest))
#define ASSERT_ARGS_bigint_set __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(dest) \
, PARROT_ASSERT_ARG(src))
#define ASSERT_ARGS_bigint_set_double __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(self))
#define ASSERT_ARGS_bigint_set_long __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(self))
#define ASSERT_ARGS_bigint_set_self __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(self) \
, PARROT_ASSERT_ARG(value))
#define ASSERT_ARGS_bigint_set_str __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(self) \
, PARROT_ASSERT_ARG(value))
#define ASSERT_ARGS_bigint_sub_bigint __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(self) \
, PARROT_ASSERT_ARG(value) \
, PARROT_ASSERT_ARG(dest))
#define ASSERT_ARGS_bigint_sub_bigint_int __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(self) \
, PARROT_ASSERT_ARG(dest))
#define ASSERT_ARGS_int_check_divide_zero __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp))
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
/* HEADERIZER END: static */
/* HEADERIZER HFILE: none */
/*
=item C<static void bigint_init(PARROT_INTERP, PMC *self)>
Initialize a BigInt
=cut
*/
static void
bigint_init(PARROT_INTERP, ARGIN(PMC *self))
{
ASSERT_ARGS(bigint_init)
BIGINT * const bi = mem_gc_allocate_zeroed_typed(interp, BIGINT);
SETATTR_BigInt_bi(interp, self, bi);
mpz_init(bi->b);
}
/*
=item C<static void bigint_clear(PARROT_INTERP, PMC *self)>
Clear the BigInt memory.
=cut
*/
static void
bigint_clear(PARROT_INTERP, ARGIN(PMC *self))
{
ASSERT_ARGS(bigint_clear)
BIGINT * bi;
GETATTR_BigInt_bi(interp, self, bi);
mpz_clear(bi->b);
mem_gc_free(interp, bi);
}
/*
=item C<static void bigint_set(PARROT_INTERP, PMC *dest, PMC *src)>
Set the BigInt value C<dest> to the same value as C<src>.
=cut
*/
static void
bigint_set(PARROT_INTERP, ARGMOD(PMC *dest), ARGIN(PMC *src))
{
ASSERT_ARGS(bigint_set)
BIGINT *bi_dest;
const BIGINT *bi_src;
GETATTR_BigInt_bi(interp, dest, bi_dest);
GETATTR_BigInt_bi(interp, src, bi_src);
mpz_clear(bi_dest->b);
mpz_init(bi_dest->b);
mpz_set(bi_dest->b, bi_src->b);
}
/*
=item C<static void bigint_set_long(PARROT_INTERP, PMC *self, long value)>
Initialize the BigInt value from a C<long>
=cut
*/
static void
bigint_set_long(PARROT_INTERP, ARGMOD(PMC *self), long value)
{
ASSERT_ARGS(bigint_set_long)
BIGINT *bi;
GETATTR_BigInt_bi(interp, self, bi);
mpz_set_si(bi->b, value);
}
/*
=item C<static void bigint_set_double(PARROT_INTERP, PMC *self, double value)>
Initialize the BigInt value from a C<double>
=cut
*/
static void
bigint_set_double(PARROT_INTERP, ARGMOD(PMC *self), double value)
{
ASSERT_ARGS(bigint_set_double)
BIGINT *bi;
GETATTR_BigInt_bi(interp, self, bi);
mpz_set_d(bi->b, value);
}
/*
=item C<static void bigint_set_str(PARROT_INTERP, PMC *self, const STRING
*value, int base)>
Initialize the BigInt value from a C<STRING>
=cut
*/
static void
bigint_set_str(PARROT_INTERP, ARGMOD(PMC *self), ARGIN(const STRING *value), int base)
{
ASSERT_ARGS(bigint_set_str)
char * const s = Parrot_str_to_cstring(interp, value);
BIGINT *bi;
GETATTR_BigInt_bi(interp, self, bi);
mpz_set_str(bi->b, s, base);
Parrot_str_free_cstring(s);
}
/*
=item C<static BIGINT* bigint_get_self(PARROT_INTERP, PMC *self)>
Get the C<BIGINT*> pointer from C<self>
=cut
*/
PARROT_CANNOT_RETURN_NULL
PARROT_WARN_UNUSED_RESULT
static BIGINT*
bigint_get_self(PARROT_INTERP, ARGIN(PMC *self))
{
ASSERT_ARGS(bigint_get_self)
BIGINT *bi;
GETATTR_BigInt_bi(interp, self, bi);
return bi;
}
/*
=item C<static void bigint_set_self(PARROT_INTERP, PMC *self, BIGINT *value)>
Set the C<BIGINT*> pointer from C<value> PMC
=cut
*/
static void
bigint_set_self(PARROT_INTERP, ARGMOD(PMC *self), ARGIN(BIGINT *value))
{
ASSERT_ARGS(bigint_set_self)
BIGINT *bi;
GETATTR_BigInt_bi(interp, self, bi);
mpz_set(bi->b, (mpz_srcptr)((BIGINT*)value)->b);
}
/*
=item C<static long bigint_get_long(PARROT_INTERP, PMC *self)>
Convert the BigInt value to a C<long>
=cut
*/
PARROT_WARN_UNUSED_RESULT
static long
bigint_get_long(PARROT_INTERP, ARGIN(PMC *self))
{
ASSERT_ARGS(bigint_get_long)
const BIGINT *bi;
GETATTR_BigInt_bi(interp, self, bi);
if (mpz_fits_slong_p(bi->b))
return mpz_get_si(bi->b);
Parrot_ex_throw_from_c_noargs(interp, EXCEPTION_ERR_OVERFLOW,
"bigint_get_long: number too big");
}
/*
=item C<static int bigint_get_bool(PARROT_INTERP, PMC *self)>
Get a boolean representation of the BigInt
=cut
*/
PARROT_WARN_UNUSED_RESULT
static int
bigint_get_bool(PARROT_INTERP, ARGIN(PMC *self))
{
ASSERT_ARGS(bigint_get_bool)
const BIGINT *bi;
GETATTR_BigInt_bi(interp, self, bi);
if (mpz_sgn(bi->b) != 0)
return 1;
else
return 0;
}
/*
=item C<static char * bigint_get_string(PARROT_INTERP, PMC *self, int base)>
Get a STRING representation of the BigInt.
=cut
*/
PARROT_WARN_UNUSED_RESULT
PARROT_CANNOT_RETURN_NULL
static char *
bigint_get_string(PARROT_INTERP, ARGIN(PMC *self), int base)
{
ASSERT_ARGS(bigint_get_string)
const BIGINT *bi;
size_t n;
char *s;
GETATTR_BigInt_bi(interp, self, bi);
n = mpz_sizeinbase(bi->b, base) + 2;
s = mem_gc_allocate_n_typed(interp, n, char);
return mpz_get_str(s, base, bi->b);
}
/*
=item C<static double bigint_get_double(PARROT_INTERP, PMC *self)>
Get a C<double> value from the BigInt.
=cut
*/
PARROT_WARN_UNUSED_RESULT
static double
bigint_get_double(PARROT_INTERP, ARGIN(PMC *self))
{
ASSERT_ARGS(bigint_get_double)
const BIGINT *bi;
GETATTR_BigInt_bi(interp, self, bi);
return mpz_get_d(bi->b);
}
/*
=item C<static void bigint_add_bigint(PARROT_INTERP, PMC *self, PMC *value, PMC
*dest)>
Add C<self> and C<value> and store the result in C<dest>.
=cut
*/
static void
bigint_add_bigint(PARROT_INTERP, ARGIN(PMC *self), ARGIN(PMC *value), ARGMOD(PMC *dest))
{
ASSERT_ARGS(bigint_add_bigint)
const BIGINT *bi_self;
const BIGINT *bi_value;
BIGINT *bi_dest;
GETATTR_BigInt_bi(interp, self, bi_self);
GETATTR_BigInt_bi(interp, value, bi_value);
GETATTR_BigInt_bi(interp, dest, bi_dest);
mpz_add(bi_dest->b, bi_self->b, bi_value->b);
}
/*
=item C<static void bigint_add_bigint_int(PARROT_INTERP, PMC *self, INTVAL
value, PMC *dest)>
Add an INTVAL to the BigInt.
=cut
*/
static void
bigint_add_bigint_int(PARROT_INTERP, ARGIN(PMC *self), INTVAL value, ARGMOD(PMC *dest))
{
ASSERT_ARGS(bigint_add_bigint_int)
const BIGINT *bi_self;
BIGINT *bi_dest;
GETATTR_BigInt_bi(interp, self, bi_self);
GETATTR_BigInt_bi(interp, dest, bi_dest);
if (value < 0)
mpz_sub_ui(bi_dest->b, bi_self->b, (unsigned long int)-value);
else
mpz_add_ui(bi_dest->b, bi_self->b, (unsigned long int)value);
}
/*
=item C<static void bigint_sub_bigint(PARROT_INTERP, PMC *self, PMC *value, PMC
*dest)>
Subtract C<value> from C<self> and store the result in C<dest>.
=cut
*/
static void
bigint_sub_bigint(PARROT_INTERP, ARGIN(PMC *self), ARGIN(PMC *value), ARGMOD(PMC *dest))
{
ASSERT_ARGS(bigint_sub_bigint)
const BIGINT *bi_self;
const BIGINT *bi_value;
BIGINT *bi_dest;
GETATTR_BigInt_bi(interp, self, bi_self);
GETATTR_BigInt_bi(interp, value, bi_value);
GETATTR_BigInt_bi(interp, dest, bi_dest);
mpz_sub(bi_dest->b, bi_self->b, bi_value->b);
}
/*
=item C<static void bigint_sub_bigint_int(PARROT_INTERP, PMC *self, INTVAL
value, PMC *dest)>
Subtract C<value> from C<self> and store the result in C<dest>.
=cut
*/
static void
bigint_sub_bigint_int(PARROT_INTERP, ARGIN(PMC *self), INTVAL value, ARGMOD(PMC *dest))
{
ASSERT_ARGS(bigint_sub_bigint_int)
const BIGINT *bi_self;
BIGINT *bi_dest;
GETATTR_BigInt_bi(interp, self, bi_self);
GETATTR_BigInt_bi(interp, dest, bi_dest);
if (value < 0)
mpz_add_ui(bi_dest->b, bi_self->b, (unsigned long int)-value);
else
mpz_sub_ui(bi_dest->b, bi_self->b, (unsigned long int)value);
}
/*
=item C<static void bigint_mul_bigint(PARROT_INTERP, PMC *self, PMC *value, PMC
*dest)>
Multiply C<self> by C<value> and store the result in C<dest>.
=cut
*/
static void
bigint_mul_bigint(PARROT_INTERP, ARGIN(PMC *self), ARGIN(PMC *value), ARGMOD(PMC *dest))
{
ASSERT_ARGS(bigint_mul_bigint)
const BIGINT *bi_self;
const BIGINT *bi_value;
BIGINT *bi_dest;
GETATTR_BigInt_bi(interp, self, bi_self);
GETATTR_BigInt_bi(interp, value, bi_value);
GETATTR_BigInt_bi(interp, dest, bi_dest);
mpz_mul(bi_dest->b, bi_self->b, bi_value->b);
}
/*
=item C<static void bigint_mul_bigint_int(PARROT_INTERP, PMC *self, INTVAL
value, PMC *dest)>
Multiply C<self> by C<value> and store the result in C<dest>.
=cut
*/
static void
bigint_mul_bigint_int(PARROT_INTERP, ARGIN(PMC *self), INTVAL value, ARGMOD(PMC *dest))
{
ASSERT_ARGS(bigint_mul_bigint_int)
const BIGINT *bi_self;
BIGINT *bi_dest;
GETATTR_BigInt_bi(interp, self, bi_self);
GETATTR_BigInt_bi(interp, dest, bi_dest);
mpz_mul_si(bi_dest->b, bi_self->b, value);
}
/*
=item C<static void bigint_pow_bigint_int(PARROT_INTERP, PMC *self, INTVAL
value, PMC *dest)>
Raise C<self> to the power C<value> and store the result in C<dest>.
=cut
*/
static void
bigint_pow_bigint_int(PARROT_INTERP, ARGIN(PMC *self), INTVAL value, ARGMOD(PMC *dest))
{
ASSERT_ARGS(bigint_pow_bigint_int)
const BIGINT *bi_self;
BIGINT *bi_dest;
GETATTR_BigInt_bi(interp, self, bi_self);
GETATTR_BigInt_bi(interp, dest, bi_dest);
mpz_pow_ui(bi_dest->b, bi_self->b, (unsigned long int)value);
}
/*
=item C<static void int_check_divide_zero(PARROT_INTERP, INTVAL value)>
If C<value> is C<0>, throw an exception.
=cut
*/
static void
int_check_divide_zero(PARROT_INTERP, INTVAL value)
{
if (value == 0)
Parrot_ex_throw_from_c_noargs(interp, EXCEPTION_DIV_BY_ZERO,
"Divide by zero");
}
/*
=item C<static void bigint_check_divide_zero(PARROT_INTERP, PMC *value)>
If C<value> is C<0>, throw an exception.
=cut
*/
static void
bigint_check_divide_zero(PARROT_INTERP, ARGIN(PMC *value))
{
ASSERT_ARGS(bigint_check_divide_zero)
/* Throw an exception if we are dividing by zero. */
const BIGINT *bi;
GETATTR_BigInt_bi(interp, value, bi);
if (mpz_cmp_si(bi->b, 0) == 0)
Parrot_ex_throw_from_c_noargs(interp, EXCEPTION_DIV_BY_ZERO,
"Divide by zero");
}
/*
=item C<static void bigint_div_bigint(PARROT_INTERP, PMC *self, PMC *value, PMC
*dest)>
Divide C<self> by C<value> and store the result in C<dest>.
=cut
*/
static void
bigint_div_bigint(PARROT_INTERP, ARGIN(PMC *self), ARGIN(PMC *value), ARGMOD(PMC *dest))
{
ASSERT_ARGS(bigint_div_bigint)
const BIGINT *bi_self;
const BIGINT *bi_value;
BIGINT *bi_dest;
bigint_check_divide_zero(interp, value);
GETATTR_BigInt_bi(interp, self, bi_self);
GETATTR_BigInt_bi(interp, value, bi_value);
GETATTR_BigInt_bi(interp, dest, bi_dest);
/* this is mpz_fdiv_q */
mpz_div(bi_dest->b, bi_self->b, bi_value->b);
}
/*
=item C<static void bigint_div_bigint_int(PARROT_INTERP, PMC *self, INTVAL
value, PMC *dest)>
Divide C<self> by C<value> and store the result in C<dest>.
=cut
*/
static void
bigint_div_bigint_int(PARROT_INTERP, ARGIN(PMC *self), INTVAL value, ARGMOD(PMC *dest))
{
ASSERT_ARGS(bigint_div_bigint_int)
const BIGINT *bi_self;
BIGINT *bi_dest;
GETATTR_BigInt_bi(interp, self, bi_self);
GETATTR_BigInt_bi(interp, dest, bi_dest);
int_check_divide_zero(interp, value);
/* this is mpz_fdiv_q */
if (value < 0) {
mpz_div_ui(bi_dest->b, bi_self->b, (unsigned long int)-value);
mpz_neg(bi_dest->b, bi_dest->b);
}
else {
mpz_div_ui(bi_dest->b, bi_self->b, (unsigned long int)value);
}
}
/*
=item C<static void bigint_fdiv_bigint(PARROT_INTERP, PMC *self, PMC *value, PMC
*dest)>
Floating-point divide C<self> by C<value> and store the result in C<dest>.
=cut
*/
static void
bigint_fdiv_bigint(PARROT_INTERP, ARGIN(PMC *self), ARGMOD(PMC *value), ARGMOD(PMC *dest))
{
ASSERT_ARGS(bigint_fdiv_bigint)
const BIGINT *bi_self;
const BIGINT *bi_value;
BIGINT *bi_dest;
GETATTR_BigInt_bi(interp, self, bi_self);
GETATTR_BigInt_bi(interp, value, bi_value);
GETATTR_BigInt_bi(interp, dest, bi_dest);
bigint_check_divide_zero(interp, value);
mpz_fdiv_q(bi_dest->b, bi_self->b, bi_value->b);
}
/*
=item C<static void bigint_fdiv_bigint_int(PARROT_INTERP, PMC *self, INTVAL
value, PMC *dest)>
Floating-point divide C<self> by C<value> and store the result in C<dest>.
=cut
*/
static void
bigint_fdiv_bigint_int(PARROT_INTERP, ARGIN(PMC *self), INTVAL value, ARGMOD(PMC *dest))
{
ASSERT_ARGS(bigint_fdiv_bigint_int)
const BIGINT *bi_self;
BIGINT *bi_dest;
GETATTR_BigInt_bi(interp, self, bi_self);
GETATTR_BigInt_bi(interp, dest, bi_dest);
int_check_divide_zero(interp, value);
if (value < 0) {
mpz_fdiv_q_ui(bi_dest->b, bi_self->b, (unsigned long int)-value);
mpz_neg(bi_dest->b, bi_dest->b);
}
else {
mpz_fdiv_q_ui(bi_dest->b, bi_self->b, (unsigned long int)value);
}
}
/*
=item C<static void bigint_mod_bigint(PARROT_INTERP, PMC *self, PMC *value, PMC
*dest)>
Modulo C<self> by C<value> and store the result in C<dest>.
=cut
*/
static void
bigint_mod_bigint(PARROT_INTERP, ARGIN(PMC *self), ARGMOD(PMC *value), ARGMOD(PMC *dest))
{
ASSERT_ARGS(bigint_mod_bigint)
const BIGINT *bi_self;
const BIGINT *bi_value;
BIGINT *bi_dest;
GETATTR_BigInt_bi(interp, self, bi_self);
GETATTR_BigInt_bi(interp, value, bi_value);
GETATTR_BigInt_bi(interp, dest, bi_dest);
bigint_check_divide_zero(interp, value);
mpz_mod(bi_dest->b, bi_self->b, bi_value->b);
}
/*
=item C<static void bigint_mod_bigint_int(PARROT_INTERP, PMC *self, INTVAL
value, PMC *dest)>
Modulo C<self> by C<value> and store the result in C<dest>.
=cut
*/
static void
bigint_mod_bigint_int(PARROT_INTERP, ARGIN(PMC *self), INTVAL value, ARGMOD(PMC *dest))
{
ASSERT_ARGS(bigint_mod_bigint_int)
const BIGINT *bi_self;
BIGINT *bi_dest;
GETATTR_BigInt_bi(interp, self, bi_self);
GETATTR_BigInt_bi(interp, dest, bi_dest);
int_check_divide_zero(interp, value);
if (value < 0) {
mpz_mod_ui(bi_dest->b, bi_self->b, (unsigned long int)-value);
}
else {
mpz_mod_ui(bi_dest->b, bi_self->b, (unsigned long int)value);
}
}
/*
=item C<static INTVAL bigint_cmp(PARROT_INTERP, PMC *self, PMC *value)>
Compare C<self> and C<value>, returning 1, 0 or -1 depending on the relation.
=cut
*/
PARROT_WARN_UNUSED_RESULT
static INTVAL
bigint_cmp(PARROT_INTERP, ARGIN(PMC *self), ARGIN(PMC *value))
{
ASSERT_ARGS(bigint_cmp)
const BIGINT *bi_self;
const BIGINT *bi_value;
GETATTR_BigInt_bi(interp, self, bi_self);
GETATTR_BigInt_bi(interp, value, bi_value);
return mpz_cmp(bi_self->b, bi_value->b);
}
/*
=item C<static INTVAL bigint_cmp_int(PARROT_INTERP, PMC *self, INTVAL value)>
Compare C<self> and C<value>, returning 1, 0 or -1 depending on the relation.
=cut
*/
PARROT_WARN_UNUSED_RESULT
static INTVAL
bigint_cmp_int(PARROT_INTERP, ARGIN(PMC *self), INTVAL value)
{
ASSERT_ARGS(bigint_cmp_int)
const BIGINT *bi;
GETATTR_BigInt_bi(interp, self, bi);
return mpz_cmp_si(bi->b, value);
}
/*
=item C<static void bigint_abs(PARROT_INTERP, PMC *self, PMC *dest)>
Take the absolute value of C<self>. Store the result in C<dest>.
=cut
*/
static void
bigint_abs(PARROT_INTERP, ARGIN(PMC *self), ARGMOD(PMC *dest))
{
ASSERT_ARGS(bigint_abs)
const BIGINT *bi_self;
BIGINT *bi_dest;
GETATTR_BigInt_bi(interp, self, bi_self);
GETATTR_BigInt_bi(interp, dest, bi_dest);
mpz_abs(bi_dest->b, bi_self->b);
}
/*
=item C<static void bigint_neg(PARROT_INTERP, PMC *self, PMC *dest)>
Take the negative value of C<self>. Store the result in C<dest>.
=cut
*/
static void
bigint_neg(PARROT_INTERP, ARGIN(PMC *self), ARGMOD(PMC *dest))
{
ASSERT_ARGS(bigint_neg)
const BIGINT *bi_self;
BIGINT *bi_dest;
GETATTR_BigInt_bi(interp, self, bi_self);
GETATTR_BigInt_bi(interp, dest, bi_dest);
mpz_neg(bi_dest->b, bi_self->b);
}
/* HEADERIZER STOP */
#else /* ifdef PARROT_HAS_GMP */
typedef struct BIGINT {
INTVAL b; /* bogus definition for users without libgmp*/
} BIGINT;
# define THROW_NOGMP Parrot_ex_throw_from_c_noargs(interp, \
EXCEPTION_LIBRARY_ERROR, "no bigint lib loaded")
static void
bigint_init(PARROT_INTERP, ARGIN(PMC *self)) {
UNUSED(self)
THROW_NOGMP;
}
static void
bigint_clear(PARROT_INTERP, ARGIN(PMC *self)) {
UNUSED(self)
THROW_NOGMP;
}
static void
bigint_set_long(PARROT_INTERP, ARGIN(PMC *self), long value) {
UNUSED(self)
UNUSED(value)
THROW_NOGMP;
}
static void
bigint_set(PARROT_INTERP, PMC *dest, PMC *src) {
UNUSED(dest)
UNUSED(src)
THROW_NOGMP;
}
static void
bigint_set_double(PARROT_INTERP, ARGIN(PMC *self), double value) {
UNUSED(self)
UNUSED(value)
THROW_NOGMP;
}
static void
bigint_set_str(PARROT_INTERP, ARGIN(PMC *self), ARGIN(const STRING *value), int base) {
UNUSED(self)
UNUSED(value)
UNUSED(base)
THROW_NOGMP;
}
static void
bigint_set_self(PARROT_INTERP, ARGIN(PMC *self), BIGINT *value) {
UNUSED(self)
UNUSED(value)
THROW_NOGMP;
}
static BIGINT*
bigint_get_self(PARROT_INTERP, ARGIN(PMC *self)) {
UNUSED(self)
THROW_NOGMP;
}
static char *
bigint_get_string(PARROT_INTERP, ARGIN(PMC *self), int base) {
UNUSED(self)
UNUSED(base)
THROW_NOGMP;
}
static long
bigint_get_long(PARROT_INTERP, ARGIN(PMC *self)) {
UNUSED(self)
THROW_NOGMP;
}
static int
bigint_get_bool(PARROT_INTERP, ARGIN(PMC *self)) {
UNUSED(self)
THROW_NOGMP;
}
static double
bigint_get_double(PARROT_INTERP, ARGIN(PMC *self)) {
UNUSED(self)
THROW_NOGMP;
}
static void
bigint_add_bigint(PARROT_INTERP, ARGIN(PMC *self), PMC *value, PMC *dest) {
UNUSED(self)
UNUSED(value)
UNUSED(dest)
THROW_NOGMP;
}
static void
bigint_add_bigint_int(PARROT_INTERP, ARGIN(PMC *self), INTVAL value, PMC *dest) {
UNUSED(self)
UNUSED(value)
UNUSED(dest)
THROW_NOGMP;
}
static void
bigint_sub_bigint(PARROT_INTERP, ARGIN(PMC *self), PMC *value, PMC *dest) {
UNUSED(self)
UNUSED(value)
UNUSED(dest)
THROW_NOGMP;
}
static void
bigint_sub_bigint_int(PARROT_INTERP, ARGIN(PMC *self), INTVAL value, PMC *dest) {
UNUSED(self)
UNUSED(value)
UNUSED(dest)
THROW_NOGMP;
}
static void
bigint_mul_bigint(PARROT_INTERP, ARGIN(PMC *self), PMC *value, PMC *dest) {
UNUSED(self)
UNUSED(value)
UNUSED(dest)
THROW_NOGMP;
}
static void
bigint_mul_bigint_int(PARROT_INTERP, ARGIN(PMC *self), INTVAL value, PMC *dest) {
UNUSED(self)
UNUSED(value)
UNUSED(dest)
THROW_NOGMP;
}
static void
bigint_pow_bigint_int(PARROT_INTERP, ARGIN(PMC *self), INTVAL value, PMC *dest) {
UNUSED(self)
UNUSED(value)
UNUSED(dest)
THROW_NOGMP;
}
static void
bigint_div_bigint(PARROT_INTERP, ARGIN(PMC *self), PMC *value, PMC *dest) {
UNUSED(self)
UNUSED(value)
UNUSED(dest)
THROW_NOGMP;
}
static void
bigint_div_bigint_int(PARROT_INTERP, ARGIN(PMC *self), INTVAL value, PMC *dest) {
UNUSED(self)
UNUSED(value)
UNUSED(dest)
THROW_NOGMP;
}
static void
bigint_fdiv_bigint(PARROT_INTERP, ARGIN(PMC *self), PMC *value, PMC *dest) {
UNUSED(self)
UNUSED(value)
UNUSED(dest)
THROW_NOGMP;
}
static void
bigint_fdiv_bigint_int(PARROT_INTERP, ARGIN(PMC *self), INTVAL value, PMC *dest) {
UNUSED(self)
UNUSED(value)
UNUSED(dest)
THROW_NOGMP;
}
static void
bigint_mod_bigint(PARROT_INTERP, ARGIN(PMC *self), PMC *value, PMC *dest) {
UNUSED(self)
UNUSED(value)
UNUSED(dest)
THROW_NOGMP;
}
static void
bigint_mod_bigint_int(PARROT_INTERP, ARGIN(PMC *self), INTVAL value, PMC *dest) {
UNUSED(self)
UNUSED(value)
UNUSED(dest)
THROW_NOGMP;
}
static INTVAL
bigint_cmp(PARROT_INTERP, ARGIN(PMC *self), PMC *value) {
UNUSED(self)
UNUSED(value)
THROW_NOGMP;
}
static INTVAL
bigint_cmp_int(PARROT_INTERP, ARGIN(PMC *self), INTVAL value) {
UNUSED(self)
UNUSED(value)
THROW_NOGMP;
}
static void
bigint_abs(PARROT_INTERP, ARGIN(PMC *self), PMC *dest) {
UNUSED(self)
UNUSED(dest)
THROW_NOGMP;
}
static void
bigint_neg(PARROT_INTERP, ARGIN(PMC *self), PMC *dest) {
UNUSED(self)
UNUSED(dest)
THROW_NOGMP;
}
#endif /* ifdef PARROT_HAS_GMP */
pmclass BigInt auto_attrs {
ATTR struct BIGINT * bi; /*bigint val*/
/*
=back
=head2 Methods
=over 4
=item C<METHOD version()>
Return GMP version string "x.y.z".
=cut
*/
METHOD version() :no_wb {
STRING *version;
#ifdef PARROT_HAS_GMP
version = Parrot_str_new(INTERP, gmp_version, 0);
#else
version = CONST_STRING(INTERP, "0.0.0");
#endif
RETURN(STRING *version);
}
VTABLE void init() {
bigint_init(INTERP, SELF);
PObj_custom_destroy_SET(SELF);
}
VTABLE void init_int(INTVAL iv) {
bigint_init(INTERP, SELF);
bigint_set_long(INTERP, SELF, (long)iv);
PObj_custom_destroy_SET(SELF);
}
VTABLE PMC *clone() :no_wb {
PMC * const res = Parrot_pmc_new(INTERP, SELF->vtable->base_type);
bigint_set(INTERP, res, SELF);
return res;
}
VTABLE void destroy() :no_wb {
bigint_clear(INTERP, SELF);
}
/*
=item C<void set_integer_native(INTVAL value)>
=cut
*/
VTABLE void set_integer_native(INTVAL value) {
bigint_set_long(INTERP, SELF, (long)value);
}
/*
=item C<void set_number_native(FLOATVAL value)>
Sets the value of the bigint to C<value>.
=cut
*/
VTABLE void set_number_native(FLOATVAL value) {
bigint_set_double(INTERP, SELF, (double)value);
}
/*
=item C<void set_string_native(STRING *value)>
Sets the value of the integer to the result of converting C<*value> to a
number.
=item C<void set_string_keyed_int(INTVAL base, STRING *value)>
Same assume number base C<base>.
=cut
*/
VTABLE void set_string_native(STRING *value) {
bigint_set_str(INTERP, SELF, value, 10);
}
VTABLE void set_string_keyed_int(INTVAL base, STRING *value) {
bigint_set_str(INTERP, SELF, value, base);
}
/*
=item C<void set_pmc(PMC *value)>
Sets the value of the integer to the integer value of C<*value>.
=cut
*/
VTABLE void set_pmc(PMC *value) {
if (value->vtable->base_type == enum_class_BigInt) {
bigint_set_self(INTERP, SELF, bigint_get_self(INTERP, value));
}
else {
const INTVAL i = VTABLE_get_integer(INTERP, value);
bigint_set_long(INTERP, SELF, (long)i);
}
}
/*
=item C<FLOATVAL get_number()>
Returns the value of the integer as a floating point number.
=cut
*/
VTABLE FLOATVAL get_number() :no_wb {
return bigint_get_double(INTERP, SELF);
}
/*
=item C<INTVAL get_integer()>
Returns the value of the integer.
=cut
*/
VTABLE INTVAL get_integer() :no_wb {
return bigint_get_long(INTERP, SELF);
}
/*
=item C<INTVAL get_bool()>
Returns the boolean value of the integer.
=cut
*/
VTABLE INTVAL get_bool() :no_wb {
return bigint_get_bool(INTERP, SELF);
}
/*
=item C<STRING *get_string()>
Returns the string representation of the integer.
=item C<STRING *get_string_keyed_int(INTVAL base)>
Returns the string representation of the integer in base C<base>.
=item C<STRING *get_repr()>
Returns the string representation of the integer with the letter 'L'
appended.
=cut
*/
VTABLE STRING *get_string() :no_wb {
char * const s = bigint_get_string(INTERP, SELF, 10);
STRING * const ps = Parrot_str_new(INTERP, s, 0);
mem_gc_free(INTERP, s);
return ps;
}
VTABLE STRING *get_string_keyed_int(INTVAL base) :no_wb {
char * const s = bigint_get_string(INTERP, SELF, base);
STRING * const ps = Parrot_str_new(INTERP, s, 0);
mem_gc_free(INTERP, s);
return ps;
}
VTABLE STRING *get_repr() :no_wb {
STRING * const s = SELF.get_string();
return Parrot_str_concat(INTERP, s, CONST_STRING(INTERP, "L"));
}
/*
=item C<void increment()>
Increments the integer.
=cut
*/
VTABLE void increment() {
bigint_add_bigint_int(INTERP, SELF, 1, SELF);
}
/*
=item C<void decrement()>
Decrements the integer.
=cut
*/
VTABLE void decrement() {
bigint_sub_bigint_int(INTERP, SELF, 1, SELF);
}
MULTI PMC *add(BigInt value, PMC *dest) :no_wb {
dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
bigint_add_bigint(INTERP, SELF, value, dest);
return dest;
}
MULTI PMC *add(Integer value, PMC *dest) :no_wb {
dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
bigint_add_bigint_int(INTERP, SELF, VTABLE_get_integer(INTERP, value), dest);
return dest;
}
MULTI PMC *add(DEFAULT value, PMC *dest) :no_wb {
UNUSED(SELF)
UNUSED(dest)
NO_MULTIPLE_DISPATCH("add");
}
VTABLE PMC *add_int(INTVAL value, PMC *dest) :no_wb {
dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
bigint_add_bigint_int(INTERP, SELF, value, dest);
return dest;
}
MULTI void i_add(BigInt value) {
bigint_add_bigint(INTERP, SELF, value, SELF);
}
MULTI void i_add(Integer value) {
bigint_add_bigint_int(INTERP, SELF, VTABLE_get_integer(INTERP, value), SELF);
}
MULTI void i_add(DEFAULT value) :no_wb {
UNUSED(SELF)
NO_MULTIPLE_DISPATCH("i_add");
}
VTABLE void i_add_int(INTVAL value) {
bigint_add_bigint_int(INTERP, SELF, value, SELF);
}
VTABLE void i_add_float(FLOATVAL value) :no_wb {
UNUSED(SELF)
UNUSED(value)
NO_MULTIPLE_DISPATCH_FLOAT("i_add_float");
}
MULTI PMC *subtract(BigInt value, PMC *dest) :no_wb {
dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
bigint_sub_bigint(INTERP, SELF, value, dest);
return dest;
}
MULTI PMC *subtract(Integer value, PMC *dest) :no_wb {
dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
bigint_sub_bigint_int(INTERP, SELF, VTABLE_get_integer(INTERP, value), dest);
return dest;
}
MULTI PMC *subtract(DEFAULT value, PMC *dest) :no_wb {
UNUSED(SELF)
UNUSED(dest)
NO_MULTIPLE_DISPATCH("subtract");
}
VTABLE PMC *subtract_int(INTVAL value, PMC *dest) :no_wb {
dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
bigint_sub_bigint_int(INTERP, SELF, value, dest);
return dest;
}
MULTI void i_subtract(BigInt value) {
bigint_sub_bigint(INTERP, SELF, value, SELF);
}
MULTI void i_subtract(Integer value) {
bigint_sub_bigint_int(INTERP, SELF, VTABLE_get_integer(INTERP, value), SELF);
}
MULTI void i_subtract(DEFAULT value) :no_wb {
UNUSED(SELF)
NO_MULTIPLE_DISPATCH("i_subtract");
}
VTABLE void i_subtract_int(INTVAL value) {
bigint_sub_bigint_int(INTERP, SELF, value, SELF);
}
VTABLE void i_subtract_float(FLOATVAL value) :no_wb {
UNUSED(SELF)
UNUSED(value)
NO_MULTIPLE_DISPATCH_FLOAT("i_subtract_float");
}
MULTI PMC *multiply(BigInt value, PMC *dest) :no_wb {
dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
bigint_mul_bigint(INTERP, SELF, value, dest);
return dest;
}
MULTI PMC *multiply(Integer value, PMC *dest) :no_wb {
dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
bigint_mul_bigint_int(INTERP, SELF, VTABLE_get_integer(INTERP, value), dest);
return dest;
}
MULTI PMC *multiply(DEFAULT value, PMC *dest) :no_wb {
UNUSED(SELF)
UNUSED(dest)
NO_MULTIPLE_DISPATCH("multiply");
}
VTABLE PMC *multiply_int(INTVAL value, PMC *dest) :no_wb {
dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
bigint_mul_bigint_int(INTERP, SELF, value, dest);
return dest;
}
MULTI void i_multiply(BigInt value) {
bigint_mul_bigint(INTERP, SELF, value, SELF);
}
MULTI void i_multiply(Integer value) {
bigint_mul_bigint_int(INTERP, SELF, VTABLE_get_integer(INTERP, value), SELF);
}
MULTI void i_multiply(DEFAULT value) :no_wb {
UNUSED(SELF)
Parrot_ex_throw_from_c_args(INTERP, NULL,
EXCEPTION_INTERNAL_NOT_IMPLEMENTED,
"BigInt: no multiple dispatch variant '%s' for %Ss",
"i_multiply", VTABLE_name(INTERP, value));
}
VTABLE void i_multiply_int(INTVAL value) {
bigint_mul_bigint_int(INTERP, SELF, value, SELF);
}
VTABLE void i_multiply_float(FLOATVAL value) :no_wb {
UNUSED(SELF)
UNUSED(value)
NO_MULTIPLE_DISPATCH_FLOAT("i_multiply_float");
}
METHOD PMC *pow(PMC *value) :no_wb {
/* XXX only Integer RHS currently */
const INTVAL r = VTABLE_get_integer(INTERP, value);
PMC * const dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
bigint_pow_bigint_int(INTERP, SELF, r, dest);
RETURN(PMC *dest);
}
MULTI PMC *divide(BigInt value, PMC *dest) :no_wb {
dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
bigint_div_bigint(INTERP, SELF, value, dest);
return dest;
}
MULTI PMC *divide(Integer value, PMC *dest) :no_wb {
dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
bigint_div_bigint_int(INTERP, SELF, VTABLE_get_integer(INTERP, value), dest);
return dest;
}
MULTI PMC *divide(DEFAULT value, PMC *dest) :no_wb {
UNUSED(SELF)
UNUSED(dest)
NO_MULTIPLE_DISPATCH("divide");
}
VTABLE PMC *divide_int(INTVAL value, PMC *dest) :no_wb {
dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
bigint_div_bigint_int(INTERP, SELF, value, dest);
return dest;
}
MULTI void i_divide(BigInt value) {
bigint_div_bigint(INTERP, SELF, value, SELF);
}
MULTI void i_divide(Integer value) {
bigint_div_bigint_int(INTERP, SELF, VTABLE_get_integer(INTERP, value), SELF);
}
MULTI void i_divide(DEFAULT value) :no_wb {
UNUSED(SELF)
NO_MULTIPLE_DISPATCH("i_divide");
}
VTABLE void i_divide_int(INTVAL value) {
bigint_div_bigint_int(INTERP, SELF, value, SELF);
}
MULTI PMC *floor_divide(BigInt value, PMC *dest) :no_wb {
dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
bigint_fdiv_bigint(INTERP, SELF, value, dest);
return dest;
}
MULTI PMC *floor_divide(Integer value, PMC *dest) :no_wb {
dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
bigint_fdiv_bigint_int(INTERP, SELF, VTABLE_get_integer(INTERP, value), dest);
return dest;
}
MULTI PMC *floor_divide(DEFAULT value, PMC *dest) :no_wb {
UNUSED(SELF)
UNUSED(dest)
NO_MULTIPLE_DISPATCH("floor_divide");
}
VTABLE PMC *floor_divide_int(INTVAL value, PMC *dest) :no_wb {
dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
bigint_fdiv_bigint_int(INTERP, SELF, value, dest);
return dest;
}
MULTI void i_floor_divide(BigInt value) {
bigint_fdiv_bigint(INTERP, SELF, value, SELF);
}
MULTI void i_floor_divide(Integer value) {
bigint_fdiv_bigint_int(INTERP, SELF, VTABLE_get_integer(INTERP, value), SELF);
}
MULTI void i_floor_divide(DEFAULT value) :no_wb {
UNUSED(SELF)
NO_MULTIPLE_DISPATCH("i_floor_divide");
}
VTABLE void i_floor_divide_int(INTVAL value) {
bigint_fdiv_bigint_int(INTERP, SELF, value, SELF);
}
MULTI PMC *modulus(BigInt value, PMC *dest) :no_wb {
dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
bigint_mod_bigint(INTERP, SELF, value, dest);
return dest;
}
MULTI PMC *modulus(Integer value, PMC *dest) :no_wb {
dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
bigint_mod_bigint_int(INTERP, SELF, VTABLE_get_integer(INTERP, value), dest);
return dest;
}
MULTI PMC *modulus(DEFAULT value, PMC *dest) :no_wb {
UNUSED(SELF)
UNUSED(dest)
NO_MULTIPLE_DISPATCH("modulus");
}
MULTI void i_modulus(BigInt value) {
bigint_mod_bigint(INTERP, SELF, value, SELF);
}
MULTI void i_modulus(Integer value) {
bigint_mod_bigint_int(INTERP, SELF, VTABLE_get_integer(INTERP, value), SELF);
}
MULTI void i_modulus(DEFAULT value) :no_wb {
UNUSED(SELF)
NO_MULTIPLE_DISPATCH("i_modulus");
}
MULTI INTVAL cmp(BigInt value) :no_wb {
return bigint_cmp(INTERP, SELF, value);
}
MULTI INTVAL cmp(Integer value) :no_wb {
return bigint_cmp_int(INTERP, SELF, VTABLE_get_integer(INTERP, value));
}
MULTI INTVAL cmp(DEFAULT value) :no_wb {
UNUSED(SELF)
NO_MULTIPLE_DISPATCH("cmp");
}
MULTI INTVAL is_equal(BigInt value) :no_wb {
return bigint_cmp(INTERP, SELF, value) == 0;
}
MULTI INTVAL is_equal(Integer value) :no_wb {
return bigint_cmp_int(INTERP, SELF, VTABLE_get_integer(INTERP, value)) == 0;
}
MULTI INTVAL is_equal(DEFAULT value) :no_wb {
UNUSED(SELF)
NO_MULTIPLE_DISPATCH("is_equal");
}
/*
=item C<PMC *absolute(PMC *dest)>
=item C<void i_absolute()>
Sets C<dest> to the absolute value of SELF.
=cut
*/
VTABLE PMC *absolute(PMC *dest) :no_wb {
dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
bigint_abs(INTERP, SELF, dest);
return dest;
}
VTABLE void i_absolute() {
bigint_abs(INTERP, SELF, SELF);
}
/*
=item C<PMC *neg(PMC *dest)>
=item C<void i_neg()>
Set C<dest> to the negated value of C<SELF>.
=cut
*/
VTABLE PMC *neg(PMC *dest) :no_wb {
dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
bigint_neg(INTERP, SELF, dest);
return dest;
}
VTABLE void i_neg() {
bigint_neg(INTERP, SELF, SELF);
}
}
/*
=back
=cut
*/
/*
* Local variables:
* c-file-style: "parrot"
* End:
* vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
*/