1#![no_std]
3#![doc(
4 html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg",
5 html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg"
6)]
7#![forbid(unsafe_code)]
8
9use hybrid_array::Array;
10use hybrid_array::typenum::{U8, U16, U32};
11
12const C64: u64 = 0b1_1011;
13const C128: u64 = 0b1000_0111;
14const C256: u64 = 0b100_0010_0101;
15
16mod sealed {
17 pub trait Sealed {}
18}
19
20pub trait Dbl: sealed::Sealed {
25 #[must_use]
32 fn dbl(self) -> Self;
33
34 #[must_use]
39 fn inv_dbl(self) -> Self;
40}
41
42impl Dbl for Array<u8, U8> {
43 #[inline]
44 fn dbl(self) -> Self {
45 let mut val = u64::from_be_bytes(self.into());
46
47 let a = val >> 63;
48 val <<= 1;
49 val ^= a * C64;
50
51 val.to_be_bytes().into()
52 }
53
54 #[inline]
55 fn inv_dbl(self) -> Self {
56 let mut val = u64::from_be_bytes(self.into());
57
58 let a = val & 1;
59 val >>= 1;
60 val ^= a * ((1 << 63) ^ (C64 >> 1));
61
62 val.to_be_bytes().into()
63 }
64}
65
66impl sealed::Sealed for Array<u8, U8> {}
67
68impl Dbl for Array<u8, U16> {
69 #[inline]
70 fn dbl(self) -> Self {
71 let mut val = [
72 u64::from_be_bytes(self[..8].try_into().unwrap()),
73 u64::from_be_bytes(self[8..].try_into().unwrap()),
74 ];
75
76 let b = val[1] >> 63;
77 let a = val[0] >> 63;
78
79 val[0] <<= 1;
80 val[0] ^= b;
81 val[1] <<= 1;
82 val[1] ^= a * C128;
83
84 let mut res = Self::default();
85 res[..8].copy_from_slice(&val[0].to_be_bytes());
86 res[8..].copy_from_slice(&val[1].to_be_bytes());
87 res
88 }
89
90 #[inline]
91 fn inv_dbl(self) -> Self {
92 let mut val = [
93 u64::from_be_bytes(self[..8].try_into().unwrap()),
94 u64::from_be_bytes(self[8..].try_into().unwrap()),
95 ];
96
97 let a = (val[0] & 1) << 63;
98 let b = val[1] & 1;
99
100 val[0] >>= 1;
101 val[1] >>= 1;
102 val[1] ^= a;
103 val[0] ^= b * (1 << 63);
104 val[1] ^= b * (C128 >> 1);
105
106 let mut res = Self::default();
107 res[..8].copy_from_slice(&val[0].to_be_bytes());
108 res[8..].copy_from_slice(&val[1].to_be_bytes());
109 res
110 }
111}
112
113impl sealed::Sealed for Array<u8, U16> {}
114
115impl Dbl for Array<u8, U32> {
116 #[inline]
117 fn dbl(self) -> Self {
118 let mut val = [
119 u64::from_be_bytes(self[0..8].try_into().unwrap()),
120 u64::from_be_bytes(self[8..16].try_into().unwrap()),
121 u64::from_be_bytes(self[16..24].try_into().unwrap()),
122 u64::from_be_bytes(self[24..32].try_into().unwrap()),
123 ];
124
125 let a = val[0] >> 63;
126 let b = val[1] >> 63;
127 let c = val[2] >> 63;
128 let d = val[3] >> 63;
129
130 val[0] <<= 1;
131 val[0] ^= b;
132 val[1] <<= 1;
133 val[1] ^= c;
134 val[2] <<= 1;
135 val[2] ^= d;
136 val[3] <<= 1;
137 val[3] ^= a * C256;
138
139 let mut res = Self::default();
140 res[0..8].copy_from_slice(&val[0].to_be_bytes());
141 res[8..16].copy_from_slice(&val[1].to_be_bytes());
142 res[16..24].copy_from_slice(&val[2].to_be_bytes());
143 res[24..32].copy_from_slice(&val[3].to_be_bytes());
144 res
145 }
146
147 #[inline]
148 fn inv_dbl(self) -> Self {
149 let mut val = [
150 u64::from_be_bytes(self[0..8].try_into().unwrap()),
151 u64::from_be_bytes(self[8..16].try_into().unwrap()),
152 u64::from_be_bytes(self[16..24].try_into().unwrap()),
153 u64::from_be_bytes(self[24..32].try_into().unwrap()),
154 ];
155
156 let a = (val[0] & 1) << 63;
157 let b = (val[1] & 1) << 63;
158 let c = (val[2] & 1) << 63;
159 let d = val[3] & 1;
160
161 val[0] >>= 1;
162 val[1] >>= 1;
163 val[2] >>= 1;
164 val[3] >>= 1;
165 val[1] ^= a;
166 val[2] ^= b;
167 val[3] ^= c;
168
169 val[0] ^= d * (1 << 63);
170 val[3] ^= d * (C256 >> 1);
171
172 let mut res = Self::default();
173 res[0..8].copy_from_slice(&val[0].to_be_bytes());
174 res[8..16].copy_from_slice(&val[1].to_be_bytes());
175 res[16..24].copy_from_slice(&val[2].to_be_bytes());
176 res[24..32].copy_from_slice(&val[3].to_be_bytes());
177 res
178 }
179}
180
181impl sealed::Sealed for Array<u8, U32> {}