Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Circle starks #924

Merged
merged 86 commits into from
Nov 4, 2024
Merged
Changes from 1 commit
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
852f856
optimize add
Sep 18, 2024
0d68798
save changes. Add, sub and mul checked
Sep 18, 2024
5ebc30a
fix tests
ColoCarletti Sep 19, 2024
81439ae
add new inv
ColoCarletti Sep 19, 2024
47cf7da
add mult by powers of two
Sep 19, 2024
2acfdd7
Merge branch 'optimize_mersenne31' of github.com:lambdaclass/lambdawo…
Sep 19, 2024
cfba8bc
replace inverse
Sep 19, 2024
01eba0d
test new inv
ColoCarletti Sep 20, 2024
60fd981
modify old algorithm for inv
ColoCarletti Sep 20, 2024
996e224
fix tests extension
Sep 20, 2024
c41b977
Merge branch 'optimize_mersenne31' of github.com:lambdaclass/lambdawo…
Sep 20, 2024
28d8b0e
add mul for degree 4 extension
Sep 20, 2024
5e1f533
add fp4 isField and isSubField operations and benchmarks
Sep 23, 2024
fde7faa
new version for fp4 mul based on the paper
Sep 23, 2024
60c8197
add mul of a fp2e by non-residue
Sep 23, 2024
25b8869
change inv using mul_fp2_by_non_resiude
Sep 23, 2024
1187be8
save work
Sep 24, 2024
ecff11e
wip fp2 test
ColoCarletti Sep 24, 2024
a6169ea
Merge branch 'optimize_mersenne31' of github.com:lambdaclass/lambdawo…
ColoCarletti Sep 24, 2024
ae1446a
add fp2 tests
ColoCarletti Sep 24, 2024
fa12fc5
add 2 * a^2 - 1 function
Sep 24, 2024
461485b
use karatsuba in fp4 mul version 1
Sep 25, 2024
d4e3f40
clean up
ColoCarletti Sep 25, 2024
f0437c7
fix Fp as subfield of Fp2. Tests Fp plus Fp4 is now correct
Sep 25, 2024
2c5a301
fix inv
ColoCarletti Sep 26, 2024
4a42dbc
fix comments
ColoCarletti Sep 26, 2024
21d09c6
create crate
ColoCarletti Sep 26, 2024
f7efd90
Revert "create crate"
ColoCarletti Sep 26, 2024
db3ab30
Merge branch 'optimize_mersenne31' into circle-starks
ColoCarletti Sep 26, 2024
eddd9be
add circle point implementation
ColoCarletti Sep 26, 2024
ba738c7
add group order
ColoCarletti Sep 26, 2024
85d80c1
rm dependencie
ColoCarletti Sep 26, 2024
14a7beb
add cosets
ColoCarletti Sep 30, 2024
b56d212
add twiddle
ColoCarletti Oct 1, 2024
58aeb0c
init cfft
ColoCarletti Oct 1, 2024
a85eb0f
test cfft
ColoCarletti Oct 2, 2024
6bda70d
test 16 not working
Oct 2, 2024
7cbd173
fix n16 test
ColoCarletti Oct 2, 2024
4f60a48
refactor
ColoCarletti Oct 3, 2024
35a9d5a
Merge branch 'main' into circle-starks
ColoCarletti Oct 4, 2024
95e87d0
clippy
ColoCarletti Oct 4, 2024
10636f9
fmt
ColoCarletti Oct 4, 2024
c76793f
Merge branch 'main' into circle-starks
diegokingston Oct 4, 2024
876459d
clippy
ColoCarletti Oct 4, 2024
dcdd18a
Merge branch 'circle-starks' of github.com:lambdaclass/lambdaworks in…
ColoCarletti Oct 4, 2024
076b683
rm std
ColoCarletti Oct 4, 2024
0d7d89f
add alloc
ColoCarletti Oct 4, 2024
9685a74
fix
ColoCarletti Oct 4, 2024
ac842bf
wip
ColoCarletti Oct 7, 2024
52655b1
Merge branch 'main' into circle-starks
ColoCarletti Oct 8, 2024
5f97990
add hand iterpolation for 4 and 8
ColoCarletti Oct 14, 2024
dc4124e
wip
ColoCarletti Oct 15, 2024
56dae17
evaluation and interpolation working
Oct 16, 2024
2546ca2
add tests and comments
Oct 16, 2024
57735cf
Merge branch 'main' into circle-starks
ColoCarletti Oct 17, 2024
da5fae7
clippy
ColoCarletti Oct 17, 2024
1166a42
Merge branch 'circle-starks' of github.com:lambdaclass/lambdaworks in…
ColoCarletti Oct 17, 2024
28ab71f
fmt
ColoCarletti Oct 17, 2024
e0c666d
remove unused functions
ColoCarletti Oct 17, 2024
3073470
add comment
ColoCarletti Oct 17, 2024
37aae9e
Update math/src/circle/polynomial.rs
nicole-graus Oct 23, 2024
4436e28
change generator and order CirclePoint functions as constants
Oct 23, 2024
835a565
impl eq as PartialEq
Oct 23, 2024
2ea3171
implement scalar_mul as Mul
Oct 23, 2024
c9acb74
Change error name to a more descriptive one and move it to point.rs
Oct 23, 2024
93fd515
fix lint
Oct 23, 2024
7ae4990
fix lint
Oct 23, 2024
8801317
fix some comments
Oct 23, 2024
7fe6a7d
Merge branch 'main' into circle-starks
diegokingston Oct 24, 2024
8b2b3d2
add alloc::vec
ColoCarletti Oct 24, 2024
ebc5e9d
fix no-std
ColoCarletti Oct 24, 2024
f3028e5
cargo fmt
ColoCarletti Oct 24, 2024
b645a7b
fix no-std
ColoCarletti Oct 24, 2024
c7cfd8f
remove macro
ColoCarletti Oct 24, 2024
fc68bea
add comment
ColoCarletti Oct 25, 2024
0a50704
addition between referenced and non-referenced values
Oct 28, 2024
a045516
Update math/src/circle/point.rs
nicole-graus Oct 30, 2024
c00a223
explain why won't panic
Oct 30, 2024
9ff3233
Merge branch 'circle-starks' of github.com:lambdaclass/lambdaworks in…
Oct 30, 2024
e0fa390
add errors.rs
ColoCarletti Oct 30, 2024
3ed8ac1
fix vec
Oct 30, 2024
a7161f2
Evaluate and interpolate functions have non-mutable inputs
Oct 30, 2024
b88794f
fix clippy
Oct 30, 2024
b2e9b9d
MulAssign for points and double function takes a reference
Oct 30, 2024
26d6078
Revert "MulAssign for points and double function takes a reference"
Oct 31, 2024
a6738c7
MulAssign and AddAssign
Oct 31, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
clean up
  • Loading branch information
