Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions cairo_programs/cairo/hints/span_life.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
fn main() {
let span = array![1, 2, 3].span();
let _slice = span.slice(0, 1);
}
8 changes: 8 additions & 0 deletions src/hints/hintHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ import {
shouldSkipSquashLoop,
} from './dict/shouldSkipSquashLoop';
import { TestLessThan, testLessThan } from './math/testLessThan';
import {
TestLessThanOrEqual,
testLessThanOrEqual,
} from './math/testLessThanOrEqual';

/**
* Map hint names to the function executing their logic.
Expand Down Expand Up @@ -125,4 +129,8 @@ export const handlers: HintHandler = {
const h = hint as TestLessThan;
testLessThan(vm, h.lhs, h.rhs, h.dst);
},
[HintName.TestLessThanOrEqual]: (vm, hint) => {
const h = hint as TestLessThanOrEqual;
testLessThanOrEqual(vm, h.lhs, h.rhs, h.dst);
},
};
1 change: 1 addition & 0 deletions src/hints/hintName.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ export enum HintName {
ShouldContinueSquashLoop = 'ShouldContinueSquashLoop',
ShouldSkipSquashLoop = 'ShouldSkipSquashLoop',
TestLessThan = 'TestLessThan',
TestLessThanOrEqual = 'TestLessThanOrEqual',
}
2 changes: 2 additions & 0 deletions src/hints/hintSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { initSquashDataParser } from './dict/initSquashData';
import { shouldContinueSquashLoopParser } from './dict/shouldContinueSquashLoop';
import { shouldSkipSquashLoopParser } from './dict/shouldSkipSquashLoop';
import { testLessThanParser } from './math/testLessThan';
import { testLessThanOrEqualParser } from './math/testLessThanOrEqual';

/** Zod object to parse any implemented hints */
const hint = z.union([
Expand All @@ -33,6 +34,7 @@ const hint = z.union([
shouldContinueSquashLoopParser,
shouldSkipSquashLoopParser,
testLessThanParser,
testLessThanOrEqualParser,
]);

/** Zod object to parse an array of hints grouped on a given PC */
Expand Down
69 changes: 69 additions & 0 deletions src/hints/math/testLessThanOrEqual.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { describe, expect, test } from 'bun:test';

import { Felt } from 'primitives/felt';
import { Register } from 'vm/instruction';
import { VirtualMachine } from 'vm/virtualMachine';

import { OpType } from 'hints/hintParamsSchema';
import { HintName } from 'hints/hintName';
import { testLessThanOrEqualParser } from './testLessThanOrEqual';

const TEST_LESS_THAN_OR_EQUAL = {
TestLessThanOrEqual: {
lhs: {
Deref: {
register: 'AP',
offset: 0,
},
},
rhs: {
Immediate: '0x100000000',
},
dst: {
register: 'AP',
offset: -1,
},
},
};

describe('TestLessThanOrEqual', () => {
test('should properly parse TestLessThanOrEqual hint', () => {
const hint = testLessThanOrEqualParser.parse(TEST_LESS_THAN_OR_EQUAL);

expect(hint).toEqual({
type: HintName.TestLessThanOrEqual,
lhs: {
type: OpType.Deref,
cell: {
register: Register.Ap,
offset: 0,
},
},
rhs: {
type: OpType.Immediate,
value: new Felt(BigInt('0x100000000')),
},
dst: {
register: Register.Ap,
offset: -1,
},
});
});

test.each([
[new Felt(2n), new Felt(1n)],
[new Felt(BigInt('0x0ffffffff')), new Felt(1n)],
[new Felt(BigInt('0x100000000')), new Felt(1n)],
[new Felt(-2n), new Felt(0n)],
])('should properly execute TestLessThanOrEqual hint', (lhs, expected) => {
const hint = testLessThanOrEqualParser.parse(TEST_LESS_THAN_OR_EQUAL);
const vm = new VirtualMachine();
vm.memory.addSegment();
vm.memory.addSegment();
vm.ap = vm.ap.add(1);
vm.memory.assertEq(vm.ap, lhs);

vm.executeHint(hint);
expect(vm.memory.get(vm.cellRefToRelocatable(hint.dst))).toEqual(expected);
});
});
59 changes: 59 additions & 0 deletions src/hints/math/testLessThanOrEqual.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { z } from 'zod';

import { Felt } from 'primitives/felt';
import { VirtualMachine } from 'vm/virtualMachine';

import { HintName } from 'hints/hintName';
import {
cellRef,
resOperand,
CellRef,
ResOperand,
} from 'hints/hintParamsSchema';

/** Zod object to parse TestLessThanOrEqual hint */
export const testLessThanOrEqualParser = z
.object({
TestLessThanOrEqual: z.object({
lhs: resOperand,
rhs: resOperand,
dst: cellRef,
}),
})
.transform(({ TestLessThanOrEqual: { lhs, rhs, dst } }) => ({
type: HintName.TestLessThanOrEqual,
lhs,
rhs,
dst,
}));

/**
* TestLessThanOrEqual hint
*
* Check whether the value at `lhs` is less than or equal to the value at `rhs`
*
*/
export type TestLessThanOrEqual = z.infer<typeof testLessThanOrEqualParser>;

/**
* TestLessThanOrEqual hint
*
* Store true at `dst` if value at `lhs` is inferior or equal to value at `rhs`, false otherwise.
*
* @param {VirtualMachine} vm - The virtual machine instance.
* @param {ResOperand} lhs - The left-hand side operand.
* @param {ResOperand} rhs - The right-hand side operand.
* @param {CellRef} dst - Pointer to where the result will be stored.
*
*/
export const testLessThanOrEqual = (
vm: VirtualMachine,
lhs: ResOperand,
rhs: ResOperand,
dst: CellRef
) => {
const lhsValue = vm.getResOperandValue(lhs);
const rhsValue = vm.getResOperandValue(rhs);
const result = new Felt(BigInt(lhsValue <= rhsValue));
vm.memory.assertEq(vm.cellRefToRelocatable(dst), result);
};