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
use crate::LinkType;
use funty::Integral;
use std::ops::{Div, Sub};

#[derive(Debug, Clone, Copy, Hash, PartialOrd, PartialEq, Ord, Eq)]
pub struct Hybrid<T> {
    value: T,
}

impl<T: LinkType> Hybrid<T> {
    pub const fn new(value: T) -> Self {
        Self::internal(value)
    }

    pub const fn half() -> T
    where
        T: ~const Div<Output = T>,
    {
        T::MAX / T::funty(2)
    }

    pub(crate) const fn external(value: T) -> Self
    where
        T: ~const Integral + ~const Sub,
    {
        Self {
            value: Self::extend_value(value),
        }
    }

    pub(crate) const fn internal(value: T) -> Self {
        Self { value }
    }

    const fn extend_value(value: T) -> T
    where
        T: ~const Integral + ~const Sub,
    {
        (T::MAX - value).wrapping_add(T::funty(1))
    }

    pub const fn is_zero(&self) -> bool
    where
        T: ~const Default + ~const PartialEq,
    {
        self.value == T::funty(0)
    }

    pub const fn is_internal(&self) -> bool
    where
        T: ~const Div + ~const PartialOrd,
    {
        self.value < Self::half() // || self.value == T::default()
    }

    pub const fn is_external(&self) -> bool
    where
        T: ~const Div + ~const PartialOrd + ~const PartialEq,
    {
        !self.is_internal() || self.value == T::funty(0)
    }

    pub const fn abs(&self) -> T
    where
        T: ~const Integral,
    {
        self.value.wrapping_add(T::funty(1)).wrapping_add(T::MAX)
    }

    pub const fn as_inner(&self) -> T {
        self.value
    }
}