no-std fpa

Fixed point arithmetic

1 unstable release

Uses old Rust 2015

 0.1.0 Apr 1, 2017

#10 in #point

Used in 12 crates (3 directly)

MIT/Apache

74KB
2K SLoC

fpa

Fixed Point Arithmetic

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

lib.rs:

Fixed point arithmetic

A fixed point number is an alternative representation for a real number. IEEE floats, f32 and f64, being the standard format in processors with Floating Point Units (FPU). You should consider using fixed numbers on systems where there's no FPU and performance is critical as fixed point arithmetic is faster than software emulated IEEE float arithmetic. Do note that fixed point numbers tend to be more prone to overflows as they operate in ranges much smaller than floats.

The fixed point numbers exposed in this library use the following naming convention: IxFy, where x is the number of bits used for the integer part and y is the number of bits used for the fractional part.

Unlike IEEE floats, fixed points numbers have fixed precision. One can exchange range for precision by selecting different values for x and y:

• Range: [-2 ^ (y - 1), 2 ^ (y - 1) - 2 ^ (-x)]
• Precision: 2 ^ (-x)

For example, the type I1F7 has range [-1, 0.9921875] and precision 0.0078125.

Examples

• Casts
// https://crates.io/crates/cast
extern crate cast;
extern crate fpa;

use cast::f64;
// 32-bit fixed point number, 16 bits for the integer part and 16 bits for
// the fractional part
use fpa::I16F16;

fn main() {
// casts an integer into a fixed point number (infallible)
let q = I16F16(1i8);

// casts the fixed point number into a float (infallible)
let f = f64(q);

assert_eq!(f, 1.);
}
• Arithmetic
use fpa::I16F16;

// NOTE the `f64` -> `I16F16` cast is fallible because of NaN and infinity
assert_eq!(I16F16(1.25_f64).unwrap() + I16F16(2.75_f64).unwrap(),
I16F16(4_f64).unwrap());

assert_eq!(I16F16(2_f64).unwrap() / I16F16(0.5_f64).unwrap(),
I16F16(4_f64).unwrap());

assert_eq!(I16F16(2_f64).unwrap() * I16F16(0.5_f64).unwrap(),
I16F16(1_f64).unwrap());
• Trigonometry
extern crate cast;
extern crate fpa;

use cast::f64;
use fpa::I2F30;

fn main() {
let (r, _) = I2F30(0.3_f64).unwrap().polar(I2F30(0.4_f64).unwrap());
assert!((f64(r) - 0.5).abs() < 1e-5);
}

~195KB