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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
use ark_std::vec::Vec;
macro_rules! adc {
($a:expr, $b:expr, &mut $carry:expr$(,)?) => {{
let tmp = ($a as u128) + ($b as u128) + ($carry as u128);
$carry = (tmp >> 64) as u64;
tmp as u64
}};
}
macro_rules! mac_with_carry {
($a:expr, $b:expr, $c:expr, &mut $carry:expr$(,)?) => {{
let tmp = ($a as u128) + ($b as u128 * $c as u128) + ($carry as u128);
$carry = (tmp >> 64) as u64;
tmp as u64
}};
}
macro_rules! sbb {
($a:expr, $b:expr, &mut $borrow:expr$(,)?) => {{
let tmp = (1u128 << 64) + ($a as u128) - ($b as u128) - ($borrow as u128);
$borrow = if tmp >> 64 == 0 { 1 } else { 0 };
tmp as u64
}};
}
#[inline(always)]
pub(crate) fn mac(a: u64, b: u64, c: u64, carry: &mut u64) -> u64 {
let tmp = (u128::from(a)) + u128::from(b) * u128::from(c);
*carry = (tmp >> 64) as u64;
tmp as u64
}
#[inline(always)]
pub(crate) fn mac_discard(a: u64, b: u64, c: u64, carry: &mut u64) {
let tmp = (u128::from(a)) + u128::from(b) * u128::from(c);
*carry = (tmp >> 64) as u64;
}
pub fn find_wnaf(num: &[u64]) -> Vec<i64> {
let is_zero = |num: &[u64]| num.iter().all(|x| *x == 0u64);
let is_odd = |num: &[u64]| num[0] & 1 == 1;
let sub_noborrow = |num: &mut [u64], z: u64| {
let mut other = vec![0u64; num.len()];
other[0] = z;
let mut borrow = 0;
for (a, b) in num.iter_mut().zip(other) {
*a = sbb!(*a, b, &mut borrow);
}
};
let add_nocarry = |num: &mut [u64], z: u64| {
let mut other = vec![0u64; num.len()];
other[0] = z;
let mut carry = 0;
for (a, b) in num.iter_mut().zip(other) {
*a = adc!(*a, b, &mut carry);
}
};
let div2 = |num: &mut [u64]| {
let mut t = 0;
for i in num.iter_mut().rev() {
let t2 = *i << 63;
*i >>= 1;
*i |= t;
t = t2;
}
};
let mut num = num.to_vec();
let mut res = vec![];
while !is_zero(&num) {
let z: i64;
if is_odd(&num) {
z = 2 - (num[0] % 4) as i64;
if z >= 0 {
sub_noborrow(&mut num, z as u64)
} else {
add_nocarry(&mut num, (-z) as u64)
}
} else {
z = 0;
}
res.push(z);
div2(&mut num);
}
res
}