106 lines
1.8 KiB
V
106 lines
1.8 KiB
V
// Fixed-point decimal numbers
|
|
// based on https://github.com/robaho/fixed/blob/master/fixed.go
|
|
module fixed
|
|
|
|
import math
|
|
import strconv
|
|
|
|
const (
|
|
c_n_places = 7
|
|
c_scale = i64(10 * 10 * 10 * 10 * 10 * 10 * 10)
|
|
|
|
c_max = f64(99999999999.9999999)
|
|
)
|
|
|
|
pub struct Fixed {
|
|
fp i64
|
|
}
|
|
|
|
// New from integer
|
|
// i: number
|
|
// n: precision/fraction amount
|
|
// n moves the decimal point N places left
|
|
pub fn new_i(i i64, n u32) Fixed {
|
|
mut ii := i
|
|
mut nn := n
|
|
|
|
if nn > c_n_places {
|
|
ii = ii / i64(math.pow(10, int(nn-c_n_places)))
|
|
nn = c_n_places
|
|
}
|
|
|
|
ii = ii * i64(math.pow(10, int(c_n_places-nn)))
|
|
|
|
return Fixed{fp: ii}
|
|
}
|
|
|
|
// New from floating point
|
|
pub fn new_f(f f64) Fixed {
|
|
if math.is_nan(f) || math.is_inf(f, 0) {
|
|
panic("error: cannot convert value to Fixed: f: $f")
|
|
}
|
|
|
|
if f >= c_max || f <= -c_max {
|
|
panic("error: cannot convert value to Fixed, it exceeds MAX range: f: $f")
|
|
}
|
|
|
|
mut round := 0.5
|
|
if f < 0 {
|
|
round = -0.5
|
|
}
|
|
|
|
return Fixed{fp: i64(f*f64(c_scale) + round)}
|
|
}
|
|
|
|
pub fn (f Fixed) add(b Fixed) Fixed {
|
|
return Fixed{fp: f.fp + b.fp}
|
|
}
|
|
|
|
pub fn (f Fixed) sub(b Fixed) Fixed {
|
|
return Fixed{fp: f.fp - b.fp}
|
|
}
|
|
|
|
pub fn (f Fixed) mul(b Fixed) Fixed {
|
|
// XXX
|
|
f0 := b
|
|
|
|
fp_a := f.fp / c_scale
|
|
fp_b := f.fp % c_scale
|
|
|
|
fp0_a := f0.fp / c_scale
|
|
fp0_b := f0.fp % c_scale
|
|
|
|
mut result := i64(0)
|
|
|
|
if fp0_a != 0 {
|
|
result = fp_a*fp0_a*c_scale + fp_b*fp0_a
|
|
}
|
|
if fp0_b != 0 {
|
|
result = result + (fp_a * fp0_b) + ((fp_b)*fp0_b)/c_scale
|
|
}
|
|
|
|
return Fixed{fp: result}
|
|
}
|
|
|
|
pub fn (f Fixed) div(b Fixed) Fixed {
|
|
return new_f(f.float() / b.float())
|
|
}
|
|
|
|
// Get value as float
|
|
pub fn (f Fixed) float() f64 {
|
|
return f64(f.fp) / f64(c_scale)
|
|
}
|
|
|
|
// XXX not tested
|
|
pub fn (f Fixed) value() f64 {
|
|
return f.float()
|
|
}
|
|
|
|
pub fn (f Fixed) str() string {
|
|
// XXX fixme, temporary
|
|
|
|
v := f.float()
|
|
s := strconv.v_sprintf("%f", v)
|
|
|
|
return s
|
|
} |