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

feat: add WideMul128 hint #126

Closed
wants to merge 7 commits into from
Closed

feat: add WideMul128 hint #126

wants to merge 7 commits into from

Conversation

D240021
Copy link

@D240021 D240021 commented Aug 7, 2024

Hi, I've made some progress with the hint. I haven't tested it yet but I wanted to see if you could give me some feedback.

Changes made

  • Added Hint name to hintName.ts enum.
  • I implemented hint's Zod object.
  • I created the Zod union in hintSchema.ts file.
  • I implemented the provisional logic of the hint

@zmalatrax zmalatrax linked an issue Aug 7, 2024 that may be closed by this pull request
Copy link
Collaborator

@zmalatrax zmalatrax left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great overall :)

Put the file wideMul128.ts in the math folder pls

Feel free to join the telegram group of the Cairo VM ts: https://t.me/cairovmts

@@ -33,6 +33,7 @@ const hint = z.union([
shouldContinueSquashLoopParser,
shouldSkipSquashLoopParser,
testLessThanParser,
wideMul128,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The hint object expects the zod object you've defined to parse the hint from the compilation artifacts: wideMul128Parser

Comment on lines 18 to 21
lhs: lhs,
rhs: rhs,
high: high,
low: low
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As the property names are unchanged, you can directly use the variable:

Suggested change
lhs: lhs,
rhs: rhs,
high: high,
low: low
lhs,
rhs,
high,
low

low: CellRef
): void => {
try {
const mask128 = (BigInt(1) << BigInt(128)) - BigInt(1);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use mask rather than mask128

Use the short notation for Bigint when possible, it is more readable: 128n instead of BigInt(128)

Suggested change
const mask128 = (BigInt(1) << BigInt(128)) - BigInt(1);
const mask = (1n << 128n) - 1n

try {
const mask128 = (BigInt(1) << BigInt(128)) - BigInt(1);

//Gets the operands' values
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to add comments, the code is self-explanatory here (same // Do multiplication) etc.

import { resOperand, ResOperand } from 'hints/hintParamsSchema';
import { VirtualMachine } from 'vm/virtualMachine';
import { Felt } from 'primitives/felt';
export const wideMul128Parser = z.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add JSDoc

low: low
}));

export const wideMul128 = (
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a well-formatted JSDoc, take example on the AllocFelt252Dict one

Comment on lines 42 to 44
const highVal = prod >> BigInt(128);
const highRef = vm.cellRefToRelocatable(high);
vm.memory.assertEq(highRef, new Felt(highVal));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Directly create highVal as a Felt

No need to declare a variable for the address (i.e. highRef), directly call cellRefToRelocatable in assertEq()

Comment on lines 51 to 53
} catch (error: any) {
throw new Error(error.message);
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't wrap the function in a try catch statement

@zmalatrax
Copy link
Collaborator

@D240021 You're not signing your commits ⚠️

},
rhs: {
type: OpType.Immediate,
value: new Felt(BigInt('0x2')),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can be simplified as new Felt(2n)


test.each([
[new Felt(1n), new Felt(0n), new Felt(2n)],
[new Felt(BigInt('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF')), new Felt(1n), new Felt(BigInt('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE'))], // max 128-bit value * 2
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hexadecimal is a bit hard to read with 128 bits, I'd rather compute it:
BigInt(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) --> (1n << 128n) - 1
BigInt(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE) --> (1n << 128n) - 2

Comment on lines 67 to 68
const vm = new VirtualMachine();
vm.memory.addSegment();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The VirtualMachine instance comes with an empty memory: without any segment. Segments are 0-indexed

The AP register points to the segment 1, a.k.a the 2nd segment of the memory, you've got to call vm.memory.addSegment() twice

const hint = wideMul128Parser.parse(WIDE_MUL_128);
const vm = new VirtualMachine();
vm.memory.addSegment();
vm.ap = vm.ap.add(1);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to increment ap for this test

Suggested change
vm.ap = vm.ap.add(1);

Comment on lines 63 to 65
export type WideMul128 = z.infer<
typeof wideMul128Parser
>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Export the type directly after wideMul128Parser (before wideMul128())

Comment on lines 54 to 59
const highVal = prod >> BigInt(128);
vm.memory.assertEq(vm.cellRefToRelocatable(high), new Felt(highVal));

const lowVal = prod & mask;
const lowRef = vm.cellRefToRelocatable(low);
vm.memory.assertEq(lowRef, new Felt(lowVal));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use 128n instead of BigInt(128)
Directly instantiate highVal and lowVal as Felt

Group the computation and the memory assertion together: first compute highVal and lowVal
Then make assertEq calls.

Inline highRef and lowRef in the assertEq

Comment on lines 1 to 2
{
"name": "cairo-vm-ts",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this file

Also bun.lockb shouldn't be modified

@D240021
Copy link
Author

D240021 commented Aug 9, 2024

Hi @zmalatrax, I've been correcting what you told me. Also, I added the cairo file for the integration test, I'm not very sure about it. I would appreciate if you could review it and give me feedback.

Comment on lines 16 to 17
disabled:
- prettier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shouldn't modify the Trunk configuration

Comment on lines 2 to 10
let lhs: felt = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
let rhs: felt = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

let product = lhs * rhs;

let low = product & ((1 << 128) - 1);
let high = product >> 128;

return ();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're making a multiplication of two 128 bits, stored on two limbs low and high but you're not actually using the WideMul128 hint.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to find a Corelib function that makes use of the WideMul128 hint:

  • Look at libfuncs defined in the cairo-lang-sierra-to-casm that uses the WideMul128 hint in their implementation
    By searching on the cairo-lang-sierra-to-casm crate of the Cairo compiler, you can see that it is used in the u256 divmod, u512 divmod by u256 and the u128 multiplication libfuncs
    The easiest libfunc directly using this hint is the u128 multiplication: build_u128_guarantee_mul which creates the u128_guarantee_mul
  • Search the u128_guaranteed_mul function in the Cairo corelib

Now you need to write a Cairo program that uses the function u128_guarantee_mul(), look at the function signature and do appropriately, something like this can be enough, as the U128 type operators have been overloaded:

fn main() {
    let _ = 0x123456_u128 * 0xFEDCBA_u128;
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you're not sure about your program using a particular hint, compile it and look at the JSON compilation artifacts, go to the hints property and see if the wanted hint is part of it

Comment on lines 18 to 19
import { wideMul128, wideMul128Parser } from './math/wideMul128';
/** Zod object to parse any implemented hints */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing blank line

* This function calculates the product of two 128-bit operands, splits the result into high and low 128-bit parts,
* and stores them in the specified memory locations within the virtual machine.
*
* @param {VirtualMachine} vm - The virtual machine instance where the operation is executed.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @param {VirtualMachine} vm - The virtual machine instance where the operation is executed.
* @param {VirtualMachine} vm - The virtual machine instance.

@zmalatrax
Copy link
Collaborator

Closing as the implementation has been moved to #137

@zmalatrax zmalatrax closed this Oct 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

feat: add WideMul128 hint
2 participants