This repository has been archived on 2026-08-31. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
donglora/vendor/fixed/src/cmp.rs
T
swaitsandClaude Opus 4.6 3102fc747a feat: add display UI with splash screen, dashboard, and RSSI sparkline
Implement full SSD1306 OLED display support:
- Splash screen on boot (1.5s) with project name, version, board
- Dashboard showing radio state, config, counters, RSSI/SNR
- RSSI history sparkline (64-sample ring buffer, 2px-wide bars)
- DisplayOn/DisplayOff host commands routed via dedicated channel
- Pure render functions against generic DrawTarget (no hardware coupling)
- Display on/off control bypasses radio task entirely

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 20:42:54 -06:00

696 lines
24 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Copyright © 2018–2025 Trevor Spiteri
// This library is free software: you can redistribute it and/or
// modify it under the terms of either
//
// * the Apache License, Version 2.0 or
// * the MIT License
//
// at your option.
//
// You should have recieved copies of the Apache License and the MIT
// License along with the library. If not, see
// <https://www.apache.org/licenses/LICENSE-2.0> and
// <https://opensource.org/licenses/MIT>.
#![allow(deprecated)]
use crate::float_helper;
use crate::int_helper;
use crate::int_helper::IntFixed;
use crate::types::extra::Unsigned;
use crate::{
F128, F128Bits, FixedI8, FixedI16, FixedI32, FixedI64, FixedI128, FixedU8, FixedU16, FixedU32,
FixedU64, FixedU128,
};
use core::cmp::Ordering;
use core::ops::{Shl, Shr};
use half::{bf16 as half_bf16, f16 as half_f16};
macro_rules! fixed_cmp_int {
($Fixed:ident, $Int:ident) => {
impl<Frac: Unsigned> PartialEq<$Int> for $Fixed<Frac> {
#[inline]
fn eq(&self, rhs: &$Int) -> bool {
let fixed_rhs = IntFixed(*rhs).fixed();
PartialEq::eq(self, &fixed_rhs)
}
}
impl<Frac: Unsigned> PartialEq<$Fixed<Frac>> for $Int {
#[inline]
fn eq(&self, rhs: &$Fixed<Frac>) -> bool {
let fixed_lhs = IntFixed(*self).fixed();
PartialEq::eq(&fixed_lhs, rhs)
}
}
impl<Frac: Unsigned> PartialOrd<$Int> for $Fixed<Frac> {
#[inline]
fn partial_cmp(&self, rhs: &$Int) -> Option<Ordering> {
let fixed_rhs = IntFixed(*rhs).fixed();
PartialOrd::partial_cmp(self, &fixed_rhs)
}
#[inline]
fn lt(&self, rhs: &$Int) -> bool {
let fixed_rhs = IntFixed(*rhs).fixed();
PartialOrd::lt(self, &fixed_rhs)
}
#[inline]
fn le(&self, rhs: &$Int) -> bool {
let fixed_rhs = IntFixed(*rhs).fixed();
PartialOrd::le(self, &fixed_rhs)
}
#[inline]
fn gt(&self, rhs: &$Int) -> bool {
let fixed_rhs = IntFixed(*rhs).fixed();
PartialOrd::gt(self, &fixed_rhs)
}
#[inline]
fn ge(&self, rhs: &$Int) -> bool {
let fixed_rhs = IntFixed(*rhs).fixed();
PartialOrd::ge(self, &fixed_rhs)
}
}
impl<Frac: Unsigned> PartialOrd<$Fixed<Frac>> for $Int {
#[inline]
fn partial_cmp(&self, rhs: &$Fixed<Frac>) -> Option<Ordering> {
let fixed_lhs = IntFixed(*self).fixed();
PartialOrd::partial_cmp(&fixed_lhs, rhs)
}
#[inline]
fn lt(&self, rhs: &$Fixed<Frac>) -> bool {
let fixed_lhs = IntFixed(*self).fixed();
PartialOrd::lt(&fixed_lhs, rhs)
}
#[inline]
fn le(&self, rhs: &$Fixed<Frac>) -> bool {
let fixed_lhs = IntFixed(*self).fixed();
PartialOrd::le(&fixed_lhs, rhs)
}
#[inline]
fn gt(&self, rhs: &$Fixed<Frac>) -> bool {
let fixed_lhs = IntFixed(*self).fixed();
PartialOrd::gt(&fixed_lhs, rhs)
}
#[inline]
fn ge(&self, rhs: &$Fixed<Frac>) -> bool {
let fixed_lhs = IntFixed(*self).fixed();
PartialOrd::ge(&fixed_lhs, rhs)
}
}
};
}
// Zero must NOT be neg
struct Value<U> {
neg: bool,
abs: U,
bits: u32,
frac_bits: i32,
}
#[inline]
// lhs_frac >= rhs_frac
fn float_rhs_shl<U>(rhs_abs: U, bits: u32, lhs_frac: i32, rhs_frac: i32) -> Option<U>
where
U: Copy + Eq + TryFrom<u32> + Shl<u32, Output = U> + Shr<u32, Output = U>,
{
debug_assert!(lhs_frac >= rhs_frac);
let rhs_shl = lhs_frac.wrapping_sub(rhs_frac) as u32;
let Ok(rhs_zero) = U::try_from(0u32) else {
unreachable!();
};
if rhs_abs == rhs_zero {
Some(rhs_zero)
} else if rhs_shl >= bits {
None
} else {
let shifted = rhs_abs << rhs_shl;
if (shifted >> rhs_shl) == rhs_abs {
Some(shifted)
} else {
None
}
}
}
#[inline]
fn float_eq_even<U>(lhs: Value<U>, rhs: Value<U>) -> bool
where
U: Copy + Eq + TryFrom<u32> + Shl<u32, Output = U> + Shr<u32, Output = U>,
{
if lhs.frac_bits < rhs.frac_bits {
return float_eq_even(rhs, lhs);
}
if lhs.neg != rhs.neg {
return false;
}
// lhs.frac_bits >= rhs.frac_bits
match float_rhs_shl(rhs.abs, rhs.bits, lhs.frac_bits, rhs.frac_bits) {
None => false,
Some(shifted_rhs_abs) => lhs.abs == shifted_rhs_abs,
}
}
#[inline]
fn float_eq<Lhs, Rhs>(lhs: Value<Lhs>, rhs: Value<Rhs>) -> bool
where
Lhs: Copy + Eq + TryFrom<u32> + TryFrom<Rhs> + Shl<u32, Output = Lhs> + Shr<u32, Output = Lhs>,
Rhs: Copy + Eq + TryFrom<u32> + TryFrom<Lhs> + Shl<u32, Output = Rhs> + Shr<u32, Output = Rhs>,
{
if lhs.bits >= rhs.bits {
let Ok(rhs_abs) = Lhs::try_from(rhs.abs) else {
unreachable!();
};
let rhs = Value {
neg: rhs.neg,
abs: rhs_abs,
bits: lhs.bits,
frac_bits: rhs.frac_bits,
};
float_eq_even(lhs, rhs)
} else {
let Ok(lhs_abs) = Rhs::try_from(lhs.abs) else {
unreachable!();
};
let lhs = Value {
neg: lhs.neg,
abs: lhs_abs,
bits: rhs.bits,
frac_bits: lhs.frac_bits,
};
float_eq_even(lhs, rhs)
}
}
#[inline]
fn float_cmp_even<U>(lhs: Value<U>, rhs: Value<U>) -> Ordering
where
U: Copy + Ord + TryFrom<u32> + Shl<u32, Output = U> + Shr<u32, Output = U>,
{
if lhs.frac_bits < rhs.frac_bits {
return float_cmp_even(rhs, lhs).reverse();
}
if !lhs.neg && rhs.neg {
return Ordering::Greater;
}
if lhs.neg && !rhs.neg {
return Ordering::Less;
}
match float_rhs_shl(rhs.abs, rhs.bits, lhs.frac_bits, rhs.frac_bits) {
None => {
// rhs is so large it doesn't fit
if lhs.neg {
// both lhs and rhs are negative, and rhs is even more negative
Ordering::Greater
} else {
Ordering::Less
}
}
Some(shifted_rhs_abs) => {
if lhs.neg {
// both lhs are negative, so reverse order
shifted_rhs_abs.cmp(&lhs.abs)
} else {
lhs.abs.cmp(&shifted_rhs_abs)
}
}
}
}
#[inline]
fn float_cmp<Lhs, Rhs>(lhs: Value<Lhs>, rhs: Value<Rhs>) -> Ordering
where
Lhs: Copy + Ord + TryFrom<u32> + TryFrom<Rhs> + Shl<u32, Output = Lhs> + Shr<u32, Output = Lhs>,
Rhs: Copy + Ord + TryFrom<u32> + TryFrom<Lhs> + Shl<u32, Output = Rhs> + Shr<u32, Output = Rhs>,
{
if lhs.bits >= rhs.bits {
let Ok(rhs_abs) = Lhs::try_from(rhs.abs) else {
unreachable!();
};
let rhs = Value {
neg: rhs.neg,
abs: rhs_abs,
bits: lhs.bits,
frac_bits: rhs.frac_bits,
};
float_cmp_even(lhs, rhs)
} else {
let Ok(lhs_abs) = Rhs::try_from(lhs.abs) else {
unreachable!();
};
let lhs = Value {
neg: lhs.neg,
abs: lhs_abs,
bits: rhs.bits,
frac_bits: lhs.frac_bits,
};
float_cmp_even(lhs, rhs)
}
}
macro_rules! fixed_cmp_float {
($Fix:ident($Inner:ident), $Float:ident, $FloatBits:ident) => {
impl<Frac: Unsigned> PartialEq<$Float> for $Fix<Frac> {
#[inline]
fn eq(&self, rhs: &$Float) -> bool {
use float_helper::$Float::Kind;
let (lhs_neg, lhs_abs) = int_helper::$Inner::neg_abs(self.to_bits());
let lhs = Value {
neg: lhs_neg,
abs: lhs_abs,
bits: $Inner::BITS,
frac_bits: Frac::to_i32(),
};
let Kind::Finite {
neg: rhs_neg,
abs: rhs_abs,
frac_bits: rhs_frac,
} = float_helper::$Float::kind(*rhs)
else {
return false;
};
let rhs = Value {
neg: rhs_neg,
abs: rhs_abs,
bits: $FloatBits::BITS,
frac_bits: rhs_frac,
};
float_eq(lhs, rhs)
}
}
impl<Frac: Unsigned> PartialEq<$Fix<Frac>> for $Float {
#[inline]
fn eq(&self, rhs: &$Fix<Frac>) -> bool {
rhs.eq(self)
}
}
impl<Frac: Unsigned> PartialOrd<$Float> for $Fix<Frac> {
#[inline]
fn partial_cmp(&self, rhs: &$Float) -> Option<Ordering> {
use float_helper::$Float::Kind;
let (lhs_neg, lhs_abs) = int_helper::$Inner::neg_abs(self.to_bits());
let lhs = Value {
neg: lhs_neg,
abs: lhs_abs,
bits: $Inner::BITS,
frac_bits: Frac::to_i32(),
};
let (rhs_neg, rhs_abs, rhs_frac) = match float_helper::$Float::kind(*rhs) {
Kind::Finite {
neg,
abs,
frac_bits,
} => (neg, abs, frac_bits),
Kind::Infinite { neg } => {
return if neg {
Some(Ordering::Greater)
} else {
Some(Ordering::Less)
};
}
Kind::NaN => return None,
};
let rhs = Value {
neg: rhs_neg,
abs: rhs_abs,
bits: $FloatBits::BITS,
frac_bits: rhs_frac,
};
Some(float_cmp(lhs, rhs))
}
}
impl<Frac: Unsigned> PartialOrd<$Fix<Frac>> for $Float {
#[inline]
fn partial_cmp(&self, rhs: &$Fix<Frac>) -> Option<Ordering> {
rhs.partial_cmp(self).map(Ordering::reverse)
}
}
};
}
macro_rules! fixed_cmp_all {
($Fix:ident($LeEqU:ident, $Inner:ident)) => {
fixed_cmp_int! { $Fix, i8 }
fixed_cmp_int! { $Fix, i16 }
fixed_cmp_int! { $Fix, i32 }
fixed_cmp_int! { $Fix, i64 }
fixed_cmp_int! { $Fix, i128 }
fixed_cmp_int! { $Fix, isize }
fixed_cmp_int! { $Fix, u8 }
fixed_cmp_int! { $Fix, u16 }
fixed_cmp_int! { $Fix, u32 }
fixed_cmp_int! { $Fix, u64 }
fixed_cmp_int! { $Fix, u128 }
fixed_cmp_int! { $Fix, usize }
#[cfg(feature = "nightly-float")]
fixed_cmp_float! { $Fix($Inner), f16, u16 }
fixed_cmp_float! { $Fix($Inner), half_f16, u16 }
fixed_cmp_float! { $Fix($Inner), half_bf16, u16 }
fixed_cmp_float! { $Fix($Inner), f32, u32 }
fixed_cmp_float! { $Fix($Inner), f64, u64 }
#[cfg(feature = "nightly-float")]
fixed_cmp_float! { $Fix($Inner), f128, u128 }
fixed_cmp_float! { $Fix($Inner), F128, u128 }
fixed_cmp_float! { $Fix($Inner), F128Bits, u128 }
};
}
fixed_cmp_all! { FixedI8(LeEqU8, i8) }
fixed_cmp_all! { FixedI16(LeEqU16, i16) }
fixed_cmp_all! { FixedI32(LeEqU32, i32) }
fixed_cmp_all! { FixedI64(LeEqU64, i64) }
fixed_cmp_all! { FixedI128(LeEqU128, i128) }
fixed_cmp_all! { FixedU8(LeEqU8, u8) }
fixed_cmp_all! { FixedU16(LeEqU16, u16) }
fixed_cmp_all! { FixedU32(LeEqU32, u32) }
fixed_cmp_all! { FixedU64(LeEqU64, u64) }
fixed_cmp_all! { FixedU128(LeEqU128, u128) }
#[cfg(test)]
mod tests {
use crate::*;
use core::cmp::Ordering;
#[test]
fn cmp_signed() {
use core::cmp::Ordering::*;
let neg1_16 = FixedI32::<types::extra::U16>::NEG_ONE;
let neg1_20 = FixedI32::<types::extra::U20>::NEG_ONE;
let mut a = neg1_16;
let mut b = neg1_20;
// a = ffff.0000 = -1, b = fff.00000 = -1
assert!(a.eq(&b) && b.eq(&a));
assert_eq!(a.partial_cmp(&b), Some(Equal));
assert_eq!(b.partial_cmp(&a), Some(Equal));
assert_eq!(a, -1i8);
assert_eq!(b, -1i128);
a >>= 16;
b >>= 16;
// a = ffff.ffff = -2^-16, b = fff.ffff0 = -2^-16
assert!(a.eq(&b) && b.eq(&a));
assert_eq!(a.partial_cmp(&b), Some(Equal));
assert_eq!(b.partial_cmp(&a), Some(Equal));
assert!(a < 0.0);
assert_eq!(a.partial_cmp(&f32::INFINITY), Some(Less));
assert!(a < f32::INFINITY);
assert!(a != f32::INFINITY);
assert_eq!(a.partial_cmp(&f32::NEG_INFINITY), Some(Greater));
assert!(a > f32::NEG_INFINITY);
assert_eq!(a, -(-16f32).exp2());
assert!(a <= -(-16f32).exp2());
assert!(a >= -(-16f32).exp2());
assert!(a < (-16f32).exp2());
assert_ne!(a, -0.75 * (-16f32).exp2());
assert!(a < -0.75 * (-16f32).exp2());
assert!(a <= -0.75 * (-16f32).exp2());
assert!(a > -1.25 * (-16f32).exp2());
assert!(a >= -1.25 * (-16f32).exp2());
a >>= 1;
b >>= 1;
// a = ffff.ffff = -2^-16, b = fff.ffff8 = -2^-17
assert!(a.ne(&b) && b.ne(&a));
assert_eq!(a.partial_cmp(&b), Some(Less));
assert_eq!(b.partial_cmp(&a), Some(Greater));
a = neg1_16 << 11;
b = neg1_20 << 11;
// a = f800.0000 = -2^11, b = 800.00000 = -2^11
assert!(a.eq(&b) && b.eq(&a));
assert_eq!(a.partial_cmp(&b), Some(Equal));
assert_eq!(b.partial_cmp(&a), Some(Equal));
assert_eq!(a, -1i16 << 11);
assert_eq!(b, -1i64 << 11);
a <<= 1;
b <<= 1;
// a = f000.0000 = -2^-12, b = 000.00000 = 0
assert!(a.ne(&b) && b.ne(&a));
assert_eq!(a.partial_cmp(&b), Some(Less));
assert_eq!(b.partial_cmp(&a), Some(Greater));
assert!(a < 1u8);
assert_eq!(b, 0);
}
#[test]
fn cmp_unsigned() {
use core::cmp::Ordering::*;
let one_16 = FixedU32::<types::extra::U16>::ONE;
let one_20 = FixedU32::<types::extra::U20>::ONE;
let mut a = one_16;
let mut b = one_20;
// a = 0001.0000 = 1, b = 001.00000 = 1
assert!(a.eq(&b) && b.eq(&a));
assert_eq!(a.partial_cmp(&b), Some(Equal));
assert_eq!(b.partial_cmp(&a), Some(Equal));
assert_eq!(a, 1u8);
assert_eq!(b, 1i128);
a >>= 16;
b >>= 16;
// a = 0000.0001 = 2^-16, b = 000.00010 = 2^-16
assert!(a.eq(&b) && b.eq(&a));
assert_eq!(a.partial_cmp(&b), Some(Equal));
assert_eq!(b.partial_cmp(&a), Some(Equal));
assert!(a > 0.0);
assert_eq!(a.partial_cmp(&f32::INFINITY), Some(Less));
assert!(a < f32::INFINITY);
assert!(a != f32::INFINITY);
assert_eq!(a.partial_cmp(&f32::NEG_INFINITY), Some(Greater));
assert!(a > f32::NEG_INFINITY);
assert_eq!(a, (-16f64).exp2());
assert!(a <= (-16f64).exp2());
assert!(a >= (-16f64).exp2());
assert!(a > -(-16f64).exp2());
assert_ne!(a, 0.75 * (-16f64).exp2());
assert!(a > 0.75 * (-16f64).exp2());
assert!(a >= 0.75 * (-16f64).exp2());
assert!(a < 1.25 * (-16f64).exp2());
assert!(a <= 1.25 * (-16f64).exp2());
a >>= 1;
b >>= 1;
// a = 0000.0000 = 0, b = 000.00008 = 2^-17
assert!(a.ne(&b) && b.ne(&a));
assert_eq!(a.partial_cmp(&b), Some(Less));
assert_eq!(b.partial_cmp(&a), Some(Greater));
a = one_16 << 11;
b = one_20 << 11;
// a = 0800.0000 = 2^11, b = 800.00000 = 2^11
assert!(a.eq(&b) && b.eq(&a));
assert_eq!(a.partial_cmp(&b), Some(Equal));
assert_eq!(b.partial_cmp(&a), Some(Equal));
assert_eq!(a, 1i16 << 11);
assert_eq!(b, 1u64 << 11);
a <<= 1;
b <<= 1;
// a = 1000.0000 = 2^12, b = 000.00000 = 0
assert!(a.ne(&b) && b.ne(&a));
assert_eq!(a.partial_cmp(&b), Some(Greater));
assert_eq!(b.partial_cmp(&a), Some(Less));
assert!(a > -1i8);
assert_eq!(a, 1i32 << 12);
assert_eq!(b, 0);
}
#[test]
fn cmp_i0() {
use crate::types::*;
assert_eq!(I0F32::checked_from_num(0.5), None);
for &float in &[
-0.5,
-0.5 + f32::EPSILON,
-0.25,
-f32::EPSILON,
0.0,
f32::EPSILON,
0.25,
0.5 - f32::EPSILON,
] {
let fixed = I0F32::from_num(float);
let half = U0F32::from_num(0.5);
assert_eq!(fixed < half, float < 0.5, "{fixed} < {half}");
assert_eq!(fixed <= half, float <= 0.5, "{fixed} <= {half}");
assert_eq!(fixed == half, float == 0.5, "{fixed} == {half}");
assert_eq!(fixed >= half, float >= 0.5, "{fixed} >= {half}");
assert_eq!(fixed > half, float > 0.5, "{fixed} > {half}");
assert_eq!(
fixed.partial_cmp(&half),
float.partial_cmp(&0.5),
"{fixed}.partial_cmp(&{half})"
);
assert_eq!(half < fixed, fixed > half);
assert_eq!(half <= fixed, fixed >= half);
assert_eq!(half == fixed, fixed == half);
assert_eq!(half >= fixed, fixed <= half);
assert_eq!(half > fixed, fixed < half);
assert_eq!(
half.partial_cmp(&fixed),
fixed.partial_cmp(&half).map(Ordering::reverse)
);
let half = I1F31::from_num(0.5);
assert_eq!(fixed < half, float < 0.5, "{fixed} < {half}");
assert_eq!(fixed <= half, float <= 0.5, "{fixed} <= {half}");
assert_eq!(fixed == half, float == 0.5, "{fixed} == {half}");
assert_eq!(fixed >= half, float >= 0.5, "{fixed} >= {half}");
assert_eq!(fixed > half, float > 0.5, "{fixed} > {half}");
assert_eq!(
fixed.partial_cmp(&half),
float.partial_cmp(&0.5),
"{fixed}.partial_cmp(&{half})"
);
assert_eq!(half < fixed, fixed > half);
assert_eq!(half <= fixed, fixed >= half);
assert_eq!(half == fixed, fixed == half);
assert_eq!(half >= fixed, fixed <= half);
assert_eq!(half > fixed, fixed < half);
assert_eq!(
half.partial_cmp(&fixed),
fixed.partial_cmp(&half).map(Ordering::reverse)
);
let half = 0.5f32;
assert_eq!(fixed < half, float < 0.5, "{fixed} < {half}");
assert_eq!(fixed <= half, float <= 0.5, "{fixed} <= {half}");
assert_eq!(fixed == half, float == 0.5, "{fixed} == {half}");
assert_eq!(fixed >= half, float >= 0.5, "{fixed} >= {half}");
assert_eq!(fixed > half, float > 0.5, "{fixed} > {half}");
assert_eq!(
fixed.partial_cmp(&half),
float.partial_cmp(&0.5),
"{fixed}.partial_cmp(&{half})"
);
assert_eq!(half < fixed, fixed > half);
assert_eq!(half <= fixed, fixed >= half);
assert_eq!(half == fixed, fixed == half);
assert_eq!(half >= fixed, fixed <= half);
assert_eq!(half > fixed, fixed < half);
assert_eq!(
half.partial_cmp(&fixed),
fixed.partial_cmp(&half).map(Ordering::reverse)
);
let m1 = I32F0::from_num(-1.0);
assert_eq!(fixed < m1, float < -1.0, "{fixed} < {m1}");
assert_eq!(fixed <= m1, float <= -1.0, "{fixed} <= {m1}");
assert_eq!(fixed == m1, float == -1.0, "{fixed} == {m1}");
assert_eq!(fixed >= m1, float >= -1.0, "{fixed} >= {m1}");
assert_eq!(fixed > m1, float > -1.0, "{fixed} > {m1}");
assert_eq!(
fixed.partial_cmp(&m1),
float.partial_cmp(&-1.0),
"{fixed}.partial_cmp(&{m1})"
);
assert_eq!(m1 < fixed, fixed > m1);
assert_eq!(m1 <= fixed, fixed >= m1);
assert_eq!(m1 == fixed, fixed == m1);
assert_eq!(m1 >= fixed, fixed <= m1);
assert_eq!(m1 > fixed, fixed < m1);
assert_eq!(
m1.partial_cmp(&fixed),
fixed.partial_cmp(&m1).map(Ordering::reverse)
);
let m1 = I1F31::from_num(-1.0);
assert_eq!(fixed < m1, float < -1.0, "{fixed} < {m1}");
assert_eq!(fixed <= m1, float <= -1.0, "{fixed} <= {m1}");
assert_eq!(fixed == m1, float == -1.0, "{fixed} == {m1}");
assert_eq!(fixed >= m1, float >= -1.0, "{fixed} >= {m1}");
assert_eq!(fixed > m1, float > -1.0, "{fixed} > {m1}");
assert_eq!(
fixed.partial_cmp(&m1),
float.partial_cmp(&-1.0),
"{fixed}.partial_cmp(&{m1})"
);
assert_eq!(m1 < fixed, fixed > m1);
assert_eq!(m1 <= fixed, fixed >= m1);
assert_eq!(m1 == fixed, fixed == m1);
assert_eq!(m1 >= fixed, fixed <= m1);
assert_eq!(m1 > fixed, fixed < m1);
assert_eq!(
m1.partial_cmp(&fixed),
fixed.partial_cmp(&m1).map(Ordering::reverse)
);
let m1 = -1.0f32;
assert_eq!(fixed < m1, float < -1.0, "{fixed} < {m1}");
assert_eq!(fixed <= m1, float <= -1.0, "{fixed} <= {m1}");
assert_eq!(fixed == m1, float == -1.0, "{fixed} == {m1}");
assert_eq!(fixed >= m1, float >= -1.0, "{fixed} >= {m1}");
assert_eq!(fixed > m1, float > -1.0, "{fixed} > {m1}");
assert_eq!(
fixed.partial_cmp(&m1),
float.partial_cmp(&-1.0),
"{fixed}.partial_cmp(&{m1})"
);
assert_eq!(m1 < fixed, fixed > m1);
assert_eq!(m1 <= fixed, fixed >= m1);
assert_eq!(m1 == fixed, fixed == m1);
assert_eq!(m1 >= fixed, fixed <= m1);
assert_eq!(m1 > fixed, fixed < m1);
assert_eq!(
m1.partial_cmp(&fixed),
fixed.partial_cmp(&m1).map(Ordering::reverse)
);
let mhalf = I1F31::from_num(-0.5);
assert_eq!(fixed < mhalf, float < -0.5, "{fixed} < {mhalf}");
assert_eq!(fixed <= mhalf, float <= -0.5, "{fixed} <= {mhalf}");
assert_eq!(fixed == mhalf, float == -0.5, "{fixed} == {mhalf}");
assert_eq!(fixed >= mhalf, float >= -0.5, "{fixed} >= {mhalf}");
assert_eq!(fixed > mhalf, float > -0.5, "{fixed} > {mhalf}");
assert_eq!(
fixed.partial_cmp(&mhalf),
float.partial_cmp(&-0.5),
"{fixed}.partial_cmp(&{mhalf})"
);
assert_eq!(mhalf < fixed, fixed > mhalf);
assert_eq!(mhalf <= fixed, fixed >= mhalf);
assert_eq!(mhalf == fixed, fixed == mhalf);
assert_eq!(mhalf >= fixed, fixed <= mhalf);
assert_eq!(mhalf > fixed, fixed < mhalf);
assert_eq!(
mhalf.partial_cmp(&fixed),
fixed.partial_cmp(&mhalf).map(Ordering::reverse)
);
let mhalf = -0.5f32;
assert_eq!(fixed < mhalf, float < -0.5, "{fixed} < {mhalf}");
assert_eq!(fixed <= mhalf, float <= -0.5, "{fixed} <= {mhalf}");
assert_eq!(fixed == mhalf, float == -0.5, "{fixed} == {mhalf}");
assert_eq!(fixed >= mhalf, float >= -0.5, "{fixed} >= {mhalf}");
assert_eq!(fixed > mhalf, float > -0.5, "{fixed} > {mhalf}");
assert_eq!(
fixed.partial_cmp(&mhalf),
float.partial_cmp(&-0.5),
"{fixed}.partial_cmp(&{mhalf})"
);
assert_eq!(mhalf < fixed, fixed > mhalf);
assert_eq!(mhalf <= fixed, fixed >= mhalf);
assert_eq!(mhalf == fixed, fixed == mhalf);
assert_eq!(mhalf >= fixed, fixed <= mhalf);
assert_eq!(mhalf > fixed, fixed < mhalf);
assert_eq!(
mhalf.partial_cmp(&fixed),
fixed.partial_cmp(&mhalf).map(Ordering::reverse)
);
}
}
}