Packages
mmath
0.2.0-alpha6
0.2.26
0.2.25
0.2.24
0.2.23
0.2.22
0.2.21
0.2.20
0.2.19
0.2.18
0.2.17
0.2.16
0.2.15
0.2.14
0.2.13
0.2.12
0.2.11
0.2.10
0.2.9
0.2.8
0.2.7
0.2.6
0.2.5
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.2.0-alpha9
0.2.0-alpha8
0.2.0-alpha7
0.2.0-alpha6
0.2.0-alpha5
0.2.0-alpha4
0.2.0-alpha3
0.2.0-alpha2
0.2.0-alpha10
0.2.0-alpha1
0.2.0-alpha
0.1.17-alpha
0.1.16
0.1.15
0.1.14
0.1.13
0.1.11
0.1.10
0.1.9
0.1.8
0.1.7
0.1.6
math library for metric sequences and binary arrays.
Current section
Files
Jump to
Current section
Files
c_src/float_math.c~
#include "erl_nif.h"
#include "mmath.h"
ffloat
float_mul(decimal v, double m) {
// TODO fix in situation when m is so big, that it will overflow coefficient
return (ffloat) {
.value = v.value * m,
.confidence = v.confidence
};
}
decimal
dec_div(decimal v, int64_t m) {
// TODO: Improve accuracy by adjusting coefficient before dividing
dec_inflate(&v);
decimal r = {
.coefficient = v.coefficient / m,
.exponent = v.exponent,
.confidence = v.confidence
};
dec_reduce(&r);
return r;
}
static decimal
dec_add_aligned(int64_t a_coef, int64_t b_coef, int8_t e, uint32_t confidence) {
decimal r = {
.coefficient = a_coef + b_coef,
.exponent = e,
.confidence = confidence
};
dec_reduce(&r);
return r;
}
/* Add decimal b to a. Decimal a has always bigger coefficient */
static decimal
dec_add_not_aligned(decimal big, decimal small, uint32_t confidence) {
int8_t over_digits = 0;
int8_t e, de;
int64_t a_coef, b_coef;
if (big.coefficient == 0) {
small.confidence = confidence;
return small;
}
if (small.coefficient == 0) {
big.confidence = confidence;
return big;
}
e = small.exponent;
de = big.exponent - e;
b_coef = small.coefficient;
over_digits = qlog10(llabs(big.coefficient)) + de - MAX_DIGITS - 1;
if (over_digits > 0) {
e += over_digits;
de -= over_digits;
b_coef /= (int64_t)qipow10(over_digits);
}
a_coef = big.coefficient * qipow10(de);
return dec_add_aligned(a_coef, b_coef, e, confidence);
}
inline decimal
dec_add(decimal a, decimal b) {
uint32_t confidence = (a.confidence + b.confidence) / 2;
if (a.exponent == b.exponent) {
return dec_add_aligned(a.coefficient, b.coefficient, a.exponent,
confidence);
} else {
if (a.exponent >= b.exponent) {
return dec_add_not_aligned(a, b, confidence);
} else {
return dec_add_not_aligned(b, a, confidence);
}
}
}
inline decimal
dec_add3(decimal a, decimal b, decimal c) {
return dec_add(dec_add(a, b), c);
}
inline decimal /* a - b */
dec_sub(decimal a, decimal b) {
return dec_add(a, dec_neg(b));
}
inline decimal
dec_neg(decimal a) {
return (decimal) {
.coefficient = -a.coefficient,
.exponent = a.exponent,
.confidence = a.confidence
};
}
/* return 1 when 1 > b, 0 when equal and -1 otherwise */
int
dec_cmp(decimal a, decimal b) {
//TODO: optimise, not going into actual computation
decimal r = dec_sub(a, b);
if (r.coefficient == 0 && r.exponent == 0) {
return 0;
} else if (r.coefficient < 0) {
return -1;
} else {
return 1;
}
}