Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
feltroidprime committed Feb 5, 2024
1 parent 5151088 commit 4564abb
Show file tree
Hide file tree
Showing 63 changed files with 1,306 additions and 6,922 deletions.
3 changes: 0 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,6 @@ clean:
mkdir -p build
mkdir build/compiled_cairo_files

cython:
./tools/make/cython.sh

go:
./tools/make/go.sh

Expand Down
2 changes: 1 addition & 1 deletion docs/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ To set up a development environment, please follow these steps:
```sh
git clone https://github.com/keep-starknet-strange/garaga
cd garaga
cargo test
make setup
```

2. TODO
Expand Down
11 changes: 0 additions & 11 deletions protostar.toml

This file was deleted.

203 changes: 101 additions & 102 deletions tools/py/polynomial.py → src/algebra.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,68 @@
from tools.py.field import *
from src.modulo_circuit import ModuloElement
from dataclasses import dataclass


@dataclass(slots=True, frozen=True)
class BaseField:
p: int

def __call__(self, integer):
return FieldElement(integer % self.p, self.p)

def zero(self):
return FieldElement(0, self.p)

def one(self):
return FieldElement(1, self.p)


@dataclass(slots=True, frozen=True)
class FieldElement:
value: int
p: int

def __add__(self, right):
return FieldElement((self.value + right.value) % self.p, self.p)

def __sub__(self, right):
return FieldElement((self.value - right.value) % self.p, self.p)

def __mul__(self, right):
return FieldElement((self.value * right.value) % self.p, self.p)

def __truediv__(self, right):
return self * right.__inv__()

def __neg__(self):
return FieldElement((-self.value) % self.p, self.p)

def __inv__(self):
return FieldElement(pow(self.value, -1, self.p), self)

def __pow__(self, exponent):
acc = FieldElement(1, self.p)
val = FieldElement(self.value, self.p)
for i in reversed(range(len(bin(exponent)[2:]))):
acc = acc * acc
if (1 << i) & exponent != 0:
acc = acc * val
return acc

def __neq__(self, other):
return self.value != other.value


class Polynomial:
def __init__(self, coefficients):
self.coefficients = [c for c in coefficients]
def __init__(self, coefficients: list):
first_coeff = coefficients[0]
if isinstance(first_coeff, FieldElement):
self.coefficients = coefficients
elif isinstance(first_coeff, ModuloElement):
self.coefficients = [c.elmt for c in coefficients]
else:
raise ValueError(
f"Unsupported coefficient type {type(first_coeff)} for Polynomial initialization."
)

def degree(self):
if self.coefficients == []:
Expand All @@ -23,9 +82,6 @@ def get_coeffs(self):
coeffs.pop()
return coeffs

def __neg__(self):
return Polynomial([-c for c in self.coefficients])

def __add__(self, other):
if self.degree() == -1:
return other
Expand All @@ -39,10 +95,21 @@ def __add__(self, other):
coeffs[i] = coeffs[i] + other.coefficients[i]
return Polynomial(coeffs)

def __neg__(self):
return Polynomial([-c for c in self.coefficients])

def __sub__(self, other):
return self.__add__(-other)

def __mul__(self, other):
if isinstance(other, (int, FieldElement)):

return Polynomial([c * other for c in self.coefficients])
elif not isinstance(other, Polynomial):
raise TypeError(
f"Cannot multiply polynomial by type {type(other)}, must be int or Polynomial"
)

if self.coefficients == [] or other.coefficients == []:
return Polynomial([])
zero = self.coefficients[0].field.zero()
Expand All @@ -62,13 +129,38 @@ def __truediv__(self, other):
return quo

def __floordiv__(self, other):
quo, rem = Polynomial.divide(self, other)
quo, rem = Polynomial.__divmod__(self, other)
return quo

def __mod__(self, other):
quo, rem = Polynomial.divide(self, other)
quo, rem = Polynomial.__divmod__(self, other)
return rem

