macro_rules! fixed_const {
(
$Fixed:ident[$s_fixed:expr](
$nbits:expr, $s_nbits:expr,
$s_nbits_m1:expr, $s_nbits_m2:expr, $s_nbits_m3:expr, $s_nbits_m4:expr
),
$nbits_cm3:expr, $nbits_cm2:expr, $nbits_cm1:expr,
$nbits_c0:expr, $nbits_c1:expr, $nbits_c2:expr, $nbits_c3:expr,
$Signedness:tt
) => {
impl<const FRAC: i32> $Fixed<FRAC> {
const fn from_const<const SRC_FRAC: i32>(src: FixedU128<SRC_FRAC>) -> $Fixed<FRAC> {
let shift_right = SRC_FRAC.saturating_sub(FRAC);
if shift_right < if_signed_unsigned!($Signedness, 129, 128) - $nbits {
panic!("overflow");
}
let bits128 = if shift_right >= 128 {
0
} else {
src.to_bits() >> shift_right
};
$Fixed::from_bits(bits128 as _)
}
const fn one() -> $Fixed<FRAC> {
if FRAC >= $nbits - if_signed_unsigned!($Signedness, 1, 0) {
panic!("overflow");
}
$Fixed::from_bits(if FRAC < 0 { 0 } else { 1 << FRAC })
}
if_signed! {
$Signedness;
const fn neg_one() -> $Fixed<FRAC> {
if FRAC >= $nbits {
panic!("overflow");
}
$Fixed::from_bits(if FRAC < 0 { -1 } else { -1 << FRAC })
}
}
}
comment! {
"This block contains constants in the range 0.125 ≤ <i>x</i> < 0.25,
which are implemented for `FRAC` ≤ ", stringify!($nbits_cm2), ".
These constants are not representable in ",
if_signed_unsigned!($Signedness, "signed", "unsigned"),
" fixed-point numbers with less than ",
if_signed_unsigned!($Signedness, "−1", "−2"),
" [integer bits].
# Examples
```rust
#![feature(generic_const_exprs)]
# #![allow(incomplete_features)]
use fixed::{consts, ", $s_fixed, "};
type Fix = ", $s_fixed, "<", stringify!($nbits_cm2), ">;
assert_eq!(Fix::FRAC_1_TAU, Fix::from_num(consts::FRAC_1_TAU));
```
If `FRAC` is very small, the constants can be rounded down to insignificance.
```rust
#![feature(generic_const_exprs)]
# #![allow(incomplete_features)]
use fixed::", $s_fixed, ";
type Fix = ", $s_fixed, "<-", $s_nbits, ">;
assert_eq!(Fix::FRAC_1_TAU, Fix::ZERO);
```
The following example fails to compile, since the maximum representable value
with ", stringify!($nbits_cm3), " [fractional bits] and ",
if_signed_unsigned!($Signedness, "−2", "−3"),
" [integer bits] is < 0.125.
```rust,compile_fail
#![feature(generic_const_exprs)]
# #![allow(incomplete_features)]
use fixed::{consts, ", $s_fixed, "};
type Fix = ", $s_fixed, "<", stringify!($nbits_cm3), ">;
let _ = Fix::FRAC_1_TAU;
```
[fractional bits]: Self::FRAC_BITS
[integer bits]: Self::INT_BITS
";
impl<const FRAC: i32> $Fixed<FRAC>
where
If<{ FRAC <= $nbits_cm2 }>: True,
{
pub const FRAC_1_TAU: $Fixed<FRAC> = Self::from_const(consts::PREC_FRAC_1_TAU);
}
}
comment! {
"This block contains constants in the range 0.25 ≤ <i>x</i> < 0.5,
which are implemented for `FRAC` ≤ ", stringify!($nbits_cm1), ".
These constants are not representable in ",
if_signed_unsigned!($Signedness, "signed", "unsigned"),
" fixed-point numbers with less than ",
if_signed_unsigned!($Signedness, "0", "−1"),
" [integer bits].
# Examples
```rust
#![feature(generic_const_exprs)]
# #![allow(incomplete_features)]
use fixed::{consts, ", $s_fixed, "};
type Fix = ", $s_fixed, "<", stringify!($nbits_cm1), ">;
assert_eq!(Fix::LOG10_2, Fix::from_num(consts::LOG10_2));
```
If `FRAC` is very small, the constants can be rounded down to insignificance.
```rust
#![feature(generic_const_exprs)]
# #![allow(incomplete_features)]
use fixed::", $s_fixed, ";
type Fix = ", $s_fixed, "<-", $s_nbits, ">;
assert_eq!(Fix::LOG10_2, Fix::ZERO);
```
The following example fails to compile, since the maximum representable value
with ", stringify!($nbits_cm2), " [fractional bits] and ",
if_signed_unsigned!($Signedness, "−1", "−2"),
" [integer bits] is < 0.25.
```rust,compile_fail
#![feature(generic_const_exprs)]
# #![allow(incomplete_features)]
use fixed::{consts, ", $s_fixed, "};
type Fix = ", $s_fixed, "<", stringify!($nbits_cm2), ">;
let _ = Fix::LOG10_2;
```
[fractional bits]: Self::FRAC_BITS
[integer bits]: Self::INT_BITS
";
impl<const FRAC: i32> $Fixed<FRAC>
where
If<{ FRAC <= $nbits_cm1 }>: True,
{
pub const FRAC_2_TAU: $Fixed<FRAC> = Self::from_const(consts::PREC_FRAC_2_TAU);
pub const FRAC_PI_8: $Fixed<FRAC> = Self::from_const(consts::PREC_FRAC_PI_8);
pub const FRAC_1_PI: $Fixed<FRAC> = Self::from_const(consts::PREC_FRAC_1_PI);
pub const LOG10_2: $Fixed<FRAC> = Self::from_const(consts::PREC_LOG10_2);
pub const LOG10_E: $Fixed<FRAC> = Self::from_const(consts::PREC_LOG10_E);
}
}
comment! {
"This block contains constants in the range 0.5 ≤ <i>x</i> < 1",
if_signed_else_empty_str!{ $Signedness; ", and −1" },
", which are implemented for `FRAC` ≤ ", stringify!($nbits_c0), ".
These constants are not representable in ",
if_signed_unsigned!($Signedness, "signed", "unsigned"),
" fixed-point numbers with less than ",
if_signed_unsigned!($Signedness, "1 [integer bit]", "0 [integer bits]"),
".
# Examples
```rust
#![feature(generic_const_exprs)]
# #![allow(incomplete_features)]
use fixed::{consts, ", $s_fixed, "};
type Fix = ", $s_fixed, "<", stringify!($nbits_c0), ">;
assert_eq!(Fix::LN_2, Fix::from_num(consts::LN_2));
assert!(0.5 <= Fix::LN_2 && Fix::LN_2 < 1);
```
If `FRAC` is very small, the constants can be rounded down to insignificance.
```rust
#![feature(generic_const_exprs)]
# #![allow(incomplete_features)]
use fixed::", $s_fixed, ";
type Fix = ", $s_fixed, "<-", $s_nbits, ">;
",
if_signed_else_empty_str! {
$Signedness;
"assert_eq!(Fix::NEG_ONE, -Fix::DELTA);
",
},
"assert_eq!(Fix::LN_2, Fix::ZERO);
```
The following example fails to compile, since the maximum representable value
with ", stringify!($nbits_cm1), " [fractional bits] and ",
if_signed_unsigned!($Signedness, "0", "−1"),
" [integer bits] is < 0.5.
```rust,compile_fail
#![feature(generic_const_exprs)]
# #![allow(incomplete_features)]
use fixed::{consts, ", $s_fixed, "};
type Fix = ", $s_fixed, "<", stringify!($nbits_cm1), ">;
let _ = Fix::LN_2;
```
[fractional bits]: Self::FRAC_BITS
[integer bit]: Self::INT_BITS
[integer bits]: Self::INT_BITS
";
impl<const FRAC: i32> $Fixed<FRAC>
where
If<{ FRAC <= $nbits_c0 }>: True,
{
if_signed! {
$Signedness;
comment! {
"Negative one.
If `FRAC` < 0 and [`DELTA`] > 1, `NEG_ONE` will be rounded down to
<code>-[DELTA][`DELTA`]</code>.
# Examples
```rust
#![feature(generic_const_exprs)]
# #![allow(incomplete_features)]
use fixed::", $s_fixed, ";
type Fix = ", $s_fixed, "<", $s_nbits_m1, ">;
assert_eq!(Fix::NEG_ONE, Fix::from_num(-1));
type Imprecise = ", $s_fixed, "<-1>;
assert!(Imprecise::DELTA > 1);
assert_eq!(Imprecise::NEG_ONE, -Imprecise::DELTA);
```
The following would fail as
<code>[", $s_fixed, "]<", $s_nbits_m1, "></code>
cannot represent 1, so there is no
<code>[", $s_fixed, "]::<", $s_nbits_m1, ">::[ONE]</code>.
```rust,compile_fail
#![feature(generic_const_exprs)]
# #![allow(incomplete_features)]
use fixed::", $s_fixed, ";
const _ERROR: ", $s_fixed, "<", $s_nbits_m1, "> = ", $s_fixed, "::ONE.unwrapped_neg();
```
[ONE]: ", $s_fixed, "::ONE
[`DELTA`]: ", $s_fixed, "::DELTA
";
pub const NEG_ONE: $Fixed<FRAC> = Self::neg_one();
}
}
pub const FRAC_TAU_8: $Fixed<FRAC> = Self::from_const(consts::FRAC_TAU_8);
pub const FRAC_TAU_12: $Fixed<FRAC> = Self::from_const(consts::FRAC_TAU_12);
pub const FRAC_4_TAU: $Fixed<FRAC> = Self::from_const(consts::FRAC_4_TAU);
pub const FRAC_PI_4: $Fixed<FRAC> = Self::from_const(consts::FRAC_PI_4);
pub const FRAC_PI_6: $Fixed<FRAC> = Self::from_const(consts::FRAC_PI_6);
pub const FRAC_2_PI: $Fixed<FRAC> = Self::from_const(consts::FRAC_2_PI);
pub const FRAC_1_SQRT_PI: $Fixed<FRAC> = Self::from_const(consts::FRAC_1_SQRT_PI);
pub const FRAC_1_SQRT_2: $Fixed<FRAC> = Self::from_const(consts::FRAC_1_SQRT_2);
pub const FRAC_1_SQRT_3: $Fixed<FRAC> = Self::from_const(consts::FRAC_1_SQRT_3);
pub const LN_2: $Fixed<FRAC> = Self::from_const(consts::LN_2);
pub const FRAC_1_PHI: $Fixed<FRAC> = Self::from_const(consts::FRAC_1_PHI);
pub const GAMMA: $Fixed<FRAC> = Self::from_const(consts::GAMMA);
pub const CATALAN: $Fixed<FRAC> = Self::from_const(consts::CATALAN);
}
}
comment! {
"This block contains constants in the range 1 ≤ <i>x</i> < 2,
which are implemented for `FRAC` ≤ ", stringify!($nbits_c1), ".
These constants are not representable in ",
if_signed_unsigned!($Signedness, "signed", "unsigned"),
" fixed-point numbers with less than ",
if_signed_unsigned!($Signedness, "2 [integer bits]", "1 [integer bit]"),
".
# Examples
```rust
#![feature(generic_const_exprs)]
# #![allow(incomplete_features)]
use fixed::{consts, ", $s_fixed, "};
type Fix = ", $s_fixed, "<", stringify!($nbits_c1), ">;
assert_eq!(Fix::LOG2_E, Fix::from_num(consts::LOG2_E));
assert!(1 <= Fix::LOG2_E && Fix::LOG2_E < 2);
```
If `FRAC` is very small, the constants can be rounded down to insignificance.
```rust
#![feature(generic_const_exprs)]
# #![allow(incomplete_features)]
use fixed::", $s_fixed, ";
type Fix = ", $s_fixed, "<-", $s_nbits, ">;
assert_eq!(Fix::ONE, Fix::ZERO);
assert_eq!(Fix::LOG2_E, Fix::ZERO);
```
The following example fails to compile, since the maximum representable value
with ", stringify!($nbits_c0), " [fractional bits] and ",
if_signed_unsigned!($Signedness, "1 [integer bit]", "0 [integer bits]"),
" is < 1.
```rust,compile_fail
#![feature(generic_const_exprs)]
# #![allow(incomplete_features)]
use fixed::{consts, ", $s_fixed, "};
type Fix = ", $s_fixed, "<", stringify!($nbits_c0), ">;
let _ = Fix::LOG2_E;
```
[fractional bits]: Self::FRAC_BITS
[integer bit]: Self::INT_BITS
[integer bits]: Self::INT_BITS
";
impl<const FRAC: i32> $Fixed<FRAC>
where
If<{ FRAC <= $nbits_c1 }>: True,
{
comment! {
"One.
If `FRAC` < 0 and [`DELTA`] > 1, `ONE` will be rounded down
to [`ZERO`].
# Examples
```rust
#![feature(generic_const_exprs)]
# #![allow(incomplete_features)]
use fixed::", $s_fixed, ";
type Fix = ", $s_fixed, "<4>;
assert_eq!(Fix::ONE, Fix::from_num(1));
type Imprecise = ", $s_fixed, "<-1>;
assert!(Imprecise::DELTA > 1);
assert_eq!(Imprecise::ONE, Imprecise::ZERO);
```
[`DELTA`]: ", $s_fixed, "::DELTA
[`ZERO`]: ", $s_fixed, "::ZERO
";
pub const ONE: $Fixed<FRAC> = Self::one();
}
pub const FRAC_TAU_4: $Fixed<FRAC> = Self::from_const(consts::FRAC_TAU_4);
pub const FRAC_TAU_6: $Fixed<FRAC> = Self::from_const(consts::FRAC_TAU_6);
pub const FRAC_PI_2: $Fixed<FRAC> = Self::from_const(consts::FRAC_PI_2);
pub const FRAC_PI_3: $Fixed<FRAC> = Self::from_const(consts::FRAC_PI_3);
pub const SQRT_PI: $Fixed<FRAC> = Self::from_const(consts::SQRT_PI);
pub const FRAC_2_SQRT_PI: $Fixed<FRAC> = Self::from_const(consts::FRAC_2_SQRT_PI);
pub const SQRT_2: $Fixed<FRAC> = Self::from_const(consts::SQRT_2);
pub const SQRT_3: $Fixed<FRAC> = Self::from_const(consts::SQRT_3);
pub const SQRT_E: $Fixed<FRAC> = Self::from_const(consts::SQRT_E);
pub const LOG2_E: $Fixed<FRAC> = Self::from_const(consts::LOG2_E);
pub const PHI: $Fixed<FRAC> = Self::from_const(consts::PHI);
pub const SQRT_PHI: $Fixed<FRAC> = Self::from_const(consts::SQRT_PHI);
}
}
comment! {
"This block contains constants in the range 2 ≤ <i>x</i> < 4,
which are implemented for `FRAC` ≤ ", stringify!($nbits_c2), ".
These constants are not representable in ",
if_signed_unsigned!($Signedness, "signed", "unsigned"),
" fixed-point numbers with less than ",
if_signed_unsigned!($Signedness, "3", "2"),
" [integer bits].
# Examples
```rust
#![feature(generic_const_exprs)]
# #![allow(incomplete_features)]
use fixed::{consts, ", $s_fixed, "};
type Fix = ", $s_fixed, "<", stringify!($nbits_c2), ">;
assert_eq!(Fix::E, Fix::from_num(consts::E));
assert!(2 <= Fix::E && Fix::E < 4);
```
If `FRAC` is very small, the constants can be rounded down to insignificance.
```rust
#![feature(generic_const_exprs)]
# #![allow(incomplete_features)]
use fixed::", $s_fixed, ";
type Fix = ", $s_fixed, "<-", $s_nbits, ">;
assert_eq!(Fix::E, Fix::ZERO);
```
The following example fails to compile, since the maximum representable value
with ", stringify!($nbits_c1), " [fractional bits] and ",
if_signed_unsigned!($Signedness, "2 [integer bits]", "1 [integer bit]"),
" is < 2.
```rust,compile_fail
#![feature(generic_const_exprs)]
# #![allow(incomplete_features)]
use fixed::{consts, ", $s_fixed, "};
type Fix = ", $s_fixed, "<", stringify!($nbits_c1), ">;
let _ = Fix::E;
```
[fractional bits]: Self::FRAC_BITS
[integer bit]: Self::INT_BITS
[integer bits]: Self::INT_BITS
";
impl<const FRAC: i32> $Fixed<FRAC>
where
If<{ FRAC <= $nbits_c2 }>: True,
{
pub const FRAC_TAU_2: $Fixed<FRAC> = Self::from_const(consts::FRAC_TAU_2);
pub const FRAC_TAU_3: $Fixed<FRAC> = Self::from_const(consts::FRAC_TAU_3);
pub const PI: $Fixed<FRAC> = Self::from_const(consts::PI);
pub const E: $Fixed<FRAC> = Self::from_const(consts::E);
pub const LOG2_10: $Fixed<FRAC> = Self::from_const(consts::LOG2_10);
pub const LN_10: $Fixed<FRAC> = Self::from_const(consts::LN_10);
}
}
comment! {
"This block contains constants in the range 4 ≤ <i>x</i> < 8,
which are implemented for `FRAC` ≤ ", stringify!($nbits_c3), ".
These constants are not representable in ",
if_signed_unsigned!($Signedness, "signed", "unsigned"),
" fixed-point numbers with less than ",
if_signed_unsigned!($Signedness, "4", "3"),
" [integer bits].
# Examples
```rust
#![feature(generic_const_exprs)]
# #![allow(incomplete_features)]
use fixed::{consts, ", $s_fixed, "};
type Fix = ", $s_fixed, "<", stringify!($nbits_c3), ">;
assert_eq!(Fix::TAU, Fix::from_num(consts::TAU));
assert!(4 <= Fix::TAU && Fix::TAU < 8);
```
If `FRAC` is very small, the constants can be rounded down to insignificance.
```rust
#![feature(generic_const_exprs)]
# #![allow(incomplete_features)]
use fixed::", $s_fixed, ";
type Fix = ", $s_fixed, "<-", $s_nbits, ">;
assert_eq!(Fix::TAU, Fix::ZERO);
```
The following example fails to compile, since the maximum representable value
with ", stringify!($nbits_c2), " [fractional bits] and ",
if_signed_unsigned!($Signedness, "3", "2"),
" [integer bits] is < 4.
```rust,compile_fail
#![feature(generic_const_exprs)]
# #![allow(incomplete_features)]
use fixed::{consts, ", $s_fixed, "};
type Fix = ", $s_fixed, "<", stringify!($nbits_c2), ">;
let _ = Fix::TAU;
```
[fractional bits]: Self::FRAC_BITS
[integer bits]: Self::INT_BITS
";
impl<const FRAC: i32> $Fixed<FRAC>
where
If<{ FRAC <= $nbits_c3 }>: True,
{
pub const TAU: $Fixed<FRAC> = Self::from_const(consts::TAU);
}
}
};
}