Skip to content

Commit

Permalink
field_arithmetic hint + test (#511)
Browse files Browse the repository at this point in the history
  • Loading branch information
StringNick authored Apr 27, 2024
1 parent ec8918c commit b7dce71
Show file tree
Hide file tree
Showing 8 changed files with 1,126 additions and 33 deletions.
1 change: 1 addition & 0 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ pub fn build(b: *std.Build) void {
.target = target,
.optimize = optimize,
.filter = test_filter,
.single_threaded = false,
});

// Add dependency modules to the tests.
Expand Down
114 changes: 114 additions & 0 deletions src/hint_processor/builtin_hint_codes.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1483,3 +1483,117 @@ pub const PACK_MODN_DIV_MODN =
\\s = pack(ids.s, PRIME) % N
\\value = res = div_mod(x, s, N)
;

pub const UINT384_GET_SQUARE_ROOT =
\\from starkware.python.math_utils import is_quad_residue, sqrt
\\
\\def split(num: int, num_bits_shift: int = 128, length: int = 3):
\\ a = []
\\ for _ in range(length):
\\ a.append( num & ((1 << num_bits_shift) - 1) )
\\ num = num >> num_bits_shift
\\ return tuple(a)
\\
\\def pack(z, num_bits_shift: int = 128) -> int:
\\ limbs = (z.d0, z.d1, z.d2)
\\ return sum(limb << (num_bits_shift * i) for i, limb in enumerate(limbs))
\\
\\
\\generator = pack(ids.generator)
\\x = pack(ids.x)
\\p = pack(ids.p)
\\
\\success_x = is_quad_residue(x, p)
\\root_x = sqrt(x, p) if success_x else None
\\
\\success_gx = is_quad_residue(generator*x, p)
\\root_gx = sqrt(generator*x, p) if success_gx else None
\\
\\# Check that one is 0 and the other is 1
\\if x != 0:
\\ assert success_x + success_gx ==1
\\
\\# `None` means that no root was found, but we need to transform these into a felt no matter what
\\if root_x == None:
\\ root_x = 0
\\if root_gx == None:
\\ root_gx = 0
\\ids.success_x = int(success_x)
\\ids.success_gx = int(success_gx)
\\split_root_x = split(root_x)
\\split_root_gx = split(root_gx)
\\ids.sqrt_x.d0 = split_root_x[0]
\\ids.sqrt_x.d1 = split_root_x[1]
\\ids.sqrt_x.d2 = split_root_x[2]
\\ids.sqrt_gx.d0 = split_root_gx[0]
\\ids.sqrt_gx.d1 = split_root_gx[1]
\\ids.sqrt_gx.d2 = split_root_gx[2]
;

pub const UINT256_GET_SQUARE_ROOT =
\\from starkware.python.math_utils import is_quad_residue, sqrt
\\
\\def split(a: int):
\\ return (a & ((1 << 128) - 1), a >> 128)
\\
\\def pack(z) -> int:
\\ return z.low + (z.high << 128)
\\
\\generator = pack(ids.generator)
\\x = pack(ids.x)
\\p = pack(ids.p)
\\
\\success_x = is_quad_residue(x, p)
\\root_x = sqrt(x, p) if success_x else None
\\success_gx = is_quad_residue(generator*x, p)
\\root_gx = sqrt(generator*x, p) if success_gx else None
\\
\\# Check that one is 0 and the other is 1
\\if x != 0:
\\ assert success_x + success_gx == 1
\\
\\# `None` means that no root was found, but we need to transform these into a felt no matter what
\\if root_x == None:
\\ root_x = 0
\\if root_gx == None:
\\ root_gx = 0
\\ids.success_x = int(success_x)
\\ids.success_gx = int(success_gx)
\\split_root_x = split(root_x)
\\# print('split root x', split_root_x)
\\split_root_gx = split(root_gx)
\\ids.sqrt_x.low = split_root_x[0]
\\ids.sqrt_x.high = split_root_x[1]
\\ids.sqrt_gx.low = split_root_gx[0]
\\ids.sqrt_gx.high = split_root_gx[1]
;

pub const UINT384_DIV =
\\from starkware.python.math_utils import div_mod
\\
\\def split(num: int, num_bits_shift: int, length: int):
\\ a = []
\\ for _ in range(length):
\\ a.append( num & ((1 << num_bits_shift) - 1) )
\\ num = num >> num_bits_shift
\\ return tuple(a)
\\
\\def pack(z, num_bits_shift: int) -> int:
\\ limbs = (z.d0, z.d1, z.d2)
\\ return sum(limb << (num_bits_shift * i) for i, limb in enumerate(limbs))
\\
\\a = pack(ids.a, num_bits_shift = 128)
\\b = pack(ids.b, num_bits_shift = 128)
\\p = pack(ids.p, num_bits_shift = 128)
\\# For python3.8 and above the modular inverse can be computed as follows:
\\# b_inverse_mod_p = pow(b, -1, p)
\\# Instead we use the python3.7-friendly function div_mod from starkware.python.math_utils
\\b_inverse_mod_p = div_mod(1, b, p)
\\
\\
\\b_inverse_mod_p_split = split(b_inverse_mod_p, num_bits_shift=128, length=3)
\\
\\ids.b_inverse_mod_p.d0 = b_inverse_mod_p_split[0]
\\ids.b_inverse_mod_p.d1 = b_inverse_mod_p_split[1]
\\ids.b_inverse_mod_p.d2 = b_inverse_mod_p_split[2]
;
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const hint_codes = @import("../../builtin_hint_codes.zig");

pub const BigInt3 = BigIntN(3);
pub const Uint384 = BigIntN(3);
pub const Uint256 = BigIntN(2);
pub const Uint512 = BigIntN(4);
pub const BigInt5 = BigIntN(5);
pub const Uint768 = BigIntN(6);
Expand Down Expand Up @@ -216,7 +217,6 @@ test "Get BigInt3 from base address with missing member should fail" {

defer vm.segments.memory.deinitData(std.testing.allocator);


try std.testing.expectError(HintError.IdentifierHasNoMember, BigInt3.fromBaseAddr(Relocatable{ .segment_index = 0, .offset = 0 }, &vm));
}

Expand All @@ -234,7 +234,6 @@ test "Get BigInt5 from base address with missing member should fail" {

defer vm.segments.memory.deinitData(std.testing.allocator);


try std.testing.expectError(HintError.IdentifierHasNoMember, BigInt5.fromBaseAddr(Relocatable{ .segment_index = 0, .offset = 0 }, &vm));
}

Expand Down Expand Up @@ -331,7 +330,6 @@ test "BigIntUtils: get bigint5 from var name with missing member should fail" {
var ids_data = try testing_utils.setupIdsForTestWithoutMemory(std.testing.allocator, &.{"x"});
defer ids_data.deinit();


try std.testing.expectError(HintError.IdentifierHasNoMember, BigInt5.fromVarName("x", &vm, ids_data, .{}));
}

Expand Down
Loading

0 comments on commit b7dce71

Please sign in to comment.