ColoCarletti committed Sep 25, 2024
commit d4e3f408b4f5f9e730931b888dba6a3689c66779
75 changes: 5 additions & 70 deletions math/benches/fields/mersenne31.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
use std::hint::black_box;

use criterion::Criterion;
use lambdaworks_math::{
elliptic_curve::edwards::curves::bandersnatch::field,
field::{
element::FieldElement,
fields::mersenne31::{
extension::{Degree2ExtensionField, Degree4ExtensionField, Degree4ExtensionFieldV2},
field::Mersenne31Field,
},
use lambdaworks_math::field::{
element::FieldElement,
fields::mersenne31::{
extension::{Degree2ExtensionField, Degree4ExtensionField},
field::Mersenne31Field,
},
};
use rand::random;
@@ -46,36 +43,8 @@ pub fn rand_fp4e(num: usize) -> Vec<(Fp4E, Fp4E)> {
result
}

pub fn rand_fp4e_v2(
num: usize,
) -> Vec<(
FieldElement<Degree4ExtensionFieldV2>,
FieldElement<Degree4ExtensionFieldV2>,
)> {
let mut result = Vec::with_capacity(num);
for _ in 0..result.capacity() {
result.push((
FieldElement::<Degree4ExtensionFieldV2>::new([
Fp2E::new([F::new(random()), F::new(random())]),
Fp2E::new([F::new(random()), F::new(random())]),
]),
FieldElement::<Degree4ExtensionFieldV2>::new([
Fp2E::new([F::new(random()), F::new(random())]),
Fp2E::new([F::new(random()), F::new(random())]),
]),
));
}
result
}

pub fn mersenne31_extension_ops_benchmarks(c: &mut Criterion) {
let input: Vec<Vec<(Fp4E, Fp4E)>> = [1000000].into_iter().map(rand_fp4e).collect::<Vec<_>>();
let input_v2: Vec<
Vec<(
FieldElement<Degree4ExtensionFieldV2>,
FieldElement<Degree4ExtensionFieldV2>,
)>,
> = [1000000].into_iter().map(rand_fp4e_v2).collect::<Vec<_>>();

let mut group = c.benchmark_group("Mersenne31 Fp4 operations");

@@ -89,16 +58,6 @@ pub fn mersenne31_extension_ops_benchmarks(c: &mut Criterion) {
});
}

for i in input_v2.clone().into_iter() {
group.bench_with_input(format!("Mul of Fp4 V2 {:?}", &i.len()), &i, |bench, i| {
bench.iter(|| {
for (x, y) in i {
black_box(black_box(x) * black_box(y));
}
});
});
}

for i in input.clone().into_iter() {
group.bench_with_input(format!("Square of Fp4 {:?}", &i.len()), &i, |bench, i| {
bench.iter(|| {
@@ -109,20 +68,6 @@ pub fn mersenne31_extension_ops_benchmarks(c: &mut Criterion) {
});
}

for i in input_v2.clone().into_iter() {
group.bench_with_input(
format!("Square of Fp4 V2 {:?}", &i.len()),
&i,
|bench, i| {
bench.iter(|| {
for (x, _) in i {
black_box(black_box(x).square());
}
});
},
);
}

for i in input.clone().into_iter() {
group.bench_with_input(format!("Inv of Fp4 {:?}", &i.len()), &i, |bench, i| {
bench.iter(|| {
@@ -132,16 +77,6 @@ pub fn mersenne31_extension_ops_benchmarks(c: &mut Criterion) {
});
});
}

for i in input_v2.clone().into_iter() {
group.bench_with_input(format!("Inv of Fp4 V2 {:?}", &i.len()), &i, |bench, i| {
bench.iter(|| {
for (x, _) in i {
black_box(black_box(x).inv().unwrap());
}
});
});
}
}

pub fn mersenne31_ops_benchmarks(c: &mut Criterion) {
223 changes: 37 additions & 186 deletions math/src/field/fields/mersenne31/extension.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use crate::field::{
element::FieldElement,
errors::FieldError,
extensions::quadratic::{HasQuadraticNonResidue, QuadraticExtensionField},
traits::{IsField, IsSubFieldOf},
};

@@ -14,6 +13,15 @@ type FpE = FieldElement<Mersenne31Field>;
#[derive(Clone, Debug)]
pub struct Degree2ExtensionField;

impl Degree2ExtensionField {
pub fn mul_fp2_by_nonresidue(a: &Fp2E) -> Fp2E {
Fp2E::new([
a.value()[0].double() - a.value()[1],
a.value()[1].double() + a.value()[0],
])
}
}

impl IsField for Degree2ExtensionField {
//Elements represents a[0] = real, a[1] = imaginary
type BaseType = [FpE; 2];
@@ -132,29 +140,6 @@ impl IsSubFieldOf<Degree2ExtensionField> for Mersenne31Field {

type Fp2E = FieldElement<Degree2ExtensionField>;

/// Extension of degree 4 defined with lambdaworks quadratic extension to test the correctness of Degree4ExtensionField
#[derive(Debug, Clone)]
pub struct Mersenne31LevelTwoResidue;
impl HasQuadraticNonResidue<Degree2ExtensionField> for Mersenne31LevelTwoResidue {
fn residue() -> Fp2E {
Fp2E::new([FpE::from(2), FpE::one()])
}
}
pub type Degree4ExtensionFieldV2 =
QuadraticExtensionField<Degree2ExtensionField, Mersenne31LevelTwoResidue>;

/// I = 0 + 1 * i
pub const I: Fp2E = Fp2E::const_from_raw([FpE::const_from_raw(0), FpE::const_from_raw(1)]);

/// TWO_PLUS_I = 2 + 1 is the non-residue of Fp2 used for the Fp4 extension.
pub const TWO_PLUS_I: Fp2E = Fp2E::const_from_raw([FpE::const_from_raw(2), FpE::const_from_raw(1)]);

pub fn mul_fp2_by_nonresidue(a: &Fp2E) -> Fp2E {
Fp2E::new([
a.value()[0].double() - a.value()[1],
&a.value()[1].double() + &a.value()[0],
])
}
#[derive(Clone, Debug)]
pub struct Degree4ExtensionField;

@@ -174,96 +159,27 @@ impl IsField for Degree4ExtensionField {
}

fn mul(a: &Self::BaseType, b: &Self::BaseType) -> Self::BaseType {
/*
// VERSION 1 (distribution by hand):
// a = a0 + a1 * u, b = b0 + b1 * u, where
// a0 = a00 + a01 * i, a1 = a11 + a11 * i, etc.
let [a00, a01] = a[0].value();
let [a10, a11] = a[1].value();
let [b00, b01] = b[0].value();
let [b10, b11] = b[1].value();

let a10b10 = a10 * b10;
let a10b11 = a10 * b11;
let a11b10 = b10 * a11;
let a11b11 = a11 * b11;

let c00 = a00 * b00 - a01 * b01 + a10b10.double() - a10b11 - a11b10 - (a11b11).double();
let c01 = a00 * b01 + a01 * b00 + a10b10 + a10b11.double() + a11b10.double() - a11b11;
let c10 = a00 * b10 - a01 * b11 + a10 * b00 - b01 * a11;
let c11 = a00 * b11 + a01 * b10 + a10 * b01 + a11 * b00;

[Fp2E::new([c00, c01]), Fp2E::new([c10, c11])]
*/

// VERSION 1 using Karatsuba:
// a = a0 + a1 * u, b = b0 + b1 * u, where
// a0 = a00 + a01 * i, a1 = a11 + a11 * i, etc.
let [a00, a01] = a[0].value();
let [a10, a11] = a[1].value();
let [b00, b01] = b[0].value();
let [b10, b11] = b[1].value();

let a00b00 = a00 * b00;
let a00b10 = a00 * b10;
let a01b01 = a01 * b01;
let a01b11 = a01 * b11;
let a10b00 = a10 * b00;
let a10b10 = a10 * b10;
let a10b11 = a10 * b11;
let a11b01 = a11 * b01;
let a11b10 = b10 * a11;
let a11b11 = a11 * b11;

let c00 = a00b00 - a01b01 + a10b10.double() - a10b11 - a11b10 - (a11b11).double();
let c01 = (a00 + a01) * (b00 + b01) - a00b00 - a01b01
+ a10b10
+ a10b11.double()
+ a11b10.double()
- a11b11;
let c10 = a00b10 - a01b11 + a10b00 - a11b01;
let c11 = (a00 + a01) * (b10 + b11) - a00b10 - a01b11 + (a10 + a11) * (b00 + b01)
- a10b00
- a11b01;

[Fp2E::new([c00, c01]), Fp2E::new([c10, c11])]

/*
// VERSION 2 (paper, karatsuba):
// Algorithm from: https://github.com/ingonyama-zk/papers/blob/main/Mersenne31_polynomial_arithmetic.pdf (page 5):
let a0b0 = &a[0] * &b[0];
let a1b1 = &a[1] * &b[1];
[
&a0b0 + mul_fp2_by_nonresidue(&a1b1),
&a0b0 + Degree2ExtensionField::mul_fp2_by_nonresidue(&a1b1),
(&a[0] + &a[1]) * (&b[0] + &b[1]) - a0b0 - a1b1,
]
*/
}

fn square(a: &Self::BaseType) -> Self::BaseType {
// a = a0 + a1 * u, where
// a0 = a00 + a01 * i and a1 = a11 + a11 * i
let [a00, a01] = a[0].value();
let [a10, a11] = a[1].value();

let a10a10 = a10 * a10;
let a10a11 = a10 * a11;
let a11a11 = a11 * a11;

let c00 = a00 * a00 - a01 * a01 + a10a10.double() - a10a11.double() - (a11a11).double();
let c01 = (a00 * a01).double() + a10a10 + a10a11.double().double() - a11a11;
let c10 = (a00 * a10).double() - (a01 * a11).double();
let c11 = (a00 * a11).double() + (a01 * a10).double();

[Fp2E::new([c00, c01]), Fp2E::new([c10, c11])]
let a0_square = &a[0].square();
let a1_square = &a[1].square();
[
a0_square + Degree2ExtensionField::mul_fp2_by_nonresidue(&a1_square),
(&a[0] + &a[1]).square() - a0_square - a1_square,
]
}

fn inv(a: &Self::BaseType) -> Result<Self::BaseType, FieldError> {
// VERSION 1:
// let a1_square = a[1].square();
// let inv_norm = (a[0].square() - a1_square.double() - a1_square * I).inv()?;

// VERSION 2:
let inv_norm = (a[0].square() - mul_fp2_by_nonresidue(&a[1].square())).inv()?;
let inv_norm =
(a[0].square() - Degree2ExtensionField::mul_fp2_by_nonresidue(&a[1].square())).inv()?;
Ok([&a[0] * &inv_norm, -&a[1] * &inv_norm])
}

@@ -661,56 +577,6 @@ mod tests {
assert_eq!(a / b, expected_result);
}

#[test]
fn mul_fp4_is_correct() {
let a = Fp4E::new([
Fp2E::new([FpE::from(2), FpE::from(3)]),
Fp2E::new([FpE::from(4), FpE::from(5)]),
]);

let b = Fp4E::new([
Fp2E::new([FpE::from(6), FpE::from(7)]),
Fp2E::new([FpE::from(8), FpE::from(9)]),
]);

let a2 = FieldElement::<Degree4ExtensionFieldV2>::new([
Fp2E::new([FpE::from(2), FpE::from(3)]),
Fp2E::new([FpE::from(4), FpE::from(5)]),
]);

let b2 = FieldElement::<Degree4ExtensionFieldV2>::new([
Fp2E::new([FpE::from(6), FpE::from(7)]),
Fp2E::new([FpE::from(8), FpE::from(9)]),
]);

assert_eq!((&a * &b).value(), (a2 * b2).value())
}

#[test]
fn mul_fp4_is_correct_2() {
let a = Fp4E::new([
Fp2E::new([FpE::from(2147483647), FpE::from(2147483648)]),
Fp2E::new([FpE::from(2147483649), FpE::from(2147483650)]),
]);

let b = Fp4E::new([
Fp2E::new([FpE::from(6), FpE::from(7)]),
Fp2E::new([FpE::from(8), FpE::from(9)]),
]);

let a2 = FieldElement::<Degree4ExtensionFieldV2>::new([
Fp2E::new([FpE::from(2147483647), FpE::from(2147483648)]),
Fp2E::new([FpE::from(2147483649), FpE::from(2147483650)]),
]);

let b2 = FieldElement::<Degree4ExtensionFieldV2>::new([
Fp2E::new([FpE::from(6), FpE::from(7)]),
Fp2E::new([FpE::from(8), FpE::from(9)]),
]);

assert_eq!((&a * &b).value(), (a2 * b2).value())
}

#[test]
fn mul_fp4_by_zero_is_zero() {
let a = Fp4E::new([
@@ -729,21 +595,6 @@ mod tests {
assert_eq!(a, a.clone() * Fp4E::one())
}

#[test]
fn square_fp4_is_correct() {
let a = Fp4E::new([
Fp2E::new([FpE::from(2), FpE::from(3)]),
Fp2E::new([FpE::from(4), FpE::from(5)]),
]);

let a2 = FieldElement::<Degree4ExtensionFieldV2>::new([
Fp2E::new([FpE::from(2), FpE::from(3)]),
Fp2E::new([FpE::from(4), FpE::from(5)]),
]);

assert_eq!(a.square().value(), a2.square().value())
}

#[test]
fn square_fp4_equals_mul_two_times() {
let a = Fp4E::new([
@@ -771,22 +622,22 @@ mod tests {
assert_eq!(a.to_extension::<Degree4ExtensionField>(), a_extension);
}

// #[test]
// fn add_fp_and_fp4() {
// let a = FpE::from(3);
// let a_extension = Fp4E::from(3);
// let b = Fp4E::from(2);
// assert_eq!(a + &b, a_extension + b);
// }

// #[test]
// fn mul_fp_by_fp4() {
// let a = FpE::from(30000000000);
// let a_extension = a.clone().to_extension::<Degree4ExtensionField>();
// let b = Fp4E::new([
// Fp2E::new([FpE::from(1), FpE::from(2)]),
// Fp2E::new([FpE::from(3), FpE::from(4)]),
// ]);
// assert_eq!(a * &b, a_extension * b);
// }
#[test]
fn add_fp_and_fp4() {
let a = FpE::from(3);
let a_extension = Fp4E::from(3);
let b = Fp4E::from(2);
assert_eq!(a + &b, a_extension + b);
}

#[test]
fn mul_fp_by_fp4() {
let a = FpE::from(30000000000);
let a_extension = a.clone().to_extension::<Degree4ExtensionField>();
let b = Fp4E::new([
Fp2E::new([FpE::from(1), FpE::from(2)]),
Fp2E::new([FpE::from(3), FpE::from(4)]),
]);
assert_eq!(a * &b, a_extension * b);
}
}
Loading