Ordering cleanup for Fq/Fq2, with documentation. Closes #9.

This commit is contained in:
Sean Bowe 2017-07-15 15:32:37 -06:00
parent 2090e76794
commit e72660056e
No known key found for this signature in database
GPG Key ID: 95684257D8F8B031
3 changed files with 37 additions and 11 deletions

View File

@ -695,7 +695,7 @@ pub mod g1 {
negy.negate();
// Get the parity of the sqrt we found.
let parity = y.into_repr() > negy.into_repr();
let parity = y > negy;
Ok(G1Affine {
x: x,
@ -735,7 +735,7 @@ pub mod g1 {
// If the correct y coordinate is the largest (lexicographically),
// the bit should be set.
if affine.y.into_repr() > negy.into_repr() {
if affine.y > negy {
res.0[0] |= 1 << 6; // Set second highest bit.
}
}

View File

@ -1,4 +1,5 @@
use ::{Field, PrimeField, SqrtField, PrimeFieldRepr};
use std::cmp::Ordering;
use super::fq2::Fq2;
// q = 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787
@ -233,22 +234,22 @@ impl From<u64> for FqRepr {
impl Ord for FqRepr {
#[inline(always)]
fn cmp(&self, other: &FqRepr) -> ::std::cmp::Ordering {
fn cmp(&self, other: &FqRepr) -> Ordering {
for (a, b) in self.0.iter().rev().zip(other.0.iter().rev()) {
if a < b {
return ::std::cmp::Ordering::Less
return Ordering::Less
} else if a > b {
return ::std::cmp::Ordering::Greater
return Ordering::Greater
}
}
::std::cmp::Ordering::Equal
Ordering::Equal
}
}
impl PartialOrd for FqRepr {
#[inline(always)]
fn partial_cmp(&self, other: &FqRepr) -> Option<::std::cmp::Ordering> {
fn partial_cmp(&self, other: &FqRepr) -> Option<Ordering> {
Some(self.cmp(other))
}
}
@ -357,6 +358,21 @@ impl PrimeFieldRepr for FqRepr {
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Fq(FqRepr);
/// `Fq` elements are ordered lexicographically.
impl Ord for Fq {
#[inline(always)]
fn cmp(&self, other: &Fq) -> Ordering {
self.into_repr().cmp(&other.into_repr())
}
}
impl PartialOrd for Fq {
#[inline(always)]
fn partial_cmp(&self, other: &Fq) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl ::std::fmt::Debug for Fq
{
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
@ -847,7 +863,7 @@ use rand::{SeedableRng, XorShiftRng, Rand};
fn test_fq_repr_ordering() {
fn assert_equality(a: FqRepr, b: FqRepr) {
assert_eq!(a, b);
assert!(a.cmp(&b) == ::std::cmp::Ordering::Equal);
assert!(a.cmp(&b) == Ordering::Equal);
}
fn assert_lt(a: FqRepr, b: FqRepr) {
@ -1718,3 +1734,12 @@ fn fq_field_tests() {
::tests::field::random_sqrt_tests::<Fq>();
::tests::field::random_frobenius_tests::<Fq, _>(Fq::char(), 13);
}
#[test]
fn test_fq_ordering() {
// FqRepr's ordering is well-tested, but we still need to make sure the Fq
// elements aren't being compared in Montgomery form.
for i in 0..100 {
assert!(Fq::from_repr(FqRepr::from(i+1)) > Fq::from_repr(FqRepr::from(i)));
}
}

View File

@ -1,5 +1,5 @@
use rand::{Rng, Rand};
use ::{Field, SqrtField, PrimeField};
use ::{Field, SqrtField};
use super::fq::{Fq, FROBENIUS_COEFF_FQ2_C1, NEGATIVE_ONE};
use std::cmp::Ordering;
@ -11,13 +11,14 @@ pub struct Fq2 {
pub c1: Fq
}
/// `Fq2` elements are ordered lexicographically.
impl Ord for Fq2 {
#[inline(always)]
fn cmp(&self, other: &Fq2) -> Ordering {
match self.c1.into_repr().cmp(&other.c1.into_repr()) {
match self.c1.cmp(&other.c1) {
Ordering::Greater => Ordering::Greater,
Ordering::Less => Ordering::Less,
Ordering::Equal => self.c0.into_repr().cmp(&other.c0.into_repr())
Ordering::Equal => self.c0.cmp(&other.c0)
}
}
}