1
0
Fork 0
auts/isotest/bits/fixed/fixed.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
}