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
use num_traits::{abs, one, zero, Signed};
use platform_num::{LinkType, ToSigned};
#[derive(Debug, Clone, Copy, Hash, PartialOrd, PartialEq, Ord, Eq)]
pub struct Hybrid<T: LinkType> {
value: T,
}
impl<T: LinkType> Hybrid<T> {
pub fn new(value: T) -> Self {
Self::internal(value)
}
pub fn external(value: T) -> Self {
Self {
value: Self::extend_value(value),
}
}
pub fn internal(value: T) -> Self {
Self { value }
}
fn extend_value(value: T) -> T {
if value == zero() {
Self::external_zero()
} else {
T::MAX - value + one()
}
}
pub fn half() -> T {
T::MAX / T::from_u8(2).unwrap()
}
pub fn external_zero() -> T {
Self::half() - one()
}
pub fn is_nothing(&self) -> bool {
self.value == Self::external_zero() || self.signed() == zero()
}
pub fn is_internal(&self) -> bool {
self.signed() > zero()
}
pub fn is_external(&self) -> bool {
self.value == Self::external_zero() || self.signed() < zero()
}
pub fn signed(&self) -> <T as ToSigned>::Type {
self.value.to_signed()
}
pub fn absolute(&self) -> T {
let abs = if self.value == Self::external_zero() {
zero()
} else {
abs(self.signed())
}
.abs();
T::from(abs).unwrap()
}
pub fn as_value(&self) -> T {
self.value
}
}