Branch :
/* c3
* Copyright 2022,2023 kmx.io <contact@kmx.io>
*
* Permission is hereby granted to use this software granted the above
* copyright notice and this permission paragraph are included in all
* copies and substantial portions of this software.
*
* THIS SOFTWARE IS PROVIDED "AS-IS" WITHOUT ANY GUARANTEE OF
* PURPOSE AND PERFORMANCE. IN NO EVENT WHATSOEVER SHALL THE
* AUTHOR BE CONSIDERED LIABLE FOR THE USE AND PERFORMANCE OF
* THIS SOFTWARE.
*/
#include <assert.h>
#include <err.h>
#include <stdlib.h>
#include "buf.h"
#include "buf_parse.h"
#include "compare.h"
#include "integer.h"
s_integer * integer_abs (const s_integer *a, s_integer *dest)
{
sw r;
assert(a);
assert(dest);
if ((r = mp_abs(&a->mp_int, &dest->mp_int)) != MP_OKAY)
errx(1, "integer_abs: %s", mp_error_to_string(r));
return dest;
}
s_integer * integer_add (const s_integer *a, const s_integer *b,
s_integer *dest)
{
sw r;
assert(dest);
assert(a);
assert(b);
if ((r = mp_add(&a->mp_int, &b->mp_int, &dest->mp_int)) != MP_OKAY)
errx(1, "integer_add: %s", mp_error_to_string(r));
return dest;
}
s_integer * integer_band (const s_integer *a, const s_integer *b,
s_integer *dest)
{
sw r;
assert(a);
assert(b);
assert(dest);
if ((r = mp_and(&a->mp_int, &b->mp_int, &dest->mp_int)) != MP_OKAY)
errx(1, "integer_band: %s", mp_error_to_string(r));
return dest;
}
uw integer_bits (const s_integer *i)
{
uw bits;
if (integer_is_zero(i))
return 1;
bits = mp_count_bits(&i->mp_int);
if (integer_is_negative(i))
bits++;
return bits;
}
s_integer * integer_bnot (const s_integer *a, s_integer *dest)
{
sw r;
assert(a);
assert(dest);
if ((r = mp_complement(&a->mp_int, &dest->mp_int)) != MP_OKAY)
errx(1, "integer_bnot: %s", mp_error_to_string(r));
return dest;
}
s_integer * integer_bor (const s_integer *a, const s_integer *b,
s_integer *dest)
{
sw r;
assert(a);
assert(b);
assert(dest);
if ((r = mp_or(&a->mp_int, &b->mp_int, &dest->mp_int)) != MP_OKAY)
errx(1, "integer_bor: %s", mp_error_to_string(r));
return dest;
}
s_integer * integer_bxor (const s_integer *a, const s_integer *b,
s_integer *dest)
{
sw r;
assert(a);
assert(b);
assert(dest);
if ((r = mp_xor(&a->mp_int, &b->mp_int, &dest->mp_int)) != MP_OKAY)
errx(1, "integer_bxor: %s", mp_error_to_string(r));
return dest;
}
uw integer_bytes (const s_integer *i)
{
return (integer_bits(i) + 7) / 8;
}
void integer_clean (s_integer *dest)
{
assert(dest);
mp_clear(&dest->mp_int);
}
s_integer * integer_copy (const s_integer *a, s_integer *dest)
{
sw r;
assert(a);
assert(dest);
if ((r = mp_copy(&a->mp_int, &dest->mp_int)) != MP_OKAY)
errx(1, "integer_copy: %s", mp_error_to_string(r));
return dest;
}
s_integer * integer_div (const s_integer *a, const s_integer *b,
s_integer *dest)
{
sw r;
assert(a);
assert(b);
assert(dest);
if ((r = mp_div(&a->mp_int, &b->mp_int, &dest->mp_int,
NULL)) != MP_OKAY)
errx(1, "integer_div: %s", mp_error_to_string(r));
return dest;
}
s_integer * integer_gcd (const s_integer *a, const s_integer *b,
s_integer *dest)
{
sw r;
assert(a);
assert(b);
assert(dest);
if ((r = mp_gcd(&a->mp_int, &b->mp_int, &dest->mp_int)) != MP_OKAY)
errx(1, "integer_gcd: %s", mp_error_to_string(r));
return dest;
}
s_integer * integer_init (s_integer *dest)
{
sw r;
assert(dest);
if ((r = mp_init(&dest->mp_int)) != MP_OKAY)
errx(1, "integer_init: %s", mp_error_to_string(r));
return dest;
}
s_integer * integer_init_1 (s_integer *i, const s8 *p)
{
s_buf buf;
assert(i);
assert(p);
buf_init_1(&buf, p);
buf_parse_integer(&buf, i);
buf_clean(&buf);
return i;
}
s_integer * integer_init_double (s_integer *a, double x)
{
assert(a);
integer_init(a);
return integer_set_double(a, x);
}
s_integer * integer_init_s8 (s_integer *a, s8 x)
{
assert(a);
integer_init(a);
return integer_set_s32(a, x);
}
s_integer * integer_init_s16 (s_integer *a, s16 x)
{
assert(a);
integer_init(a);
return integer_set_s32(a, x);
}
s_integer * integer_init_s32 (s_integer *a, s32 x)
{
assert(a);
integer_init(a);
return integer_set_s32(a, x);
}
s_integer * integer_init_s64 (s_integer *a, s64 x)
{
assert(a);
integer_init(a);
return integer_set_s64(a, x);
}
s_integer * integer_init_sw (s_integer *a, sw x)
{
assert(a);
integer_init(a);
return integer_set_sw(a, x);
}
s_integer * integer_init_u8 (s_integer *a, u8 x)
{
assert(a);
integer_init(a);
return integer_set_u32(a, x);
}
s_integer * integer_init_u16 (s_integer *a, u16 x)
{
assert(a);
integer_init(a);
return integer_set_u32(a, x);
}
s_integer * integer_init_u32 (s_integer *a, u32 x)
{
assert(a);
integer_init(a);
return integer_set_u32(a, x);
}
s_integer * integer_init_u64 (s_integer *a, u64 x)
{
assert(a);
integer_init(a);
return integer_set_u64(a, x);
}
s_integer * integer_init_uw (s_integer *a, uw x)
{
assert(a);
integer_init(a);
return integer_set_uw(a, x);
}
s_integer * integer_init_zero (s_integer *dest)
{
assert(dest);
integer_init(dest);
mp_zero(&dest->mp_int);
return dest;
}
bool integer_is_negative (const s_integer *i)
{
assert(i);
return i->mp_int.sign == MP_NEG;
}
bool integer_is_zero (const s_integer *i)
{
assert(i);
return (i->mp_int.used == 0);
}
s_integer * integer_lcm (const s_integer *a, const s_integer *b,
s_integer *dest)
{
sw r;
assert(a);
assert(b);
assert(dest);
if ((r = mp_lcm(&a->mp_int, &b->mp_int, &dest->mp_int)) != MP_OKAY)
errx(1, "integer_lcm: %s", mp_error_to_string(r));
return dest;
}
s_integer * integer_lshift (s_integer *a, sw b, s_integer *dest)
{
sw r;
assert(a);
assert(dest);
if ((r = mp_mul_2d(&a->mp_int, b, &dest->mp_int)) != MP_OKAY)
errx(1, "integer_lshift: %s", mp_error_to_string(r));
return dest;
}
s_integer * integer_mod (const s_integer *a, const s_integer *b,
s_integer *dest)
{
sw r;
assert(a);
assert(b);
assert(dest);
if ((r = mp_mod(&a->mp_int, &b->mp_int, &dest->mp_int)) != MP_OKAY)
errx(1, "integer_mod: %s", mp_error_to_string(r));
return dest;
}
s_integer * integer_mul (const s_integer *a, const s_integer *b,
s_integer *dest)
{
sw r;
assert(a);
assert(b);
assert(dest);
if ((r = mp_mul(&a->mp_int, &b->mp_int, &dest->mp_int)) != MP_OKAY)
errx(1, "integer_mul: %s", mp_error_to_string(r));
return dest;
}
s_integer * integer_neg (const s_integer *a, s_integer *dest)
{
sw r;
assert(a);
assert(dest);
if ((r = mp_neg(&a->mp_int, &dest->mp_int)) != MP_OKAY)
errx(1, "integer_neg: %s", mp_error_to_string(r));
return dest;
}
s_integer * integer_new_copy (const s_integer *a)
{
s_integer *dest;
assert(a);
dest = malloc(sizeof(s_integer));
if (!dest)
errx(1, "integer_new_copy: out of memory");
return integer_copy(a, dest);
}
s_integer * integer_pow (const s_integer *a, const s_integer *b,
s_integer *dest)
{
sw r;
assert(a);
assert(b);
assert(dest);
if ((r = mp_exptmod(&a->mp_int, &b->mp_int, &dest->mp_int, &dest->mp_int))
!= MP_OKAY)
errx(1, "integer_pow: %s", mp_error_to_string(r));
return dest;
}
s_integer * integer_set_double (s_integer *a, double x)
{
sw r;
assert(a);
if ((r = mp_set_double(&a->mp_int, x)) != MP_OKAY)
errx(1, "integer_set_double: %s", mp_error_to_string(r));
return a;
}
s_integer * integer_set_s32 (s_integer *a, s32 x)
{
assert(a);
mp_set_i32(&a->mp_int, x);
return a;
}
s_integer * integer_set_s64 (s_integer *a, s64 x)
{
assert(a);
mp_set_i64(&a->mp_int, x);
return a;
}
s_integer * integer_set_sw (s_integer *a, sw x)
{
assert(a);
mp_set_l(&a->mp_int, x);
return a;
}
s_integer * integer_set_u32 (s_integer *a, u32 x)
{
assert(a);
mp_set_u32(&a->mp_int, x);
return a;
}
s_integer * integer_set_u64 (s_integer *a, u64 x)
{
assert(a);
mp_set_u64(&a->mp_int, x);
return a;
}
s_integer * integer_set_uw (s_integer *a, uw x)
{
assert(a);
mp_set_ul(&a->mp_int, x);
return a;
}
s_integer * integer_sqrt (const s_integer *a, s_integer *dest)
{
sw r;
assert(a);
assert(dest);
if ((r = mp_sqrt(&a->mp_int, &dest->mp_int)) != MP_OKAY)
errx(1, "integer_sqrt: %s", mp_error_to_string(r));
return dest;
}
s_integer * integer_sub (const s_integer *a, const s_integer *b,
s_integer *dest)
{
sw r;
assert(dest);
assert(a);
assert(b);
if ((r = mp_sub(&a->mp_int, &b->mp_int, &dest->mp_int)) != MP_OKAY)
errx(1, "integer_sub: %s", mp_error_to_string(r));
return dest;
}
f64 integer_to_f64 (const s_integer *i)
{
assert(i);
return mp_get_double(&i->mp_int);
}
s8 integer_to_s8 (const s_integer *i)
{
assert(i);
return (s8) mp_get_i32(&i->mp_int);
}
s16 integer_to_s16 (const s_integer *i)
{
assert(i);
return (s16) mp_get_i32(&i->mp_int);
}
s32 integer_to_s32 (const s_integer *i)
{
assert(i);
return mp_get_i32(&i->mp_int);
}
s64 integer_to_s64 (const s_integer *i)
{
assert(i);
return mp_get_i64(&i->mp_int);
}
u8 integer_to_u8 (const s_integer *i)
{
assert(i);
return (u8) mp_get_u32(&i->mp_int);
}
u16 integer_to_u16 (const s_integer *i)
{
assert(i);
return (u16) mp_get_u32(&i->mp_int);
}
u32 integer_to_u32 (const s_integer *i)
{
assert(i);
return mp_get_u32(&i->mp_int);
}
u64 integer_to_u64 (const s_integer *i)
{
assert(i);
return mp_get_u64(&i->mp_int);
}