• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
15 use crate::{
16     arithmetic::montgomery::{Encoding, ProductEncoding},
17     limb::{Limb, LIMB_BITS},
18 };
19 use 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)]
24 pub 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 
36 impl<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.
zero() -> Self40     pub fn zero() -> Self {
41         Self {
42             limbs: [0; MAX_LIMBS],
43             m: PhantomData,
44             encoding: PhantomData,
45         }
46     }
47 }
48 
49 #[inline]
mul_mont<M, EA: Encoding, EB: Encoding>( f: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb), a: &Elem<M, EA>, b: &Elem<M, EB>, ) -> Elem<M, <(EA, EB) as ProductEncoding>::Output> where (EA, EB): ProductEncoding,50 pub 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>
55 where
56     (EA, EB): ProductEncoding,
57 {
58     binary_op(f, a, b)
59 }
60 
61 // let r = f(a, b); return r;
62 #[inline]
binary_op<M, EA: Encoding, EB: Encoding, ER: Encoding>( f: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb), a: &Elem<M, EA>, b: &Elem<M, EB>, ) -> Elem<M, ER>63 pub 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]
binary_op_assign<M, EA: Encoding, EB: Encoding>( f: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb), a: &mut Elem<M, EA>, b: &Elem<M, EB>, )79 pub 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]
unary_op<M, E: Encoding>( f: unsafe extern "C" fn(r: *mut Limb, a: *const Limb), a: &Elem<M, E>, ) -> Elem<M, E>89 pub 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]
unary_op_assign<M, E: Encoding>( f: unsafe extern "C" fn(r: *mut Limb, a: *const Limb), a: &mut Elem<M, E>, )104 pub 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]
unary_op_from_binary_op_assign<M, E: Encoding>( f: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb), a: &mut Elem<M, E>, )113 pub 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 
120 pub const MAX_LIMBS: usize = (384 + (LIMB_BITS - 1)) / LIMB_BITS;
121