2020-10-11 17:05:00 +03:00
|
|
|
#include "mathFunctions.h"
|
|
|
|
#include "memoryManagement.h"
|
2022-09-21 13:13:15 +03:00
|
|
|
#include "runtime.h"
|
2020-10-11 17:05:00 +03:00
|
|
|
|
|
|
|
/* 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;
|
2021-06-03 12:44:42 +03:00
|
|
|
}
|
2020-10-11 17:05:00 +03:00
|
|
|
|
|
|
|
/* 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;
|
2021-06-03 12:44:42 +03:00
|
|
|
}
|
2020-10-11 17:05:00 +03:00
|
|
|
|
2021-04-02 16:02:40 +03:00
|
|
|
/* 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;
|
2021-06-03 12:44:42 +03:00
|
|
|
}
|
|
|
|
|
2020-10-11 17:05:00 +03:00
|
|
|
/* 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;
|
2021-06-03 12:44:42 +03:00
|
|
|
}
|
2020-10-11 17:05:00 +03:00
|
|
|
|
|
|
|
/* 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/
|
2021-06-03 12:44:42 +03:00
|
|
|
|
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/
|
2021-06-03 12:44:42 +03:00
|
|
|
|
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/
|
2021-06-03 12:44:42 +03:00
|
|
|
|
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/
|
2021-06-03 12:44:42 +03:00
|
|
|
|
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);
|
2021-06-03 12:44:42 +03:00
|
|
|
|
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);
|
2021-06-03 12:44:42 +03:00
|
|
|
|
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);
|
2021-06-03 12:44:42 +03:00
|
|
|
|
2022-09-21 13:13:15 +03:00
|
|
|
mpz_clears(rem, yq, NULL);
|
2021-06-03 12:44:42 +03:00
|
|
|
|
2022-09-21 13:13:15 +03:00
|
|
|
return (Value *)retVal;
|
2020-10-11 17:05:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* 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;
|
2020-10-11 17:05:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* 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;
|
2021-06-03 12:44:42 +03:00
|
|
|
}
|
2020-10-11 17:05:00 +03:00
|
|
|
|
|
|
|
/* 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;
|
2021-06-03 12:44:42 +03:00
|
|
|
}
|
2020-10-11 17:05:00 +03:00
|
|
|
|
|
|
|
/* 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;
|
2021-06-03 12:44:42 +03:00
|
|
|
}
|
2020-10-11 17:05:00 +03:00
|
|
|
|
|
|
|
/* 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;
|
2021-06-03 12:44:42 +03:00
|
|
|
}
|
2020-10-11 17:05:00 +03:00
|
|
|
|
|
|
|
/* 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;
|
2021-06-03 12:44:42 +03:00
|
|
|
}
|