# Supported library versions: # # * libgmp # * libmpir # # See https://crystal-lang.org/reference/man/required_libraries.html#big-numbers {% if flag?(:win32) && !flag?(:gnu) %} @[Link("mpir")] {% if compare_versions(Crystal::VERSION, "1.11.0-dev") >= 0 %} @[Link(dll: "mpir.dll")] {% end %} {% else %} @[Link("gmp")] {% end %} lib LibGMP alias Int = LibC::Int alias Long = LibC::Long alias ULong = LibC::ULong # MPIR uses its own `mpir_si` and `mpir_ui` typedefs in places where GMP uses # the LibC types, when the function name has `si` or `ui`; we follow this # distinction {% if flag?(:win32) && !flag?(:gnu) && flag?(:bits64) %} alias SI = LibC::LongLong alias UI = LibC::ULongLong {% else %} alias SI = LibC::Long alias UI = LibC::ULong {% end %} alias SizeT = LibC::SizeT alias Double = LibC::Double alias BitcntT = UI alias MpExp = LibC::Long {% if flag?(:win32) && !flag?(:gnu) %} alias MpSize = LibC::LongLong {% else %} alias MpSize = LibC::Long {% end %} # NOTE: this assumes GMP is configured by build time to define # `_LONG_LONG_LIMB=1` on Windows {% if flag?(:win32) %} alias MpLimb = LibC::ULongLong {% else %} alias MpLimb = LibC::ULong {% end %} struct MPZ _mp_alloc : Int _mp_size : Int _mp_d : MpLimb* end # # Initialization fun init = __gmpz_init(x : MPZ*) fun init2 = __gmpz_init2(x : MPZ*, bits : BitcntT) fun init_set_ui = __gmpz_init_set_ui(rop : MPZ*, op : UI) fun init_set_si = __gmpz_init_set_si(rop : MPZ*, op : SI) fun init_set_d = __gmpz_init_set_d(rop : MPZ*, op : Double) fun init_set_str = __gmpz_init_set_str(rop : MPZ*, str : UInt8*, base : Int) : Int # # I/O fun set = __gmpz_set(rop : MPZ*, op : MPZ*) fun set_ui = __gmpz_set_ui(rop : MPZ*, op : UI) fun set_si = __gmpz_set_si(rop : MPZ*, op : SI) fun set_d = __gmpz_set_d(rop : MPZ*, op : Double) fun set_q = __gmpz_set_q(rop : MPZ*, op : MPQ*) fun set_f = __gmpz_set_f(rop : MPZ*, op : MPF*) fun set_str = __gmpz_set_str(rop : MPZ*, str : UInt8*, base : Int) : Int fun get_str = __gmpz_get_str(str : UInt8*, base : Int, op : MPZ*) : UInt8* fun get_si = __gmpz_get_si(op : MPZ*) : SI fun get_ui = __gmpz_get_ui(op : MPZ*) : UI fun get_d = __gmpz_get_d(op : MPZ*) : Double fun get_d_2exp = __gmpz_get_d_2exp(exp : Long*, op : MPZ*) : Double # # Arithmetic fun add = __gmpz_add(rop : MPZ*, op1 : MPZ*, op2 : MPZ*) fun add_ui = __gmpz_add_ui(rop : MPZ*, op1 : MPZ*, op2 : UI) fun sub = __gmpz_sub(rop : MPZ*, op1 : MPZ*, op2 : MPZ*) fun sub_ui = __gmpz_sub_ui(rop : MPZ*, op1 : MPZ*, op2 : UI) fun ui_sub = __gmpz_ui_sub(rop : MPZ*, op1 : UI, op2 : MPZ*) fun mul = __gmpz_mul(rop : MPZ*, op1 : MPZ*, op2 : MPZ*) fun mul_si = __gmpz_mul_si(rop : MPZ*, op1 : MPZ*, op2 : SI) fun mul_ui = __gmpz_mul_ui(rop : MPZ*, op1 : MPZ*, op2 : UI) fun addmul = __gmpz_addmul(rop : MPZ*, op1 : MPZ*, op2 : MPZ*) fun addmul_ui = __gmpz_addmul_ui(rop : MPZ*, op1 : MPZ*, op2 : UI) fun fdiv_q = __gmpz_fdiv_q(rop : MPZ*, op1 : MPZ*, op2 : MPZ*) fun fdiv_q_ui = __gmpz_fdiv_q_ui(rop : MPZ*, op1 : MPZ*, op2 : UI) fun tdiv_q = __gmpz_tdiv_q(rop : MPZ*, op1 : MPZ*, op2 : MPZ*) fun tdiv_q_ui = __gmpz_tdiv_q_ui(rop : MPZ*, op1 : MPZ*, op2 : UI) fun fdiv_r = __gmpz_fdiv_r(rop : MPZ*, op1 : MPZ*, op2 : MPZ*) fun fdiv_r_ui = __gmpz_fdiv_r_ui(rop : MPZ*, op1 : MPZ*, op2 : UI) fun fdiv_qr = __gmpz_fdiv_qr(q : MPZ*, r : MPZ*, n : MPZ*, d : MPZ*) fun fdiv_qr_ui = __gmpz_fdiv_qr_ui(q : MPZ*, r : MPZ*, n : MPZ*, d : UI) : UI fun tdiv_r = __gmpz_tdiv_r(rop : MPZ*, op1 : MPZ*, op2 : MPZ*) fun tdiv_r_ui = __gmpz_tdiv_r_ui(rop : MPZ*, op1 : MPZ*, op2 : UI) fun tdiv_ui = __gmpz_tdiv_ui(op1 : MPZ*, op2 : UI) : UI fun tdiv_qr = __gmpz_tdiv_qr(q : MPZ*, r : MPZ*, n : MPZ*, d : MPZ*) fun tdiv_qr_ui = __gmpz_tdiv_qr_ui(q : MPZ*, r : MPZ*, n : MPZ*, d : UI) : UI fun divisible_p = __gmpz_divisible_p(n : MPZ*, d : MPZ*) : Int fun divisible_ui_p = __gmpz_divisible_ui_p(n : MPZ*, d : UI) : Int fun neg = __gmpz_neg(rop : MPZ*, op : MPZ*) fun abs = __gmpz_abs(rop : MPZ*, op : MPZ*) fun pow_ui = __gmpz_pow_ui(rop : MPZ*, base : MPZ*, exp : UI) fun fac_ui = __gmpz_fac_ui(rop : MPZ*, n : UI) fun sqrt = __gmpz_sqrt(rop : MPZ*, op : MPZ*) # # Bitwise operations fun and = __gmpz_and(rop : MPZ*, op1 : MPZ*, op2 : MPZ*) fun ior = __gmpz_ior(rop : MPZ*, op1 : MPZ*, op2 : MPZ*) fun xor = __gmpz_xor(rop : MPZ*, op1 : MPZ*, op2 : MPZ*) fun com = __gmpz_com(rop : MPZ*, op : MPZ*) fun tstbit = __gmpz_tstbit(op : MPZ*, bit_index : BitcntT) : Int fun fdiv_q_2exp = __gmpz_fdiv_q_2exp(q : MPZ*, n : MPZ*, b : BitcntT) fun mul_2exp = __gmpz_mul_2exp(rop : MPZ*, op1 : MPZ*, op2 : BitcntT) # # Logic fun popcount = __gmpz_popcount(op : MPZ*) : BitcntT fun scan0 = __gmpz_scan0(op : MPZ*, starting_bit : BitcntT) : BitcntT fun scan1 = __gmpz_scan1(op : MPZ*, starting_bit : BitcntT) : BitcntT fun sizeinbase = __gmpz_sizeinbase(op : MPZ*, base : Int) : SizeT # # Comparison fun cmp = __gmpz_cmp(op1 : MPZ*, op2 : MPZ*) : Int fun cmp_si = __gmpz_cmp_si(op1 : MPZ*, op2 : SI) : Int fun cmp_ui = __gmpz_cmp_ui(op1 : MPZ*, op2 : UI) : Int fun cmp_d = __gmpz_cmp_d(op1 : MPZ*, op2 : Double) : Int # # Number Theoretic Functions fun gcd = __gmpz_gcd(rop : MPZ*, op1 : MPZ*, op2 : MPZ*) fun gcd_ui = __gmpz_gcd_ui(rop : MPZ*, op1 : MPZ*, op2 : UI) : UI fun lcm = __gmpz_lcm(rop : MPZ*, op1 : MPZ*, op2 : MPZ*) fun lcm_ui = __gmpz_lcm_ui(rop : MPZ*, op1 : MPZ*, op2 : UI) fun invert = __gmpz_invert(rop : MPZ*, op1 : MPZ*, op2 : MPZ*) : Int fun remove = __gmpz_remove(rop : MPZ*, op : MPZ*, f : MPZ*) : BitcntT # # Miscellaneous Functions {% if flag?(:win32) && !flag?(:gnu) %} fun fits_ui_p = __gmpz_fits_ui_p(op : MPZ*) : Int fun fits_si_p = __gmpz_fits_si_p(op : MPZ*) : Int {% else %} fun fits_ulong_p = __gmpz_fits_ulong_p(op : MPZ*) : Int fun fits_slong_p = __gmpz_fits_slong_p(op : MPZ*) : Int {% end %} # # Special Functions fun size = __gmpz_size(op : MPZ*) : SizeT fun limbs_read = __gmpz_limbs_read(x : MPZ*) : MpLimb* fun limbs_write = __gmpz_limbs_write(x : MPZ*, n : MpSize) : MpLimb* fun limbs_finish = __gmpz_limbs_finish(x : MPZ*, s : MpSize) # MPQ struct MPQ _mp_num : MPZ _mp_den : MPZ end # # Initialization fun mpq_init = __gmpq_init(x : MPQ*) fun mpq_set_num = __gmpq_set_num(x : MPQ*, num : MPZ*) fun mpq_set_den = __gmpq_set_den(x : MPQ*, den : MPZ*) fun mpq_get_num = __gmpq_get_num(rop : MPZ*, op : MPQ*) fun mpq_get_den = __gmpq_get_den(rop : MPZ*, op : MPQ*) fun mpq_canonicalize = __gmpq_canonicalize(x : MPQ*) # # Conversion fun mpq_get_str = __gmpq_get_str(str : UInt8*, base : Int, op : MPQ*) : UInt8* fun mpq_get_d = __gmpq_get_d(op : MPQ*) : Double fun mpq_set_d = __gmpq_set_d(rop : MPQ*, op : Double) fun mpq_set_f = __gmpq_set_f(rop : MPQ*, op : MPF*) # # Arithmetic fun mpq_add = __gmpq_add(rop : MPQ*, op1 : MPQ*, op2 : MPQ*) fun mpq_sub = __gmpq_sub(rop : MPQ*, op1 : MPQ*, op2 : MPQ*) fun mpq_mul = __gmpq_mul(rop : MPQ*, op1 : MPQ*, op2 : MPQ*) fun mpq_div = __gmpq_div(rop : MPQ*, op1 : MPQ*, op2 : MPQ*) fun mpq_inv = __gmpq_inv(rop : MPQ*, op1 : MPQ*) fun mpq_neg = __gmpq_neg(rop : MPQ*, op1 : MPQ*) fun mpq_abs = __gmpq_abs(rop : MPQ*, op1 : MPQ*) fun mpq_div_2exp = __gmpq_div_2exp(q : MPQ*, n : MPQ*, b : BitcntT) fun mpq_mul_2exp = __gmpq_mul_2exp(rop : MPQ*, op1 : MPQ*, op2 : BitcntT) # # Compare fun mpq_cmp = __gmpq_cmp(op1 : MPQ*, op2 : MPQ*) : Int fun mpq_cmp_z = __gmpq_cmp_z(op1 : MPQ*, op2 : MPZ*) : Int fun mpq_cmp_ui = __gmpq_cmp_ui(op1 : MPQ*, num2 : UI, den2 : UI) : Int fun mpq_cmp_si = __gmpq_cmp_si(op1 : MPQ*, num2 : SI, den2 : UI) : Int fun mpq_equal = __gmpq_equal(op1 : MPQ*, op2 : MPQ*) : Int # MPF struct MPF _mp_prec : Int _mp_size : Int _mp_exp : MpExp _mp_d : MpLimb* end # # Initialization fun mpf_init = __gmpf_init(x : MPF*) fun mpf_init2 = __gmpf_init2(x : MPF*, prec : BitcntT) fun mpf_init_set_d = __gmpf_init_set_d(rop : MPF*, op : Double) fun mpf_init_set_str = __gmpf_init_set_str(rop : MPF*, str : UInt8*, base : Int) : Int fun mpf_init_set_ui = __gmpf_init_set_ui(rop : MPF*, op : UI) fun mpf_init_set_si = __gmpf_init_set_si(rop : MPF*, op : SI) # # Precision fun mpf_set_default_prec = __gmpf_set_default_prec(prec : BitcntT) fun mpf_get_default_prec = __gmpf_get_default_prec : BitcntT fun mpf_get_prec = __gmpf_get_prec(op : MPF*) : BitcntT # # Conversion fun mpf_get_str = __gmpf_get_str(str : UInt8*, expptr : MpExp*, base : Int, n_digits : LibC::SizeT, op : MPF*) : UInt8* fun mpf_get_d = __gmpf_get_d(op : MPF*) : Double fun mpf_set_d = __gmpf_set_d(rop : MPF*, op : Double) fun mpf_set = __gmpf_set(rop : MPF*, op : MPF*) fun mpf_set_z = __gmpf_set_z(rop : MPF*, op : MPZ*) fun mpf_set_q = __gmpf_set_q(rop : MPF*, op : MPQ*) fun mpf_get_si = __gmpf_get_si(op : MPF*) : SI fun mpf_get_ui = __gmpf_get_ui(op : MPF*) : UI fun mpf_get_d_2exp = __gmpf_get_d_2exp(exp : Long*, op : MPF*) : Double # # Arithmetic fun mpf_add = __gmpf_add(rop : MPF*, op1 : MPF*, op2 : MPF*) fun mpf_add_ui = __gmpf_add_ui(rop : MPF*, op1 : MPF*, op2 : UI) fun mpf_sub = __gmpf_sub(rop : MPF*, op1 : MPF*, op2 : MPF*) fun mpf_sub_ui = __gmpf_sub_ui(rop : MPF*, op1 : MPF*, op2 : UI) fun mpf_mul = __gmpf_mul(rop : MPF*, op1 : MPF*, op2 : MPF*) fun mpf_mul_ui = __gmpf_mul_ui(rop : MPF*, op1 : MPF*, op2 : UI) fun mpf_div = __gmpf_div(rop : MPF*, op1 : MPF*, op2 : MPF*) fun mpf_div_ui = __gmpf_div_ui(rop : MPF*, op1 : MPF*, op2 : UI) fun mpf_ui_div = __gmpf_ui_div(rop : MPF*, op1 : UI, op2 : MPF*) fun mpf_neg = __gmpf_neg(rop : MPF*, op : MPF*) fun mpf_abs = __gmpf_abs(rop : MPF*, op : MPF*) fun mpf_sqrt = __gmpf_sqrt(rop : MPF*, op : MPF*) fun mpf_pow_ui = __gmpf_pow_ui(rop : MPF*, op1 : MPF*, op2 : UI) fun mpf_mul_2exp = __gmpf_mul_2exp(rop : MPF*, op1 : MPF*, op2 : BitcntT) fun mpf_div_2exp = __gmpf_div_2exp(rop : MPF*, op1 : MPF*, op2 : BitcntT) # # Comparison fun mpf_cmp = __gmpf_cmp(op1 : MPF*, op2 : MPF*) : Int fun mpf_cmp_d = __gmpf_cmp_d(op1 : MPF*, op2 : Double) : Int fun mpf_cmp_ui = __gmpf_cmp_ui(op1 : MPF*, op2 : UI) : Int fun mpf_cmp_si = __gmpf_cmp_si(op1 : MPF*, op2 : SI) : Int fun mpf_cmp_z = __gmpf_cmp_z(op1 : MPF*, op2 : MPZ*) : Int # # Miscellaneous fun mpf_ceil = __gmpf_ceil(rop : MPF*, op : MPF*) fun mpf_floor = __gmpf_floor(rop : MPF*, op : MPF*) fun mpf_trunc = __gmpf_trunc(rop : MPF*, op : MPF*) fun mpf_integer_p = __gmpf_integer_p(op : MPF*) : Int # # Memory fun set_memory_functions = __gmp_set_memory_functions(malloc : SizeT -> Void*, realloc : Void*, SizeT, SizeT -> Void*, free : Void*, SizeT ->) end LibGMP.set_memory_functions( ->(size) { GC.malloc(size) }, ->(ptr, old_size, new_size) { GC.realloc(ptr, new_size) }, ->(ptr, size) { GC.free(ptr) } )