def __divmod__(numerator, denominator):
if denominator.degree() == -1:
return None
if numerator.degree() < denominator.degree():
return (Polynomial([]), numerator)
field = denominator.coefficients[0].field
remainder = Polynomial([n for n in numerator.coefficients])
quotient_coefficients = [
field.zero() for i in range(numerator.degree() - denominator.degree() + 1)
]
for i in range(numerator.degree() - denominator.degree() + 1):
if remainder.degree() < denominator.degree():
break
coefficient = (
remainder.leading_coefficient() / denominator.leading_coefficient()
)
shift = remainder.degree() - denominator.degree()
subtractee = (
Polynomial([field.zero()] * shift + [coefficient]) * denominator
)
quotient_coefficients[shift] = coefficient
remainder = remainder - subtractee
quotient = Polynomial(quotient_coefficients)
return quotient, remainder

def __eq__(self, other):
assert type(self) == type(
other
Expand Down Expand Up @@ -96,31 +188,6 @@ def __str__(self):
def leading_coefficient(self):
return self.coefficients[self.degree()]

def divide(numerator, denominator):
if denominator.degree() == -1:
return None
if numerator.degree() < denominator.degree():
return (Polynomial([]), numerator)
field = denominator.coefficients[0].field
remainder = Polynomial([n for n in numerator.coefficients])
quotient_coefficients = [
field.zero() for i in range(numerator.degree() - denominator.degree() + 1)
]
for i in range(numerator.degree() - denominator.degree() + 1):
if remainder.degree() < denominator.degree():
break
coefficient = (
remainder.leading_coefficient() / denominator.leading_coefficient()
)
shift = remainder.degree() - denominator.degree()
subtractee = (
Polynomial([field.zero()] * shift + [coefficient]) * denominator
)
quotient_coefficients[shift] = coefficient
remainder = remainder - subtractee
quotient = Polynomial(quotient_coefficients)
return quotient, remainder

def is_zero(self):
if self.coefficients == []:
return True
Expand All @@ -129,35 +196,6 @@ def is_zero(self):
return False
return True

def interpolate_domain(domain, values):
assert len(domain) == len(
values
), "number of elements in domain does not match number of values -- cannot interpolate"
assert len(domain) > 0, "cannot interpolate between zero points"
field = domain[0].field
x = Polynomial([field.zero(), field.one()])
acc = Polynomial([])
for i in range(len(domain)):
prod = Polynomial([values[i]])
for j in range(len(domain)):
if j == i:
continue
prod = (
prod
* (x - Polynomial([domain[j]]))
* Polynomial([(domain[i] - domain[j]).inverse()])
)
acc = acc + prod
return acc

def zerofier_domain(domain):
field = domain[0].field
x = Polynomial([field.zero(), field.one()])
acc = Polynomial([field.one()])
for d in domain:
acc = acc * (x - Polynomial([d]))
return acc

def evaluate(self, point):
xi = point.field.one()
value = point.field.zero()
Expand All @@ -166,12 +204,7 @@ def evaluate(self, point):
xi = xi * point
return value

def evaluate_domain(self, domain):
return [self.evaluate(d) for d in domain]

def __xor__(self, exponent):
if self.is_zero():
return Polynomial([])
def __pow__(self, exponent):
if exponent == 0:
return Polynomial([self.coefficients[0].field.one()])
acc = Polynomial([self.coefficients[0].field.one()])
Expand All @@ -180,37 +213,3 @@ def __xor__(self, exponent):
if (1 << i) & exponent != 0:
acc = acc * self
return acc

def scale(self, factor):
return Polynomial(
[(factor ^ i) * self.coefficients[i] for i in range(len(self.coefficients))]
)

def xgcd(x, y):
one = Polynomial([x.coefficients[0].field.one()])
zero = Polynomial([x.coefficients[0].field.zero()])
old_r, r = (x, y)
old_s, s = (one, zero)
old_t, t = (zero, one)

while not r.is_zero():
quotient = old_r // r
old_r, r = (r, old_r - quotient * r)
old_s, s = (s, old_s - quotient * s)
old_t, t = (t, old_t - quotient * t)

lcinv = old_r.coefficients[old_r.degree()].inverse()

# a, b, g
return (
Polynomial([c * lcinv for c in old_s.coefficients]),
Polynomial([c * lcinv for c in old_t.coefficients]),
Polynomial([c * lcinv for c in old_r.coefficients]),
)


def test_colinearity(points):
domain = [p[0] for p in points]
values = [p[1] for p in points]
polynomial = Polynomial.interpolate_domain(domain, values)
return polynomial.degree() == 1
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit 4564abb

Please sign in to comment.