primeorder/tables/
lookup.rs1use elliptic_curve::{
5 group::Group,
6 subtle::{Choice, ConditionallySelectable, ConstantTimeEq},
7};
8
9const LUT_SIZE: usize = 8;
14
15#[derive(Clone, Copy, Debug, Default)]
17pub struct LookupTable<Point> {
18 points: [Point; LUT_SIZE],
19}
20
21impl<Point> LookupTable<Point>
22where
23 Point: ConditionallySelectable + Group,
24{
25 pub const SIZE: usize = LUT_SIZE;
27
28 #[inline]
30 pub fn new(p: Point) -> Self {
31 let mut points = [p; LUT_SIZE];
32
33 for j in 0..(LUT_SIZE - 1) {
34 points[j + 1] = p + points[j];
35 }
36
37 Self { points }
38 }
39
40 #[allow(clippy::cast_sign_loss)]
42 #[inline]
43 pub fn select(&self, x: i8) -> Point {
44 debug_assert!((-8..=8).contains(&x));
45
46 let xmask = x >> 7;
48 let xabs = (x + xmask) ^ xmask;
49
50 let mut t = Point::identity();
52
53 #[allow(clippy::cast_possible_truncation)]
54 for j in 1..(LUT_SIZE + 1) {
55 let c = (xabs as u8).ct_eq(&(j as u8));
56 t.conditional_assign(&self.points[j - 1], c);
57 }
58 let neg_mask = Choice::from((xmask & 1) as u8);
61 t.conditional_assign(&-t, neg_mask);
62 t
65 }
66
67 #[allow(clippy::cast_sign_loss)]
69 #[inline]
70 pub fn select_vartime(&self, x: i8) -> Point {
71 debug_assert!((-8..=8).contains(&x));
72
73 let xabs = x.unsigned_abs();
74 let t = if xabs == 0 {
75 Point::identity()
76 } else {
77 self.points[xabs as usize - 1]
78 };
79
80 if x < 0 { -t } else { t }
81 }
82}