Idris2/support/refc/mathFunctions.c

163 lines
5.6 KiB
C
Raw Normal View History

#include "mathFunctions.h"
#include "memoryManagement.h"
2022-09-21 13:13:15 +03:00
#include "runtime.h"
/* add */
2024-03-21 15:32:37 +03:00
Value *idris2_add_Integer(Value *x, Value *y) {
Value_Integer *retVal = idris2_mkInteger();
2022-09-21 13:13:15 +03:00
mpz_add(retVal->i, ((Value_Integer *)x)->i, ((Value_Integer *)y)->i);
return (Value *)retVal;
}
/* sub */
2024-03-21 15:32:37 +03:00
Value *idris2_sub_Integer(Value *x, Value *y) {
Value_Integer *retVal = idris2_mkInteger();
2022-09-21 13:13:15 +03:00
mpz_sub(retVal->i, ((Value_Integer *)x)->i, ((Value_Integer *)y)->i);
return (Value *)retVal;
}
/* negate */
2024-03-21 15:32:37 +03:00
Value *idris2_negate_Integer(Value *x) {
Value_Integer *retVal = idris2_mkInteger();
2022-09-21 13:13:15 +03:00
mpz_neg(retVal->i, ((Value_Integer *)x)->i);
return (Value *)retVal;
}
/* mul */
2024-03-21 15:32:37 +03:00
Value *idris2_mul_Integer(Value *x, Value *y) {
Value_Integer *retVal = idris2_mkInteger();
2022-09-21 13:13:15 +03:00
mpz_mul(retVal->i, ((Value_Integer *)x)->i, ((Value_Integer *)y)->i);
return (Value *)retVal;
}
/* div */
2024-03-21 15:32:37 +03:00
Value *idris2_div_Int8(Value *x, Value *y) {
2022-09-21 13:13:15 +03:00
// Correction term added to convert from truncated division (C default) to
// Euclidean division For proof of correctness, see Division and Modulus for
// Computer Scientists (Daan Leijen)
// https://www.microsoft.com/en-us/research/publication/division-and-modulus-for-computer-scientists/
2024-03-21 15:32:37 +03:00
int8_t num = idris2_vp_to_Int8(x);
int8_t denom = idris2_vp_to_Int8(y);
2022-09-21 13:13:15 +03:00
int8_t rem = num % denom;
2024-03-21 15:32:37 +03:00
return idris2_mkInt8(num / denom + ((rem < 0) ? (denom < 0) ? 1 : -1 : 0));
2022-09-21 13:13:15 +03:00
}
2024-03-21 15:32:37 +03:00
Value *idris2_div_Int16(Value *x, Value *y) {
2022-09-21 13:13:15 +03:00
// Correction term added to convert from truncated division (C default) to
// Euclidean division For proof of correctness, see Division and Modulus for
// Computer Scientists (Daan Leijen)
// https://www.microsoft.com/en-us/research/publication/division-and-modulus-for-computer-scientists/
2024-03-21 15:32:37 +03:00
int16_t num = idris2_vp_to_Int16(x);
int16_t denom = idris2_vp_to_Int16(y);
2022-09-21 13:13:15 +03:00
int16_t rem = num % denom;
2024-03-21 15:32:37 +03:00
return idris2_mkInt16(num / denom + ((rem < 0) ? (denom < 0) ? 1 : -1 : 0));
2022-09-21 13:13:15 +03:00
}
2024-03-21 15:32:37 +03:00
Value *idris2_div_Int32(Value *x, Value *y) {
2022-09-21 13:13:15 +03:00
// Correction term added to convert from truncated division (C default) to
// Euclidean division For proof of correctness, see Division and Modulus for
// Computer Scientists (Daan Leijen)
// https://www.microsoft.com/en-us/research/publication/division-and-modulus-for-computer-scientists/
2024-03-21 15:32:37 +03:00
int32_t num = idris2_vp_to_Int32(x);
int32_t denom = idris2_vp_to_Int32(y);
2022-09-21 13:13:15 +03:00
int32_t rem = num % denom;
2024-03-21 15:32:37 +03:00
return idris2_mkInt32(num / denom + ((rem < 0) ? (denom < 0) ? 1 : -1 : 0));
2022-09-21 13:13:15 +03:00
}
2024-03-21 15:32:37 +03:00
Value *idris2_div_Int64(Value *x, Value *y) {
2022-09-21 13:13:15 +03:00
// Correction term added to convert from truncated division (C default) to
// Euclidean division For proof of correctness, see Division and Modulus for
// Computer Scientists (Daan Leijen)
// https://www.microsoft.com/en-us/research/publication/division-and-modulus-for-computer-scientists/
2024-03-21 15:32:37 +03:00
int64_t num = idris2_vp_to_Int64(x);
int64_t denom = idris2_vp_to_Int64(y);
2022-09-21 13:13:15 +03:00
int64_t rem = num % denom;
2024-03-21 15:32:37 +03:00
return (Value *)idris2_mkInt64(num / denom +
((rem < 0) ? (denom < 0) ? 1 : -1 : 0));
2022-09-21 13:13:15 +03:00
}
2024-03-21 15:32:37 +03:00
Value *idris2_div_Integer(Value *x, Value *y) {
2022-09-21 13:13:15 +03:00
mpz_t rem, yq;
mpz_inits(rem, yq, NULL);
2022-09-21 13:13:15 +03:00
mpz_mod(rem, ((Value_Integer *)x)->i, ((Value_Integer *)y)->i);
mpz_sub(yq, ((Value_Integer *)x)->i, rem);
2024-03-21 15:32:37 +03:00
Value_Integer *retVal = idris2_mkInteger();
2022-09-21 13:13:15 +03:00
mpz_divexact(retVal->i, yq, ((Value_Integer *)y)->i);
2022-09-21 13:13:15 +03:00
mpz_clears(rem, yq, NULL);
2022-09-21 13:13:15 +03:00
return (Value *)retVal;
}
/* mod */
2024-03-21 15:32:37 +03:00
Value *idris2_mod_Int8(Value *x, Value *y) {
int8_t num = idris2_vp_to_Int8(x);
int8_t denom = idris2_vp_to_Int8(y);
2022-09-21 13:13:15 +03:00
denom = (denom < 0) ? -denom : denom;
2024-03-21 15:32:37 +03:00
return (Value *)idris2_mkInt8(num % denom + (num < 0 ? denom : 0));
2022-09-21 13:13:15 +03:00
}
2024-03-21 15:32:37 +03:00
Value *idris2_mod_Int16(Value *x, Value *y) {
int16_t num = idris2_vp_to_Int16(x);
int16_t denom = idris2_vp_to_Int16(y);
2022-09-21 13:13:15 +03:00
denom = (denom < 0) ? -denom : denom;
2024-03-21 15:32:37 +03:00
return (Value *)idris2_mkInt16(num % denom + (num < 0 ? denom : 0));
2022-09-21 13:13:15 +03:00
}
2024-03-21 15:32:37 +03:00
Value *idris2_mod_Int32(Value *x, Value *y) {
int32_t num = idris2_vp_to_Int32(x);
int32_t denom = idris2_vp_to_Int32(y);
2022-09-21 13:13:15 +03:00
denom = (denom < 0) ? -denom : denom;
2024-03-21 15:32:37 +03:00
return (Value *)idris2_mkInt32(num % denom + (num < 0 ? denom : 0));
2022-09-21 13:13:15 +03:00
}
2024-03-21 15:32:37 +03:00
Value *idris2_mod_Int64(Value *x, Value *y) {
int64_t num = idris2_vp_to_Int64(x);
int64_t denom = idris2_vp_to_Int64(y);
2022-09-21 13:13:15 +03:00
denom = (denom < 0) ? -denom : denom;
2024-03-21 15:32:37 +03:00
return (Value *)idris2_mkInt64(num % denom + (num < 0 ? denom : 0));
2022-09-21 13:13:15 +03:00
}
2024-03-21 15:32:37 +03:00
Value *idris2_mod_Integer(Value *x, Value *y) {
Value_Integer *retVal = idris2_mkInteger();
2022-09-21 13:13:15 +03:00
mpz_mod(retVal->i, ((Value_Integer *)x)->i, ((Value_Integer *)y)->i);
return (Value *)retVal;
}
/* shiftl */
2024-03-21 15:32:37 +03:00
Value *idris2_shiftl_Integer(Value *x, Value *y) {
Value_Integer *retVal = idris2_mkInteger();
2022-09-21 13:13:15 +03:00
mp_bitcnt_t cnt = (mp_bitcnt_t)mpz_get_ui(((Value_Integer *)y)->i);
mpz_mul_2exp(retVal->i, ((Value_Integer *)x)->i, cnt);
return (Value *)retVal;
}
/* shiftr */
2024-03-21 15:32:37 +03:00
Value *idris2_shiftr_Integer(Value *x, Value *y) {
Value_Integer *retVal = idris2_mkInteger();
2022-09-21 13:13:15 +03:00
mp_bitcnt_t cnt = (mp_bitcnt_t)mpz_get_ui(((Value_Integer *)y)->i);
mpz_fdiv_q_2exp(retVal->i, ((Value_Integer *)x)->i, cnt);
return (Value *)retVal;
}
/* and */
2024-03-21 15:32:37 +03:00
Value *idris2_and_Integer(Value *x, Value *y) {
Value_Integer *retVal = idris2_mkInteger();
2022-09-21 13:13:15 +03:00
mpz_and(retVal->i, ((Value_Integer *)x)->i, ((Value_Integer *)y)->i);
return (Value *)retVal;
}
/* or */
2024-03-21 15:32:37 +03:00
Value *idris2_or_Integer(Value *x, Value *y) {
Value_Integer *retVal = idris2_mkInteger();
2022-09-21 13:13:15 +03:00
mpz_ior(retVal->i, ((Value_Integer *)x)->i, ((Value_Integer *)y)->i);
return (Value *)retVal;
}
/* xor */
2024-03-21 15:32:37 +03:00
Value *idris2_xor_Integer(Value *x, Value *y) {
Value_Integer *retVal = idris2_mkInteger();
2022-09-21 13:13:15 +03:00
mpz_xor(retVal->i, ((Value_Integer *)x)->i, ((Value_Integer *)y)->i);
return (Value *)retVal;
}