Skip to content

Commit

Permalink
refactor: Add small refactorings and field documentation (#92)
Browse files Browse the repository at this point in the history
various refac and doc
  • Loading branch information
tcoratger authored Nov 1, 2023
1 parent b46dd08 commit a16ebee
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 36 deletions.
76 changes: 74 additions & 2 deletions src/math/fields/fields.zig
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ pub fn Field(

fe: F.MontgomeryDomainFieldElement,

/// Create a field element from an integer in Montgomery representation.
///
/// This function converts an integer to a field element in Montgomery form.
pub fn fromInteger(num: u256) Self {
var lbe: [BytesSize]u8 = [_]u8{0} ** BytesSize;
std.mem.writeInt(
Expand All @@ -47,10 +50,16 @@ pub fn Field(
return .{ .fe = mont };
}

/// Get the field element representing zero.
///
/// Returns a field element with a value of zero.
pub fn zero() Self {
return base_zero;
}

/// Get the field element representing one.
///
/// Returns a field element with a value of one.
pub fn one() Self {
const oneValue = comptime blk: {
var baseOne: F.MontgomeryDomainFieldElement = undefined;
Expand All @@ -60,6 +69,9 @@ pub fn Field(
return oneValue;
}

/// Create a field element from a byte array.
///
/// Converts a byte array into a field element in Montgomery representation.
pub fn fromBytes(bytes: [BytesSize]u8) Self {
var non_mont: F.NonMontgomeryDomainFieldElement = undefined;
inline for (0..4) |i| {
Expand All @@ -78,6 +90,9 @@ pub fn Field(
return ret;
}

/// Convert the field element to a byte array.
///
/// This function converts the field element to a byte array for serialization.
pub fn toBytes(self: Self) [BytesSize]u8 {
var non_mont: F.NonMontgomeryDomainFieldElement = undefined;
F.fromMontgomery(
Expand All @@ -97,11 +112,17 @@ pub fn Field(
return ret;
}

/// Check if the field element is lexicographically largest.
///
/// Determines whether the field element is larger than half of the field's modulus.
pub fn lexographicallyLargest(self: Self) bool {
const selfNonMont = self.toInteger();
return selfNonMont > QMinOneDiv2;
}

/// Convert the field element to its non-Montgomery representation.
///
/// Converts a field element from Montgomery form to non-Montgomery representation.
pub fn fromMontgomery(self: Self) F.NonMontgomeryDomainFieldElement {
var nonMont: F.NonMontgomeryDomainFieldElement = undefined;
F.fromMontgomery(
Expand All @@ -110,6 +131,10 @@ pub fn Field(
);
return nonMont;
}

/// Add two field elements.
///
/// Adds the current field element to another field element.
pub fn add(
self: Self,
other: Self,
Expand All @@ -123,6 +148,9 @@ pub fn Field(
return .{ .fe = ret };
}

/// Subtract one field element from another.
///
/// Subtracts another field element from the current field element.
pub fn sub(
self: Self,
other: Self,
Expand All @@ -136,6 +164,9 @@ pub fn Field(
return .{ .fe = ret };
}

/// Multiply two field elements.
///
/// Multiplies the current field element by another field element.
pub fn mul(
self: Self,
other: Self,
Expand All @@ -149,6 +180,9 @@ pub fn Field(
return .{ .fe = ret };
}

/// Multiply a field element by 5.
///
/// Multiplies the current field element by the constant 5.
pub fn mulBy5(self: Self) Self {
var ret: F.MontgomeryDomainFieldElement = undefined;
F.add(
Expand All @@ -169,6 +203,9 @@ pub fn Field(
return .{ .fe = ret };
}

/// Negate a field element.
///
/// Negates the value of the current field element.
pub fn neg(self: Self) Self {
var ret: F.MontgomeryDomainFieldElement = undefined;
F.sub(
Expand All @@ -179,18 +216,31 @@ pub fn Field(
return .{ .fe = ret };
}

/// Check if the field element is zero.
///
/// Determines if the current field element is equal to zero.
pub fn isZero(self: Self) bool {
return self.equal(base_zero);
}

/// Check if the field element is one.
///
/// Determines if the current field element is equal to one.
pub fn isOne(self: Self) bool {
return self.equal(one());
}

/// Calculate the square of a field element.
///
/// Computes the square of the current field element.
pub fn square(self: Self) Self {
return self.mul(self);
}

/// Raise a field element to a power of 2.
///
/// Computes the current field element raised to the power of 2 to the `exponent` power.
/// The result is equivalent to repeatedly squaring the field element.
pub fn pow2(
self: Self,
comptime exponent: u8,
Expand All @@ -202,6 +252,9 @@ pub fn Field(
return ret;
}

/// Raise a field element to a general power.
///
/// Computes the field element raised to a general power specified by the `exponent`.
pub fn pow(
self: Self,
exponent: u256,
Expand All @@ -219,6 +272,9 @@ pub fn Field(
return res;
}

/// Batch inversion of multiple field elements.
///
/// Performs batch inversion of a slice of field elements in place.
pub fn batchInv(
out: []Self,
in: []const Self,
Expand Down Expand Up @@ -246,6 +302,9 @@ pub fn Field(
}
}

/// Calculate the multiplicative inverse of a field element.
///
/// Computes the multiplicative inverse of the current field element.
pub fn inv(self: Self) ?Self {
var r: u256 = Modulo;
var t: i512 = 0;
Expand Down Expand Up @@ -276,6 +335,9 @@ pub fn Field(
return Self.fromInteger(@intCast(t));
}

/// Divide one field element by another.
///
/// Divides the current field element by another field element.
pub fn div(
self: Self,
den: Self,
Expand All @@ -284,6 +346,9 @@ pub fn Field(
return self.mul(den_inv);
}

/// Check if two field elements are equal.
///
/// Determines whether the current field element is equal to another field element.
pub fn equal(
self: Self,
other: Self,
Expand All @@ -295,6 +360,9 @@ pub fn Field(
);
}

/// Convert the field element to a u256 integer.
///
/// Converts the field element to a u256 integer.
pub fn toInteger(self: Self) u256 {
var non_mont: F.NonMontgomeryDomainFieldElement = undefined;
F.fromMontgomery(
Expand All @@ -315,8 +383,9 @@ pub fn Field(
);
}

// Try to convert the field element into a u64.
// If the value is too large, return an error.
/// Try to convert the field element to a u64 if its value is small enough.
///
/// Attempts to convert the field element to a u64 if its value is within the representable range.
pub fn tryIntoU64(self: Self) !u64 {
const asU256 = self.toInteger();
// Check if the value is small enough to fit into a u64
Expand All @@ -334,6 +403,9 @@ pub fn Field(
);
}

/// Calculate the Legendre symbol of a field element.
///
/// Computes the Legendre symbol of the field element using Euler's criterion.
pub fn legendre(a: Self) i2 {
// Compute the Legendre symbol a|p using
// Euler's criterion. p is a prime, a is
Expand Down
11 changes: 7 additions & 4 deletions src/vm/instructions.zig
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,17 @@ const std = @import("std");

/// Error type to represent different error conditions during instruction decoding.
pub const Error = error{
/// Represents an error condition where the high bit in the instruction's first word is non-zero.
NonZeroHighBit,
/// Indicates an error when an invalid register value is encountered for the `op1` field in the instruction.
InvalidOp1Reg,
/// Represents an error when the `pc_update` field in the instruction is invalid.
Invalidpc_update,
/// Signifies an error related to an invalid value for the `res_logic` field in the instruction.
Invalidres_logic,
/// Indicates an error condition when the opcode in the instruction is invalid.
InvalidOpcode,
/// Represents an error when the `ap_update` field in the instruction is invalid.
Invalidap_update,
};

Expand Down Expand Up @@ -342,10 +348,7 @@ pub fn fromBiasedRepresentation(biased_repr: u16) i16 {
i32,
@intCast(biased_repr),
);
return @as(
i16,
@intCast(as_i32 - 32768),
);
return @intCast(as_i32 - 32768);
}

// ************************************************************
Expand Down
36 changes: 6 additions & 30 deletions src/vm/run_context.zig
Original file line number Diff line number Diff line change
Expand Up @@ -112,18 +112,10 @@ pub const RunContext = struct {

if (instruction.off_0 < 0) {
// Convert i16 to u64 safely and then negate
const abs_offset = @as(
u64,
@intCast(-instruction.off_0),
);
return try base_addr.subUint(abs_offset);
return try base_addr.subUint(@intCast(-instruction.off_0));
} else {
// Convert i16 to u64 safely
const offset = @as(
u64,
@intCast(instruction.off_0),
);
return try base_addr.addUint(offset);
return try base_addr.addUint(@intCast(instruction.off_0));
}
}

Expand All @@ -143,18 +135,10 @@ pub const RunContext = struct {

if (instruction.off_1 < 0) {
// Convert i16 to u64 safely and then negate
const abs_offset = @as(
u64,
@intCast(-instruction.off_1),
);
return try base_addr.subUint(abs_offset);
return try base_addr.subUint(@intCast(-instruction.off_1));
} else {
// Convert i16 to u64 safely
const offset = @as(
u64,
@intCast(instruction.off_1),
);
return try base_addr.addUint(offset);
return try base_addr.addUint(@intCast(instruction.off_1));
}
}

Expand Down Expand Up @@ -190,18 +174,10 @@ pub const RunContext = struct {

if (instruction.off_2 < 0) {
// Convert i16 to u64 safely and then negate
const abs_offset = @as(
u64,
@intCast(-instruction.off_2),
);
return try base_addr.subUint(abs_offset);
return try base_addr.subUint(@intCast(-instruction.off_2));
} else {
// Convert i16 to u64 safely
const offset = @as(
u64,
@intCast(instruction.off_2),
);
return try base_addr.addUint(offset);
return try base_addr.addUint(@intCast(instruction.off_2));
}
}
};
Expand Down

0 comments on commit a16ebee

Please sign in to comment.