use core::fmt::Debug;
use subtle::ConditionallySelectable;
use subtle::Choice;
#[cfg(test)]
use quickcheck::{Arbitrary,Gen};
pub const FP751_NUM_WORDS: usize = 12;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct Fp751Element(pub (crate) [u64; FP751_NUM_WORDS]);
#[cfg(test)]
pub struct Fp751ElementDist;
impl ConditionallySelectable for Fp751Element {
fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
let mut bytes = [0u64; FP751_NUM_WORDS];
for i in 0..FP751_NUM_WORDS {
bytes[i] = u64::conditional_select(&a.0[i], &b.0[i], choice);
}
Fp751Element(bytes)
}
fn conditional_swap(a: &mut Self, b: &mut Self, choice: Choice) {
unsafe { cswap751_asm(a, b, choice); }
}
}
impl Debug for Fp751Element {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
write!(f, "Fp751Element({:?})", &self.0[..])
}
}
#[cfg(test)]
impl Arbitrary for Fp751Element {
fn arbitrary(g: &mut Gen) -> Fp751Element {
let mut rng = rand::thread_rng();
let high_limb = rng.gen::<u64>() % 246065832128056;
Fp751Element([
rng.gen::<u64>(),
rng.gen::<u64>(),
rng.gen::<u64>(),
rng.gen::<u64>(),
rng.gen::<u64>(),
rng.gen::<u64>(),
rng.gen::<u64>(),
rng.gen::<u64>(),
rng.gen::<u64>(),
rng.gen::<u64>(),
rng.gen::<u64>(),
high_limb
])
}
}
impl Fp751Element {
pub fn zero() -> Fp751Element {
Fp751Element([0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0])
}
pub fn to_bytes(&self) -> [u8; 94] {
let mut bytes = [0u8; 94];
let mut a = Fp751Element::zero();
let mut aR = Fp751X2::zero();
aR.0[..FP751_NUM_WORDS].clone_from_slice(&self.0);
a = aR.reduce(); a = a.strong_reduce();
let mut j;
let mut k: u64;
for i in 0..94 {
j = i / 8;
k = (i % 8) as u64;
bytes[i as usize] = (a.0[j as usize] >> (8 * k)) as u8;
}
bytes
}
pub fn from_bytes(bytes: &[u8]) -> Fp751Element {
assert!(bytes.len() >= 94, "Too short input to Fp751Element from_bytes, expected 94 bytes");
let mut a = Fp751Element::zero();
let mut j;
let mut k: u64;
for i in 0..94 {
j = i / 8;
k = (i % 8) as u64;
a.0[j as usize] |= (bytes[i as usize] as u64) << (8 * k);
}
let aRR = &a * &MONTGOMERY_RSQ; let output = aRR.reduce(); output
}
}
#[repr(C)]
#[derive(Copy, Clone, PartialEq)]
pub struct Fp751X2(pub (crate) [u64; 2*FP751_NUM_WORDS]);
impl Debug for Fp751X2 {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
write!(f, "Fp751X2({:?})", &self.0[..])
}
}
impl Fp751X2 {
pub fn zero() -> Fp751X2 {
Fp751X2([0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0])
}
}
pub const MONTGOMERY_R: Fp751Element = Fp751Element([149933, 0, 0, 0, 0, 9444048418595930112, 6136068611055053926, 7599709743867700432, 14455912356952952366, 5522737203492907350, 1222606818372667369, 49869481633250]);
pub const MONTGOMERY_RSQ: Fp751Element = Fp751Element([2535603850726686808, 15780896088201250090, 6788776303855402382, 17585428585582356230, 5274503137951975249, 2266259624764636289, 11695651972693921304, 13072885652150159301, 4908312795585420432, 6229583484603254826, 488927695601805643, 72213483953973]);
extern {
#[no_mangle]
fn cswap751_asm(x: &mut Fp751Element, y: &mut Fp751Element, choice: Choice);
#[no_mangle]
fn cassign751_asm(x: &mut Fp751Element, y: &Fp751Element, choice: u8);
#[no_mangle]
fn fpadd751_asm(x: &Fp751Element, y: &Fp751Element, z: &mut Fp751Element);
#[no_mangle]
fn fpsub751_asm(x: &Fp751Element, y: &Fp751Element, z: &mut Fp751Element);
#[no_mangle]
fn mul751_asm(x: &Fp751Element, y: &Fp751Element, z: &mut Fp751X2);
#[no_mangle]
fn rdc751_asm(x: &Fp751X2, z: &mut Fp751Element);
#[no_mangle]
fn srdc751_asm(x: &mut Fp751Element);
#[no_mangle]
fn mp_add751_asm(x: &Fp751Element, y: &Fp751Element, z: &mut Fp751Element);
#[no_mangle]
fn mp_add751x2_asm(x: &Fp751X2, y: &Fp751X2, z: &mut Fp751X2);
#[no_mangle]
fn mp_sub751x2_asm(x: &Fp751X2, y: &Fp751X2, z: &mut Fp751X2);
#[no_mangle]
fn checklt238_asm(scalar: &[u8; 48], result: &mut u32);
#[no_mangle]
fn mulby3_asm(scalar: &mut [u8; 48]);
}
pub fn fpadd751(x: &Fp751Element, y: &Fp751Element, z: &mut Fp751Element) {
unsafe { fpadd751_asm(x, y, z); }
}
pub fn fpsub751(x: &Fp751Element, y: &Fp751Element, z: &mut Fp751Element) {
unsafe { fpsub751_asm(x, y, z); }
}
pub fn mul751(x: &Fp751Element, y: &Fp751Element, z: &mut Fp751X2) {
unsafe { mul751_asm(x, y, z); }
}
pub fn rdc751(x: &Fp751X2, z: &mut Fp751Element) {
unsafe { rdc751_asm(x, z); }
}
pub fn srdc751(x: &mut Fp751Element) {
unsafe { srdc751_asm(x); }
}
pub fn mp_add751(x: &Fp751Element, y: &Fp751Element, z: &mut Fp751Element) {
unsafe { mp_add751_asm(x, y, z); }
}
pub fn mp_add751x2(x: &Fp751X2, y: &Fp751X2, z: &mut Fp751X2) {
unsafe { mp_add751x2_asm(x, y, z); }
}
pub fn mp_sub751x2(x: &Fp751X2, y: &Fp751X2, z: &mut Fp751X2) {
unsafe { mp_sub751x2_asm(x, y, z); }
}
pub fn checklt238(scalar: &[u8; 48], result: &mut u32) {
unsafe { checklt238_asm(scalar, result); }
}
pub fn mulby3(scalar: &mut [u8; 48]) {
unsafe { mulby3_asm(scalar); }
}