ring/ec/suite_b/ops/
elem.rs

1// Copyright 2017 Brian Smith.
2//
3// Permission to use, copy, modify, and/or distribute this software for any
4// purpose with or without fee is hereby granted, provided that the above
5// copyright notice and this permission notice appear in all copies.
6//
7// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
8// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
10// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
15use crate::{
16    arithmetic::montgomery::{Encoding, ProductEncoding},
17    limb::{Limb, LIMB_BITS},
18};
19use core::marker::PhantomData;
20
21/// Elements of ℤ/mℤ for some modulus *m*. Elements are always fully reduced
22/// with respect to *m*; i.e. the 0 <= x < m for every value x.
23#[derive(Clone, Copy)]
24pub struct Elem<M, E: Encoding> {
25    // XXX: pub
26    pub limbs: [Limb; MAX_LIMBS],
27
28    /// The modulus *m* for the ring ℤ/mℤ for which this element is a value.
29    pub m: PhantomData<M>,
30
31    /// The number of Montgomery factors that need to be canceled out from
32    /// `value` to get the actual value.
33    pub encoding: PhantomData<E>,
34}
35
36impl<M, E: Encoding> Elem<M, E> {
37    // There's no need to convert `value` to the Montgomery domain since
38    // 0 * R**2 (mod m) == 0, so neither the modulus nor the encoding are needed
39    // as inputs for constructing a zero-valued element.
40    pub fn zero() -> Self {
41        Self {
42            limbs: [0; MAX_LIMBS],
43            m: PhantomData,
44            encoding: PhantomData,
45        }
46    }
47}
48
49#[inline]
50pub fn mul_mont<M, EA: Encoding, EB: Encoding>(
51    f: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb),
52    a: &Elem<M, EA>,
53    b: &Elem<M, EB>,
54) -> Elem<M, <(EA, EB) as ProductEncoding>::Output>
55where
56    (EA, EB): ProductEncoding,
57{
58    binary_op(f, a, b)
59}
60
61// let r = f(a, b); return r;
62#[inline]
63pub fn binary_op<M, EA: Encoding, EB: Encoding, ER: Encoding>(
64    f: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb),
65    a: &Elem<M, EA>,
66    b: &Elem<M, EB>,
67) -> Elem<M, ER> {
68    let mut r = Elem {
69        limbs: [0; MAX_LIMBS],
70        m: PhantomData,
71        encoding: PhantomData,
72    };
73    unsafe { f(r.limbs.as_mut_ptr(), a.limbs.as_ptr(), b.limbs.as_ptr()) }
74    r
75}
76
77// a := f(a, b);
78#[inline]
79pub fn binary_op_assign<M, EA: Encoding, EB: Encoding>(
80    f: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb),
81    a: &mut Elem<M, EA>,
82    b: &Elem<M, EB>,
83) {
84    unsafe { f(a.limbs.as_mut_ptr(), a.limbs.as_ptr(), b.limbs.as_ptr()) }
85}
86
87// let r = f(a); return r;
88#[inline]
89pub fn unary_op<M, E: Encoding>(
90    f: unsafe extern "C" fn(r: *mut Limb, a: *const Limb),
91    a: &Elem<M, E>,
92) -> Elem<M, E> {
93    let mut r = Elem {
94        limbs: [0; MAX_LIMBS],
95        m: PhantomData,
96        encoding: PhantomData,
97    };
98    unsafe { f(r.limbs.as_mut_ptr(), a.limbs.as_ptr()) }
99    r
100}
101
102// a := f(a);
103#[inline]
104pub fn unary_op_assign<M, E: Encoding>(
105    f: unsafe extern "C" fn(r: *mut Limb, a: *const Limb),
106    a: &mut Elem<M, E>,
107) {
108    unsafe { f(a.limbs.as_mut_ptr(), a.limbs.as_ptr()) }
109}
110
111// a := f(a, a);
112#[inline]
113pub fn unary_op_from_binary_op_assign<M, E: Encoding>(
114    f: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb),
115    a: &mut Elem<M, E>,
116) {
117    unsafe { f(a.limbs.as_mut_ptr(), a.limbs.as_ptr(), a.limbs.as_ptr()) }
118}
119
120pub const MAX_LIMBS: usize = (384 + (LIMB_BITS - 1)) / LIMB_BITS;