ore_encoding_rs/
encode.rs1use std::{ops::{Sub, Add}};
2
3use num::{Bounded, One};
4
5pub trait OrePlaintextOps: Ord + Bounded + One + Copy + Sub<Output=Self> + Add<Output=Self> {}
8
9impl<T: Ord + Sized + Bounded + One + Copy + Sub<Output=T> + Add<Output=T>> OrePlaintextOps for T {}
11
12#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Copy, Clone)]
15pub struct OrePlaintext<T>(pub T) where T: OrePlaintextOps;
16
17impl From<f32> for OrePlaintext<u64> {
18 fn from(term: f32) -> OrePlaintext<u64> {
19 OrePlaintext::from(f64::from(term))
20 }
21}
22
23impl From<f64> for OrePlaintext<u64> {
24 fn from(term: f64) -> OrePlaintext<u64> {
25 use core::mem::transmute;
26 let num: u64 = term.to_bits();
27 let signed: i64 = -(unsafe { transmute(num >> 63) });
28 let mut mask: u64 = unsafe { transmute(signed) };
29 mask |= 0x8000000000000000;
30 OrePlaintext(num ^ mask)
31 }
32}
33
34impl From<OrePlaintext<u64>> for f64 {
36 fn from(plaintext: OrePlaintext<u64>) -> f64 {
37 let OrePlaintext(term) = plaintext;
38 let i = (((term >> 63) as i64) - 1) as u64;
39 let mask: u64 = i | 0x8000000000000000;
40 f64::from_bits(term ^ mask)
41 }
42}
43
44impl From<bool> for OrePlaintext<u64> {
45 fn from(term: bool) -> OrePlaintext<u64> {
46 OrePlaintext(term.into())
47 }
48}
49
50impl From<u8> for OrePlaintext<u64> {
51 fn from(term: u8) -> OrePlaintext<u64> {
52 OrePlaintext(term.into())
53 }
54}
55
56impl From<u16> for OrePlaintext<u64> {
57 fn from(term: u16) -> OrePlaintext<u64> {
58 OrePlaintext(term.into())
59 }
60}
61
62impl From<u32> for OrePlaintext<u64> {
63 fn from(term: u32) -> OrePlaintext<u64> {
64 OrePlaintext(term.into())
65 }
66}
67
68impl From<u64> for OrePlaintext<u64> {
69 fn from(term: u64) -> OrePlaintext<u64> {
70 OrePlaintext(term)
71 }
72}
73
74
75#[cfg(test)]
76mod tests {
77 use std::cmp::Ordering;
78
79 use super::*;
80 use quickcheck::TestResult;
81
82 #[test]
83 fn zero_and_negative_zero() -> () {
89 assert_eq!(0.0f64.partial_cmp(&-0.0f64), Some(Ordering::Equal))
90 }
91
92 quickcheck! {
93 fn roundtrip_one_f64(x: f64) -> TestResult {
94 if !x.is_nan() && x.is_finite() {
95 TestResult::from_bool(x == f64::from(OrePlaintext::<u64>::from(x)))
96 } else {
97 TestResult::discard()
98 }
99 }
100
101 fn sort_order_is_preserved_for_vec_of_f64_after_converting_to_vec_of_ore_plaintext(numbers: Vec<f64>) -> TestResult {
102 let mut filtered: Vec<f64> = numbers.into_iter().filter(|n| !n.is_nan() && n.is_finite() && *n != -0.0f64).collect();
103 filtered.sort_by(|a, b| a.partial_cmp(b).unwrap());
104 if filtered.len() == 0 {
105 TestResult::discard()
106 } else {
107 let mut sorted_by_f64 = filtered.clone().into_iter().collect::<Vec<f64>>();
108 sorted_by_f64.sort_by(|a, b| a.partial_cmp(b).unwrap());
109
110 let mut sorted_by_u64 = filtered.clone().into_iter().collect::<Vec<f64>>();
111 sorted_by_u64.sort_by(|a, b| OrePlaintext::from(*a).cmp(&OrePlaintext::from(*b)));
112
113 TestResult::from_bool(sorted_by_f64 == sorted_by_u64)
114 }
115 }
116 }
117}