p521/arithmetic/
util.rs

1//! Utility functions.
2
3use elliptic_curve::bigint::U576;
4
5/// Convert an 18-element array of `u32` into a 9-element array of `u16`,
6/// assuming integer arrays are in little-endian order.
7#[cfg(target_pointer_width = "32")]
8pub(crate) const fn u32x18_to_u64x9(w: &[u32; 18]) -> [u64; 9] {
9    let mut ret = [0u64; 9];
10    let mut i = 0;
11
12    while i < 9 {
13        ret[i] = (w[i * 2] as u64) | ((w[(i * 2) + 1] as u64) << 32);
14        i += 1;
15    }
16
17    ret
18}
19
20/// Convert a 9-element array of `u64` into an 18-element array of `u32`,
21/// assuming integers are in little-endian order.
22#[cfg(target_pointer_width = "32")]
23pub(crate) const fn u64x9_to_u32x18(w: &[u64; 9]) -> [u32; 18] {
24    let mut ret = [0u32; 18];
25    let mut i = 0;
26
27    while i < 9 {
28        ret[i * 2] = (w[i] & 0xFFFFFFFF) as u32;
29        ret[(i * 2) + 1] = (w[i] >> 32) as u32;
30        i += 1;
31    }
32
33    ret
34}
35
36/// Converts the saturated representation [`U576`] into a 528bit array. Each
37/// word is copied in little-endian.
38pub const fn u576_to_le_bytes(w: U576) -> [u8; 66] {
39    #[cfg(target_pointer_width = "32")]
40    let words = u32x18_to_u64x9(w.as_words());
41    #[cfg(target_pointer_width = "64")]
42    let words = w.as_words();
43
44    let mut result: [u8; 66] = [0u8; 66];
45    let mut i = 0;
46    while i < words.len() - 1 {
47        let word = words[i].to_le_bytes();
48        let start = i * 8;
49        result[start] = word[0];
50        result[start + 1] = word[1];
51        result[start + 2] = word[2];
52        result[start + 3] = word[3];
53        result[start + 4] = word[4];
54        result[start + 5] = word[5];
55        result[start + 6] = word[6];
56        result[start + 7] = word[7];
57        i += 1;
58    }
59    let last_word = words[8].to_le_bytes();
60    result[i * 8] = last_word[0];
61    result[(i * 8) + 1] = last_word[1];
62
63    result
64}