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

M31 and CM31 Fields #1

Merged
merged 1 commit into from
Apr 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
30 changes: 30 additions & 0 deletions .github/workflows/cairo-ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Cairo workflow
on:
push:
branches:
- main

pull_request:
types:
- opened
- reopened
- synchronize
- auto_merge_enabled

merge_group:
types:
- checks_requested

jobs:
scarb-test:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./stwo_cairo_verifier
steps:
- uses: actions/checkout@v3
- uses: software-mansion/setup-scarb@v1
with:
scarb-version: "2.6.4"
- run: scarb fmt --check
- run: scarb test
1 change: 1 addition & 0 deletions stwo_cairo_verifier/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
target
6 changes: 6 additions & 0 deletions stwo_cairo_verifier/Scarb.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Code generated by scarb DO NOT EDIT.
version = 1

[[package]]
name = "stwo_cairo_verifier"
version = "0.1.0"
8 changes: 8 additions & 0 deletions stwo_cairo_verifier/Scarb.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
name = "stwo_cairo_verifier"
version = "0.1.0"
edition = "2023_11"

# See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html

[dependencies]
2 changes: 2 additions & 0 deletions stwo_cairo_verifier/src/fields.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod m31;
pub mod cm31;
83 changes: 83 additions & 0 deletions stwo_cairo_verifier/src/fields/cm31.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
use super::m31::{M31, m31};

#[derive(Copy, Drop, Debug, PartialEq, Eq)]
pub struct CM31 {
a: M31,
b: M31,
}

pub impl CM31Add of core::traits::Add<CM31> {
fn add(lhs: CM31, rhs: CM31) -> CM31 {
CM31 { a: lhs.a + rhs.a, b: lhs.b + rhs.b }
}
}
pub impl CM31Sub of core::traits::Sub<CM31> {
fn sub(lhs: CM31, rhs: CM31) -> CM31 {
CM31 { a: lhs.a - rhs.a, b: lhs.b - rhs.b }
}
}
pub impl CM31Mul of core::traits::Mul<CM31> {
fn mul(lhs: CM31, rhs: CM31) -> CM31 {
CM31 { a: lhs.a * rhs.a - lhs.b * rhs.b, b: lhs.a * rhs.b + lhs.b * rhs.a }
}
}
pub impl CM31Zero of core::num::traits::Zero<CM31> {
fn zero() -> CM31 {
cm31(0, 0)
}
fn is_zero(self: @CM31) -> bool {
(*self).a.is_zero() && (*self).b.is_zero()
}
fn is_non_zero(self: @CM31) -> bool {
(*self).a.is_non_zero() || (*self).b.is_non_zero()
}
}
pub impl CM31One of core::num::traits::One<CM31> {
fn one() -> CM31 {
cm31(1, 0)
}
fn is_one(self: @CM31) -> bool {
(*self).a.is_one() && (*self).b.is_zero()
}
fn is_non_one(self: @CM31) -> bool {
(*self).a.is_non_one() || (*self).b.is_non_zero()
}
}
pub impl M31IntoCM31 of core::traits::Into<M31, CM31> {
fn into(self: M31) -> CM31 {
CM31 { a: self, b: m31(0) }
}
}
pub impl CM31Neg of Neg<CM31> {
fn neg(a: CM31) -> CM31 {
CM31 { a: -a.a, b: -a.b }
}
}

pub fn cm31(a: u32, b: u32) -> CM31 {
CM31 { a: m31(a), b: m31(b) }
}


#[cfg(test)]
mod tests {
use super::{cm31};
use super::super::m31::{m31, P};

#[test]
fn test_cm31() {
let cm0 = cm31(1, 2);
let cm1 = cm31(4, 5);
let m = m31(8);
let cm = cm31(8, 0);
let cm0_x_cm1 = cm31(P - 6, 13);

assert_eq!(cm0 + cm1, cm31(5, 7));
assert_eq!(cm1 + m.into(), cm1 + cm);
assert_eq!(cm0 * cm1, cm0_x_cm1);
assert_eq!(cm1 * m.into(), cm1 * cm);
assert_eq!(-cm0, cm31(P - 1, P - 2));
assert_eq!(cm0 - cm1, cm31(P - 3, P - 3));
assert_eq!(cm1 - m.into(), cm1 - cm);
}
}
93 changes: 93 additions & 0 deletions stwo_cairo_verifier/src/fields/m31.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
use core::option::OptionTrait;
use core::traits::TryInto;
use core::result::ResultTrait;

pub const P: u32 = 0x7fffffff;
const P32NZ: NonZero<u32> = 0x7fffffff;
const P64NZ: NonZero<u64> = 0x7fffffff;

#[derive(Copy, Drop, Debug, PartialEq, Eq)]
pub struct M31 {
inner: u32
}

#[generate_trait]
pub impl M31Impl of M31Trait {
fn reduce_u32(val: u32) -> M31 {
let (_, res) = core::integer::u32_safe_divmod(val, P32NZ);
M31 { inner: res.try_into().unwrap() }
}

fn reduce_u64(val: u64) -> M31 {
let (_, res) = core::integer::u64_safe_divmod(val, P64NZ);
M31 { inner: res.try_into().unwrap() }
}
}
pub impl M31Add of core::traits::Add<M31> {
fn add(lhs: M31, rhs: M31) -> M31 {
let res = lhs.inner + rhs.inner;
let res = core::integer::u32_overflowing_sub(res, P).unwrap_or(res);
M31 { inner: res }
}
}
pub impl M31Sub of core::traits::Sub<M31> {
fn sub(lhs: M31, rhs: M31) -> M31 {
lhs + (-rhs)
}
}
pub impl M31Mul of core::traits::Mul<M31> {
fn mul(lhs: M31, rhs: M31) -> M31 {
M31Impl::reduce_u64(core::integer::u32_wide_mul(lhs.inner, rhs.inner))
}
}
pub impl M31Zero of core::num::traits::Zero<M31> {
fn zero() -> M31 {
M31 { inner: 0 }
}
fn is_zero(self: @M31) -> bool {
*self.inner == 0
}
fn is_non_zero(self: @M31) -> bool {
*self.inner != 0
}
}
pub impl M31One of core::num::traits::One<M31> {
fn one() -> M31 {
M31 { inner: 1 }
}
fn is_one(self: @M31) -> bool {
*self.inner == 1
}
fn is_non_one(self: @M31) -> bool {
*self.inner != 1
}
}
pub impl M31Neg of Neg<M31> {
fn neg(a: M31) -> M31 {
if a.inner == 0 {
M31 { inner: 0 }
} else {
M31 { inner: P - a.inner }
}
}
}

pub fn m31(val: u32) -> M31 {
M31Impl::reduce_u32(val)
}

#[cfg(test)]
mod tests {
use super::{m31, P};

#[test]
fn test_m31() {
assert_eq!(m31(P), m31(0));
assert_eq!(m31(P + 1), m31(1));
assert_eq!(m31(1) + m31(2), m31(3));
assert_eq!(m31(3) - m31(2), m31(1));
assert_eq!(m31(P - 1) + m31(1), m31(0));
assert_eq!(m31(0) - m31(1), m31(P - 1));
assert_eq!(m31(0) - m31(P - 1), m31(1));
}
}
3 changes: 3 additions & 0 deletions stwo_cairo_verifier/src/lib.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mod fields;

fn main() {}
Loading