Skip to content

Commit

Permalink
Implemented SplitOutputMidLowHigh (#511)
Browse files Browse the repository at this point in the history
Implemented SplitOutputMidLowHigh
  • Loading branch information
Sh0g0-1758 committed Jul 3, 2024
1 parent 707d13f commit 27817ff
Show file tree
Hide file tree
Showing 4 changed files with 203 additions and 0 deletions.
1 change: 1 addition & 0 deletions pkg/hintrunner/zero/hintcode.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ ids.multiplicities = segments.gen_arg([len(positions_dict[k]) for k in output])`
blockPermutationCode string = "from starkware.cairo.common.keccak_utils.keccak_utils import keccak_func\n_keccak_state_size_felts = int(ids.KECCAK_STATE_SIZE_FELTS)\nassert 0 <= _keccak_state_size_felts < 100\noutput_values = keccak_func(memory.get_range(\nids.keccak_ptr - _keccak_state_size_felts, _keccak_state_size_felts))\nsegments.write_arg(ids.keccak_ptr, output_values)"
compareBytesInWordCode string = "memory[ap] = to_felt_or_relocatable(ids.n_bytes < ids.BYTES_IN_WORD)"
compareKeccakFullRateInBytesCode string = "memory[ap] = to_felt_or_relocatable(ids.n_bytes >= ids.KECCAK_FULL_RATE_IN_BYTES)"
splitOutputMidLowHighCode string = "tmp, ids.output1_low = divmod(ids.output1, 256 ** 7)\nids.output1_high, ids.output1_mid = divmod(tmp, 2 ** 128)"

// ------ Dictionaries hints related code ------
dictNewCode string = "if '__dict_manager' not in globals():\n from starkware.cairo.common.dict import DictManager\n __dict_manager = DictManager()\n\nmemory[ap] = __dict_manager.new_dict(segments, initial_dict)\ndel initial_dict"
Expand Down
2 changes: 2 additions & 0 deletions pkg/hintrunner/zero/zerohint.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@ func GetHintFromCode(program *zero.ZeroProgram, rawHint zero.Hint, hintPC uint64
return createBlockPermutationHinter(resolver)
case compareBytesInWordCode:
return createCompareBytesInWordNondetHinter(resolver)
case splitOutputMidLowHighCode:
return createSplitOutputMidLowHighHinter(resolver)
// Usort hints
case usortEnterScopeCode:
return createUsortEnterScopeHinter()
Expand Down
102 changes: 102 additions & 0 deletions pkg/hintrunner/zero/zerohint_keccak.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package zero
import (
"fmt"
"math"
"math/big"

"github.com/NethermindEth/cairo-vm-go/pkg/hintrunner/hinter"
"github.com/NethermindEth/cairo-vm-go/pkg/utils"
Expand Down Expand Up @@ -572,3 +573,104 @@ func createCompareBytesInWordNondetHinter(resolver hintReferenceResolver) (hinte

return newCompareBytesInWordHint(nBytes), nil
}

// SplitOutputMidLowHigh hint assigns to `ids.output1_low` the remainder of the division
// of `ids.output1` variable by 256 ** 7 and uses its quotient as a variable which is
// divided by 2 ** 128, the quotient and remainder of which are then assigned to `ids.output1_high`
// and `ids.output1_mid` respectively.
//
// `newSplitOutputMidLowHighHint` takes 4 operanders as arguments
// - `output1Low` is the variable that will store the remainder of the first division
// - `output1Mid` is the variable that will store the remainder of the second division
// - `output1High` is the variable that will store the quotient of the second division
// - `output1` is the variable that will be divided in the first division
func newSplitOutputMidLowHighHint(output1, output1Low, output1Mid, output1High hinter.ResOperander) hinter.Hinter {
return &GenericZeroHinter{
Name: "SplitOutputMidLowHigh",
Op: func(vm *VM.VirtualMachine, _ *hinter.HintRunnerContext) error {
//> tmp, ids.output1_low = divmod(ids.output1, 256 ** 7)
//> ids.output1_high, ids.output1_mid = divmod(tmp, 2 ** 128)

output1LowAddr, err := output1Low.GetAddress(vm)
if err != nil {
return err
}

output1MidAddr, err := output1Mid.GetAddress(vm)
if err != nil {
return err
}

output1HighAddr, err := output1High.GetAddress(vm)
if err != nil {
return err
}

output1Felt, err := hinter.ResolveAsFelt(vm, output1)
if err != nil {
return err
}

output1BigInt := new(big.Int)
output1Felt.BigInt(output1BigInt)

tmpBigInt := new(big.Int)
output1LowBigInt := new(big.Int)
output1MidBigInt := new(big.Int)
output1HighBigInt := new(big.Int)

divisorOne := new(big.Int).Exp(big.NewInt(256), big.NewInt(7), nil)
divisorTwo := new(big.Int).Exp(big.NewInt(2), big.NewInt(128), nil)

tmpBigInt.DivMod(output1BigInt, divisorOne, output1LowBigInt)
output1HighBigInt.DivMod(tmpBigInt, divisorTwo, output1MidBigInt)

var output1LowFelt fp.Element
output1LowFelt.SetBigInt(output1LowBigInt)
output1LowMv := memory.MemoryValueFromFieldElement(&output1LowFelt)

var output1MidFelt fp.Element
output1MidFelt.SetBigInt(output1MidBigInt)
output1MidMv := memory.MemoryValueFromFieldElement(&output1MidFelt)

var output1HighFelt fp.Element
output1HighFelt.SetBigInt(output1HighBigInt)
output1HighMv := memory.MemoryValueFromFieldElement(&output1HighFelt)

err = vm.Memory.WriteToAddress(&output1LowAddr, &output1LowMv)
if err != nil {
return err
}

err = vm.Memory.WriteToAddress(&output1MidAddr, &output1MidMv)
if err != nil {
return err
}
return vm.Memory.WriteToAddress(&output1HighAddr, &output1HighMv)
},
}
}

func createSplitOutputMidLowHighHinter(resolver hintReferenceResolver) (hinter.Hinter, error) {
output1, err := resolver.GetResOperander("output1")
if err != nil {
return nil, err
}

output1Low, err := resolver.GetResOperander("output1_low")
if err != nil {
return nil, err
}

output1Mid, err := resolver.GetResOperander("output1_mid")
if err != nil {
return nil, err
}

output1High, err := resolver.GetResOperander("output1_high")
if err != nil {
return nil, err
}

return newSplitOutputMidLowHighHint(output1, output1Low, output1Mid, output1High), nil
}
98 changes: 98 additions & 0 deletions pkg/hintrunner/zero/zerohint_keccak_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -605,5 +605,103 @@ func TestZeroHintKeccak(t *testing.T) {
check: apValueEquals(feltUint64(0)),
},
},
"SplitOutputMidLowHigh": {
{
operanders: []*hintOperander{
{Name: "output1", Kind: apRelative, Value: feltUint64(0)},
{Name: "output1_low", Kind: uninitialized},
{Name: "output1_mid", Kind: uninitialized},
{Name: "output1_high", Kind: uninitialized},
},
makeHinter: func(ctx *hintTestContext) hinter.Hinter {
return newSplitOutputMidLowHighHint(ctx.operanders["output1"], ctx.operanders["output1_low"], ctx.operanders["output1_mid"], ctx.operanders["output1_high"])
},
check: allVarValueEquals(map[string]*fp.Element{"output1_low": feltUint64(0), "output1_mid": feltUint64(0), "output1_high": feltUint64(0)}),
},
{
operanders: []*hintOperander{
{Name: "output1", Kind: apRelative, Value: feltUint64(72365738)},
{Name: "output1_low", Kind: uninitialized},
{Name: "output1_mid", Kind: uninitialized},
{Name: "output1_high", Kind: uninitialized},
},
makeHinter: func(ctx *hintTestContext) hinter.Hinter {
return newSplitOutputMidLowHighHint(ctx.operanders["output1"], ctx.operanders["output1_low"], ctx.operanders["output1_mid"], ctx.operanders["output1_high"])
},
check: allVarValueEquals(map[string]*fp.Element{"output1_low": feltUint64(72365738), "output1_mid": feltUint64(0), "output1_high": feltUint64(0)}),
},
{
operanders: []*hintOperander{
{Name: "output1", Kind: apRelative, Value: feltUint64(72057594037927936)},
{Name: "output1_low", Kind: uninitialized},
{Name: "output1_mid", Kind: uninitialized},
{Name: "output1_high", Kind: uninitialized},
},
makeHinter: func(ctx *hintTestContext) hinter.Hinter {
return newSplitOutputMidLowHighHint(ctx.operanders["output1"], ctx.operanders["output1_low"], ctx.operanders["output1_mid"], ctx.operanders["output1_high"])
},
check: allVarValueEquals(map[string]*fp.Element{"output1_low": feltUint64(0), "output1_mid": feltUint64(1), "output1_high": feltUint64(0)}),
},
{
operanders: []*hintOperander{
{Name: "output1", Kind: apRelative, Value: feltString("24519928653854221733733552434404946937899825954937634816")},
{Name: "output1_low", Kind: uninitialized},
{Name: "output1_mid", Kind: uninitialized},
{Name: "output1_high", Kind: uninitialized},
},
makeHinter: func(ctx *hintTestContext) hinter.Hinter {
return newSplitOutputMidLowHighHint(ctx.operanders["output1"], ctx.operanders["output1_low"], ctx.operanders["output1_mid"], ctx.operanders["output1_high"])
},
check: allVarValueEquals(map[string]*fp.Element{"output1_low": feltUint64(0), "output1_mid": feltUint64(0), "output1_high": feltUint64(1)}),
},
{
operanders: []*hintOperander{
{Name: "output1", Kind: apRelative, Value: feltString("24519928653854221733733552434404946940926244904530608128")},
{Name: "output1_low", Kind: uninitialized},
{Name: "output1_mid", Kind: uninitialized},
{Name: "output1_high", Kind: uninitialized},
},
makeHinter: func(ctx *hintTestContext) hinter.Hinter {
return newSplitOutputMidLowHighHint(ctx.operanders["output1"], ctx.operanders["output1_low"], ctx.operanders["output1_mid"], ctx.operanders["output1_high"])
},
check: allVarValueEquals(map[string]*fp.Element{"output1_low": feltUint64(0), "output1_mid": feltUint64(42), "output1_high": feltUint64(1)}),
},
{
operanders: []*hintOperander{
{Name: "output1", Kind: apRelative, Value: feltString("894386062958165334425")},
{Name: "output1_low", Kind: uninitialized},
{Name: "output1_mid", Kind: uninitialized},
{Name: "output1_high", Kind: uninitialized},
},
makeHinter: func(ctx *hintTestContext) hinter.Hinter {
return newSplitOutputMidLowHighHint(ctx.operanders["output1"], ctx.operanders["output1_low"], ctx.operanders["output1_mid"], ctx.operanders["output1_high"])
},
check: allVarValueEquals(map[string]*fp.Element{"output1_low": feltUint64(7205759403792793), "output1_mid": feltUint64(12412), "output1_high": feltUint64(0)}),
},
{
operanders: []*hintOperander{
{Name: "output1", Kind: apRelative, Value: feltString("24519928653854221733733552434404946937899825956147353057")},
{Name: "output1_low", Kind: uninitialized},
{Name: "output1_mid", Kind: uninitialized},
{Name: "output1_high", Kind: uninitialized},
},
makeHinter: func(ctx *hintTestContext) hinter.Hinter {
return newSplitOutputMidLowHighHint(ctx.operanders["output1"], ctx.operanders["output1_low"], ctx.operanders["output1_mid"], ctx.operanders["output1_high"])
},
check: allVarValueEquals(map[string]*fp.Element{"output1_low": feltUint64(1209718241), "output1_mid": feltUint64(0), "output1_high": feltUint64(1)}),
},
{
operanders: []*hintOperander{
{Name: "output1", Kind: apRelative, Value: feltString("24519928653854221733733552434404946940926244943286781240")},
{Name: "output1_low", Kind: uninitialized},
{Name: "output1_mid", Kind: uninitialized},
{Name: "output1_high", Kind: uninitialized},
},
makeHinter: func(ctx *hintTestContext) hinter.Hinter {
return newSplitOutputMidLowHighHint(ctx.operanders["output1"], ctx.operanders["output1_low"], ctx.operanders["output1_mid"], ctx.operanders["output1_high"])
},
check: allVarValueEquals(map[string]*fp.Element{"output1_low": feltUint64(38756173112), "output1_mid": feltUint64(42), "output1_high": feltUint64(1)}),
},
},
})
}

0 comments on commit 27817ff

Please sign in to comment.