pub trait Fp: Clone + Copy + Eq + Ord + PartialEq + PartialOrd + Sized {
type Raw: Fp + Shl<u32, Output = Self::Raw> + Shr<u32, Output = Self::Raw>;
type Output<const B: u32, const S: i32>: Fp<Raw = Self::Raw>;
const BITS: u32;
const SHIFT: i32;
const MIN: Self;
const MAX: Self;
const SIGNED: bool;
Show 19 methods
// Required methods
unsafe fn new_unchecked(val: Self::Raw) -> Self;
fn raw(self) -> Self::Raw;
unsafe fn from_f32_unchecked(val: f32) -> Self;
unsafe fn from_f64_unchecked(val: f64) -> Self;
fn into_f32(self) -> f32;
fn into_f64(self) -> f64;
// Provided methods
fn new(val: Self::Raw) -> Result<Self, RangeError> { ... }
fn from_f32(val: f32) -> Result<Self, RangeError> { ... }
fn from_f64(val: f64) -> Result<Self, RangeError> { ... }
fn from_fp<T: Fp, F: Fp<Raw = T>>(val: F) -> Self
where Self::Raw: TryFrom<T> { ... }
fn into_fp<T, F: Fp<Raw = T>>(self) -> F
where T: TryFrom<Self::Raw> + Fp { ... }
fn add_bits<const N: u32>(self) -> Self::Output<{ _ }, { Self::SHIFT }>
where [(); { _ }]: { ... }
fn set_bits<const N: u32>(
self
) -> Result<Self::Output<N, { Self::SHIFT }>, RangeError> { ... }
unsafe fn set_bits_unchecked<const N: u32>(
self
) -> Self::Output<N, { Self::SHIFT }> { ... }
fn saturate<const N: u32>(self) -> Self::Output<N, { Self::SHIFT }> { ... }
fn logical_shl<const N: i32>(self) -> Self::Output<{ Self::BITS }, { _ }>
where [(); { _ }]: { ... }
fn logical_shr<const N: i32>(self) -> Self::Output<{ Self::BITS }, { _ }>
where [(); { _ }]: { ... }
fn raw_shl<const N: u32>(self) -> Self::Output<{ _ }, { _ }>
where [(); { _ }]: { ... }
fn raw_shr<const N: u32>(self) -> Self::Output<{ _ }, { _ }>
where [(); { _ }]: { ... }
}
Expand description
A fixed-point number, stored as type Raw
,
where only the BITS
least-significant bits may be nonzero.
The raw value is divided by 2.pow(SHIFT)
to obtain the logical value.
Required Associated Types§
Required Associated Constants§
sourceconst BITS: u32
const BITS: u32
BITS
is the number of least-significant bits which are permitted to vary.
The Raw::BITS - BITS
high-order bits must be zero (for unsigned Raw
) or the
same as the high bit of the lower BITS
bits (for signed Raw
).
sourceconst SHIFT: i32
const SHIFT: i32
SHIFT
sets the scaling factor between the stored raw value (of type Raw
)
and the “logical” value with it represents. The logical value of this
fixed-point number is equal to the raw value divided by 2.pow(SHIFT)
.
In other words, positive SHIFT
means that the logical value consists of
BITS - SHIFT
integer bits followed by SHIFT
fractional bits, and negative
shift means that the logical value consists of BITS - SHIFT
integer bits
(of which the last -SHIFT
bits are zero).
Required Methods§
sourceunsafe fn new_unchecked(val: Self::Raw) -> Self
unsafe fn new_unchecked(val: Self::Raw) -> Self
Interpret the provided raw value as a fixed-point number of type Self
.
Unsafe: no bounds checking is performed; the caller must ensure that the
result lies between Self::MIN
and Self::MAX
. It is almost always better
to use .new().unwrap()
instead of this function, so that an out-of-bounds
value panics with a reasonable message instead of propagating undefined
behavior.
sourcefn raw(self) -> Self::Raw
fn raw(self) -> Self::Raw
Return the raw value which internally represents this fixed-point number.
unsafe fn from_f32_unchecked(val: f32) -> Self
unsafe fn from_f64_unchecked(val: f64) -> Self
Provided Methods§
sourcefn new(val: Self::Raw) -> Result<Self, RangeError>
fn new(val: Self::Raw) -> Result<Self, RangeError>
Interpret the provided raw value as a fixed-point number of type Self
,
or return a RangeError
if it is too small or too large to represent
a valid instance of Self
.
Examples found in repository?
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
fn main() {
// There are many ways to create a new fixed-point number
let options: [FpI32<10, 5>; 4] = [
FpI32::from_f32(3.125).unwrap(),
FpI32::from_f64(3.125).unwrap(),
FpI32::new(100).unwrap(),
100i32.logical_shr::<5>().set_bits().unwrap(),
];
assert!(options.iter().min() == options.iter().max()); // all equal
// Arithmetic works pretty much seamlessly
let a = 12i32.set_bits::<5>().unwrap();
let b = (-1i32).set_bits::<1>().unwrap();
let c = a + b; // type of C is FpI32<6, 0>
// Addition is associative in value, but not in type
let d: FpI32<6, 0> = a + (b + b);
let e: FpI32<7, 0> = (a + b) + b;
let x = FpI32::<21, 20>::from_f32(0.497).unwrap();
let y = x.div_const::<12>();
let z = x + (-y);
println!("{} {}", x.raw(), x.into_f64());
println!("{} {}", z.raw(), z.into_f64());
}
sourcefn from_f32(val: f32) -> Result<Self, RangeError>
fn from_f32(val: f32) -> Result<Self, RangeError>
Return the fixed-point number of type Self
which has a logical value of val
,
or return a RangeError if val
is too small or too large to be represented
by Self
.
Examples found in repository?
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
fn main() {
// There are many ways to create a new fixed-point number
let options: [FpI32<10, 5>; 4] = [
FpI32::from_f32(3.125).unwrap(),
FpI32::from_f64(3.125).unwrap(),
FpI32::new(100).unwrap(),
100i32.logical_shr::<5>().set_bits().unwrap(),
];
assert!(options.iter().min() == options.iter().max()); // all equal
// Arithmetic works pretty much seamlessly
let a = 12i32.set_bits::<5>().unwrap();
let b = (-1i32).set_bits::<1>().unwrap();
let c = a + b; // type of C is FpI32<6, 0>
// Addition is associative in value, but not in type
let d: FpI32<6, 0> = a + (b + b);
let e: FpI32<7, 0> = (a + b) + b;
let x = FpI32::<21, 20>::from_f32(0.497).unwrap();
let y = x.div_const::<12>();
let z = x + (-y);
println!("{} {}", x.raw(), x.into_f64());
println!("{} {}", z.raw(), z.into_f64());
}
sourcefn from_f64(val: f64) -> Result<Self, RangeError>
fn from_f64(val: f64) -> Result<Self, RangeError>
Return the fixed-point number of type Self
which has a logical value of val
,
or return a RangeError if val
is too small or too large to be represented
by Self
.
Examples found in repository?
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
fn main() {
// There are many ways to create a new fixed-point number
let options: [FpI32<10, 5>; 4] = [
FpI32::from_f32(3.125).unwrap(),
FpI32::from_f64(3.125).unwrap(),
FpI32::new(100).unwrap(),
100i32.logical_shr::<5>().set_bits().unwrap(),
];
assert!(options.iter().min() == options.iter().max()); // all equal
// Arithmetic works pretty much seamlessly
let a = 12i32.set_bits::<5>().unwrap();
let b = (-1i32).set_bits::<1>().unwrap();
let c = a + b; // type of C is FpI32<6, 0>
// Addition is associative in value, but not in type
let d: FpI32<6, 0> = a + (b + b);
let e: FpI32<7, 0> = (a + b) + b;
let x = FpI32::<21, 20>::from_f32(0.497).unwrap();
let y = x.div_const::<12>();
let z = x + (-y);
println!("{} {}", x.raw(), x.into_f64());
println!("{} {}", z.raw(), z.into_f64());
}
sourcefn from_fp<T: Fp, F: Fp<Raw = T>>(val: F) -> Self
fn from_fp<T: Fp, F: Fp<Raw = T>>(val: F) -> Self
Return the fixed-point number of type Self
which has the same logical value as val
.
F
and Self
must have the same shift and signedness. Self
must have at least as
many bits as F
.
sourcefn into_fp<T, F: Fp<Raw = T>>(self) -> F
fn into_fp<T, F: Fp<Raw = T>>(self) -> F
Return the fixed-point number of type F
which has the same logical value as self
.
F
and Self
must have the same shift and signedness. F
must have at least as
many bits as Self
.
sourcefn add_bits<const N: u32>(self) -> Self::Output<{ _ }, { Self::SHIFT }>
fn add_bits<const N: u32>(self) -> Self::Output<{ _ }, { Self::SHIFT }>
Increase the number of bits used to represent this value. Both the raw and logical values are unchanged. This is a type system operation only. Compilation will fail if the new number of bits is too large for the raw type.
sourcefn set_bits<const N: u32>(
self
) -> Result<Self::Output<N, { Self::SHIFT }>, RangeError>
fn set_bits<const N: u32>( self ) -> Result<Self::Output<N, { Self::SHIFT }>, RangeError>
Set the number of bits used to represent this value. The value is checked at runtime to ensure it is in range for the new number of bits. If succesful, both the raw and logical values are unchanged.
Examples found in repository?
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
fn main() {
// There are many ways to create a new fixed-point number
let options: [FpI32<10, 5>; 4] = [
FpI32::from_f32(3.125).unwrap(),
FpI32::from_f64(3.125).unwrap(),
FpI32::new(100).unwrap(),
100i32.logical_shr::<5>().set_bits().unwrap(),
];
assert!(options.iter().min() == options.iter().max()); // all equal
// Arithmetic works pretty much seamlessly
let a = 12i32.set_bits::<5>().unwrap();
let b = (-1i32).set_bits::<1>().unwrap();
let c = a + b; // type of C is FpI32<6, 0>
// Addition is associative in value, but not in type
let d: FpI32<6, 0> = a + (b + b);
let e: FpI32<7, 0> = (a + b) + b;
let x = FpI32::<21, 20>::from_f32(0.497).unwrap();
let y = x.div_const::<12>();
let z = x + (-y);
println!("{} {}", x.raw(), x.into_f64());
println!("{} {}", z.raw(), z.into_f64());
}
sourceunsafe fn set_bits_unchecked<const N: u32>(
self
) -> Self::Output<N, { Self::SHIFT }>
unsafe fn set_bits_unchecked<const N: u32>( self ) -> Self::Output<N, { Self::SHIFT }>
Set the number of bits used to represent this value. Unsafe: no bounds checking
is performed; the caller must ensure that the value fits within
the new number of bits. It is almost always better to call .set_bits().unwrap()
instead, so that an out-of-bounds
value panics with a reasonable message instead of propagating undefined
behavior.
sourcefn saturate<const N: u32>(self) -> Self::Output<N, { Self::SHIFT }>
fn saturate<const N: u32>(self) -> Self::Output<N, { Self::SHIFT }>
Set the number of bits used to represent this value, saturating in case of overflow.
sourcefn logical_shl<const N: i32>(self) -> Self::Output<{ Self::BITS }, { _ }>
fn logical_shl<const N: i32>(self) -> Self::Output<{ Self::BITS }, { _ }>
Shift the logical value of this number left by N bits. (N may be negative for a right shift). This is a type system operation only; the raw value is unchanged. The logical value is multiplied by 2^N.
sourcefn logical_shr<const N: i32>(self) -> Self::Output<{ Self::BITS }, { _ }>
fn logical_shr<const N: i32>(self) -> Self::Output<{ Self::BITS }, { _ }>
Shift the logical value of this number right by N bits. (N may be negative for a left shift). This is a type system operation only; the raw value is unchanged. The logical value is divided by 2^N.
Examples found in repository?
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
fn main() {
// There are many ways to create a new fixed-point number
let options: [FpI32<10, 5>; 4] = [
FpI32::from_f32(3.125).unwrap(),
FpI32::from_f64(3.125).unwrap(),
FpI32::new(100).unwrap(),
100i32.logical_shr::<5>().set_bits().unwrap(),
];
assert!(options.iter().min() == options.iter().max()); // all equal
// Arithmetic works pretty much seamlessly
let a = 12i32.set_bits::<5>().unwrap();
let b = (-1i32).set_bits::<1>().unwrap();
let c = a + b; // type of C is FpI32<6, 0>
// Addition is associative in value, but not in type
let d: FpI32<6, 0> = a + (b + b);
let e: FpI32<7, 0> = (a + b) + b;
let x = FpI32::<21, 20>::from_f32(0.497).unwrap();
let y = x.div_const::<12>();
let z = x + (-y);
println!("{} {}", x.raw(), x.into_f64());
println!("{} {}", z.raw(), z.into_f64());
}