-
Notifications
You must be signed in to change notification settings - Fork 0
/
ty.rs
90 lines (75 loc) · 2.18 KB
/
ty.rs
1
2
3
4
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#![allow(
clippy::derive_ord_xor_partial_ord,
clippy::transmute_float_to_int,
)]
use core::cmp::Ordering;
use core::ops::Deref;
use pyo3::prelude::*;
use rand::distributions::Standard;
use rand::prelude::Distribution;
#[derive(FromPyObject)]
pub(crate) enum OrdNum {
#[pyo3(transparent, annotation = "list[int]")]
Int(Vec<i32>),
#[pyo3(transparent, annotation = "list[float]")]
Float(Vec<FloatOrd>),
}
impl FromPyObject<'_> for FloatOrd {
fn extract(ob: &PyAny) -> PyResult<Self> {
Ok(FloatOrd(ob.extract()?))
}
}
impl ToPyObject for FloatOrd {
fn to_object(&self, py: Python) -> PyObject {
self.0.to_object(py)
}
}
#[derive(PartialEq, PartialOrd, Debug, Clone, Copy, Default)]
#[repr(transparent)] // guarantees same layout as a single f32
pub struct FloatOrd(pub f32);
impl Deref for FloatOrd {
type Target = f32;
fn deref(&self) -> &f32 {
&self.0
}
}
macro_rules! impl_float_ord {
($($t:ty),*) => {
$(
impl From<$t> for FloatOrd {
fn from(f: $t) -> Self {
FloatOrd(f as f32)
}
}
impl From<FloatOrd> for $t {
fn from(f: FloatOrd) -> Self {
f.0 as $t
}
}
)*
};
}
impl_float_ord!(usize, u8, u16, u32, u64, isize, i8, i16, i32, i64, f32, f64);
// compiler defines
impl Eq for FloatOrd {}
impl Ord for FloatOrd {
fn cmp(&self, other: &Self) -> Ordering {
#[inline]
/// manual transmute to bypass Nan/inf checks
/// my implementation referred to:
/// https://github.com/notriddle/rust-float-ord
fn f32_bits(a: f32) -> i32 { unsafe { std::mem::transmute(a) } }
// ideally this would be replaced by a totalorder primitive when that's available
let mut a = f32_bits(self.0);
let mut b = f32_bits(other.0);
if a < 0 { a ^= 0x7fffffff; }
if b < 0 { b ^= 0x7fffffff; }
a.cmp(&b)
}
}
// for rng sampling to generate random floats
impl Distribution<FloatOrd> for Standard {
fn sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> FloatOrd {
FloatOrd(rng.gen())
}
}