From Code to Community: Sponsoring The Perl and Raku Conference 2025 Learn more

# [[[ HEADER ]]]
use strict;
our $VERSION = 0.004_000;
# [[[ OO INHERITANCE ]]]
# [[[ CRITICS ]]]
## no critic qw(ProhibitUselessNoCritic ProhibitMagicNumbers RequireCheckedSyscalls) # USER DEFAULT 1: allow numeric values & print operator
## no critic qw(RequireInterpolationOfMetachars) # USER DEFAULT 2: allow single-quoted control characters & sigils
# [[[ INCLUDES ]]]
use Math::BigInt lib => 'GMP'; # we still actually use GMP in PERLOPS_PERLTYPES mode, albeit indirectly via Math::BigInt::GMP
use RPerl::Exporter 'import';
our @EXPORT = qw(
gmp_init gmp_init_set_unsigned_integer gmp_init_set_signed_integer
gmp_set gmp_set_unsigned_integer gmp_set_signed_integer gmp_set_number gmp_set_string
gmp_get_unsigned_integer gmp_get_signed_integer gmp_get_number gmp_get_string
gmp_add gmp_sub gmp_mul gmp_mul_unsigned_integer gmp_mul_signed_integer gmp_sub_mul_unsigned_integer gmp_add_mul_unsigned_integer gmp_neg
gmp_div_truncate_quotient
gmp_cmp
);
# [[[ OO PROPERTIES ]]]
our hashref $properties = {};
# [[[ SUBROUTINES & OO METHODS ]]]
# [[[ INITIALIZATION FUNCTIONS ]]]
# void mpz_init (mpz_t x)
sub gmp_init {
{ my void $RETURN_TYPE };
# ( my gmp_integer $x ) = @ARG;
return;
}
# [[[ COMBINED INITIALIZATION AND ASSIGNMENT FUNCTIONS ]]]
# void mpz_init_set_ui (mpz_t rop, unsigned long int op)
sub gmp_init_set_unsigned_integer {
{ my void $RETURN_TYPE };
( my gmp_integer $rop, my unsigned_integer $op ) = @ARG;
$rop->bzero();
$rop->badd($op);
return;
}
# void mpz_init_set_si (mpz_t rop, signed long int op)
sub gmp_init_set_signed_integer {
{ my void $RETURN_TYPE };
( my gmp_integer $rop, my integer $op ) = @ARG;
$rop->bzero();
$rop->badd($op);
return;
}
# [[[ ASSIGNMENT FUNCTIONS ]]]
# void mpz_set (mpz_t rop, const mpz_t op)
sub gmp_set {
{ my void $RETURN_TYPE };
( my gmp_integer $rop, my gmp_integer $op ) = @ARG;
$rop->bzero();
$rop->badd($op);
return;
}
# void mpz_set_ui (mpz_t rop, unsigned long int op)
sub gmp_set_unsigned_integer {
{ my void $RETURN_TYPE };
( my gmp_integer $rop, my unsigned_integer $op ) = @ARG;
$rop->bzero();
$rop->badd($op);
return;
}
# void mpz_set_si (mpz_t rop, signed long int op)
sub gmp_set_signed_integer {
{ my void $RETURN_TYPE };
( my gmp_integer $rop, my integer $op ) = @ARG;
$rop->bzero();
$rop->badd($op);
return;
}
# void mpz_set_d (mpz_t rop, double op)
sub gmp_set_number {
{ my void $RETURN_TYPE };
( my gmp_integer $rop, my number $op ) = @ARG;
$rop->bzero();
$rop->badd($op);
return;
}
# int mpz_set_str (mpz_t rop, const char *str, int base)
sub gmp_set_string {
{ my integer $RETURN_TYPE };
( my gmp_integer $rop, my string $str ) = @ARG;
my Math::BigInt $tmp = Math::BigInt->new($str);
$rop->bzero();
$rop->badd($tmp);
return;
}
# [[[ CONVERSION FUNCTIONS ]]]
# unsigned long int mpz_get_ui (const mpz_t op)
sub gmp_get_unsigned_integer {
{ my unsigned_integer $RETURN_TYPE };
( my gmp_integer $op ) = @ARG;
return $op->numify();
}
# signed long int mpz_get_si (const mpz_t op)
sub gmp_get_signed_integer {
{ my integer $RETURN_TYPE };
( my gmp_integer $op ) = @ARG;
return $op->numify();
}
# double mpz_get_d (const mpz_t op)
sub gmp_get_number {
{ my integer $RETURN_TYPE };
( my gmp_integer $op ) = @ARG;
return $op->numify();
}
# char * mpz_get_str (char *str, int base, const mpz_t op)
sub gmp_get_string {
{ my string $RETURN_TYPE };
( my gmp_integer $op ) = @ARG;
return $op->bstr();
}
# [[[ ARITHMETIC FUNCTIONS ]]]
# void mpz_add (mpz_t rop, const mpz_t op1, const mpz_t op2)
sub gmp_add {
{ my gmp_integer $RETURN_TYPE };
( my gmp_integer $rop, my gmp_integer $op1, my gmp_integer $op2 ) = @ARG;
# in case $op1 and/or $op2 are the same variables as $rop, make copies so you don't zero them out before reading them
my gmp_integer $op1_copy = $op1->copy();
my gmp_integer $op2_copy = $op2->copy();
$rop->bzero();
$rop->badd($op1_copy);
$rop->badd($op2_copy);
return;
}
# void mpz_sub (mpz_t rop, const mpz_t op1, const mpz_t op2)
sub gmp_sub {
{ my gmp_integer $RETURN_TYPE };
( my gmp_integer $rop, my gmp_integer $op1, my gmp_integer $op2 ) = @ARG;
my gmp_integer $op1_copy = $op1->copy();
my gmp_integer $op2_copy = $op2->copy();
$rop->bzero();
$rop->badd($op1_copy);
$rop->bsub($op2_copy);
return;
}
# void mpz_mul (mpz_t rop, const mpz_t op1, const mpz_t op2)
sub gmp_mul {
{ my void $RETURN_TYPE };
( my gmp_integer $rop, my gmp_integer $op1, my gmp_integer $op2 ) = @ARG;
my gmp_integer $op1_copy = $op1->copy();
$rop->bzero();
$rop->badd($op1_copy);
$rop->bmul($op2);
return;
}
# void mpz_mul_ui (mpz_t rop, const mpz_t op1, unsigned long int op2)
sub gmp_mul_unsigned_integer {
{ my void $RETURN_TYPE };
( my gmp_integer $rop, my gmp_integer $op1, my unsigned_integer $op2 ) = @ARG;
my gmp_integer $op1_copy = $op1->copy();
$rop->bzero();
$rop->badd($op1_copy);
$rop->bmul($op2);
return;
}
# void mpz_mul_si (mpz_t rop, const mpz_t op1, long int op2)
sub gmp_mul_signed_integer {
{ my void $RETURN_TYPE };
( my gmp_integer $rop, my gmp_integer $op1, my integer $op2 ) = @ARG;
my gmp_integer $op1_copy = $op1->copy();
$rop->bzero();
$rop->badd($op1_copy);
$rop->bmul($op2);
return;
}
# void mpz_submul_ui (mpz_t rop, const mpz_t op1, unsigned long int op2)
sub gmp_sub_mul_unsigned_integer {
{ my gmp_integer $RETURN_TYPE };
( my gmp_integer $rop, my gmp_integer $op1, my unsigned_integer $op2 ) = @ARG;
my gmp_integer $op1_copy = $op1->copy();
$op1_copy->bmul($op2);
$rop->bsub($op1_copy);
return;
}
# void mpz_addmul_ui (mpz_t rop, const mpz_t op1, unsigned long int op2)
sub gmp_add_mul_unsigned_integer {
{ my void $RETURN_TYPE };
( my gmp_integer $rop, my gmp_integer $op1, my unsigned_integer $op2 ) = @ARG;
my gmp_integer $op1_copy = $op1->copy();
$op1_copy->bmul($op2);
$rop->badd($op1_copy);
return;
}
# void mpz_neg (mpz_t rop, const mpz_t op)
sub gmp_neg {
{ my void $RETURN_TYPE };
( my gmp_integer $rop, my gmp_integer $op1 ) = @ARG;
my gmp_integer $op1_copy = $op1->copy();
$rop->bzero();
$rop->badd($op1_copy);
$rop->bmul(Math::BigInt->bone('-'));
return;
}
# [[[ DIVISION FUNCTIONS ]]]
# void mpz_tdiv_q (mpz_t q, const mpz_t n, const mpz_t d)
sub gmp_div_truncate_quotient {
{ my void $RETURN_TYPE };
( my gmp_integer $q, my gmp_integer $n, my gmp_integer $d ) = @ARG;
my gmp_integer $n_copy = $n->copy();
my gmp_integer $d_copy = $d->copy();
$q->bzero();
$q->badd($n_copy);
$q->bdiv($d_copy);
return;
}
# [[[ COMPARISON FUNCTIONS ]]]
# int mpz_cmp (const mpz_t op1, const mpz_t op2)
sub gmp_cmp {
{ my integer $RETURN_TYPE };
( my gmp_integer $op1, my gmp_integer $op2 ) = @ARG;
return $op1->bcmp($op2);
}
1; # end of class