Skip to content

Commit

Permalink
feat: add felt division based on binary exponentiation
Browse files Browse the repository at this point in the history
  • Loading branch information
zmalatrax committed Apr 29, 2024
1 parent e766e66 commit d371370
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 14 deletions.
21 changes: 8 additions & 13 deletions src/primitives/felt.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,19 +107,14 @@ describe('Felt', () => {
});

describe('div', () => {
test('should divide two felts properly', () => {
const a = new Felt(10n);
const b = new Felt(2n);
const result = a.div(b);
const expected = new Felt(5n);
expect(result.eq(expected)).toBeTrue();
});
test('should go to 0 if a < b in a/b', () => {
const a = new Felt(5n);
const b = new Felt(10n);
const result = a.div(b);
const expected = new Felt(0n);
expect(result.eq(expected)).toBeTrue();
test.each([
[new Felt(10n), new Felt(2n)],
[new Felt(5n), new Felt(10n)],
[new Felt(Felt.PRIME - 10n), new Felt(10n)],
[new Felt(10n), new Felt(Felt.PRIME - 10n)],
])('should divide two felts properly', (a: Felt, b: Felt) => {
const result = a.div(b).mul(b);
expect(result).toStrictEqual(a);
});
});
});
27 changes: 26 additions & 1 deletion src/primitives/felt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ export class Felt {
if (!isFelt(other) || other.inner === 0n) {
throw new ForbiddenOperation();
}
return new Felt(this.inner / other.inner);

return this.mul(other.inv());
}

eq(other: MaybeRelocatable): boolean {
Expand All @@ -60,4 +61,28 @@ export class Felt {
toHexString(): string {
return this.inner.toString(16);
}

/**
* @dev Compute modular multiplicative inverse with
* Euler totient's function and Fermat's little theorem
*/
private inv(): Felt {
return this.pow(Felt.PRIME - 2n);
}

/** @dev Binary Exponentiation - Iterative version */
private pow(exp: bigint): Felt {
if (exp === 0n) return new Felt(1n);
if (exp === 1n) return this;
let res = 1n;
let inner = this.inner;
while (exp !== 0n) {
if (exp & 1n) {
res = (res * inner) % Felt.PRIME;
}
inner = (inner * inner) % Felt.PRIME;
exp >>= 1n;
}
return new Felt(res);
}
}

0 comments on commit d371370

Please sign in to comment.