diff --git a/go.mod b/go.mod index 46665ef37a0..c4ecd750098 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible github.com/Shopify/sarama v1.20.1 github.com/VictoriaMetrics/fastcache v1.9.0 - github.com/bits-and-blooms/bitset v1.13.0 + github.com/bits-and-blooms/bitset v1.20.0 github.com/cheggaaa/pb v1.0.29 github.com/davecgh/go-spew v1.1.1 github.com/fsouza/go-dockerclient v1.10.0 @@ -31,8 +31,8 @@ require ( github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.20.5 github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 - github.com/spf13/cobra v1.5.0 - github.com/spf13/pflag v1.0.5 + github.com/spf13/cobra v1.8.1 + github.com/spf13/pflag v1.0.6 github.com/spf13/viper v1.7.0 github.com/stretchr/testify v1.10.0 // includes ErrorContains github.com/sykesm/zap-logfmt v0.0.4 @@ -65,8 +65,7 @@ require ( github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/consensys/bavard v0.1.13 // indirect - github.com/consensys/gnark-crypto v0.12.1 // indirect + github.com/consensys/gnark-crypto v0.18.1 // indirect github.com/containerd/log v0.1.0 // indirect github.com/docker/docker v28.0.0+incompatible // indirect github.com/docker/go-connections v0.4.0 // indirect @@ -87,13 +86,12 @@ require ( github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hyperledger/fabric-amcl v0.0.0-20230602173724-9e02669dceb2 // indirect - github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/kilic/bls12-381 v0.1.0 // indirect github.com/klauspost/compress v1.17.9 // indirect github.com/kr/text v0.2.0 // indirect github.com/magiconair/properties v1.8.1 // indirect github.com/mattn/go-runewidth v0.0.4 // indirect - github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/patternmatcher v0.6.0 // indirect github.com/moby/sys/sequential v0.5.0 // indirect @@ -129,7 +127,6 @@ require ( gopkg.in/ini.v1 v1.51.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools/v3 v3.5.0 // indirect - rsc.io/tmplfunc v0.0.3 // indirect ) replace ( diff --git a/go.sum b/go.sum index 46819b10eba..86563cdb5c2 100644 --- a/go.sum +++ b/go.sum @@ -72,8 +72,8 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE= -github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/bits-and-blooms/bitset v1.20.0 h1:2F+rfL86jE2d/bmw7OhqUg2Sj/1rURkBn3MdfoPyRVU= +github.com/bits-and-blooms/bitset v1.20.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce h1:YtWJF7RHm2pYCvA5t0RPmAaLUhREsKuKd+SLhxFbFeQ= github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= @@ -94,10 +94,8 @@ github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:z github.com/cockroachdb/datadriven v1.0.2 h1:H9MtNqVoVhvd9nCBwOyDjUEdZCREqbIdCJD93PBm/jA= github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= -github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= -github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= -github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= +github.com/consensys/gnark-crypto v0.18.1 h1:RyLV6UhPRoYYzaFnPQA4qK3DyuDgkTgskDdoGqFt3fI= +github.com/consensys/gnark-crypto v0.18.1/go.mod h1:L3mXGFTe1ZN+RSJ+CLjUt9x7PNdx8ubaYfDROyp2Z8c= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= @@ -109,7 +107,7 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7 github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= @@ -222,7 +220,6 @@ github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OI github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8= github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -282,8 +279,9 @@ github.com/hyperledger/fabric-chaincode-go v0.0.0-20220920210243-7bc6fa0dd58b h1 github.com/hyperledger/fabric-chaincode-go v0.0.0-20220920210243-7bc6fa0dd58b/go.mod h1:OxME3M0bbgoWYHpXIVMzpbXgFqrTZnFmlH0Cpml54m0= github.com/hyperledger/fabric-lib-go v1.0.0 h1:UL1w7c9LvHZUSkIvHTDGklxFv2kTeva1QI2emOVc324= github.com/hyperledger/fabric-lib-go v1.0.0/go.mod h1:H362nMlunurmHwkYqR5uHL2UDWbQdbfz74n8kbCFsqc= -github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= @@ -313,8 +311,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= -github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= +github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4= +github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= @@ -344,9 +342,6 @@ github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:F github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= -github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= -github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= @@ -495,15 +490,16 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU= -github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= +github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.7.0 h1:xVKxvI7ouOI5I+U9s2eeiUfMaWBVoXA3AWskkrqK0VM= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= @@ -812,7 +808,5 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= -rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/vendor/github.com/bits-and-blooms/bitset/README.md b/vendor/github.com/bits-and-blooms/bitset/README.md index fe7bca65ebb..ac826cd9f6a 100644 --- a/vendor/github.com/bits-and-blooms/bitset/README.md +++ b/vendor/github.com/bits-and-blooms/bitset/README.md @@ -12,7 +12,7 @@ This library is part of the [awesome go collection](https://github.com/avelino/a * [beego](https://github.com/beego/beego) * [CubeFS](https://github.com/cubefs/cubefs) * [Amazon EKS Distro](https://github.com/aws/eks-distro) -* [sourcegraph](https://github.com/sourcegraph/sourcegraph) +* [sourcegraph](https://github.com/sourcegraph/sourcegraph-public-snapshot) * [torrent](https://github.com/anacrolix/torrent) @@ -25,7 +25,7 @@ It provides methods for setting, clearing, flipping, and testing individual inte But it also provides set intersection, union, difference, complement, and symmetric operations, as well as tests to check whether any, all, or no bits are set, and querying a bitset's current length and number of positive bits. -BitSets are expanded to the size of the largest set bit; the memory allocation is approximately Max bits, where Max is the largest set bit. BitSets are never shrunk. On creation, a hint can be given for the number of bits that will be used. +BitSets are expanded to the size of the largest set bit; the memory allocation is approximately Max bits, where Max is the largest set bit. BitSets are never shrunk automatically, but `Shrink` and `Compact` methods are available. On creation, a hint can be given for the number of bits that will be used. Many of the methods, including Set, Clear, and Flip, return a BitSet pointer, which allows for chaining. @@ -125,7 +125,7 @@ E.g., ## Memory Usage -The memory usage of a bitset using `N` bits is at least `N/8` bytes. The number of bits in a bitset is at least as large as one plus the greatest bit index you have accessed. Thus it is possible to run out of memory while using a bitset. If you have lots of bits, you might prefer compressed bitsets, like the [Roaring bitmaps](http://roaringbitmap.org) and its [Go implementation](https://github.com/RoaringBitmap/roaring). +The memory usage of a bitset using `N` bits is at least `N/8` bytes. The number of bits in a bitset is at least as large as one plus the greatest bit index you have accessed. Thus it is possible to run out of memory while using a bitset. If you have lots of bits, you might prefer compressed bitsets, like the [Roaring bitmaps](https://roaringbitmap.org) and its [Go implementation](https://github.com/RoaringBitmap/roaring). The `roaring` library allows you to go back and forth between compressed Roaring bitmaps and the conventional bitset instances: ```Go @@ -134,11 +134,11 @@ The `roaring` library allows you to go back and forth between compressed Roaring ``` -## Implementation Note +### Goroutine safety -Go 1.9 introduced a native `math/bits` library. We provide backward compatibility to Go 1.7, which might be removed. +In general, it's not safe to access the same BitSet using different goroutines--they are unsynchronized for performance. -It is possible that a later version will match the `math/bits` return signature for counts (which is `int`, rather than our library's `uint64`). If so, the version will be bumped. +Should you want to access a BitSet from more than one goroutine, you should provide synchronization. Typically this is done by using channels to pass the *BitSet around (in Go style; so there is only ever one owner), or by using `sync.Mutex` to serialize operations on BitSets. ## Installation diff --git a/vendor/github.com/bits-and-blooms/bitset/bitset.go b/vendor/github.com/bits-and-blooms/bitset/bitset.go index 9f38ed3a9dc..23958ef89fd 100644 --- a/vendor/github.com/bits-and-blooms/bitset/bitset.go +++ b/vendor/github.com/bits-and-blooms/bitset/bitset.go @@ -44,17 +44,21 @@ import ( "errors" "fmt" "io" + "math/bits" "strconv" ) // the wordSize of a bit set -const wordSize = uint(64) +const wordSize = 64 // the wordSize of a bit set in bytes const wordBytes = wordSize / 8 +// wordMask is wordSize-1, used for bit indexing in a word +const wordMask = wordSize - 1 + // log2WordSize is lg(wordSize) -const log2WordSize = uint(6) +const log2WordSize = 6 // allBits has every bit set const allBits uint64 = 0xffffffffffffffff @@ -68,9 +72,16 @@ var base64Encoding = base64.URLEncoding // Base64StdEncoding Marshal/Unmarshal BitSet with base64.StdEncoding(Default: base64.URLEncoding) func Base64StdEncoding() { base64Encoding = base64.StdEncoding } -// LittleEndian Marshal/Unmarshal Binary as Little Endian(Default: binary.BigEndian) +// LittleEndian sets Marshal/Unmarshal Binary as Little Endian (Default: binary.BigEndian) func LittleEndian() { binaryOrder = binary.LittleEndian } +// BigEndian sets Marshal/Unmarshal Binary as Big Endian (Default: binary.BigEndian) +func BigEndian() { binaryOrder = binary.BigEndian } + +// BinaryOrder returns the current binary order, see also LittleEndian() +// and BigEndian() to change the order. +func BinaryOrder() binary.ByteOrder { return binaryOrder } + // A BitSet is a set of bits. The zero value of a BitSet is an empty set of length 0. type BitSet struct { length uint @@ -99,36 +110,58 @@ func From(buf []uint64) *BitSet { return FromWithLength(uint(len(buf))*64, buf) } -// FromWithLength constructs from an array of words and length. -func FromWithLength(len uint, set []uint64) *BitSet { - return &BitSet{len, set} +// FromWithLength constructs from an array of words and length in bits. +// This function is for advanced users, most users should prefer +// the From function. +// As a user of FromWithLength, you are responsible for ensuring +// that the length is correct: your slice should have length at +// least (length+63)/64 in 64-bit words. +func FromWithLength(length uint, set []uint64) *BitSet { + if len(set) < wordsNeeded(length) { + panic("BitSet.FromWithLength: slice is too short") + } + return &BitSet{length, set} } -// Bytes returns the bitset as array of words +// Bytes returns the bitset as array of 64-bit words, giving direct access to the internal representation. +// It is not a copy, so changes to the returned slice will affect the bitset. +// It is meant for advanced users. +// +// Deprecated: Bytes is deprecated. Use [BitSet.Words] instead. func (b *BitSet) Bytes() []uint64 { return b.set } +// Words returns the bitset as array of 64-bit words, giving direct access to the internal representation. +// It is not a copy, so changes to the returned slice will affect the bitset. +// It is meant for advanced users. +func (b *BitSet) Words() []uint64 { + return b.set +} + // wordsNeeded calculates the number of words needed for i bits func wordsNeeded(i uint) int { - if i > (Cap() - wordSize + 1) { + if i > (Cap() - wordMask) { return int(Cap() >> log2WordSize) } - return int((i + (wordSize - 1)) >> log2WordSize) + return int((i + wordMask) >> log2WordSize) } // wordsNeededUnbound calculates the number of words needed for i bits, possibly exceeding the capacity. -// This function is useful if you know that the capacity cannot be exceeded (e.g., you have an existing bitmap). +// This function is useful if you know that the capacity cannot be exceeded (e.g., you have an existing BitSet). func wordsNeededUnbound(i uint) int { - return int((i + (wordSize - 1)) >> log2WordSize) + return (int(i) + wordMask) >> log2WordSize } // wordsIndex calculates the index of words in a `uint64` func wordsIndex(i uint) uint { - return i & (wordSize - 1) + return i & wordMask } -// New creates a new BitSet with a hint that length bits will be required +// New creates a new BitSet with a hint that length bits will be required. +// The memory usage is at least length/8 bytes. +// In case of allocation failure, the function will return a BitSet with zero +// capacity. func New(length uint) (bset *BitSet) { defer func() { if r := recover(); r != nil { @@ -147,13 +180,30 @@ func New(length uint) (bset *BitSet) { return bset } +// MustNew creates a new BitSet with the given length bits. +// It panics if length exceeds the possible capacity or by a lack of memory. +func MustNew(length uint) (bset *BitSet) { + if length >= Cap() { + panic("You are exceeding the capacity") + } + + return &BitSet{ + length, + make([]uint64, wordsNeeded(length)), // may panic on lack of memory + } +} + // Cap returns the total possible capacity, or number of bits +// that can be stored in the BitSet theoretically. Under 32-bit system, +// it is 4294967295 and under 64-bit system, it is 18446744073709551615. +// Note that this is further limited by the maximum allocation size in Go, +// and your available memory, as any Go data structure. func Cap() uint { return ^uint(0) } // Len returns the number of bits in the BitSet. -// Note the difference to method Count, see example. +// Note that it differ from Count function. func (b *BitSet) Len() uint { return b.length } @@ -184,12 +234,32 @@ func (b *BitSet) Test(i uint) bool { return b.set[i>>log2WordSize]&(1<> log2WordSize) + subWordIndex := wordsIndex(i) + + // The word that the index falls within, shifted so the index is at bit 0 + var firstWord, secondWord uint64 + if firstWordIndex < len(b.set) { + firstWord = b.set[firstWordIndex] >> subWordIndex + } + + // The next word, masked to only include the necessary bits and shifted to cover the + // top of the word + if (firstWordIndex + 1) < len(b.set) { + secondWord = b.set[firstWordIndex+1] << uint64(wordSize-subWordIndex) + } + + return firstWord | secondWord +} + // Set bit i to 1, the capacity of the bitset is automatically // increased accordingly. -// If i>= Cap(), this function will panic. // Warning: using a very large value for 'i' // may lead to a memory shortage and a panic: the caller is responsible // for providing sensible parameters in line with their memory capacity. +// The memory usage is at least slightly over i/8 bytes. func (b *BitSet) Set(i uint) *BitSet { if i >= b.length { // if we need more bits, make 'em b.extendSet(i) @@ -198,7 +268,7 @@ func (b *BitSet) Set(i uint) *BitSet { return b } -// Clear bit i to 0 +// Clear bit i to 0. This never cause a memory allocation. It is always safe. func (b *BitSet) Clear(i uint) *BitSet { if i >= b.length { return b @@ -208,7 +278,6 @@ func (b *BitSet) Clear(i uint) *BitSet { } // SetTo sets bit i to value. -// If i>= Cap(), this function will panic. // Warning: using a very large value for 'i' // may lead to a memory shortage and a panic: the caller is responsible // for providing sensible parameters in line with their memory capacity. @@ -220,7 +289,6 @@ func (b *BitSet) SetTo(i uint, value bool) *BitSet { } // Flip bit at i. -// If i>= Cap(), this function will panic. // Warning: using a very large value for 'i' // may lead to a memory shortage and a panic: the caller is responsible // for providing sensible parameters in line with their memory capacity. @@ -233,7 +301,6 @@ func (b *BitSet) Flip(i uint) *BitSet { } // FlipRange bit in [start, end). -// If end>= Cap(), this function will panic. // Warning: using a very large value for 'end' // may lead to a memory shortage and a panic: the caller is responsible // for providing sensible parameters in line with their memory capacity. @@ -241,23 +308,54 @@ func (b *BitSet) FlipRange(start, end uint) *BitSet { if start >= end { return b } + if end-1 >= b.length { // if we need more bits, make 'em b.extendSet(end - 1) } - var startWord uint = start >> log2WordSize - var endWord uint = end >> log2WordSize + + startWord := int(start >> log2WordSize) + endWord := int(end >> log2WordSize) + + // b.set[startWord] ^= ^(^uint64(0) << wordsIndex(start)) + // e.g: + // start = 71, + // startWord = 1 + // wordsIndex(start) = 71 % 64 = 7 + // (^uint64(0) << 7) = 0b111111....11110000000 + // + // mask = ^(^uint64(0) << 7) = 0b000000....00001111111 + // + // flips the first 7 bits in b.set[1] and + // in the range loop, the b.set[1] gets again flipped + // so the two expressions flip results in a flip + // in b.set[1] from [7,63] + // + // handle startWord special, get's reflipped in range loop b.set[startWord] ^= ^(^uint64(0) << wordsIndex(start)) - if endWord > 0 { - // bounds check elimination - data := b.set - _ = data[endWord-1] - for i := startWord; i < endWord; i++ { - data[i] = ^data[i] - } - } - if end&(wordSize-1) != 0 { - b.set[endWord] ^= ^uint64(0) >> wordsIndex(-end) + + for idx := range b.set[startWord:endWord] { + b.set[startWord+idx] = ^b.set[startWord+idx] + } + + // handle endWord special + // e.g. + // end = 135 + // endWord = 2 + // + // wordsIndex(-7) = 57 + // see the golang spec: + // "For unsigned integer values, the operations +, -, *, and << are computed + // modulo 2n, where n is the bit width of the unsigned integer's type." + // + // mask = ^uint64(0) >> 57 = 0b00000....0001111111 + // + // flips in b.set[2] from [0,7] + // + // is end at word boundary? + if idx := wordsIndex(-end); idx != 0 { + b.set[endWord] ^= ^uint64(0) >> wordsIndex(idx) } + return b } @@ -275,6 +373,7 @@ func (b *BitSet) FlipRange(start, end uint) *BitSet { // memory usage until the GC runs. Normally this should not be a problem, but if you // have an extremely large BitSet its important to understand that the old BitSet will // remain in memory until the GC frees it. +// If you are memory constrained, this function may cause a panic. func (b *BitSet) Shrink(lastbitindex uint) *BitSet { length := lastbitindex + 1 idx := wordsNeeded(length) @@ -294,6 +393,11 @@ func (b *BitSet) Shrink(lastbitindex uint) *BitSet { // Compact shrinks BitSet to so that we preserve all set bits, while minimizing // memory usage. Compact calls Shrink. +// A new slice is allocated to store the new bits, so you may see an increase in +// memory usage until the GC runs. Normally this should not be a problem, but if you +// have an extremely large BitSet its important to understand that the old BitSet will +// remain in memory until the GC frees it. +// If you are memory constrained, this function may cause a panic. func (b *BitSet) Compact() *BitSet { idx := len(b.set) - 1 for ; idx >= 0 && b.set[idx] == 0; idx-- { @@ -353,7 +457,8 @@ func (b *BitSet) InsertAt(idx uint) *BitSet { return b } -// String creates a string representation of the Bitmap +// String creates a string representation of the BitSet. It is only intended for +// human-readable output and not for serialization. func (b *BitSet) String() string { // follows code from https://github.com/RoaringBitmap/roaring var buffer bytes.Buffer @@ -415,6 +520,50 @@ func (b *BitSet) DeleteAt(i uint) *BitSet { return b } +// AppendTo appends all set bits to buf and returns the (maybe extended) buf. +// In case of allocation failure, the function will panic. +// +// See also [BitSet.AsSlice] and [BitSet.NextSetMany]. +func (b *BitSet) AppendTo(buf []uint) []uint { + // In theory, we could overflow uint, but in practice, we will not. + for idx, word := range b.set { + for word != 0 { + // In theory idx<= len(b.set) { return 0, false } - w := b.set[x] - w = w >> wordsIndex(i) - if w != 0 { - return i + trailingZeroes64(w), true + + // process first (partial) word + word := b.set[x] >> wordsIndex(i) + if word != 0 { + return i + uint(bits.TrailingZeros64(word)), true } + + // process the following full words until next bit is set + // x < len(b.set), no out-of-bounds panic in following slice expression x++ - // bounds check elimination in the loop - if x < 0 { - return 0, false - } - for x < len(b.set) { - if b.set[x] != 0 { - return uint(x)*wordSize + trailingZeroes64(b.set[x]), true + for idx, word := range b.set[x:] { + if word != 0 { + return uint((x+idx)<> log2WordSize) if x >= len(b.set) || capacity == 0 { - return 0, myanswer[:0] + return 0, result[:0] } - skip := wordsIndex(i) - word := b.set[x] >> skip - myanswer = myanswer[:capacity] - size := int(0) + + // process first (partial) word + word := b.set[x] >> wordsIndex(i) + + size := 0 for word != 0 { - r := trailingZeroes64(word) - t := word & ((^word) + 1) - myanswer[size] = r + i + result[size] = i + uint(bits.TrailingZeros64(word)) + size++ if size == capacity { - goto End + return result[size-1], result[:size] } - word = word ^ t + + // clear the rightmost set bit + word &= word - 1 } + + // process the following full words + // x < len(b.set), no out-of-bounds panic in following slice expression x++ for idx, word := range b.set[x:] { for word != 0 { - r := trailingZeroes64(word) - t := word & ((^word) + 1) - myanswer[size] = r + (uint(x+idx) << 6) + result[size] = uint((x+idx)< 0 { - return myanswer[size-1], myanswer[:size] + return result[size-1], result[:size] } - return 0, myanswer[:0] + return 0, result[:0] } // NextClear returns the next clear bit from the specified index, @@ -517,31 +676,89 @@ func (b *BitSet) NextClear(i uint) (uint, bool) { if x >= len(b.set) { return 0, false } - w := b.set[x] - w = w >> wordsIndex(i) - wA := allBits >> wordsIndex(i) - index := i + trailingZeroes64(^w) - if w != wA && index < b.length { + + // process first (maybe partial) word + word := b.set[x] + word = word >> wordsIndex(i) + wordAll := allBits >> wordsIndex(i) + + index := i + uint(bits.TrailingZeros64(^word)) + if word != wordAll && index < b.length { return index, true } + + // process the following full words until next bit is cleared + // x < len(b.set), no out-of-bounds panic in following slice expression x++ - // bounds check elimination in the loop - if x < 0 { - return 0, false - } - for x < len(b.set) { - if b.set[x] != allBits { - index = uint(x)*wordSize + trailingZeroes64(^b.set[x]) + for idx, word := range b.set[x:] { + if word != allBits { + index = uint((x+idx)*wordSize + bits.TrailingZeros64(^word)) if index < b.length { return index, true } } - x++ + } + + return 0, false +} + +// PreviousSet returns the previous set bit from the specified index, +// including possibly the current index +// along with an error code (true = valid, false = no bit found i.e. all bits are clear) +func (b *BitSet) PreviousSet(i uint) (uint, bool) { + x := int(i >> log2WordSize) + if x >= len(b.set) { + return 0, false + } + word := b.set[x] + + // Clear the bits above the index + word = word & ((1 << (wordsIndex(i) + 1)) - 1) + if word != 0 { + return uint(x<= 0; x-- { + word = b.set[x] + if word != 0 { + return uint(x<> log2WordSize) + if x >= len(b.set) { + return 0, false + } + word := b.set[x] + + // Flip all bits and find the highest one bit + word = ^word + + // Clear the bits above the index + word = word & ((1 << (wordsIndex(i) + 1)) - 1) + + if word != 0 { + return uint(x<= 0; x-- { + word = b.set[x] + word = ^word + if word != 0 { + return uint(x< length { end = length - buffer = buffer[:wordBytes*uint(end-i)] + buffer = buffer[:wordBytes*(end-i)] } chunk := data[i:end] if _, err := io.ReadFull(reader, buffer); err != nil { @@ -998,12 +1219,12 @@ func readUint64Array(reader io.Reader, data []uint64) error { func writeUint64Array(writer io.Writer, data []uint64) error { bufferSize := 128 - buffer := make([]byte, bufferSize*int(wordBytes)) + buffer := make([]byte, bufferSize*wordBytes) for i := 0; i < len(data); i += bufferSize { end := i + bufferSize if end > len(data) { end = len(data) - buffer = buffer[:wordBytes*uint(end-i)] + buffer = buffer[:wordBytes*(end-i)] } chunk := data[i:end] for i, x := range chunk { @@ -1020,6 +1241,15 @@ func writeUint64Array(writer io.Writer, data []uint64) error { // WriteTo writes a BitSet to a stream. The format is: // 1. uint64 length // 2. []uint64 set +// The length is the number of bits in the BitSet. +// +// The set is a slice of uint64s containing between length and length + 63 bits. +// It is interpreted as a big-endian array of uint64s by default (see BinaryOrder()) +// meaning that the first 8 bits are stored at byte index 7, the next 8 bits are stored +// at byte index 6... the bits 64 to 71 are stored at byte index 8, etc. +// If you change the binary order, you need to do so for both reading and writing. +// We recommend using the default binary order. +// // Upon success, the number of bytes written is returned. // // Performance: if this function is used to write to a disk or network @@ -1050,6 +1280,7 @@ func (b *BitSet) WriteTo(stream io.Writer) (int64, error) { // The format is: // 1. uint64 length // 2. []uint64 set +// See WriteTo for details. // Upon success, the number of bytes read is returned. // If the current BitSet is not large enough to hold the data, // it is extended. In case of error, the BitSet is either @@ -1101,6 +1332,7 @@ func (b *BitSet) ReadFrom(stream io.Reader) (int64, error) { } // MarshalBinary encodes a BitSet into a binary form and returns the result. +// Please see WriteTo for details. func (b *BitSet) MarshalBinary() ([]byte, error) { var buf bytes.Buffer _, err := b.WriteTo(&buf) @@ -1112,6 +1344,7 @@ func (b *BitSet) MarshalBinary() ([]byte, error) { } // UnmarshalBinary decodes the binary form generated by MarshalBinary. +// Please see WriteTo for details. func (b *BitSet) UnmarshalBinary(data []byte) error { buf := bytes.NewReader(data) _, err := b.ReadFrom(buf) @@ -1149,7 +1382,7 @@ func (b *BitSet) UnmarshalJSON(data []byte) error { return err } -// Rank returns the nunber of set bits up to and including the index +// Rank returns the number of set bits up to and including the index // that are set in the bitset. // See https://en.wikipedia.org/wiki/Ranking#Ranking_in_statistics func (b *BitSet) Rank(index uint) uint { @@ -1159,7 +1392,7 @@ func (b *BitSet) Rank(index uint) uint { leftover := (index + 1) & 63 answer := uint(popcntSlice(b.set[:(index+1)>>6])) if leftover != 0 { - answer += uint(popcount(b.set[(index+1)>>6] << (64 - leftover))) + answer += uint(bits.OnesCount64(b.set[(index+1)>>6] << (64 - leftover))) } return answer } @@ -1174,7 +1407,7 @@ func (b *BitSet) Rank(index uint) uint { func (b *BitSet) Select(index uint) uint { leftover := index for idx, word := range b.set { - w := uint(popcount(word)) + w := uint(bits.OnesCount64(word)) if w > leftover { return uint(idx)*64 + select64(word, leftover) } @@ -1182,3 +1415,327 @@ func (b *BitSet) Select(index uint) uint { } return b.length } + +// top detects the top bit set +func (b *BitSet) top() (uint, bool) { + panicIfNull(b) + + idx := len(b.set) - 1 + for ; idx >= 0 && b.set[idx] == 0; idx-- { + } + + // no set bits + if idx < 0 { + return 0, false + } + + return uint(idx*wordSize+bits.Len64(b.set[idx])) - 1, true +} + +// ShiftLeft shifts the bitset like << operation would do. +// +// Left shift may require bitset size extension. We try to avoid the +// unnecessary memory operations by detecting the leftmost set bit. +// The function will panic if shift causes excess of capacity. +func (b *BitSet) ShiftLeft(bits uint) { + panicIfNull(b) + + if bits == 0 { + return + } + + top, ok := b.top() + if !ok { + return + } + + // capacity check + if top+bits < bits { + panic("You are exceeding the capacity") + } + + // destination set + dst := b.set + + // not using extendSet() to avoid unneeded data copying + nsize := wordsNeeded(top + bits) + if len(b.set) < nsize { + dst = make([]uint64, nsize) + } + if top+bits >= b.length { + b.length = top + bits + 1 + } + + pad, idx := top%wordSize, top>>log2WordSize + shift, pages := bits%wordSize, bits>>log2WordSize + if bits%wordSize == 0 { // happy case: just add pages + copy(dst[pages:nsize], b.set) + } else { + if pad+shift >= wordSize { + dst[idx+pages+1] = b.set[idx] >> (wordSize - shift) + } + + for i := int(idx); i >= 0; i-- { + if i > 0 { + dst[i+int(pages)] = (b.set[i] << shift) | (b.set[i-1] >> (wordSize - shift)) + } else { + dst[i+int(pages)] = b.set[i] << shift + } + } + } + + // zeroing extra pages + for i := 0; i < int(pages); i++ { + dst[i] = 0 + } + + b.set = dst +} + +// ShiftRight shifts the bitset like >> operation would do. +func (b *BitSet) ShiftRight(bits uint) { + panicIfNull(b) + + if bits == 0 { + return + } + + top, ok := b.top() + if !ok { + return + } + + if bits >= top { + b.set = make([]uint64, wordsNeeded(b.length)) + return + } + + pad, idx := top%wordSize, top>>log2WordSize + shift, pages := bits%wordSize, bits>>log2WordSize + if bits%wordSize == 0 { // happy case: just clear pages + b.set = b.set[pages:] + b.length -= pages * wordSize + } else { + for i := 0; i <= int(idx-pages); i++ { + if i < int(idx-pages) { + b.set[i] = (b.set[i+int(pages)] >> shift) | (b.set[i+int(pages)+1] << (wordSize - shift)) + } else { + b.set[i] = b.set[i+int(pages)] >> shift + } + } + + if pad < shift { + b.set[int(idx-pages)] = 0 + } + } + + for i := int(idx-pages) + 1; i <= int(idx); i++ { + b.set[i] = 0 + } +} + +// OnesBetween returns the number of set bits in the range [from, to). +// The range is inclusive of 'from' and exclusive of 'to'. +// Returns 0 if from >= to. +func (b *BitSet) OnesBetween(from, to uint) uint { + panicIfNull(b) + + if from >= to { + return 0 + } + + // Calculate indices and masks for the starting and ending words + startWord := from >> log2WordSize // Divide by wordSize + endWord := to >> log2WordSize + startOffset := from & wordMask // Mod wordSize + endOffset := to & wordMask + + // Case 1: Bits lie within a single word + if startWord == endWord { + // Create mask for bits between from and to + mask := uint64((1<= startOffset + count = uint(bits.OnesCount64(b.set[startWord] & startMask)) + + // 2b: Count all bits in complete words between start and end + if endWord > startWord+1 { + count += uint(popcntSlice(b.set[startWord+1 : endWord])) + } + + // 2c: Count bits in last word (from start of word to endOffset) + if endOffset > 0 { + endMask := uint64(1<> log2WordSize + bitOffset := outPos & wordMask + + // Write extracted bits, handling word boundary crossing + dst.set[wordIdx] |= extracted << bitOffset + if bitOffset+bitsExtracted > wordSize { + dst.set[wordIdx+1] = extracted >> (wordSize - bitOffset) + } + + outPos += bitsExtracted + } +} + +// Deposit creates a new BitSet and deposits bits according to a mask. +// See DepositTo for details. +func (b *BitSet) Deposit(mask *BitSet) *BitSet { + dst := New(mask.length) + b.DepositTo(mask, dst) + return dst +} + +// DepositTo spreads bits from a compacted form in the BitSet into positions +// specified by mask in dst. This is the inverse operation of Extract. +// +// For example, if mask has bits set at positions 1,4,5, then DepositTo will +// take consecutive bits 0,1,2 from the source BitSet and place them into +// positions 1,4,5 in the destination BitSet. +func (b *BitSet) DepositTo(mask *BitSet, dst *BitSet) { + panicIfNull(b) + panicIfNull(mask) + panicIfNull(dst) + + if len(dst.set) == 0 || len(mask.set) == 0 || len(b.set) == 0 { + return + } + + inPos := uint(0) + length := len(mask.set) + if len(dst.set) < length { + length = len(dst.set) + } + + // Process each word + for i := 0; i < length; i++ { + if mask.set[i] == 0 { + continue // Skip words with no bits to deposit + } + + // Calculate source word index + wordIdx := inPos >> log2WordSize + if wordIdx >= uint(len(b.set)) { + break // No more source bits available + } + + // Get source bits, handling word boundary crossing + sourceBits := b.set[wordIdx] + bitOffset := inPos & wordMask + if wordIdx+1 < uint(len(b.set)) && bitOffset != 0 { + // Combine bits from current and next word + sourceBits = (sourceBits >> bitOffset) | + (b.set[wordIdx+1] << (wordSize - bitOffset)) + } else { + sourceBits >>= bitOffset + } + + // Deposit bits according to mask + dst.set[i] = (dst.set[i] &^ mask.set[i]) | pdep(sourceBits, mask.set[i]) + inPos += uint(bits.OnesCount64(mask.set[i])) + } +} + +//go:generate go run cmd/pextgen/main.go -pkg=bitset + +func pext(w, m uint64) (result uint64) { + var outPos uint + + // Process byte by byte + for i := 0; i < 8; i++ { + shift := i << 3 // i * 8 using bit shift + b := uint8(w >> shift) + mask := uint8(m >> shift) + + extracted := pextLUT[b][mask] + bits := popLUT[mask] + + result |= uint64(extracted) << outPos + outPos += uint(bits) + } + + return result +} + +func pdep(w, m uint64) (result uint64) { + var inPos uint + + // Process byte by byte + for i := 0; i < 8; i++ { + shift := i << 3 // i * 8 using bit shift + mask := uint8(m >> shift) + bits := popLUT[mask] + + // Get the bits we'll deposit from the source + b := uint8(w >> inPos) + + // Deposit them according to the mask for this byte + deposited := pdepLUT[b][mask] + + // Add to result + result |= uint64(deposited) << shift + inPos += uint(bits) + } + + return result +} diff --git a/vendor/github.com/bits-and-blooms/bitset/pext.gen.go b/vendor/github.com/bits-and-blooms/bitset/pext.gen.go new file mode 100644 index 00000000000..94f01ae511a --- /dev/null +++ b/vendor/github.com/bits-and-blooms/bitset/pext.gen.go @@ -0,0 +1,8866 @@ +// Code generated by cmd/pextgen/main.go; DO NOT EDIT. +// +// To regenerate this file: +// go run cmd/pextgen/main.go + +package bitset + +// pextLUT contains pre-computed parallel bit extraction results +var pextLUT = [256][256]uint8{ + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, { + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + }, { + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + }, { + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + }, + { + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + }, { + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + }, { + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + }, { + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + }, { + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + }, { + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + }, { + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + }, + { + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + }, { + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + }, { + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + }, { + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + }, { + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + }, { + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + }, { + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + }, + { + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + }, { + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + }, { + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + }, { + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + }, { + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + }, { + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + }, { + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + }, + { + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + }, { + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + }, { + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + }, { + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 2, 4, 4, 8, 4, 8, 8, 16, 4, 8, 8, 16, 8, 16, 16, 32, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 2, 4, 4, 8, 4, 8, 8, 16, 4, 8, 8, 16, 8, 16, 16, 32, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 2, 4, 4, 8, 4, 8, 8, 16, 4, 8, 8, 16, 8, 16, 16, 32, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 2, 4, 4, 8, 4, 8, 8, 16, 4, 8, 8, 16, 8, 16, 16, 32, + }, { + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 2, 5, 4, 9, 4, 9, 8, 17, 4, 9, 8, 17, 8, 17, 16, 33, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 2, 5, 4, 9, 4, 9, 8, 17, 4, 9, 8, 17, 8, 17, 16, 33, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 2, 5, 4, 9, 4, 9, 8, 17, 4, 9, 8, 17, 8, 17, 16, 33, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 2, 5, 4, 9, 4, 9, 8, 17, 4, 9, 8, 17, 8, 17, 16, 33, + }, { + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 2, 4, 5, 10, 4, 8, 9, 18, 4, 8, 9, 18, 8, 16, 17, 34, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 2, 4, 5, 10, 4, 8, 9, 18, 4, 8, 9, 18, 8, 16, 17, 34, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 2, 4, 5, 10, 4, 8, 9, 18, 4, 8, 9, 18, 8, 16, 17, 34, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 2, 4, 5, 10, 4, 8, 9, 18, 4, 8, 9, 18, 8, 16, 17, 34, + }, { + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 2, 5, 5, 11, 4, 9, 9, 19, 4, 9, 9, 19, 8, 17, 17, 35, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 2, 5, 5, 11, 4, 9, 9, 19, 4, 9, 9, 19, 8, 17, 17, 35, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 2, 5, 5, 11, 4, 9, 9, 19, 4, 9, 9, 19, 8, 17, 17, 35, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 2, 5, 5, 11, 4, 9, 9, 19, 4, 9, 9, 19, 8, 17, 17, 35, + }, + { + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 2, 4, 4, 8, 5, 10, 10, 20, 4, 8, 8, 16, 9, 18, 18, 36, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 2, 4, 4, 8, 5, 10, 10, 20, 4, 8, 8, 16, 9, 18, 18, 36, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 2, 4, 4, 8, 5, 10, 10, 20, 4, 8, 8, 16, 9, 18, 18, 36, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 2, 4, 4, 8, 5, 10, 10, 20, 4, 8, 8, 16, 9, 18, 18, 36, + }, { + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 2, 5, 4, 9, 5, 11, 10, 21, 4, 9, 8, 17, 9, 19, 18, 37, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 2, 5, 4, 9, 5, 11, 10, 21, 4, 9, 8, 17, 9, 19, 18, 37, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 2, 5, 4, 9, 5, 11, 10, 21, 4, 9, 8, 17, 9, 19, 18, 37, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 2, 5, 4, 9, 5, 11, 10, 21, 4, 9, 8, 17, 9, 19, 18, 37, + }, { + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 2, 4, 5, 10, 5, 10, 11, 22, 4, 8, 9, 18, 9, 18, 19, 38, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 2, 4, 5, 10, 5, 10, 11, 22, 4, 8, 9, 18, 9, 18, 19, 38, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 2, 4, 5, 10, 5, 10, 11, 22, 4, 8, 9, 18, 9, 18, 19, 38, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 2, 4, 5, 10, 5, 10, 11, 22, 4, 8, 9, 18, 9, 18, 19, 38, + }, { + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 2, 5, 5, 11, 5, 11, 11, 23, 4, 9, 9, 19, 9, 19, 19, 39, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 2, 5, 5, 11, 5, 11, 11, 23, 4, 9, 9, 19, 9, 19, 19, 39, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 2, 5, 5, 11, 5, 11, 11, 23, 4, 9, 9, 19, 9, 19, 19, 39, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 2, 5, 5, 11, 5, 11, 11, 23, 4, 9, 9, 19, 9, 19, 19, 39, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 2, 4, 4, 8, 4, 8, 8, 16, 5, 10, 10, 20, 10, 20, 20, 40, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 2, 4, 4, 8, 4, 8, 8, 16, 5, 10, 10, 20, 10, 20, 20, 40, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 2, 4, 4, 8, 4, 8, 8, 16, 5, 10, 10, 20, 10, 20, 20, 40, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 2, 4, 4, 8, 4, 8, 8, 16, 5, 10, 10, 20, 10, 20, 20, 40, + }, { + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 2, 5, 4, 9, 4, 9, 8, 17, 5, 11, 10, 21, 10, 21, 20, 41, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 2, 5, 4, 9, 4, 9, 8, 17, 5, 11, 10, 21, 10, 21, 20, 41, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 2, 5, 4, 9, 4, 9, 8, 17, 5, 11, 10, 21, 10, 21, 20, 41, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 2, 5, 4, 9, 4, 9, 8, 17, 5, 11, 10, 21, 10, 21, 20, 41, + }, { + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 2, 4, 5, 10, 4, 8, 9, 18, 5, 10, 11, 22, 10, 20, 21, 42, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 2, 4, 5, 10, 4, 8, 9, 18, 5, 10, 11, 22, 10, 20, 21, 42, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 2, 4, 5, 10, 4, 8, 9, 18, 5, 10, 11, 22, 10, 20, 21, 42, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 2, 4, 5, 10, 4, 8, 9, 18, 5, 10, 11, 22, 10, 20, 21, 42, + }, { + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 2, 5, 5, 11, 4, 9, 9, 19, 5, 11, 11, 23, 10, 21, 21, 43, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 2, 5, 5, 11, 4, 9, 9, 19, 5, 11, 11, 23, 10, 21, 21, 43, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 2, 5, 5, 11, 4, 9, 9, 19, 5, 11, 11, 23, 10, 21, 21, 43, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 2, 5, 5, 11, 4, 9, 9, 19, 5, 11, 11, 23, 10, 21, 21, 43, + }, + { + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 2, 4, 4, 8, 5, 10, 10, 20, 5, 10, 10, 20, 11, 22, 22, 44, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 2, 4, 4, 8, 5, 10, 10, 20, 5, 10, 10, 20, 11, 22, 22, 44, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 2, 4, 4, 8, 5, 10, 10, 20, 5, 10, 10, 20, 11, 22, 22, 44, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 2, 4, 4, 8, 5, 10, 10, 20, 5, 10, 10, 20, 11, 22, 22, 44, + }, { + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 2, 5, 4, 9, 5, 11, 10, 21, 5, 11, 10, 21, 11, 23, 22, 45, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 2, 5, 4, 9, 5, 11, 10, 21, 5, 11, 10, 21, 11, 23, 22, 45, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 2, 5, 4, 9, 5, 11, 10, 21, 5, 11, 10, 21, 11, 23, 22, 45, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 2, 5, 4, 9, 5, 11, 10, 21, 5, 11, 10, 21, 11, 23, 22, 45, + }, { + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 2, 4, 5, 10, 5, 10, 11, 22, 5, 10, 11, 22, 11, 22, 23, 46, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 2, 4, 5, 10, 5, 10, 11, 22, 5, 10, 11, 22, 11, 22, 23, 46, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 2, 4, 5, 10, 5, 10, 11, 22, 5, 10, 11, 22, 11, 22, 23, 46, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 2, 4, 5, 10, 5, 10, 11, 22, 5, 10, 11, 22, 11, 22, 23, 46, + }, { + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 2, 5, 5, 11, 5, 11, 11, 23, 5, 11, 11, 23, 11, 23, 23, 47, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 2, 5, 5, 11, 5, 11, 11, 23, 5, 11, 11, 23, 11, 23, 23, 47, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 2, 5, 5, 11, 5, 11, 11, 23, 5, 11, 11, 23, 11, 23, 23, 47, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 2, 5, 5, 11, 5, 11, 11, 23, 5, 11, 11, 23, 11, 23, 23, 47, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 3, 6, 6, 12, 6, 12, 12, 24, 6, 12, 12, 24, 12, 24, 24, 48, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 3, 6, 6, 12, 6, 12, 12, 24, 6, 12, 12, 24, 12, 24, 24, 48, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 3, 6, 6, 12, 6, 12, 12, 24, 6, 12, 12, 24, 12, 24, 24, 48, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 3, 6, 6, 12, 6, 12, 12, 24, 6, 12, 12, 24, 12, 24, 24, 48, + }, { + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 3, 7, 6, 13, 6, 13, 12, 25, 6, 13, 12, 25, 12, 25, 24, 49, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 3, 7, 6, 13, 6, 13, 12, 25, 6, 13, 12, 25, 12, 25, 24, 49, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 3, 7, 6, 13, 6, 13, 12, 25, 6, 13, 12, 25, 12, 25, 24, 49, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 3, 7, 6, 13, 6, 13, 12, 25, 6, 13, 12, 25, 12, 25, 24, 49, + }, { + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 3, 6, 7, 14, 6, 12, 13, 26, 6, 12, 13, 26, 12, 24, 25, 50, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 3, 6, 7, 14, 6, 12, 13, 26, 6, 12, 13, 26, 12, 24, 25, 50, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 3, 6, 7, 14, 6, 12, 13, 26, 6, 12, 13, 26, 12, 24, 25, 50, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 3, 6, 7, 14, 6, 12, 13, 26, 6, 12, 13, 26, 12, 24, 25, 50, + }, { + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 3, 7, 7, 15, 6, 13, 13, 27, 6, 13, 13, 27, 12, 25, 25, 51, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 3, 7, 7, 15, 6, 13, 13, 27, 6, 13, 13, 27, 12, 25, 25, 51, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 3, 7, 7, 15, 6, 13, 13, 27, 6, 13, 13, 27, 12, 25, 25, 51, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 3, 7, 7, 15, 6, 13, 13, 27, 6, 13, 13, 27, 12, 25, 25, 51, + }, + { + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 3, 6, 6, 12, 7, 14, 14, 28, 6, 12, 12, 24, 13, 26, 26, 52, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 3, 6, 6, 12, 7, 14, 14, 28, 6, 12, 12, 24, 13, 26, 26, 52, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 3, 6, 6, 12, 7, 14, 14, 28, 6, 12, 12, 24, 13, 26, 26, 52, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 3, 6, 6, 12, 7, 14, 14, 28, 6, 12, 12, 24, 13, 26, 26, 52, + }, { + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 3, 7, 6, 13, 7, 15, 14, 29, 6, 13, 12, 25, 13, 27, 26, 53, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 3, 7, 6, 13, 7, 15, 14, 29, 6, 13, 12, 25, 13, 27, 26, 53, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 3, 7, 6, 13, 7, 15, 14, 29, 6, 13, 12, 25, 13, 27, 26, 53, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 3, 7, 6, 13, 7, 15, 14, 29, 6, 13, 12, 25, 13, 27, 26, 53, + }, { + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 3, 6, 7, 14, 7, 14, 15, 30, 6, 12, 13, 26, 13, 26, 27, 54, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 3, 6, 7, 14, 7, 14, 15, 30, 6, 12, 13, 26, 13, 26, 27, 54, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 3, 6, 7, 14, 7, 14, 15, 30, 6, 12, 13, 26, 13, 26, 27, 54, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 3, 6, 7, 14, 7, 14, 15, 30, 6, 12, 13, 26, 13, 26, 27, 54, + }, { + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 3, 7, 7, 15, 7, 15, 15, 31, 6, 13, 13, 27, 13, 27, 27, 55, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 3, 7, 7, 15, 7, 15, 15, 31, 6, 13, 13, 27, 13, 27, 27, 55, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 3, 7, 7, 15, 7, 15, 15, 31, 6, 13, 13, 27, 13, 27, 27, 55, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 3, 7, 7, 15, 7, 15, 15, 31, 6, 13, 13, 27, 13, 27, 27, 55, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 3, 6, 6, 12, 6, 12, 12, 24, 7, 14, 14, 28, 14, 28, 28, 56, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 3, 6, 6, 12, 6, 12, 12, 24, 7, 14, 14, 28, 14, 28, 28, 56, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 3, 6, 6, 12, 6, 12, 12, 24, 7, 14, 14, 28, 14, 28, 28, 56, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 3, 6, 6, 12, 6, 12, 12, 24, 7, 14, 14, 28, 14, 28, 28, 56, + }, { + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 3, 7, 6, 13, 6, 13, 12, 25, 7, 15, 14, 29, 14, 29, 28, 57, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 3, 7, 6, 13, 6, 13, 12, 25, 7, 15, 14, 29, 14, 29, 28, 57, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 3, 7, 6, 13, 6, 13, 12, 25, 7, 15, 14, 29, 14, 29, 28, 57, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 3, 7, 6, 13, 6, 13, 12, 25, 7, 15, 14, 29, 14, 29, 28, 57, + }, { + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 3, 6, 7, 14, 6, 12, 13, 26, 7, 14, 15, 30, 14, 28, 29, 58, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 3, 6, 7, 14, 6, 12, 13, 26, 7, 14, 15, 30, 14, 28, 29, 58, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 3, 6, 7, 14, 6, 12, 13, 26, 7, 14, 15, 30, 14, 28, 29, 58, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 3, 6, 7, 14, 6, 12, 13, 26, 7, 14, 15, 30, 14, 28, 29, 58, + }, { + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 3, 7, 7, 15, 6, 13, 13, 27, 7, 15, 15, 31, 14, 29, 29, 59, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 3, 7, 7, 15, 6, 13, 13, 27, 7, 15, 15, 31, 14, 29, 29, 59, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 3, 7, 7, 15, 6, 13, 13, 27, 7, 15, 15, 31, 14, 29, 29, 59, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 3, 7, 7, 15, 6, 13, 13, 27, 7, 15, 15, 31, 14, 29, 29, 59, + }, + { + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 3, 6, 6, 12, 7, 14, 14, 28, 7, 14, 14, 28, 15, 30, 30, 60, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 3, 6, 6, 12, 7, 14, 14, 28, 7, 14, 14, 28, 15, 30, 30, 60, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 3, 6, 6, 12, 7, 14, 14, 28, 7, 14, 14, 28, 15, 30, 30, 60, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 3, 6, 6, 12, 7, 14, 14, 28, 7, 14, 14, 28, 15, 30, 30, 60, + }, { + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 3, 7, 6, 13, 7, 15, 14, 29, 7, 15, 14, 29, 15, 31, 30, 61, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 3, 7, 6, 13, 7, 15, 14, 29, 7, 15, 14, 29, 15, 31, 30, 61, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 3, 7, 6, 13, 7, 15, 14, 29, 7, 15, 14, 29, 15, 31, 30, 61, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 3, 7, 6, 13, 7, 15, 14, 29, 7, 15, 14, 29, 15, 31, 30, 61, + }, { + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 3, 6, 7, 14, 7, 14, 15, 30, 7, 14, 15, 30, 15, 30, 31, 62, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 3, 6, 7, 14, 7, 14, 15, 30, 7, 14, 15, 30, 15, 30, 31, 62, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 3, 6, 7, 14, 7, 14, 15, 30, 7, 14, 15, 30, 15, 30, 31, 62, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 3, 6, 7, 14, 7, 14, 15, 30, 7, 14, 15, 30, 15, 30, 31, 62, + }, { + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 3, 7, 7, 15, 7, 15, 15, 31, 7, 15, 15, 31, 15, 31, 31, 63, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 3, 7, 7, 15, 7, 15, 15, 31, 7, 15, 15, 31, 15, 31, 31, 63, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 3, 7, 7, 15, 7, 15, 15, 31, 7, 15, 15, 31, 15, 31, 31, 63, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 3, 7, 7, 15, 7, 15, 15, 31, 7, 15, 15, 31, 15, 31, 31, 63, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 2, 4, 4, 8, 4, 8, 8, 16, 4, 8, 8, 16, 8, 16, 16, 32, + 2, 4, 4, 8, 4, 8, 8, 16, 4, 8, 8, 16, 8, 16, 16, 32, + 4, 8, 8, 16, 8, 16, 16, 32, 8, 16, 16, 32, 16, 32, 32, 64, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 2, 4, 4, 8, 4, 8, 8, 16, 4, 8, 8, 16, 8, 16, 16, 32, + 2, 4, 4, 8, 4, 8, 8, 16, 4, 8, 8, 16, 8, 16, 16, 32, + 4, 8, 8, 16, 8, 16, 16, 32, 8, 16, 16, 32, 16, 32, 32, 64, + }, { + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 2, 5, 4, 9, 4, 9, 8, 17, 4, 9, 8, 17, 8, 17, 16, 33, + 2, 5, 4, 9, 4, 9, 8, 17, 4, 9, 8, 17, 8, 17, 16, 33, + 4, 9, 8, 17, 8, 17, 16, 33, 8, 17, 16, 33, 16, 33, 32, 65, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 2, 5, 4, 9, 4, 9, 8, 17, 4, 9, 8, 17, 8, 17, 16, 33, + 2, 5, 4, 9, 4, 9, 8, 17, 4, 9, 8, 17, 8, 17, 16, 33, + 4, 9, 8, 17, 8, 17, 16, 33, 8, 17, 16, 33, 16, 33, 32, 65, + }, { + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 2, 4, 5, 10, 4, 8, 9, 18, 4, 8, 9, 18, 8, 16, 17, 34, + 2, 4, 5, 10, 4, 8, 9, 18, 4, 8, 9, 18, 8, 16, 17, 34, + 4, 8, 9, 18, 8, 16, 17, 34, 8, 16, 17, 34, 16, 32, 33, 66, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 2, 4, 5, 10, 4, 8, 9, 18, 4, 8, 9, 18, 8, 16, 17, 34, + 2, 4, 5, 10, 4, 8, 9, 18, 4, 8, 9, 18, 8, 16, 17, 34, + 4, 8, 9, 18, 8, 16, 17, 34, 8, 16, 17, 34, 16, 32, 33, 66, + }, { + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 2, 5, 5, 11, 4, 9, 9, 19, 4, 9, 9, 19, 8, 17, 17, 35, + 2, 5, 5, 11, 4, 9, 9, 19, 4, 9, 9, 19, 8, 17, 17, 35, + 4, 9, 9, 19, 8, 17, 17, 35, 8, 17, 17, 35, 16, 33, 33, 67, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 2, 5, 5, 11, 4, 9, 9, 19, 4, 9, 9, 19, 8, 17, 17, 35, + 2, 5, 5, 11, 4, 9, 9, 19, 4, 9, 9, 19, 8, 17, 17, 35, + 4, 9, 9, 19, 8, 17, 17, 35, 8, 17, 17, 35, 16, 33, 33, 67, + }, + { + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 2, 4, 4, 8, 5, 10, 10, 20, 4, 8, 8, 16, 9, 18, 18, 36, + 2, 4, 4, 8, 5, 10, 10, 20, 4, 8, 8, 16, 9, 18, 18, 36, + 4, 8, 8, 16, 9, 18, 18, 36, 8, 16, 16, 32, 17, 34, 34, 68, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 2, 4, 4, 8, 5, 10, 10, 20, 4, 8, 8, 16, 9, 18, 18, 36, + 2, 4, 4, 8, 5, 10, 10, 20, 4, 8, 8, 16, 9, 18, 18, 36, + 4, 8, 8, 16, 9, 18, 18, 36, 8, 16, 16, 32, 17, 34, 34, 68, + }, { + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 2, 5, 4, 9, 5, 11, 10, 21, 4, 9, 8, 17, 9, 19, 18, 37, + 2, 5, 4, 9, 5, 11, 10, 21, 4, 9, 8, 17, 9, 19, 18, 37, + 4, 9, 8, 17, 9, 19, 18, 37, 8, 17, 16, 33, 17, 35, 34, 69, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 2, 5, 4, 9, 5, 11, 10, 21, 4, 9, 8, 17, 9, 19, 18, 37, + 2, 5, 4, 9, 5, 11, 10, 21, 4, 9, 8, 17, 9, 19, 18, 37, + 4, 9, 8, 17, 9, 19, 18, 37, 8, 17, 16, 33, 17, 35, 34, 69, + }, { + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 2, 4, 5, 10, 5, 10, 11, 22, 4, 8, 9, 18, 9, 18, 19, 38, + 2, 4, 5, 10, 5, 10, 11, 22, 4, 8, 9, 18, 9, 18, 19, 38, + 4, 8, 9, 18, 9, 18, 19, 38, 8, 16, 17, 34, 17, 34, 35, 70, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 2, 4, 5, 10, 5, 10, 11, 22, 4, 8, 9, 18, 9, 18, 19, 38, + 2, 4, 5, 10, 5, 10, 11, 22, 4, 8, 9, 18, 9, 18, 19, 38, + 4, 8, 9, 18, 9, 18, 19, 38, 8, 16, 17, 34, 17, 34, 35, 70, + }, { + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 2, 5, 5, 11, 5, 11, 11, 23, 4, 9, 9, 19, 9, 19, 19, 39, + 2, 5, 5, 11, 5, 11, 11, 23, 4, 9, 9, 19, 9, 19, 19, 39, + 4, 9, 9, 19, 9, 19, 19, 39, 8, 17, 17, 35, 17, 35, 35, 71, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 2, 5, 5, 11, 5, 11, 11, 23, 4, 9, 9, 19, 9, 19, 19, 39, + 2, 5, 5, 11, 5, 11, 11, 23, 4, 9, 9, 19, 9, 19, 19, 39, + 4, 9, 9, 19, 9, 19, 19, 39, 8, 17, 17, 35, 17, 35, 35, 71, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 2, 4, 4, 8, 4, 8, 8, 16, 5, 10, 10, 20, 10, 20, 20, 40, + 2, 4, 4, 8, 4, 8, 8, 16, 5, 10, 10, 20, 10, 20, 20, 40, + 4, 8, 8, 16, 8, 16, 16, 32, 9, 18, 18, 36, 18, 36, 36, 72, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 2, 4, 4, 8, 4, 8, 8, 16, 5, 10, 10, 20, 10, 20, 20, 40, + 2, 4, 4, 8, 4, 8, 8, 16, 5, 10, 10, 20, 10, 20, 20, 40, + 4, 8, 8, 16, 8, 16, 16, 32, 9, 18, 18, 36, 18, 36, 36, 72, + }, { + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 2, 5, 4, 9, 4, 9, 8, 17, 5, 11, 10, 21, 10, 21, 20, 41, + 2, 5, 4, 9, 4, 9, 8, 17, 5, 11, 10, 21, 10, 21, 20, 41, + 4, 9, 8, 17, 8, 17, 16, 33, 9, 19, 18, 37, 18, 37, 36, 73, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 2, 5, 4, 9, 4, 9, 8, 17, 5, 11, 10, 21, 10, 21, 20, 41, + 2, 5, 4, 9, 4, 9, 8, 17, 5, 11, 10, 21, 10, 21, 20, 41, + 4, 9, 8, 17, 8, 17, 16, 33, 9, 19, 18, 37, 18, 37, 36, 73, + }, { + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 2, 4, 5, 10, 4, 8, 9, 18, 5, 10, 11, 22, 10, 20, 21, 42, + 2, 4, 5, 10, 4, 8, 9, 18, 5, 10, 11, 22, 10, 20, 21, 42, + 4, 8, 9, 18, 8, 16, 17, 34, 9, 18, 19, 38, 18, 36, 37, 74, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 2, 4, 5, 10, 4, 8, 9, 18, 5, 10, 11, 22, 10, 20, 21, 42, + 2, 4, 5, 10, 4, 8, 9, 18, 5, 10, 11, 22, 10, 20, 21, 42, + 4, 8, 9, 18, 8, 16, 17, 34, 9, 18, 19, 38, 18, 36, 37, 74, + }, { + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 2, 5, 5, 11, 4, 9, 9, 19, 5, 11, 11, 23, 10, 21, 21, 43, + 2, 5, 5, 11, 4, 9, 9, 19, 5, 11, 11, 23, 10, 21, 21, 43, + 4, 9, 9, 19, 8, 17, 17, 35, 9, 19, 19, 39, 18, 37, 37, 75, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 2, 5, 5, 11, 4, 9, 9, 19, 5, 11, 11, 23, 10, 21, 21, 43, + 2, 5, 5, 11, 4, 9, 9, 19, 5, 11, 11, 23, 10, 21, 21, 43, + 4, 9, 9, 19, 8, 17, 17, 35, 9, 19, 19, 39, 18, 37, 37, 75, + }, + { + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 2, 4, 4, 8, 5, 10, 10, 20, 5, 10, 10, 20, 11, 22, 22, 44, + 2, 4, 4, 8, 5, 10, 10, 20, 5, 10, 10, 20, 11, 22, 22, 44, + 4, 8, 8, 16, 9, 18, 18, 36, 9, 18, 18, 36, 19, 38, 38, 76, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 2, 4, 4, 8, 5, 10, 10, 20, 5, 10, 10, 20, 11, 22, 22, 44, + 2, 4, 4, 8, 5, 10, 10, 20, 5, 10, 10, 20, 11, 22, 22, 44, + 4, 8, 8, 16, 9, 18, 18, 36, 9, 18, 18, 36, 19, 38, 38, 76, + }, { + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 2, 5, 4, 9, 5, 11, 10, 21, 5, 11, 10, 21, 11, 23, 22, 45, + 2, 5, 4, 9, 5, 11, 10, 21, 5, 11, 10, 21, 11, 23, 22, 45, + 4, 9, 8, 17, 9, 19, 18, 37, 9, 19, 18, 37, 19, 39, 38, 77, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 2, 5, 4, 9, 5, 11, 10, 21, 5, 11, 10, 21, 11, 23, 22, 45, + 2, 5, 4, 9, 5, 11, 10, 21, 5, 11, 10, 21, 11, 23, 22, 45, + 4, 9, 8, 17, 9, 19, 18, 37, 9, 19, 18, 37, 19, 39, 38, 77, + }, { + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 2, 4, 5, 10, 5, 10, 11, 22, 5, 10, 11, 22, 11, 22, 23, 46, + 2, 4, 5, 10, 5, 10, 11, 22, 5, 10, 11, 22, 11, 22, 23, 46, + 4, 8, 9, 18, 9, 18, 19, 38, 9, 18, 19, 38, 19, 38, 39, 78, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 2, 4, 5, 10, 5, 10, 11, 22, 5, 10, 11, 22, 11, 22, 23, 46, + 2, 4, 5, 10, 5, 10, 11, 22, 5, 10, 11, 22, 11, 22, 23, 46, + 4, 8, 9, 18, 9, 18, 19, 38, 9, 18, 19, 38, 19, 38, 39, 78, + }, { + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 2, 5, 5, 11, 5, 11, 11, 23, 5, 11, 11, 23, 11, 23, 23, 47, + 2, 5, 5, 11, 5, 11, 11, 23, 5, 11, 11, 23, 11, 23, 23, 47, + 4, 9, 9, 19, 9, 19, 19, 39, 9, 19, 19, 39, 19, 39, 39, 79, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 2, 5, 5, 11, 5, 11, 11, 23, 5, 11, 11, 23, 11, 23, 23, 47, + 2, 5, 5, 11, 5, 11, 11, 23, 5, 11, 11, 23, 11, 23, 23, 47, + 4, 9, 9, 19, 9, 19, 19, 39, 9, 19, 19, 39, 19, 39, 39, 79, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 3, 6, 6, 12, 6, 12, 12, 24, 6, 12, 12, 24, 12, 24, 24, 48, + 2, 4, 4, 8, 4, 8, 8, 16, 4, 8, 8, 16, 8, 16, 16, 32, + 5, 10, 10, 20, 10, 20, 20, 40, 10, 20, 20, 40, 20, 40, 40, 80, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 3, 6, 6, 12, 6, 12, 12, 24, 6, 12, 12, 24, 12, 24, 24, 48, + 2, 4, 4, 8, 4, 8, 8, 16, 4, 8, 8, 16, 8, 16, 16, 32, + 5, 10, 10, 20, 10, 20, 20, 40, 10, 20, 20, 40, 20, 40, 40, 80, + }, { + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 3, 7, 6, 13, 6, 13, 12, 25, 6, 13, 12, 25, 12, 25, 24, 49, + 2, 5, 4, 9, 4, 9, 8, 17, 4, 9, 8, 17, 8, 17, 16, 33, + 5, 11, 10, 21, 10, 21, 20, 41, 10, 21, 20, 41, 20, 41, 40, 81, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 3, 7, 6, 13, 6, 13, 12, 25, 6, 13, 12, 25, 12, 25, 24, 49, + 2, 5, 4, 9, 4, 9, 8, 17, 4, 9, 8, 17, 8, 17, 16, 33, + 5, 11, 10, 21, 10, 21, 20, 41, 10, 21, 20, 41, 20, 41, 40, 81, + }, { + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 3, 6, 7, 14, 6, 12, 13, 26, 6, 12, 13, 26, 12, 24, 25, 50, + 2, 4, 5, 10, 4, 8, 9, 18, 4, 8, 9, 18, 8, 16, 17, 34, + 5, 10, 11, 22, 10, 20, 21, 42, 10, 20, 21, 42, 20, 40, 41, 82, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 3, 6, 7, 14, 6, 12, 13, 26, 6, 12, 13, 26, 12, 24, 25, 50, + 2, 4, 5, 10, 4, 8, 9, 18, 4, 8, 9, 18, 8, 16, 17, 34, + 5, 10, 11, 22, 10, 20, 21, 42, 10, 20, 21, 42, 20, 40, 41, 82, + }, { + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 3, 7, 7, 15, 6, 13, 13, 27, 6, 13, 13, 27, 12, 25, 25, 51, + 2, 5, 5, 11, 4, 9, 9, 19, 4, 9, 9, 19, 8, 17, 17, 35, + 5, 11, 11, 23, 10, 21, 21, 43, 10, 21, 21, 43, 20, 41, 41, 83, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 3, 7, 7, 15, 6, 13, 13, 27, 6, 13, 13, 27, 12, 25, 25, 51, + 2, 5, 5, 11, 4, 9, 9, 19, 4, 9, 9, 19, 8, 17, 17, 35, + 5, 11, 11, 23, 10, 21, 21, 43, 10, 21, 21, 43, 20, 41, 41, 83, + }, + { + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 3, 6, 6, 12, 7, 14, 14, 28, 6, 12, 12, 24, 13, 26, 26, 52, + 2, 4, 4, 8, 5, 10, 10, 20, 4, 8, 8, 16, 9, 18, 18, 36, + 5, 10, 10, 20, 11, 22, 22, 44, 10, 20, 20, 40, 21, 42, 42, 84, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 3, 6, 6, 12, 7, 14, 14, 28, 6, 12, 12, 24, 13, 26, 26, 52, + 2, 4, 4, 8, 5, 10, 10, 20, 4, 8, 8, 16, 9, 18, 18, 36, + 5, 10, 10, 20, 11, 22, 22, 44, 10, 20, 20, 40, 21, 42, 42, 84, + }, { + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 3, 7, 6, 13, 7, 15, 14, 29, 6, 13, 12, 25, 13, 27, 26, 53, + 2, 5, 4, 9, 5, 11, 10, 21, 4, 9, 8, 17, 9, 19, 18, 37, + 5, 11, 10, 21, 11, 23, 22, 45, 10, 21, 20, 41, 21, 43, 42, 85, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 3, 7, 6, 13, 7, 15, 14, 29, 6, 13, 12, 25, 13, 27, 26, 53, + 2, 5, 4, 9, 5, 11, 10, 21, 4, 9, 8, 17, 9, 19, 18, 37, + 5, 11, 10, 21, 11, 23, 22, 45, 10, 21, 20, 41, 21, 43, 42, 85, + }, { + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 3, 6, 7, 14, 7, 14, 15, 30, 6, 12, 13, 26, 13, 26, 27, 54, + 2, 4, 5, 10, 5, 10, 11, 22, 4, 8, 9, 18, 9, 18, 19, 38, + 5, 10, 11, 22, 11, 22, 23, 46, 10, 20, 21, 42, 21, 42, 43, 86, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 3, 6, 7, 14, 7, 14, 15, 30, 6, 12, 13, 26, 13, 26, 27, 54, + 2, 4, 5, 10, 5, 10, 11, 22, 4, 8, 9, 18, 9, 18, 19, 38, + 5, 10, 11, 22, 11, 22, 23, 46, 10, 20, 21, 42, 21, 42, 43, 86, + }, { + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 3, 7, 7, 15, 7, 15, 15, 31, 6, 13, 13, 27, 13, 27, 27, 55, + 2, 5, 5, 11, 5, 11, 11, 23, 4, 9, 9, 19, 9, 19, 19, 39, + 5, 11, 11, 23, 11, 23, 23, 47, 10, 21, 21, 43, 21, 43, 43, 87, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 3, 7, 7, 15, 7, 15, 15, 31, 6, 13, 13, 27, 13, 27, 27, 55, + 2, 5, 5, 11, 5, 11, 11, 23, 4, 9, 9, 19, 9, 19, 19, 39, + 5, 11, 11, 23, 11, 23, 23, 47, 10, 21, 21, 43, 21, 43, 43, 87, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 3, 6, 6, 12, 6, 12, 12, 24, 7, 14, 14, 28, 14, 28, 28, 56, + 2, 4, 4, 8, 4, 8, 8, 16, 5, 10, 10, 20, 10, 20, 20, 40, + 5, 10, 10, 20, 10, 20, 20, 40, 11, 22, 22, 44, 22, 44, 44, 88, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 3, 6, 6, 12, 6, 12, 12, 24, 7, 14, 14, 28, 14, 28, 28, 56, + 2, 4, 4, 8, 4, 8, 8, 16, 5, 10, 10, 20, 10, 20, 20, 40, + 5, 10, 10, 20, 10, 20, 20, 40, 11, 22, 22, 44, 22, 44, 44, 88, + }, { + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 3, 7, 6, 13, 6, 13, 12, 25, 7, 15, 14, 29, 14, 29, 28, 57, + 2, 5, 4, 9, 4, 9, 8, 17, 5, 11, 10, 21, 10, 21, 20, 41, + 5, 11, 10, 21, 10, 21, 20, 41, 11, 23, 22, 45, 22, 45, 44, 89, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 3, 7, 6, 13, 6, 13, 12, 25, 7, 15, 14, 29, 14, 29, 28, 57, + 2, 5, 4, 9, 4, 9, 8, 17, 5, 11, 10, 21, 10, 21, 20, 41, + 5, 11, 10, 21, 10, 21, 20, 41, 11, 23, 22, 45, 22, 45, 44, 89, + }, { + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 3, 6, 7, 14, 6, 12, 13, 26, 7, 14, 15, 30, 14, 28, 29, 58, + 2, 4, 5, 10, 4, 8, 9, 18, 5, 10, 11, 22, 10, 20, 21, 42, + 5, 10, 11, 22, 10, 20, 21, 42, 11, 22, 23, 46, 22, 44, 45, 90, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 3, 6, 7, 14, 6, 12, 13, 26, 7, 14, 15, 30, 14, 28, 29, 58, + 2, 4, 5, 10, 4, 8, 9, 18, 5, 10, 11, 22, 10, 20, 21, 42, + 5, 10, 11, 22, 10, 20, 21, 42, 11, 22, 23, 46, 22, 44, 45, 90, + }, { + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 3, 7, 7, 15, 6, 13, 13, 27, 7, 15, 15, 31, 14, 29, 29, 59, + 2, 5, 5, 11, 4, 9, 9, 19, 5, 11, 11, 23, 10, 21, 21, 43, + 5, 11, 11, 23, 10, 21, 21, 43, 11, 23, 23, 47, 22, 45, 45, 91, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 3, 7, 7, 15, 6, 13, 13, 27, 7, 15, 15, 31, 14, 29, 29, 59, + 2, 5, 5, 11, 4, 9, 9, 19, 5, 11, 11, 23, 10, 21, 21, 43, + 5, 11, 11, 23, 10, 21, 21, 43, 11, 23, 23, 47, 22, 45, 45, 91, + }, + { + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 3, 6, 6, 12, 7, 14, 14, 28, 7, 14, 14, 28, 15, 30, 30, 60, + 2, 4, 4, 8, 5, 10, 10, 20, 5, 10, 10, 20, 11, 22, 22, 44, + 5, 10, 10, 20, 11, 22, 22, 44, 11, 22, 22, 44, 23, 46, 46, 92, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 3, 6, 6, 12, 7, 14, 14, 28, 7, 14, 14, 28, 15, 30, 30, 60, + 2, 4, 4, 8, 5, 10, 10, 20, 5, 10, 10, 20, 11, 22, 22, 44, + 5, 10, 10, 20, 11, 22, 22, 44, 11, 22, 22, 44, 23, 46, 46, 92, + }, { + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 3, 7, 6, 13, 7, 15, 14, 29, 7, 15, 14, 29, 15, 31, 30, 61, + 2, 5, 4, 9, 5, 11, 10, 21, 5, 11, 10, 21, 11, 23, 22, 45, + 5, 11, 10, 21, 11, 23, 22, 45, 11, 23, 22, 45, 23, 47, 46, 93, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 3, 7, 6, 13, 7, 15, 14, 29, 7, 15, 14, 29, 15, 31, 30, 61, + 2, 5, 4, 9, 5, 11, 10, 21, 5, 11, 10, 21, 11, 23, 22, 45, + 5, 11, 10, 21, 11, 23, 22, 45, 11, 23, 22, 45, 23, 47, 46, 93, + }, { + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 3, 6, 7, 14, 7, 14, 15, 30, 7, 14, 15, 30, 15, 30, 31, 62, + 2, 4, 5, 10, 5, 10, 11, 22, 5, 10, 11, 22, 11, 22, 23, 46, + 5, 10, 11, 22, 11, 22, 23, 46, 11, 22, 23, 46, 23, 46, 47, 94, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 3, 6, 7, 14, 7, 14, 15, 30, 7, 14, 15, 30, 15, 30, 31, 62, + 2, 4, 5, 10, 5, 10, 11, 22, 5, 10, 11, 22, 11, 22, 23, 46, + 5, 10, 11, 22, 11, 22, 23, 46, 11, 22, 23, 46, 23, 46, 47, 94, + }, { + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 3, 7, 7, 15, 7, 15, 15, 31, 7, 15, 15, 31, 15, 31, 31, 63, + 2, 5, 5, 11, 5, 11, 11, 23, 5, 11, 11, 23, 11, 23, 23, 47, + 5, 11, 11, 23, 11, 23, 23, 47, 11, 23, 23, 47, 23, 47, 47, 95, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 3, 7, 7, 15, 7, 15, 15, 31, 7, 15, 15, 31, 15, 31, 31, 63, + 2, 5, 5, 11, 5, 11, 11, 23, 5, 11, 11, 23, 11, 23, 23, 47, + 5, 11, 11, 23, 11, 23, 23, 47, 11, 23, 23, 47, 23, 47, 47, 95, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 2, 4, 4, 8, 4, 8, 8, 16, 4, 8, 8, 16, 8, 16, 16, 32, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 2, 4, 4, 8, 4, 8, 8, 16, 4, 8, 8, 16, 8, 16, 16, 32, + 3, 6, 6, 12, 6, 12, 12, 24, 6, 12, 12, 24, 12, 24, 24, 48, + 6, 12, 12, 24, 12, 24, 24, 48, 12, 24, 24, 48, 24, 48, 48, 96, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 2, 4, 4, 8, 4, 8, 8, 16, 4, 8, 8, 16, 8, 16, 16, 32, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 2, 4, 4, 8, 4, 8, 8, 16, 4, 8, 8, 16, 8, 16, 16, 32, + 3, 6, 6, 12, 6, 12, 12, 24, 6, 12, 12, 24, 12, 24, 24, 48, + 6, 12, 12, 24, 12, 24, 24, 48, 12, 24, 24, 48, 24, 48, 48, 96, + }, { + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 2, 5, 4, 9, 4, 9, 8, 17, 4, 9, 8, 17, 8, 17, 16, 33, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 2, 5, 4, 9, 4, 9, 8, 17, 4, 9, 8, 17, 8, 17, 16, 33, + 3, 7, 6, 13, 6, 13, 12, 25, 6, 13, 12, 25, 12, 25, 24, 49, + 6, 13, 12, 25, 12, 25, 24, 49, 12, 25, 24, 49, 24, 49, 48, 97, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 2, 5, 4, 9, 4, 9, 8, 17, 4, 9, 8, 17, 8, 17, 16, 33, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 2, 5, 4, 9, 4, 9, 8, 17, 4, 9, 8, 17, 8, 17, 16, 33, + 3, 7, 6, 13, 6, 13, 12, 25, 6, 13, 12, 25, 12, 25, 24, 49, + 6, 13, 12, 25, 12, 25, 24, 49, 12, 25, 24, 49, 24, 49, 48, 97, + }, { + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 2, 4, 5, 10, 4, 8, 9, 18, 4, 8, 9, 18, 8, 16, 17, 34, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 2, 4, 5, 10, 4, 8, 9, 18, 4, 8, 9, 18, 8, 16, 17, 34, + 3, 6, 7, 14, 6, 12, 13, 26, 6, 12, 13, 26, 12, 24, 25, 50, + 6, 12, 13, 26, 12, 24, 25, 50, 12, 24, 25, 50, 24, 48, 49, 98, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 2, 4, 5, 10, 4, 8, 9, 18, 4, 8, 9, 18, 8, 16, 17, 34, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 2, 4, 5, 10, 4, 8, 9, 18, 4, 8, 9, 18, 8, 16, 17, 34, + 3, 6, 7, 14, 6, 12, 13, 26, 6, 12, 13, 26, 12, 24, 25, 50, + 6, 12, 13, 26, 12, 24, 25, 50, 12, 24, 25, 50, 24, 48, 49, 98, + }, { + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 2, 5, 5, 11, 4, 9, 9, 19, 4, 9, 9, 19, 8, 17, 17, 35, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 2, 5, 5, 11, 4, 9, 9, 19, 4, 9, 9, 19, 8, 17, 17, 35, + 3, 7, 7, 15, 6, 13, 13, 27, 6, 13, 13, 27, 12, 25, 25, 51, + 6, 13, 13, 27, 12, 25, 25, 51, 12, 25, 25, 51, 24, 49, 49, 99, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 2, 5, 5, 11, 4, 9, 9, 19, 4, 9, 9, 19, 8, 17, 17, 35, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 2, 5, 5, 11, 4, 9, 9, 19, 4, 9, 9, 19, 8, 17, 17, 35, + 3, 7, 7, 15, 6, 13, 13, 27, 6, 13, 13, 27, 12, 25, 25, 51, + 6, 13, 13, 27, 12, 25, 25, 51, 12, 25, 25, 51, 24, 49, 49, 99, + }, + { + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 2, 4, 4, 8, 5, 10, 10, 20, 4, 8, 8, 16, 9, 18, 18, 36, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 2, 4, 4, 8, 5, 10, 10, 20, 4, 8, 8, 16, 9, 18, 18, 36, + 3, 6, 6, 12, 7, 14, 14, 28, 6, 12, 12, 24, 13, 26, 26, 52, + 6, 12, 12, 24, 13, 26, 26, 52, 12, 24, 24, 48, 25, 50, 50, 100, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 2, 4, 4, 8, 5, 10, 10, 20, 4, 8, 8, 16, 9, 18, 18, 36, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 2, 4, 4, 8, 5, 10, 10, 20, 4, 8, 8, 16, 9, 18, 18, 36, + 3, 6, 6, 12, 7, 14, 14, 28, 6, 12, 12, 24, 13, 26, 26, 52, + 6, 12, 12, 24, 13, 26, 26, 52, 12, 24, 24, 48, 25, 50, 50, 100, + }, { + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 2, 5, 4, 9, 5, 11, 10, 21, 4, 9, 8, 17, 9, 19, 18, 37, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 2, 5, 4, 9, 5, 11, 10, 21, 4, 9, 8, 17, 9, 19, 18, 37, + 3, 7, 6, 13, 7, 15, 14, 29, 6, 13, 12, 25, 13, 27, 26, 53, + 6, 13, 12, 25, 13, 27, 26, 53, 12, 25, 24, 49, 25, 51, 50, 101, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 2, 5, 4, 9, 5, 11, 10, 21, 4, 9, 8, 17, 9, 19, 18, 37, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 2, 5, 4, 9, 5, 11, 10, 21, 4, 9, 8, 17, 9, 19, 18, 37, + 3, 7, 6, 13, 7, 15, 14, 29, 6, 13, 12, 25, 13, 27, 26, 53, + 6, 13, 12, 25, 13, 27, 26, 53, 12, 25, 24, 49, 25, 51, 50, 101, + }, { + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 2, 4, 5, 10, 5, 10, 11, 22, 4, 8, 9, 18, 9, 18, 19, 38, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 2, 4, 5, 10, 5, 10, 11, 22, 4, 8, 9, 18, 9, 18, 19, 38, + 3, 6, 7, 14, 7, 14, 15, 30, 6, 12, 13, 26, 13, 26, 27, 54, + 6, 12, 13, 26, 13, 26, 27, 54, 12, 24, 25, 50, 25, 50, 51, 102, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 2, 4, 5, 10, 5, 10, 11, 22, 4, 8, 9, 18, 9, 18, 19, 38, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 2, 4, 5, 10, 5, 10, 11, 22, 4, 8, 9, 18, 9, 18, 19, 38, + 3, 6, 7, 14, 7, 14, 15, 30, 6, 12, 13, 26, 13, 26, 27, 54, + 6, 12, 13, 26, 13, 26, 27, 54, 12, 24, 25, 50, 25, 50, 51, 102, + }, { + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 2, 5, 5, 11, 5, 11, 11, 23, 4, 9, 9, 19, 9, 19, 19, 39, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 2, 5, 5, 11, 5, 11, 11, 23, 4, 9, 9, 19, 9, 19, 19, 39, + 3, 7, 7, 15, 7, 15, 15, 31, 6, 13, 13, 27, 13, 27, 27, 55, + 6, 13, 13, 27, 13, 27, 27, 55, 12, 25, 25, 51, 25, 51, 51, 103, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 2, 5, 5, 11, 5, 11, 11, 23, 4, 9, 9, 19, 9, 19, 19, 39, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 2, 5, 5, 11, 5, 11, 11, 23, 4, 9, 9, 19, 9, 19, 19, 39, + 3, 7, 7, 15, 7, 15, 15, 31, 6, 13, 13, 27, 13, 27, 27, 55, + 6, 13, 13, 27, 13, 27, 27, 55, 12, 25, 25, 51, 25, 51, 51, 103, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 2, 4, 4, 8, 4, 8, 8, 16, 5, 10, 10, 20, 10, 20, 20, 40, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 2, 4, 4, 8, 4, 8, 8, 16, 5, 10, 10, 20, 10, 20, 20, 40, + 3, 6, 6, 12, 6, 12, 12, 24, 7, 14, 14, 28, 14, 28, 28, 56, + 6, 12, 12, 24, 12, 24, 24, 48, 13, 26, 26, 52, 26, 52, 52, 104, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 2, 4, 4, 8, 4, 8, 8, 16, 5, 10, 10, 20, 10, 20, 20, 40, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 2, 4, 4, 8, 4, 8, 8, 16, 5, 10, 10, 20, 10, 20, 20, 40, + 3, 6, 6, 12, 6, 12, 12, 24, 7, 14, 14, 28, 14, 28, 28, 56, + 6, 12, 12, 24, 12, 24, 24, 48, 13, 26, 26, 52, 26, 52, 52, 104, + }, { + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 2, 5, 4, 9, 4, 9, 8, 17, 5, 11, 10, 21, 10, 21, 20, 41, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 2, 5, 4, 9, 4, 9, 8, 17, 5, 11, 10, 21, 10, 21, 20, 41, + 3, 7, 6, 13, 6, 13, 12, 25, 7, 15, 14, 29, 14, 29, 28, 57, + 6, 13, 12, 25, 12, 25, 24, 49, 13, 27, 26, 53, 26, 53, 52, 105, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 2, 5, 4, 9, 4, 9, 8, 17, 5, 11, 10, 21, 10, 21, 20, 41, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 2, 5, 4, 9, 4, 9, 8, 17, 5, 11, 10, 21, 10, 21, 20, 41, + 3, 7, 6, 13, 6, 13, 12, 25, 7, 15, 14, 29, 14, 29, 28, 57, + 6, 13, 12, 25, 12, 25, 24, 49, 13, 27, 26, 53, 26, 53, 52, 105, + }, { + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 2, 4, 5, 10, 4, 8, 9, 18, 5, 10, 11, 22, 10, 20, 21, 42, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 2, 4, 5, 10, 4, 8, 9, 18, 5, 10, 11, 22, 10, 20, 21, 42, + 3, 6, 7, 14, 6, 12, 13, 26, 7, 14, 15, 30, 14, 28, 29, 58, + 6, 12, 13, 26, 12, 24, 25, 50, 13, 26, 27, 54, 26, 52, 53, 106, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 2, 4, 5, 10, 4, 8, 9, 18, 5, 10, 11, 22, 10, 20, 21, 42, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 2, 4, 5, 10, 4, 8, 9, 18, 5, 10, 11, 22, 10, 20, 21, 42, + 3, 6, 7, 14, 6, 12, 13, 26, 7, 14, 15, 30, 14, 28, 29, 58, + 6, 12, 13, 26, 12, 24, 25, 50, 13, 26, 27, 54, 26, 52, 53, 106, + }, { + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 2, 5, 5, 11, 4, 9, 9, 19, 5, 11, 11, 23, 10, 21, 21, 43, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 2, 5, 5, 11, 4, 9, 9, 19, 5, 11, 11, 23, 10, 21, 21, 43, + 3, 7, 7, 15, 6, 13, 13, 27, 7, 15, 15, 31, 14, 29, 29, 59, + 6, 13, 13, 27, 12, 25, 25, 51, 13, 27, 27, 55, 26, 53, 53, 107, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 2, 5, 5, 11, 4, 9, 9, 19, 5, 11, 11, 23, 10, 21, 21, 43, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 2, 5, 5, 11, 4, 9, 9, 19, 5, 11, 11, 23, 10, 21, 21, 43, + 3, 7, 7, 15, 6, 13, 13, 27, 7, 15, 15, 31, 14, 29, 29, 59, + 6, 13, 13, 27, 12, 25, 25, 51, 13, 27, 27, 55, 26, 53, 53, 107, + }, + { + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 2, 4, 4, 8, 5, 10, 10, 20, 5, 10, 10, 20, 11, 22, 22, 44, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 2, 4, 4, 8, 5, 10, 10, 20, 5, 10, 10, 20, 11, 22, 22, 44, + 3, 6, 6, 12, 7, 14, 14, 28, 7, 14, 14, 28, 15, 30, 30, 60, + 6, 12, 12, 24, 13, 26, 26, 52, 13, 26, 26, 52, 27, 54, 54, 108, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 2, 4, 4, 8, 5, 10, 10, 20, 5, 10, 10, 20, 11, 22, 22, 44, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 2, 4, 4, 8, 5, 10, 10, 20, 5, 10, 10, 20, 11, 22, 22, 44, + 3, 6, 6, 12, 7, 14, 14, 28, 7, 14, 14, 28, 15, 30, 30, 60, + 6, 12, 12, 24, 13, 26, 26, 52, 13, 26, 26, 52, 27, 54, 54, 108, + }, { + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 2, 5, 4, 9, 5, 11, 10, 21, 5, 11, 10, 21, 11, 23, 22, 45, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 2, 5, 4, 9, 5, 11, 10, 21, 5, 11, 10, 21, 11, 23, 22, 45, + 3, 7, 6, 13, 7, 15, 14, 29, 7, 15, 14, 29, 15, 31, 30, 61, + 6, 13, 12, 25, 13, 27, 26, 53, 13, 27, 26, 53, 27, 55, 54, 109, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 2, 5, 4, 9, 5, 11, 10, 21, 5, 11, 10, 21, 11, 23, 22, 45, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 2, 5, 4, 9, 5, 11, 10, 21, 5, 11, 10, 21, 11, 23, 22, 45, + 3, 7, 6, 13, 7, 15, 14, 29, 7, 15, 14, 29, 15, 31, 30, 61, + 6, 13, 12, 25, 13, 27, 26, 53, 13, 27, 26, 53, 27, 55, 54, 109, + }, { + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 2, 4, 5, 10, 5, 10, 11, 22, 5, 10, 11, 22, 11, 22, 23, 46, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 2, 4, 5, 10, 5, 10, 11, 22, 5, 10, 11, 22, 11, 22, 23, 46, + 3, 6, 7, 14, 7, 14, 15, 30, 7, 14, 15, 30, 15, 30, 31, 62, + 6, 12, 13, 26, 13, 26, 27, 54, 13, 26, 27, 54, 27, 54, 55, 110, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 2, 4, 5, 10, 5, 10, 11, 22, 5, 10, 11, 22, 11, 22, 23, 46, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 2, 4, 5, 10, 5, 10, 11, 22, 5, 10, 11, 22, 11, 22, 23, 46, + 3, 6, 7, 14, 7, 14, 15, 30, 7, 14, 15, 30, 15, 30, 31, 62, + 6, 12, 13, 26, 13, 26, 27, 54, 13, 26, 27, 54, 27, 54, 55, 110, + }, { + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 2, 5, 5, 11, 5, 11, 11, 23, 5, 11, 11, 23, 11, 23, 23, 47, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 2, 5, 5, 11, 5, 11, 11, 23, 5, 11, 11, 23, 11, 23, 23, 47, + 3, 7, 7, 15, 7, 15, 15, 31, 7, 15, 15, 31, 15, 31, 31, 63, + 6, 13, 13, 27, 13, 27, 27, 55, 13, 27, 27, 55, 27, 55, 55, 111, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 2, 5, 5, 11, 5, 11, 11, 23, 5, 11, 11, 23, 11, 23, 23, 47, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 2, 5, 5, 11, 5, 11, 11, 23, 5, 11, 11, 23, 11, 23, 23, 47, + 3, 7, 7, 15, 7, 15, 15, 31, 7, 15, 15, 31, 15, 31, 31, 63, + 6, 13, 13, 27, 13, 27, 27, 55, 13, 27, 27, 55, 27, 55, 55, 111, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 3, 6, 6, 12, 6, 12, 12, 24, 6, 12, 12, 24, 12, 24, 24, 48, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 3, 6, 6, 12, 6, 12, 12, 24, 6, 12, 12, 24, 12, 24, 24, 48, + 3, 6, 6, 12, 6, 12, 12, 24, 6, 12, 12, 24, 12, 24, 24, 48, + 7, 14, 14, 28, 14, 28, 28, 56, 14, 28, 28, 56, 28, 56, 56, 112, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 3, 6, 6, 12, 6, 12, 12, 24, 6, 12, 12, 24, 12, 24, 24, 48, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 3, 6, 6, 12, 6, 12, 12, 24, 6, 12, 12, 24, 12, 24, 24, 48, + 3, 6, 6, 12, 6, 12, 12, 24, 6, 12, 12, 24, 12, 24, 24, 48, + 7, 14, 14, 28, 14, 28, 28, 56, 14, 28, 28, 56, 28, 56, 56, 112, + }, { + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 3, 7, 6, 13, 6, 13, 12, 25, 6, 13, 12, 25, 12, 25, 24, 49, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 3, 7, 6, 13, 6, 13, 12, 25, 6, 13, 12, 25, 12, 25, 24, 49, + 3, 7, 6, 13, 6, 13, 12, 25, 6, 13, 12, 25, 12, 25, 24, 49, + 7, 15, 14, 29, 14, 29, 28, 57, 14, 29, 28, 57, 28, 57, 56, 113, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 3, 7, 6, 13, 6, 13, 12, 25, 6, 13, 12, 25, 12, 25, 24, 49, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 3, 7, 6, 13, 6, 13, 12, 25, 6, 13, 12, 25, 12, 25, 24, 49, + 3, 7, 6, 13, 6, 13, 12, 25, 6, 13, 12, 25, 12, 25, 24, 49, + 7, 15, 14, 29, 14, 29, 28, 57, 14, 29, 28, 57, 28, 57, 56, 113, + }, { + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 3, 6, 7, 14, 6, 12, 13, 26, 6, 12, 13, 26, 12, 24, 25, 50, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 3, 6, 7, 14, 6, 12, 13, 26, 6, 12, 13, 26, 12, 24, 25, 50, + 3, 6, 7, 14, 6, 12, 13, 26, 6, 12, 13, 26, 12, 24, 25, 50, + 7, 14, 15, 30, 14, 28, 29, 58, 14, 28, 29, 58, 28, 56, 57, 114, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 3, 6, 7, 14, 6, 12, 13, 26, 6, 12, 13, 26, 12, 24, 25, 50, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 3, 6, 7, 14, 6, 12, 13, 26, 6, 12, 13, 26, 12, 24, 25, 50, + 3, 6, 7, 14, 6, 12, 13, 26, 6, 12, 13, 26, 12, 24, 25, 50, + 7, 14, 15, 30, 14, 28, 29, 58, 14, 28, 29, 58, 28, 56, 57, 114, + }, { + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 3, 7, 7, 15, 6, 13, 13, 27, 6, 13, 13, 27, 12, 25, 25, 51, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 3, 7, 7, 15, 6, 13, 13, 27, 6, 13, 13, 27, 12, 25, 25, 51, + 3, 7, 7, 15, 6, 13, 13, 27, 6, 13, 13, 27, 12, 25, 25, 51, + 7, 15, 15, 31, 14, 29, 29, 59, 14, 29, 29, 59, 28, 57, 57, 115, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 3, 7, 7, 15, 6, 13, 13, 27, 6, 13, 13, 27, 12, 25, 25, 51, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 3, 7, 7, 15, 6, 13, 13, 27, 6, 13, 13, 27, 12, 25, 25, 51, + 3, 7, 7, 15, 6, 13, 13, 27, 6, 13, 13, 27, 12, 25, 25, 51, + 7, 15, 15, 31, 14, 29, 29, 59, 14, 29, 29, 59, 28, 57, 57, 115, + }, + { + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 3, 6, 6, 12, 7, 14, 14, 28, 6, 12, 12, 24, 13, 26, 26, 52, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 3, 6, 6, 12, 7, 14, 14, 28, 6, 12, 12, 24, 13, 26, 26, 52, + 3, 6, 6, 12, 7, 14, 14, 28, 6, 12, 12, 24, 13, 26, 26, 52, + 7, 14, 14, 28, 15, 30, 30, 60, 14, 28, 28, 56, 29, 58, 58, 116, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 3, 6, 6, 12, 7, 14, 14, 28, 6, 12, 12, 24, 13, 26, 26, 52, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 3, 6, 6, 12, 7, 14, 14, 28, 6, 12, 12, 24, 13, 26, 26, 52, + 3, 6, 6, 12, 7, 14, 14, 28, 6, 12, 12, 24, 13, 26, 26, 52, + 7, 14, 14, 28, 15, 30, 30, 60, 14, 28, 28, 56, 29, 58, 58, 116, + }, { + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 3, 7, 6, 13, 7, 15, 14, 29, 6, 13, 12, 25, 13, 27, 26, 53, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 3, 7, 6, 13, 7, 15, 14, 29, 6, 13, 12, 25, 13, 27, 26, 53, + 3, 7, 6, 13, 7, 15, 14, 29, 6, 13, 12, 25, 13, 27, 26, 53, + 7, 15, 14, 29, 15, 31, 30, 61, 14, 29, 28, 57, 29, 59, 58, 117, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 3, 7, 6, 13, 7, 15, 14, 29, 6, 13, 12, 25, 13, 27, 26, 53, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 3, 7, 6, 13, 7, 15, 14, 29, 6, 13, 12, 25, 13, 27, 26, 53, + 3, 7, 6, 13, 7, 15, 14, 29, 6, 13, 12, 25, 13, 27, 26, 53, + 7, 15, 14, 29, 15, 31, 30, 61, 14, 29, 28, 57, 29, 59, 58, 117, + }, { + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 3, 6, 7, 14, 7, 14, 15, 30, 6, 12, 13, 26, 13, 26, 27, 54, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 3, 6, 7, 14, 7, 14, 15, 30, 6, 12, 13, 26, 13, 26, 27, 54, + 3, 6, 7, 14, 7, 14, 15, 30, 6, 12, 13, 26, 13, 26, 27, 54, + 7, 14, 15, 30, 15, 30, 31, 62, 14, 28, 29, 58, 29, 58, 59, 118, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 3, 6, 7, 14, 7, 14, 15, 30, 6, 12, 13, 26, 13, 26, 27, 54, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 3, 6, 7, 14, 7, 14, 15, 30, 6, 12, 13, 26, 13, 26, 27, 54, + 3, 6, 7, 14, 7, 14, 15, 30, 6, 12, 13, 26, 13, 26, 27, 54, + 7, 14, 15, 30, 15, 30, 31, 62, 14, 28, 29, 58, 29, 58, 59, 118, + }, { + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 3, 7, 7, 15, 7, 15, 15, 31, 6, 13, 13, 27, 13, 27, 27, 55, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 3, 7, 7, 15, 7, 15, 15, 31, 6, 13, 13, 27, 13, 27, 27, 55, + 3, 7, 7, 15, 7, 15, 15, 31, 6, 13, 13, 27, 13, 27, 27, 55, + 7, 15, 15, 31, 15, 31, 31, 63, 14, 29, 29, 59, 29, 59, 59, 119, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 3, 7, 7, 15, 7, 15, 15, 31, 6, 13, 13, 27, 13, 27, 27, 55, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 3, 7, 7, 15, 7, 15, 15, 31, 6, 13, 13, 27, 13, 27, 27, 55, + 3, 7, 7, 15, 7, 15, 15, 31, 6, 13, 13, 27, 13, 27, 27, 55, + 7, 15, 15, 31, 15, 31, 31, 63, 14, 29, 29, 59, 29, 59, 59, 119, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 3, 6, 6, 12, 6, 12, 12, 24, 7, 14, 14, 28, 14, 28, 28, 56, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 3, 6, 6, 12, 6, 12, 12, 24, 7, 14, 14, 28, 14, 28, 28, 56, + 3, 6, 6, 12, 6, 12, 12, 24, 7, 14, 14, 28, 14, 28, 28, 56, + 7, 14, 14, 28, 14, 28, 28, 56, 15, 30, 30, 60, 30, 60, 60, 120, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 3, 6, 6, 12, 6, 12, 12, 24, 7, 14, 14, 28, 14, 28, 28, 56, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 3, 6, 6, 12, 6, 12, 12, 24, 7, 14, 14, 28, 14, 28, 28, 56, + 3, 6, 6, 12, 6, 12, 12, 24, 7, 14, 14, 28, 14, 28, 28, 56, + 7, 14, 14, 28, 14, 28, 28, 56, 15, 30, 30, 60, 30, 60, 60, 120, + }, { + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 3, 7, 6, 13, 6, 13, 12, 25, 7, 15, 14, 29, 14, 29, 28, 57, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 3, 7, 6, 13, 6, 13, 12, 25, 7, 15, 14, 29, 14, 29, 28, 57, + 3, 7, 6, 13, 6, 13, 12, 25, 7, 15, 14, 29, 14, 29, 28, 57, + 7, 15, 14, 29, 14, 29, 28, 57, 15, 31, 30, 61, 30, 61, 60, 121, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 3, 7, 6, 13, 6, 13, 12, 25, 7, 15, 14, 29, 14, 29, 28, 57, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 3, 7, 6, 13, 6, 13, 12, 25, 7, 15, 14, 29, 14, 29, 28, 57, + 3, 7, 6, 13, 6, 13, 12, 25, 7, 15, 14, 29, 14, 29, 28, 57, + 7, 15, 14, 29, 14, 29, 28, 57, 15, 31, 30, 61, 30, 61, 60, 121, + }, { + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 3, 6, 7, 14, 6, 12, 13, 26, 7, 14, 15, 30, 14, 28, 29, 58, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 3, 6, 7, 14, 6, 12, 13, 26, 7, 14, 15, 30, 14, 28, 29, 58, + 3, 6, 7, 14, 6, 12, 13, 26, 7, 14, 15, 30, 14, 28, 29, 58, + 7, 14, 15, 30, 14, 28, 29, 58, 15, 30, 31, 62, 30, 60, 61, 122, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 3, 6, 7, 14, 6, 12, 13, 26, 7, 14, 15, 30, 14, 28, 29, 58, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 3, 6, 7, 14, 6, 12, 13, 26, 7, 14, 15, 30, 14, 28, 29, 58, + 3, 6, 7, 14, 6, 12, 13, 26, 7, 14, 15, 30, 14, 28, 29, 58, + 7, 14, 15, 30, 14, 28, 29, 58, 15, 30, 31, 62, 30, 60, 61, 122, + }, { + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 3, 7, 7, 15, 6, 13, 13, 27, 7, 15, 15, 31, 14, 29, 29, 59, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 3, 7, 7, 15, 6, 13, 13, 27, 7, 15, 15, 31, 14, 29, 29, 59, + 3, 7, 7, 15, 6, 13, 13, 27, 7, 15, 15, 31, 14, 29, 29, 59, + 7, 15, 15, 31, 14, 29, 29, 59, 15, 31, 31, 63, 30, 61, 61, 123, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 3, 7, 7, 15, 6, 13, 13, 27, 7, 15, 15, 31, 14, 29, 29, 59, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 3, 7, 7, 15, 6, 13, 13, 27, 7, 15, 15, 31, 14, 29, 29, 59, + 3, 7, 7, 15, 6, 13, 13, 27, 7, 15, 15, 31, 14, 29, 29, 59, + 7, 15, 15, 31, 14, 29, 29, 59, 15, 31, 31, 63, 30, 61, 61, 123, + }, + { + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 3, 6, 6, 12, 7, 14, 14, 28, 7, 14, 14, 28, 15, 30, 30, 60, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 3, 6, 6, 12, 7, 14, 14, 28, 7, 14, 14, 28, 15, 30, 30, 60, + 3, 6, 6, 12, 7, 14, 14, 28, 7, 14, 14, 28, 15, 30, 30, 60, + 7, 14, 14, 28, 15, 30, 30, 60, 15, 30, 30, 60, 31, 62, 62, 124, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 3, 6, 6, 12, 7, 14, 14, 28, 7, 14, 14, 28, 15, 30, 30, 60, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 3, 6, 6, 12, 7, 14, 14, 28, 7, 14, 14, 28, 15, 30, 30, 60, + 3, 6, 6, 12, 7, 14, 14, 28, 7, 14, 14, 28, 15, 30, 30, 60, + 7, 14, 14, 28, 15, 30, 30, 60, 15, 30, 30, 60, 31, 62, 62, 124, + }, { + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 3, 7, 6, 13, 7, 15, 14, 29, 7, 15, 14, 29, 15, 31, 30, 61, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 3, 7, 6, 13, 7, 15, 14, 29, 7, 15, 14, 29, 15, 31, 30, 61, + 3, 7, 6, 13, 7, 15, 14, 29, 7, 15, 14, 29, 15, 31, 30, 61, + 7, 15, 14, 29, 15, 31, 30, 61, 15, 31, 30, 61, 31, 63, 62, 125, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 3, 7, 6, 13, 7, 15, 14, 29, 7, 15, 14, 29, 15, 31, 30, 61, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 3, 7, 6, 13, 7, 15, 14, 29, 7, 15, 14, 29, 15, 31, 30, 61, + 3, 7, 6, 13, 7, 15, 14, 29, 7, 15, 14, 29, 15, 31, 30, 61, + 7, 15, 14, 29, 15, 31, 30, 61, 15, 31, 30, 61, 31, 63, 62, 125, + }, { + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 3, 6, 7, 14, 7, 14, 15, 30, 7, 14, 15, 30, 15, 30, 31, 62, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 3, 6, 7, 14, 7, 14, 15, 30, 7, 14, 15, 30, 15, 30, 31, 62, + 3, 6, 7, 14, 7, 14, 15, 30, 7, 14, 15, 30, 15, 30, 31, 62, + 7, 14, 15, 30, 15, 30, 31, 62, 15, 30, 31, 62, 31, 62, 63, 126, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 3, 6, 7, 14, 7, 14, 15, 30, 7, 14, 15, 30, 15, 30, 31, 62, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 3, 6, 7, 14, 7, 14, 15, 30, 7, 14, 15, 30, 15, 30, 31, 62, + 3, 6, 7, 14, 7, 14, 15, 30, 7, 14, 15, 30, 15, 30, 31, 62, + 7, 14, 15, 30, 15, 30, 31, 62, 15, 30, 31, 62, 31, 62, 63, 126, + }, { + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 3, 7, 7, 15, 7, 15, 15, 31, 7, 15, 15, 31, 15, 31, 31, 63, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 3, 7, 7, 15, 7, 15, 15, 31, 7, 15, 15, 31, 15, 31, 31, 63, + 3, 7, 7, 15, 7, 15, 15, 31, 7, 15, 15, 31, 15, 31, 31, 63, + 7, 15, 15, 31, 15, 31, 31, 63, 15, 31, 31, 63, 31, 63, 63, 127, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 3, 7, 7, 15, 7, 15, 15, 31, 7, 15, 15, 31, 15, 31, 31, 63, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 3, 7, 7, 15, 7, 15, 15, 31, 7, 15, 15, 31, 15, 31, 31, 63, + 3, 7, 7, 15, 7, 15, 15, 31, 7, 15, 15, 31, 15, 31, 31, 63, + 7, 15, 15, 31, 15, 31, 31, 63, 15, 31, 31, 63, 31, 63, 63, 127, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 2, 4, 4, 8, 4, 8, 8, 16, 4, 8, 8, 16, 8, 16, 16, 32, + 2, 4, 4, 8, 4, 8, 8, 16, 4, 8, 8, 16, 8, 16, 16, 32, + 4, 8, 8, 16, 8, 16, 16, 32, 8, 16, 16, 32, 16, 32, 32, 64, + 2, 4, 4, 8, 4, 8, 8, 16, 4, 8, 8, 16, 8, 16, 16, 32, + 4, 8, 8, 16, 8, 16, 16, 32, 8, 16, 16, 32, 16, 32, 32, 64, + 4, 8, 8, 16, 8, 16, 16, 32, 8, 16, 16, 32, 16, 32, 32, 64, + 8, 16, 16, 32, 16, 32, 32, 64, 16, 32, 32, 64, 32, 64, 64, 128, + }, { + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 2, 5, 4, 9, 4, 9, 8, 17, 4, 9, 8, 17, 8, 17, 16, 33, + 2, 5, 4, 9, 4, 9, 8, 17, 4, 9, 8, 17, 8, 17, 16, 33, + 4, 9, 8, 17, 8, 17, 16, 33, 8, 17, 16, 33, 16, 33, 32, 65, + 2, 5, 4, 9, 4, 9, 8, 17, 4, 9, 8, 17, 8, 17, 16, 33, + 4, 9, 8, 17, 8, 17, 16, 33, 8, 17, 16, 33, 16, 33, 32, 65, + 4, 9, 8, 17, 8, 17, 16, 33, 8, 17, 16, 33, 16, 33, 32, 65, + 8, 17, 16, 33, 16, 33, 32, 65, 16, 33, 32, 65, 32, 65, 64, 129, + }, { + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 2, 4, 5, 10, 4, 8, 9, 18, 4, 8, 9, 18, 8, 16, 17, 34, + 2, 4, 5, 10, 4, 8, 9, 18, 4, 8, 9, 18, 8, 16, 17, 34, + 4, 8, 9, 18, 8, 16, 17, 34, 8, 16, 17, 34, 16, 32, 33, 66, + 2, 4, 5, 10, 4, 8, 9, 18, 4, 8, 9, 18, 8, 16, 17, 34, + 4, 8, 9, 18, 8, 16, 17, 34, 8, 16, 17, 34, 16, 32, 33, 66, + 4, 8, 9, 18, 8, 16, 17, 34, 8, 16, 17, 34, 16, 32, 33, 66, + 8, 16, 17, 34, 16, 32, 33, 66, 16, 32, 33, 66, 32, 64, 65, 130, + }, { + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 2, 5, 5, 11, 4, 9, 9, 19, 4, 9, 9, 19, 8, 17, 17, 35, + 2, 5, 5, 11, 4, 9, 9, 19, 4, 9, 9, 19, 8, 17, 17, 35, + 4, 9, 9, 19, 8, 17, 17, 35, 8, 17, 17, 35, 16, 33, 33, 67, + 2, 5, 5, 11, 4, 9, 9, 19, 4, 9, 9, 19, 8, 17, 17, 35, + 4, 9, 9, 19, 8, 17, 17, 35, 8, 17, 17, 35, 16, 33, 33, 67, + 4, 9, 9, 19, 8, 17, 17, 35, 8, 17, 17, 35, 16, 33, 33, 67, + 8, 17, 17, 35, 16, 33, 33, 67, 16, 33, 33, 67, 32, 65, 65, 131, + }, + { + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 2, 4, 4, 8, 5, 10, 10, 20, 4, 8, 8, 16, 9, 18, 18, 36, + 2, 4, 4, 8, 5, 10, 10, 20, 4, 8, 8, 16, 9, 18, 18, 36, + 4, 8, 8, 16, 9, 18, 18, 36, 8, 16, 16, 32, 17, 34, 34, 68, + 2, 4, 4, 8, 5, 10, 10, 20, 4, 8, 8, 16, 9, 18, 18, 36, + 4, 8, 8, 16, 9, 18, 18, 36, 8, 16, 16, 32, 17, 34, 34, 68, + 4, 8, 8, 16, 9, 18, 18, 36, 8, 16, 16, 32, 17, 34, 34, 68, + 8, 16, 16, 32, 17, 34, 34, 68, 16, 32, 32, 64, 33, 66, 66, 132, + }, { + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 2, 5, 4, 9, 5, 11, 10, 21, 4, 9, 8, 17, 9, 19, 18, 37, + 2, 5, 4, 9, 5, 11, 10, 21, 4, 9, 8, 17, 9, 19, 18, 37, + 4, 9, 8, 17, 9, 19, 18, 37, 8, 17, 16, 33, 17, 35, 34, 69, + 2, 5, 4, 9, 5, 11, 10, 21, 4, 9, 8, 17, 9, 19, 18, 37, + 4, 9, 8, 17, 9, 19, 18, 37, 8, 17, 16, 33, 17, 35, 34, 69, + 4, 9, 8, 17, 9, 19, 18, 37, 8, 17, 16, 33, 17, 35, 34, 69, + 8, 17, 16, 33, 17, 35, 34, 69, 16, 33, 32, 65, 33, 67, 66, 133, + }, { + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 2, 4, 5, 10, 5, 10, 11, 22, 4, 8, 9, 18, 9, 18, 19, 38, + 2, 4, 5, 10, 5, 10, 11, 22, 4, 8, 9, 18, 9, 18, 19, 38, + 4, 8, 9, 18, 9, 18, 19, 38, 8, 16, 17, 34, 17, 34, 35, 70, + 2, 4, 5, 10, 5, 10, 11, 22, 4, 8, 9, 18, 9, 18, 19, 38, + 4, 8, 9, 18, 9, 18, 19, 38, 8, 16, 17, 34, 17, 34, 35, 70, + 4, 8, 9, 18, 9, 18, 19, 38, 8, 16, 17, 34, 17, 34, 35, 70, + 8, 16, 17, 34, 17, 34, 35, 70, 16, 32, 33, 66, 33, 66, 67, 134, + }, { + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 2, 5, 5, 11, 5, 11, 11, 23, 4, 9, 9, 19, 9, 19, 19, 39, + 2, 5, 5, 11, 5, 11, 11, 23, 4, 9, 9, 19, 9, 19, 19, 39, + 4, 9, 9, 19, 9, 19, 19, 39, 8, 17, 17, 35, 17, 35, 35, 71, + 2, 5, 5, 11, 5, 11, 11, 23, 4, 9, 9, 19, 9, 19, 19, 39, + 4, 9, 9, 19, 9, 19, 19, 39, 8, 17, 17, 35, 17, 35, 35, 71, + 4, 9, 9, 19, 9, 19, 19, 39, 8, 17, 17, 35, 17, 35, 35, 71, + 8, 17, 17, 35, 17, 35, 35, 71, 16, 33, 33, 67, 33, 67, 67, 135, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 2, 4, 4, 8, 4, 8, 8, 16, 5, 10, 10, 20, 10, 20, 20, 40, + 2, 4, 4, 8, 4, 8, 8, 16, 5, 10, 10, 20, 10, 20, 20, 40, + 4, 8, 8, 16, 8, 16, 16, 32, 9, 18, 18, 36, 18, 36, 36, 72, + 2, 4, 4, 8, 4, 8, 8, 16, 5, 10, 10, 20, 10, 20, 20, 40, + 4, 8, 8, 16, 8, 16, 16, 32, 9, 18, 18, 36, 18, 36, 36, 72, + 4, 8, 8, 16, 8, 16, 16, 32, 9, 18, 18, 36, 18, 36, 36, 72, + 8, 16, 16, 32, 16, 32, 32, 64, 17, 34, 34, 68, 34, 68, 68, 136, + }, { + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 2, 5, 4, 9, 4, 9, 8, 17, 5, 11, 10, 21, 10, 21, 20, 41, + 2, 5, 4, 9, 4, 9, 8, 17, 5, 11, 10, 21, 10, 21, 20, 41, + 4, 9, 8, 17, 8, 17, 16, 33, 9, 19, 18, 37, 18, 37, 36, 73, + 2, 5, 4, 9, 4, 9, 8, 17, 5, 11, 10, 21, 10, 21, 20, 41, + 4, 9, 8, 17, 8, 17, 16, 33, 9, 19, 18, 37, 18, 37, 36, 73, + 4, 9, 8, 17, 8, 17, 16, 33, 9, 19, 18, 37, 18, 37, 36, 73, + 8, 17, 16, 33, 16, 33, 32, 65, 17, 35, 34, 69, 34, 69, 68, 137, + }, { + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 2, 4, 5, 10, 4, 8, 9, 18, 5, 10, 11, 22, 10, 20, 21, 42, + 2, 4, 5, 10, 4, 8, 9, 18, 5, 10, 11, 22, 10, 20, 21, 42, + 4, 8, 9, 18, 8, 16, 17, 34, 9, 18, 19, 38, 18, 36, 37, 74, + 2, 4, 5, 10, 4, 8, 9, 18, 5, 10, 11, 22, 10, 20, 21, 42, + 4, 8, 9, 18, 8, 16, 17, 34, 9, 18, 19, 38, 18, 36, 37, 74, + 4, 8, 9, 18, 8, 16, 17, 34, 9, 18, 19, 38, 18, 36, 37, 74, + 8, 16, 17, 34, 16, 32, 33, 66, 17, 34, 35, 70, 34, 68, 69, 138, + }, { + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 2, 5, 5, 11, 4, 9, 9, 19, 5, 11, 11, 23, 10, 21, 21, 43, + 2, 5, 5, 11, 4, 9, 9, 19, 5, 11, 11, 23, 10, 21, 21, 43, + 4, 9, 9, 19, 8, 17, 17, 35, 9, 19, 19, 39, 18, 37, 37, 75, + 2, 5, 5, 11, 4, 9, 9, 19, 5, 11, 11, 23, 10, 21, 21, 43, + 4, 9, 9, 19, 8, 17, 17, 35, 9, 19, 19, 39, 18, 37, 37, 75, + 4, 9, 9, 19, 8, 17, 17, 35, 9, 19, 19, 39, 18, 37, 37, 75, + 8, 17, 17, 35, 16, 33, 33, 67, 17, 35, 35, 71, 34, 69, 69, 139, + }, + { + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 2, 4, 4, 8, 5, 10, 10, 20, 5, 10, 10, 20, 11, 22, 22, 44, + 2, 4, 4, 8, 5, 10, 10, 20, 5, 10, 10, 20, 11, 22, 22, 44, + 4, 8, 8, 16, 9, 18, 18, 36, 9, 18, 18, 36, 19, 38, 38, 76, + 2, 4, 4, 8, 5, 10, 10, 20, 5, 10, 10, 20, 11, 22, 22, 44, + 4, 8, 8, 16, 9, 18, 18, 36, 9, 18, 18, 36, 19, 38, 38, 76, + 4, 8, 8, 16, 9, 18, 18, 36, 9, 18, 18, 36, 19, 38, 38, 76, + 8, 16, 16, 32, 17, 34, 34, 68, 17, 34, 34, 68, 35, 70, 70, 140, + }, { + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 2, 5, 4, 9, 5, 11, 10, 21, 5, 11, 10, 21, 11, 23, 22, 45, + 2, 5, 4, 9, 5, 11, 10, 21, 5, 11, 10, 21, 11, 23, 22, 45, + 4, 9, 8, 17, 9, 19, 18, 37, 9, 19, 18, 37, 19, 39, 38, 77, + 2, 5, 4, 9, 5, 11, 10, 21, 5, 11, 10, 21, 11, 23, 22, 45, + 4, 9, 8, 17, 9, 19, 18, 37, 9, 19, 18, 37, 19, 39, 38, 77, + 4, 9, 8, 17, 9, 19, 18, 37, 9, 19, 18, 37, 19, 39, 38, 77, + 8, 17, 16, 33, 17, 35, 34, 69, 17, 35, 34, 69, 35, 71, 70, 141, + }, { + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 2, 4, 5, 10, 5, 10, 11, 22, 5, 10, 11, 22, 11, 22, 23, 46, + 2, 4, 5, 10, 5, 10, 11, 22, 5, 10, 11, 22, 11, 22, 23, 46, + 4, 8, 9, 18, 9, 18, 19, 38, 9, 18, 19, 38, 19, 38, 39, 78, + 2, 4, 5, 10, 5, 10, 11, 22, 5, 10, 11, 22, 11, 22, 23, 46, + 4, 8, 9, 18, 9, 18, 19, 38, 9, 18, 19, 38, 19, 38, 39, 78, + 4, 8, 9, 18, 9, 18, 19, 38, 9, 18, 19, 38, 19, 38, 39, 78, + 8, 16, 17, 34, 17, 34, 35, 70, 17, 34, 35, 70, 35, 70, 71, 142, + }, { + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 2, 5, 5, 11, 5, 11, 11, 23, 5, 11, 11, 23, 11, 23, 23, 47, + 2, 5, 5, 11, 5, 11, 11, 23, 5, 11, 11, 23, 11, 23, 23, 47, + 4, 9, 9, 19, 9, 19, 19, 39, 9, 19, 19, 39, 19, 39, 39, 79, + 2, 5, 5, 11, 5, 11, 11, 23, 5, 11, 11, 23, 11, 23, 23, 47, + 4, 9, 9, 19, 9, 19, 19, 39, 9, 19, 19, 39, 19, 39, 39, 79, + 4, 9, 9, 19, 9, 19, 19, 39, 9, 19, 19, 39, 19, 39, 39, 79, + 8, 17, 17, 35, 17, 35, 35, 71, 17, 35, 35, 71, 35, 71, 71, 143, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 3, 6, 6, 12, 6, 12, 12, 24, 6, 12, 12, 24, 12, 24, 24, 48, + 2, 4, 4, 8, 4, 8, 8, 16, 4, 8, 8, 16, 8, 16, 16, 32, + 5, 10, 10, 20, 10, 20, 20, 40, 10, 20, 20, 40, 20, 40, 40, 80, + 2, 4, 4, 8, 4, 8, 8, 16, 4, 8, 8, 16, 8, 16, 16, 32, + 5, 10, 10, 20, 10, 20, 20, 40, 10, 20, 20, 40, 20, 40, 40, 80, + 4, 8, 8, 16, 8, 16, 16, 32, 8, 16, 16, 32, 16, 32, 32, 64, + 9, 18, 18, 36, 18, 36, 36, 72, 18, 36, 36, 72, 36, 72, 72, 144, + }, { + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 3, 7, 6, 13, 6, 13, 12, 25, 6, 13, 12, 25, 12, 25, 24, 49, + 2, 5, 4, 9, 4, 9, 8, 17, 4, 9, 8, 17, 8, 17, 16, 33, + 5, 11, 10, 21, 10, 21, 20, 41, 10, 21, 20, 41, 20, 41, 40, 81, + 2, 5, 4, 9, 4, 9, 8, 17, 4, 9, 8, 17, 8, 17, 16, 33, + 5, 11, 10, 21, 10, 21, 20, 41, 10, 21, 20, 41, 20, 41, 40, 81, + 4, 9, 8, 17, 8, 17, 16, 33, 8, 17, 16, 33, 16, 33, 32, 65, + 9, 19, 18, 37, 18, 37, 36, 73, 18, 37, 36, 73, 36, 73, 72, 145, + }, { + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 3, 6, 7, 14, 6, 12, 13, 26, 6, 12, 13, 26, 12, 24, 25, 50, + 2, 4, 5, 10, 4, 8, 9, 18, 4, 8, 9, 18, 8, 16, 17, 34, + 5, 10, 11, 22, 10, 20, 21, 42, 10, 20, 21, 42, 20, 40, 41, 82, + 2, 4, 5, 10, 4, 8, 9, 18, 4, 8, 9, 18, 8, 16, 17, 34, + 5, 10, 11, 22, 10, 20, 21, 42, 10, 20, 21, 42, 20, 40, 41, 82, + 4, 8, 9, 18, 8, 16, 17, 34, 8, 16, 17, 34, 16, 32, 33, 66, + 9, 18, 19, 38, 18, 36, 37, 74, 18, 36, 37, 74, 36, 72, 73, 146, + }, { + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 3, 7, 7, 15, 6, 13, 13, 27, 6, 13, 13, 27, 12, 25, 25, 51, + 2, 5, 5, 11, 4, 9, 9, 19, 4, 9, 9, 19, 8, 17, 17, 35, + 5, 11, 11, 23, 10, 21, 21, 43, 10, 21, 21, 43, 20, 41, 41, 83, + 2, 5, 5, 11, 4, 9, 9, 19, 4, 9, 9, 19, 8, 17, 17, 35, + 5, 11, 11, 23, 10, 21, 21, 43, 10, 21, 21, 43, 20, 41, 41, 83, + 4, 9, 9, 19, 8, 17, 17, 35, 8, 17, 17, 35, 16, 33, 33, 67, + 9, 19, 19, 39, 18, 37, 37, 75, 18, 37, 37, 75, 36, 73, 73, 147, + }, + { + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 3, 6, 6, 12, 7, 14, 14, 28, 6, 12, 12, 24, 13, 26, 26, 52, + 2, 4, 4, 8, 5, 10, 10, 20, 4, 8, 8, 16, 9, 18, 18, 36, + 5, 10, 10, 20, 11, 22, 22, 44, 10, 20, 20, 40, 21, 42, 42, 84, + 2, 4, 4, 8, 5, 10, 10, 20, 4, 8, 8, 16, 9, 18, 18, 36, + 5, 10, 10, 20, 11, 22, 22, 44, 10, 20, 20, 40, 21, 42, 42, 84, + 4, 8, 8, 16, 9, 18, 18, 36, 8, 16, 16, 32, 17, 34, 34, 68, + 9, 18, 18, 36, 19, 38, 38, 76, 18, 36, 36, 72, 37, 74, 74, 148, + }, { + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 3, 7, 6, 13, 7, 15, 14, 29, 6, 13, 12, 25, 13, 27, 26, 53, + 2, 5, 4, 9, 5, 11, 10, 21, 4, 9, 8, 17, 9, 19, 18, 37, + 5, 11, 10, 21, 11, 23, 22, 45, 10, 21, 20, 41, 21, 43, 42, 85, + 2, 5, 4, 9, 5, 11, 10, 21, 4, 9, 8, 17, 9, 19, 18, 37, + 5, 11, 10, 21, 11, 23, 22, 45, 10, 21, 20, 41, 21, 43, 42, 85, + 4, 9, 8, 17, 9, 19, 18, 37, 8, 17, 16, 33, 17, 35, 34, 69, + 9, 19, 18, 37, 19, 39, 38, 77, 18, 37, 36, 73, 37, 75, 74, 149, + }, { + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 3, 6, 7, 14, 7, 14, 15, 30, 6, 12, 13, 26, 13, 26, 27, 54, + 2, 4, 5, 10, 5, 10, 11, 22, 4, 8, 9, 18, 9, 18, 19, 38, + 5, 10, 11, 22, 11, 22, 23, 46, 10, 20, 21, 42, 21, 42, 43, 86, + 2, 4, 5, 10, 5, 10, 11, 22, 4, 8, 9, 18, 9, 18, 19, 38, + 5, 10, 11, 22, 11, 22, 23, 46, 10, 20, 21, 42, 21, 42, 43, 86, + 4, 8, 9, 18, 9, 18, 19, 38, 8, 16, 17, 34, 17, 34, 35, 70, + 9, 18, 19, 38, 19, 38, 39, 78, 18, 36, 37, 74, 37, 74, 75, 150, + }, { + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 3, 7, 7, 15, 7, 15, 15, 31, 6, 13, 13, 27, 13, 27, 27, 55, + 2, 5, 5, 11, 5, 11, 11, 23, 4, 9, 9, 19, 9, 19, 19, 39, + 5, 11, 11, 23, 11, 23, 23, 47, 10, 21, 21, 43, 21, 43, 43, 87, + 2, 5, 5, 11, 5, 11, 11, 23, 4, 9, 9, 19, 9, 19, 19, 39, + 5, 11, 11, 23, 11, 23, 23, 47, 10, 21, 21, 43, 21, 43, 43, 87, + 4, 9, 9, 19, 9, 19, 19, 39, 8, 17, 17, 35, 17, 35, 35, 71, + 9, 19, 19, 39, 19, 39, 39, 79, 18, 37, 37, 75, 37, 75, 75, 151, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 3, 6, 6, 12, 6, 12, 12, 24, 7, 14, 14, 28, 14, 28, 28, 56, + 2, 4, 4, 8, 4, 8, 8, 16, 5, 10, 10, 20, 10, 20, 20, 40, + 5, 10, 10, 20, 10, 20, 20, 40, 11, 22, 22, 44, 22, 44, 44, 88, + 2, 4, 4, 8, 4, 8, 8, 16, 5, 10, 10, 20, 10, 20, 20, 40, + 5, 10, 10, 20, 10, 20, 20, 40, 11, 22, 22, 44, 22, 44, 44, 88, + 4, 8, 8, 16, 8, 16, 16, 32, 9, 18, 18, 36, 18, 36, 36, 72, + 9, 18, 18, 36, 18, 36, 36, 72, 19, 38, 38, 76, 38, 76, 76, 152, + }, { + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 3, 7, 6, 13, 6, 13, 12, 25, 7, 15, 14, 29, 14, 29, 28, 57, + 2, 5, 4, 9, 4, 9, 8, 17, 5, 11, 10, 21, 10, 21, 20, 41, + 5, 11, 10, 21, 10, 21, 20, 41, 11, 23, 22, 45, 22, 45, 44, 89, + 2, 5, 4, 9, 4, 9, 8, 17, 5, 11, 10, 21, 10, 21, 20, 41, + 5, 11, 10, 21, 10, 21, 20, 41, 11, 23, 22, 45, 22, 45, 44, 89, + 4, 9, 8, 17, 8, 17, 16, 33, 9, 19, 18, 37, 18, 37, 36, 73, + 9, 19, 18, 37, 18, 37, 36, 73, 19, 39, 38, 77, 38, 77, 76, 153, + }, { + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 3, 6, 7, 14, 6, 12, 13, 26, 7, 14, 15, 30, 14, 28, 29, 58, + 2, 4, 5, 10, 4, 8, 9, 18, 5, 10, 11, 22, 10, 20, 21, 42, + 5, 10, 11, 22, 10, 20, 21, 42, 11, 22, 23, 46, 22, 44, 45, 90, + 2, 4, 5, 10, 4, 8, 9, 18, 5, 10, 11, 22, 10, 20, 21, 42, + 5, 10, 11, 22, 10, 20, 21, 42, 11, 22, 23, 46, 22, 44, 45, 90, + 4, 8, 9, 18, 8, 16, 17, 34, 9, 18, 19, 38, 18, 36, 37, 74, + 9, 18, 19, 38, 18, 36, 37, 74, 19, 38, 39, 78, 38, 76, 77, 154, + }, { + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 3, 7, 7, 15, 6, 13, 13, 27, 7, 15, 15, 31, 14, 29, 29, 59, + 2, 5, 5, 11, 4, 9, 9, 19, 5, 11, 11, 23, 10, 21, 21, 43, + 5, 11, 11, 23, 10, 21, 21, 43, 11, 23, 23, 47, 22, 45, 45, 91, + 2, 5, 5, 11, 4, 9, 9, 19, 5, 11, 11, 23, 10, 21, 21, 43, + 5, 11, 11, 23, 10, 21, 21, 43, 11, 23, 23, 47, 22, 45, 45, 91, + 4, 9, 9, 19, 8, 17, 17, 35, 9, 19, 19, 39, 18, 37, 37, 75, + 9, 19, 19, 39, 18, 37, 37, 75, 19, 39, 39, 79, 38, 77, 77, 155, + }, + { + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 3, 6, 6, 12, 7, 14, 14, 28, 7, 14, 14, 28, 15, 30, 30, 60, + 2, 4, 4, 8, 5, 10, 10, 20, 5, 10, 10, 20, 11, 22, 22, 44, + 5, 10, 10, 20, 11, 22, 22, 44, 11, 22, 22, 44, 23, 46, 46, 92, + 2, 4, 4, 8, 5, 10, 10, 20, 5, 10, 10, 20, 11, 22, 22, 44, + 5, 10, 10, 20, 11, 22, 22, 44, 11, 22, 22, 44, 23, 46, 46, 92, + 4, 8, 8, 16, 9, 18, 18, 36, 9, 18, 18, 36, 19, 38, 38, 76, + 9, 18, 18, 36, 19, 38, 38, 76, 19, 38, 38, 76, 39, 78, 78, 156, + }, { + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 3, 7, 6, 13, 7, 15, 14, 29, 7, 15, 14, 29, 15, 31, 30, 61, + 2, 5, 4, 9, 5, 11, 10, 21, 5, 11, 10, 21, 11, 23, 22, 45, + 5, 11, 10, 21, 11, 23, 22, 45, 11, 23, 22, 45, 23, 47, 46, 93, + 2, 5, 4, 9, 5, 11, 10, 21, 5, 11, 10, 21, 11, 23, 22, 45, + 5, 11, 10, 21, 11, 23, 22, 45, 11, 23, 22, 45, 23, 47, 46, 93, + 4, 9, 8, 17, 9, 19, 18, 37, 9, 19, 18, 37, 19, 39, 38, 77, + 9, 19, 18, 37, 19, 39, 38, 77, 19, 39, 38, 77, 39, 79, 78, 157, + }, { + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 3, 6, 7, 14, 7, 14, 15, 30, 7, 14, 15, 30, 15, 30, 31, 62, + 2, 4, 5, 10, 5, 10, 11, 22, 5, 10, 11, 22, 11, 22, 23, 46, + 5, 10, 11, 22, 11, 22, 23, 46, 11, 22, 23, 46, 23, 46, 47, 94, + 2, 4, 5, 10, 5, 10, 11, 22, 5, 10, 11, 22, 11, 22, 23, 46, + 5, 10, 11, 22, 11, 22, 23, 46, 11, 22, 23, 46, 23, 46, 47, 94, + 4, 8, 9, 18, 9, 18, 19, 38, 9, 18, 19, 38, 19, 38, 39, 78, + 9, 18, 19, 38, 19, 38, 39, 78, 19, 38, 39, 78, 39, 78, 79, 158, + }, { + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 3, 7, 7, 15, 7, 15, 15, 31, 7, 15, 15, 31, 15, 31, 31, 63, + 2, 5, 5, 11, 5, 11, 11, 23, 5, 11, 11, 23, 11, 23, 23, 47, + 5, 11, 11, 23, 11, 23, 23, 47, 11, 23, 23, 47, 23, 47, 47, 95, + 2, 5, 5, 11, 5, 11, 11, 23, 5, 11, 11, 23, 11, 23, 23, 47, + 5, 11, 11, 23, 11, 23, 23, 47, 11, 23, 23, 47, 23, 47, 47, 95, + 4, 9, 9, 19, 9, 19, 19, 39, 9, 19, 19, 39, 19, 39, 39, 79, + 9, 19, 19, 39, 19, 39, 39, 79, 19, 39, 39, 79, 39, 79, 79, 159, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 2, 4, 4, 8, 4, 8, 8, 16, 4, 8, 8, 16, 8, 16, 16, 32, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 2, 4, 4, 8, 4, 8, 8, 16, 4, 8, 8, 16, 8, 16, 16, 32, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 2, 4, 4, 8, 4, 8, 8, 16, 4, 8, 8, 16, 8, 16, 16, 32, + 3, 6, 6, 12, 6, 12, 12, 24, 6, 12, 12, 24, 12, 24, 24, 48, + 6, 12, 12, 24, 12, 24, 24, 48, 12, 24, 24, 48, 24, 48, 48, 96, + 2, 4, 4, 8, 4, 8, 8, 16, 4, 8, 8, 16, 8, 16, 16, 32, + 4, 8, 8, 16, 8, 16, 16, 32, 8, 16, 16, 32, 16, 32, 32, 64, + 5, 10, 10, 20, 10, 20, 20, 40, 10, 20, 20, 40, 20, 40, 40, 80, + 10, 20, 20, 40, 20, 40, 40, 80, 20, 40, 40, 80, 40, 80, 80, 160, + }, { + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 2, 5, 4, 9, 4, 9, 8, 17, 4, 9, 8, 17, 8, 17, 16, 33, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 2, 5, 4, 9, 4, 9, 8, 17, 4, 9, 8, 17, 8, 17, 16, 33, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 2, 5, 4, 9, 4, 9, 8, 17, 4, 9, 8, 17, 8, 17, 16, 33, + 3, 7, 6, 13, 6, 13, 12, 25, 6, 13, 12, 25, 12, 25, 24, 49, + 6, 13, 12, 25, 12, 25, 24, 49, 12, 25, 24, 49, 24, 49, 48, 97, + 2, 5, 4, 9, 4, 9, 8, 17, 4, 9, 8, 17, 8, 17, 16, 33, + 4, 9, 8, 17, 8, 17, 16, 33, 8, 17, 16, 33, 16, 33, 32, 65, + 5, 11, 10, 21, 10, 21, 20, 41, 10, 21, 20, 41, 20, 41, 40, 81, + 10, 21, 20, 41, 20, 41, 40, 81, 20, 41, 40, 81, 40, 81, 80, 161, + }, { + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 2, 4, 5, 10, 4, 8, 9, 18, 4, 8, 9, 18, 8, 16, 17, 34, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 2, 4, 5, 10, 4, 8, 9, 18, 4, 8, 9, 18, 8, 16, 17, 34, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 2, 4, 5, 10, 4, 8, 9, 18, 4, 8, 9, 18, 8, 16, 17, 34, + 3, 6, 7, 14, 6, 12, 13, 26, 6, 12, 13, 26, 12, 24, 25, 50, + 6, 12, 13, 26, 12, 24, 25, 50, 12, 24, 25, 50, 24, 48, 49, 98, + 2, 4, 5, 10, 4, 8, 9, 18, 4, 8, 9, 18, 8, 16, 17, 34, + 4, 8, 9, 18, 8, 16, 17, 34, 8, 16, 17, 34, 16, 32, 33, 66, + 5, 10, 11, 22, 10, 20, 21, 42, 10, 20, 21, 42, 20, 40, 41, 82, + 10, 20, 21, 42, 20, 40, 41, 82, 20, 40, 41, 82, 40, 80, 81, 162, + }, { + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 2, 5, 5, 11, 4, 9, 9, 19, 4, 9, 9, 19, 8, 17, 17, 35, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 2, 5, 5, 11, 4, 9, 9, 19, 4, 9, 9, 19, 8, 17, 17, 35, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 2, 5, 5, 11, 4, 9, 9, 19, 4, 9, 9, 19, 8, 17, 17, 35, + 3, 7, 7, 15, 6, 13, 13, 27, 6, 13, 13, 27, 12, 25, 25, 51, + 6, 13, 13, 27, 12, 25, 25, 51, 12, 25, 25, 51, 24, 49, 49, 99, + 2, 5, 5, 11, 4, 9, 9, 19, 4, 9, 9, 19, 8, 17, 17, 35, + 4, 9, 9, 19, 8, 17, 17, 35, 8, 17, 17, 35, 16, 33, 33, 67, + 5, 11, 11, 23, 10, 21, 21, 43, 10, 21, 21, 43, 20, 41, 41, 83, + 10, 21, 21, 43, 20, 41, 41, 83, 20, 41, 41, 83, 40, 81, 81, 163, + }, + { + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 2, 4, 4, 8, 5, 10, 10, 20, 4, 8, 8, 16, 9, 18, 18, 36, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 2, 4, 4, 8, 5, 10, 10, 20, 4, 8, 8, 16, 9, 18, 18, 36, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 2, 4, 4, 8, 5, 10, 10, 20, 4, 8, 8, 16, 9, 18, 18, 36, + 3, 6, 6, 12, 7, 14, 14, 28, 6, 12, 12, 24, 13, 26, 26, 52, + 6, 12, 12, 24, 13, 26, 26, 52, 12, 24, 24, 48, 25, 50, 50, 100, + 2, 4, 4, 8, 5, 10, 10, 20, 4, 8, 8, 16, 9, 18, 18, 36, + 4, 8, 8, 16, 9, 18, 18, 36, 8, 16, 16, 32, 17, 34, 34, 68, + 5, 10, 10, 20, 11, 22, 22, 44, 10, 20, 20, 40, 21, 42, 42, 84, + 10, 20, 20, 40, 21, 42, 42, 84, 20, 40, 40, 80, 41, 82, 82, 164, + }, { + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 2, 5, 4, 9, 5, 11, 10, 21, 4, 9, 8, 17, 9, 19, 18, 37, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 2, 5, 4, 9, 5, 11, 10, 21, 4, 9, 8, 17, 9, 19, 18, 37, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 2, 5, 4, 9, 5, 11, 10, 21, 4, 9, 8, 17, 9, 19, 18, 37, + 3, 7, 6, 13, 7, 15, 14, 29, 6, 13, 12, 25, 13, 27, 26, 53, + 6, 13, 12, 25, 13, 27, 26, 53, 12, 25, 24, 49, 25, 51, 50, 101, + 2, 5, 4, 9, 5, 11, 10, 21, 4, 9, 8, 17, 9, 19, 18, 37, + 4, 9, 8, 17, 9, 19, 18, 37, 8, 17, 16, 33, 17, 35, 34, 69, + 5, 11, 10, 21, 11, 23, 22, 45, 10, 21, 20, 41, 21, 43, 42, 85, + 10, 21, 20, 41, 21, 43, 42, 85, 20, 41, 40, 81, 41, 83, 82, 165, + }, { + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 2, 4, 5, 10, 5, 10, 11, 22, 4, 8, 9, 18, 9, 18, 19, 38, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 2, 4, 5, 10, 5, 10, 11, 22, 4, 8, 9, 18, 9, 18, 19, 38, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 2, 4, 5, 10, 5, 10, 11, 22, 4, 8, 9, 18, 9, 18, 19, 38, + 3, 6, 7, 14, 7, 14, 15, 30, 6, 12, 13, 26, 13, 26, 27, 54, + 6, 12, 13, 26, 13, 26, 27, 54, 12, 24, 25, 50, 25, 50, 51, 102, + 2, 4, 5, 10, 5, 10, 11, 22, 4, 8, 9, 18, 9, 18, 19, 38, + 4, 8, 9, 18, 9, 18, 19, 38, 8, 16, 17, 34, 17, 34, 35, 70, + 5, 10, 11, 22, 11, 22, 23, 46, 10, 20, 21, 42, 21, 42, 43, 86, + 10, 20, 21, 42, 21, 42, 43, 86, 20, 40, 41, 82, 41, 82, 83, 166, + }, { + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 2, 5, 5, 11, 5, 11, 11, 23, 4, 9, 9, 19, 9, 19, 19, 39, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 2, 5, 5, 11, 5, 11, 11, 23, 4, 9, 9, 19, 9, 19, 19, 39, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 2, 5, 5, 11, 5, 11, 11, 23, 4, 9, 9, 19, 9, 19, 19, 39, + 3, 7, 7, 15, 7, 15, 15, 31, 6, 13, 13, 27, 13, 27, 27, 55, + 6, 13, 13, 27, 13, 27, 27, 55, 12, 25, 25, 51, 25, 51, 51, 103, + 2, 5, 5, 11, 5, 11, 11, 23, 4, 9, 9, 19, 9, 19, 19, 39, + 4, 9, 9, 19, 9, 19, 19, 39, 8, 17, 17, 35, 17, 35, 35, 71, + 5, 11, 11, 23, 11, 23, 23, 47, 10, 21, 21, 43, 21, 43, 43, 87, + 10, 21, 21, 43, 21, 43, 43, 87, 20, 41, 41, 83, 41, 83, 83, 167, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 2, 4, 4, 8, 4, 8, 8, 16, 5, 10, 10, 20, 10, 20, 20, 40, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 2, 4, 4, 8, 4, 8, 8, 16, 5, 10, 10, 20, 10, 20, 20, 40, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 2, 4, 4, 8, 4, 8, 8, 16, 5, 10, 10, 20, 10, 20, 20, 40, + 3, 6, 6, 12, 6, 12, 12, 24, 7, 14, 14, 28, 14, 28, 28, 56, + 6, 12, 12, 24, 12, 24, 24, 48, 13, 26, 26, 52, 26, 52, 52, 104, + 2, 4, 4, 8, 4, 8, 8, 16, 5, 10, 10, 20, 10, 20, 20, 40, + 4, 8, 8, 16, 8, 16, 16, 32, 9, 18, 18, 36, 18, 36, 36, 72, + 5, 10, 10, 20, 10, 20, 20, 40, 11, 22, 22, 44, 22, 44, 44, 88, + 10, 20, 20, 40, 20, 40, 40, 80, 21, 42, 42, 84, 42, 84, 84, 168, + }, { + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 2, 5, 4, 9, 4, 9, 8, 17, 5, 11, 10, 21, 10, 21, 20, 41, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 2, 5, 4, 9, 4, 9, 8, 17, 5, 11, 10, 21, 10, 21, 20, 41, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 2, 5, 4, 9, 4, 9, 8, 17, 5, 11, 10, 21, 10, 21, 20, 41, + 3, 7, 6, 13, 6, 13, 12, 25, 7, 15, 14, 29, 14, 29, 28, 57, + 6, 13, 12, 25, 12, 25, 24, 49, 13, 27, 26, 53, 26, 53, 52, 105, + 2, 5, 4, 9, 4, 9, 8, 17, 5, 11, 10, 21, 10, 21, 20, 41, + 4, 9, 8, 17, 8, 17, 16, 33, 9, 19, 18, 37, 18, 37, 36, 73, + 5, 11, 10, 21, 10, 21, 20, 41, 11, 23, 22, 45, 22, 45, 44, 89, + 10, 21, 20, 41, 20, 41, 40, 81, 21, 43, 42, 85, 42, 85, 84, 169, + }, { + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 2, 4, 5, 10, 4, 8, 9, 18, 5, 10, 11, 22, 10, 20, 21, 42, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 2, 4, 5, 10, 4, 8, 9, 18, 5, 10, 11, 22, 10, 20, 21, 42, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 2, 4, 5, 10, 4, 8, 9, 18, 5, 10, 11, 22, 10, 20, 21, 42, + 3, 6, 7, 14, 6, 12, 13, 26, 7, 14, 15, 30, 14, 28, 29, 58, + 6, 12, 13, 26, 12, 24, 25, 50, 13, 26, 27, 54, 26, 52, 53, 106, + 2, 4, 5, 10, 4, 8, 9, 18, 5, 10, 11, 22, 10, 20, 21, 42, + 4, 8, 9, 18, 8, 16, 17, 34, 9, 18, 19, 38, 18, 36, 37, 74, + 5, 10, 11, 22, 10, 20, 21, 42, 11, 22, 23, 46, 22, 44, 45, 90, + 10, 20, 21, 42, 20, 40, 41, 82, 21, 42, 43, 86, 42, 84, 85, 170, + }, { + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 2, 5, 5, 11, 4, 9, 9, 19, 5, 11, 11, 23, 10, 21, 21, 43, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 2, 5, 5, 11, 4, 9, 9, 19, 5, 11, 11, 23, 10, 21, 21, 43, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 2, 5, 5, 11, 4, 9, 9, 19, 5, 11, 11, 23, 10, 21, 21, 43, + 3, 7, 7, 15, 6, 13, 13, 27, 7, 15, 15, 31, 14, 29, 29, 59, + 6, 13, 13, 27, 12, 25, 25, 51, 13, 27, 27, 55, 26, 53, 53, 107, + 2, 5, 5, 11, 4, 9, 9, 19, 5, 11, 11, 23, 10, 21, 21, 43, + 4, 9, 9, 19, 8, 17, 17, 35, 9, 19, 19, 39, 18, 37, 37, 75, + 5, 11, 11, 23, 10, 21, 21, 43, 11, 23, 23, 47, 22, 45, 45, 91, + 10, 21, 21, 43, 20, 41, 41, 83, 21, 43, 43, 87, 42, 85, 85, 171, + }, + { + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 2, 4, 4, 8, 5, 10, 10, 20, 5, 10, 10, 20, 11, 22, 22, 44, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 2, 4, 4, 8, 5, 10, 10, 20, 5, 10, 10, 20, 11, 22, 22, 44, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 2, 4, 4, 8, 5, 10, 10, 20, 5, 10, 10, 20, 11, 22, 22, 44, + 3, 6, 6, 12, 7, 14, 14, 28, 7, 14, 14, 28, 15, 30, 30, 60, + 6, 12, 12, 24, 13, 26, 26, 52, 13, 26, 26, 52, 27, 54, 54, 108, + 2, 4, 4, 8, 5, 10, 10, 20, 5, 10, 10, 20, 11, 22, 22, 44, + 4, 8, 8, 16, 9, 18, 18, 36, 9, 18, 18, 36, 19, 38, 38, 76, + 5, 10, 10, 20, 11, 22, 22, 44, 11, 22, 22, 44, 23, 46, 46, 92, + 10, 20, 20, 40, 21, 42, 42, 84, 21, 42, 42, 84, 43, 86, 86, 172, + }, { + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 2, 5, 4, 9, 5, 11, 10, 21, 5, 11, 10, 21, 11, 23, 22, 45, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 2, 5, 4, 9, 5, 11, 10, 21, 5, 11, 10, 21, 11, 23, 22, 45, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 2, 5, 4, 9, 5, 11, 10, 21, 5, 11, 10, 21, 11, 23, 22, 45, + 3, 7, 6, 13, 7, 15, 14, 29, 7, 15, 14, 29, 15, 31, 30, 61, + 6, 13, 12, 25, 13, 27, 26, 53, 13, 27, 26, 53, 27, 55, 54, 109, + 2, 5, 4, 9, 5, 11, 10, 21, 5, 11, 10, 21, 11, 23, 22, 45, + 4, 9, 8, 17, 9, 19, 18, 37, 9, 19, 18, 37, 19, 39, 38, 77, + 5, 11, 10, 21, 11, 23, 22, 45, 11, 23, 22, 45, 23, 47, 46, 93, + 10, 21, 20, 41, 21, 43, 42, 85, 21, 43, 42, 85, 43, 87, 86, 173, + }, { + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 2, 4, 5, 10, 5, 10, 11, 22, 5, 10, 11, 22, 11, 22, 23, 46, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 2, 4, 5, 10, 5, 10, 11, 22, 5, 10, 11, 22, 11, 22, 23, 46, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 2, 4, 5, 10, 5, 10, 11, 22, 5, 10, 11, 22, 11, 22, 23, 46, + 3, 6, 7, 14, 7, 14, 15, 30, 7, 14, 15, 30, 15, 30, 31, 62, + 6, 12, 13, 26, 13, 26, 27, 54, 13, 26, 27, 54, 27, 54, 55, 110, + 2, 4, 5, 10, 5, 10, 11, 22, 5, 10, 11, 22, 11, 22, 23, 46, + 4, 8, 9, 18, 9, 18, 19, 38, 9, 18, 19, 38, 19, 38, 39, 78, + 5, 10, 11, 22, 11, 22, 23, 46, 11, 22, 23, 46, 23, 46, 47, 94, + 10, 20, 21, 42, 21, 42, 43, 86, 21, 42, 43, 86, 43, 86, 87, 174, + }, { + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 2, 5, 5, 11, 5, 11, 11, 23, 5, 11, 11, 23, 11, 23, 23, 47, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 2, 5, 5, 11, 5, 11, 11, 23, 5, 11, 11, 23, 11, 23, 23, 47, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 2, 5, 5, 11, 5, 11, 11, 23, 5, 11, 11, 23, 11, 23, 23, 47, + 3, 7, 7, 15, 7, 15, 15, 31, 7, 15, 15, 31, 15, 31, 31, 63, + 6, 13, 13, 27, 13, 27, 27, 55, 13, 27, 27, 55, 27, 55, 55, 111, + 2, 5, 5, 11, 5, 11, 11, 23, 5, 11, 11, 23, 11, 23, 23, 47, + 4, 9, 9, 19, 9, 19, 19, 39, 9, 19, 19, 39, 19, 39, 39, 79, + 5, 11, 11, 23, 11, 23, 23, 47, 11, 23, 23, 47, 23, 47, 47, 95, + 10, 21, 21, 43, 21, 43, 43, 87, 21, 43, 43, 87, 43, 87, 87, 175, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 3, 6, 6, 12, 6, 12, 12, 24, 6, 12, 12, 24, 12, 24, 24, 48, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 3, 6, 6, 12, 6, 12, 12, 24, 6, 12, 12, 24, 12, 24, 24, 48, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 3, 6, 6, 12, 6, 12, 12, 24, 6, 12, 12, 24, 12, 24, 24, 48, + 3, 6, 6, 12, 6, 12, 12, 24, 6, 12, 12, 24, 12, 24, 24, 48, + 7, 14, 14, 28, 14, 28, 28, 56, 14, 28, 28, 56, 28, 56, 56, 112, + 2, 4, 4, 8, 4, 8, 8, 16, 4, 8, 8, 16, 8, 16, 16, 32, + 5, 10, 10, 20, 10, 20, 20, 40, 10, 20, 20, 40, 20, 40, 40, 80, + 5, 10, 10, 20, 10, 20, 20, 40, 10, 20, 20, 40, 20, 40, 40, 80, + 11, 22, 22, 44, 22, 44, 44, 88, 22, 44, 44, 88, 44, 88, 88, 176, + }, { + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 3, 7, 6, 13, 6, 13, 12, 25, 6, 13, 12, 25, 12, 25, 24, 49, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 3, 7, 6, 13, 6, 13, 12, 25, 6, 13, 12, 25, 12, 25, 24, 49, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 3, 7, 6, 13, 6, 13, 12, 25, 6, 13, 12, 25, 12, 25, 24, 49, + 3, 7, 6, 13, 6, 13, 12, 25, 6, 13, 12, 25, 12, 25, 24, 49, + 7, 15, 14, 29, 14, 29, 28, 57, 14, 29, 28, 57, 28, 57, 56, 113, + 2, 5, 4, 9, 4, 9, 8, 17, 4, 9, 8, 17, 8, 17, 16, 33, + 5, 11, 10, 21, 10, 21, 20, 41, 10, 21, 20, 41, 20, 41, 40, 81, + 5, 11, 10, 21, 10, 21, 20, 41, 10, 21, 20, 41, 20, 41, 40, 81, + 11, 23, 22, 45, 22, 45, 44, 89, 22, 45, 44, 89, 44, 89, 88, 177, + }, { + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 3, 6, 7, 14, 6, 12, 13, 26, 6, 12, 13, 26, 12, 24, 25, 50, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 3, 6, 7, 14, 6, 12, 13, 26, 6, 12, 13, 26, 12, 24, 25, 50, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 3, 6, 7, 14, 6, 12, 13, 26, 6, 12, 13, 26, 12, 24, 25, 50, + 3, 6, 7, 14, 6, 12, 13, 26, 6, 12, 13, 26, 12, 24, 25, 50, + 7, 14, 15, 30, 14, 28, 29, 58, 14, 28, 29, 58, 28, 56, 57, 114, + 2, 4, 5, 10, 4, 8, 9, 18, 4, 8, 9, 18, 8, 16, 17, 34, + 5, 10, 11, 22, 10, 20, 21, 42, 10, 20, 21, 42, 20, 40, 41, 82, + 5, 10, 11, 22, 10, 20, 21, 42, 10, 20, 21, 42, 20, 40, 41, 82, + 11, 22, 23, 46, 22, 44, 45, 90, 22, 44, 45, 90, 44, 88, 89, 178, + }, { + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 3, 7, 7, 15, 6, 13, 13, 27, 6, 13, 13, 27, 12, 25, 25, 51, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 3, 7, 7, 15, 6, 13, 13, 27, 6, 13, 13, 27, 12, 25, 25, 51, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 3, 7, 7, 15, 6, 13, 13, 27, 6, 13, 13, 27, 12, 25, 25, 51, + 3, 7, 7, 15, 6, 13, 13, 27, 6, 13, 13, 27, 12, 25, 25, 51, + 7, 15, 15, 31, 14, 29, 29, 59, 14, 29, 29, 59, 28, 57, 57, 115, + 2, 5, 5, 11, 4, 9, 9, 19, 4, 9, 9, 19, 8, 17, 17, 35, + 5, 11, 11, 23, 10, 21, 21, 43, 10, 21, 21, 43, 20, 41, 41, 83, + 5, 11, 11, 23, 10, 21, 21, 43, 10, 21, 21, 43, 20, 41, 41, 83, + 11, 23, 23, 47, 22, 45, 45, 91, 22, 45, 45, 91, 44, 89, 89, 179, + }, + { + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 3, 6, 6, 12, 7, 14, 14, 28, 6, 12, 12, 24, 13, 26, 26, 52, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 3, 6, 6, 12, 7, 14, 14, 28, 6, 12, 12, 24, 13, 26, 26, 52, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 3, 6, 6, 12, 7, 14, 14, 28, 6, 12, 12, 24, 13, 26, 26, 52, + 3, 6, 6, 12, 7, 14, 14, 28, 6, 12, 12, 24, 13, 26, 26, 52, + 7, 14, 14, 28, 15, 30, 30, 60, 14, 28, 28, 56, 29, 58, 58, 116, + 2, 4, 4, 8, 5, 10, 10, 20, 4, 8, 8, 16, 9, 18, 18, 36, + 5, 10, 10, 20, 11, 22, 22, 44, 10, 20, 20, 40, 21, 42, 42, 84, + 5, 10, 10, 20, 11, 22, 22, 44, 10, 20, 20, 40, 21, 42, 42, 84, + 11, 22, 22, 44, 23, 46, 46, 92, 22, 44, 44, 88, 45, 90, 90, 180, + }, { + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 3, 7, 6, 13, 7, 15, 14, 29, 6, 13, 12, 25, 13, 27, 26, 53, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 3, 7, 6, 13, 7, 15, 14, 29, 6, 13, 12, 25, 13, 27, 26, 53, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 3, 7, 6, 13, 7, 15, 14, 29, 6, 13, 12, 25, 13, 27, 26, 53, + 3, 7, 6, 13, 7, 15, 14, 29, 6, 13, 12, 25, 13, 27, 26, 53, + 7, 15, 14, 29, 15, 31, 30, 61, 14, 29, 28, 57, 29, 59, 58, 117, + 2, 5, 4, 9, 5, 11, 10, 21, 4, 9, 8, 17, 9, 19, 18, 37, + 5, 11, 10, 21, 11, 23, 22, 45, 10, 21, 20, 41, 21, 43, 42, 85, + 5, 11, 10, 21, 11, 23, 22, 45, 10, 21, 20, 41, 21, 43, 42, 85, + 11, 23, 22, 45, 23, 47, 46, 93, 22, 45, 44, 89, 45, 91, 90, 181, + }, { + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 3, 6, 7, 14, 7, 14, 15, 30, 6, 12, 13, 26, 13, 26, 27, 54, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 3, 6, 7, 14, 7, 14, 15, 30, 6, 12, 13, 26, 13, 26, 27, 54, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 3, 6, 7, 14, 7, 14, 15, 30, 6, 12, 13, 26, 13, 26, 27, 54, + 3, 6, 7, 14, 7, 14, 15, 30, 6, 12, 13, 26, 13, 26, 27, 54, + 7, 14, 15, 30, 15, 30, 31, 62, 14, 28, 29, 58, 29, 58, 59, 118, + 2, 4, 5, 10, 5, 10, 11, 22, 4, 8, 9, 18, 9, 18, 19, 38, + 5, 10, 11, 22, 11, 22, 23, 46, 10, 20, 21, 42, 21, 42, 43, 86, + 5, 10, 11, 22, 11, 22, 23, 46, 10, 20, 21, 42, 21, 42, 43, 86, + 11, 22, 23, 46, 23, 46, 47, 94, 22, 44, 45, 90, 45, 90, 91, 182, + }, { + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 3, 7, 7, 15, 7, 15, 15, 31, 6, 13, 13, 27, 13, 27, 27, 55, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 3, 7, 7, 15, 7, 15, 15, 31, 6, 13, 13, 27, 13, 27, 27, 55, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 3, 7, 7, 15, 7, 15, 15, 31, 6, 13, 13, 27, 13, 27, 27, 55, + 3, 7, 7, 15, 7, 15, 15, 31, 6, 13, 13, 27, 13, 27, 27, 55, + 7, 15, 15, 31, 15, 31, 31, 63, 14, 29, 29, 59, 29, 59, 59, 119, + 2, 5, 5, 11, 5, 11, 11, 23, 4, 9, 9, 19, 9, 19, 19, 39, + 5, 11, 11, 23, 11, 23, 23, 47, 10, 21, 21, 43, 21, 43, 43, 87, + 5, 11, 11, 23, 11, 23, 23, 47, 10, 21, 21, 43, 21, 43, 43, 87, + 11, 23, 23, 47, 23, 47, 47, 95, 22, 45, 45, 91, 45, 91, 91, 183, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 3, 6, 6, 12, 6, 12, 12, 24, 7, 14, 14, 28, 14, 28, 28, 56, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 3, 6, 6, 12, 6, 12, 12, 24, 7, 14, 14, 28, 14, 28, 28, 56, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 3, 6, 6, 12, 6, 12, 12, 24, 7, 14, 14, 28, 14, 28, 28, 56, + 3, 6, 6, 12, 6, 12, 12, 24, 7, 14, 14, 28, 14, 28, 28, 56, + 7, 14, 14, 28, 14, 28, 28, 56, 15, 30, 30, 60, 30, 60, 60, 120, + 2, 4, 4, 8, 4, 8, 8, 16, 5, 10, 10, 20, 10, 20, 20, 40, + 5, 10, 10, 20, 10, 20, 20, 40, 11, 22, 22, 44, 22, 44, 44, 88, + 5, 10, 10, 20, 10, 20, 20, 40, 11, 22, 22, 44, 22, 44, 44, 88, + 11, 22, 22, 44, 22, 44, 44, 88, 23, 46, 46, 92, 46, 92, 92, 184, + }, { + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 3, 7, 6, 13, 6, 13, 12, 25, 7, 15, 14, 29, 14, 29, 28, 57, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 3, 7, 6, 13, 6, 13, 12, 25, 7, 15, 14, 29, 14, 29, 28, 57, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 3, 7, 6, 13, 6, 13, 12, 25, 7, 15, 14, 29, 14, 29, 28, 57, + 3, 7, 6, 13, 6, 13, 12, 25, 7, 15, 14, 29, 14, 29, 28, 57, + 7, 15, 14, 29, 14, 29, 28, 57, 15, 31, 30, 61, 30, 61, 60, 121, + 2, 5, 4, 9, 4, 9, 8, 17, 5, 11, 10, 21, 10, 21, 20, 41, + 5, 11, 10, 21, 10, 21, 20, 41, 11, 23, 22, 45, 22, 45, 44, 89, + 5, 11, 10, 21, 10, 21, 20, 41, 11, 23, 22, 45, 22, 45, 44, 89, + 11, 23, 22, 45, 22, 45, 44, 89, 23, 47, 46, 93, 46, 93, 92, 185, + }, { + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 3, 6, 7, 14, 6, 12, 13, 26, 7, 14, 15, 30, 14, 28, 29, 58, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 3, 6, 7, 14, 6, 12, 13, 26, 7, 14, 15, 30, 14, 28, 29, 58, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 3, 6, 7, 14, 6, 12, 13, 26, 7, 14, 15, 30, 14, 28, 29, 58, + 3, 6, 7, 14, 6, 12, 13, 26, 7, 14, 15, 30, 14, 28, 29, 58, + 7, 14, 15, 30, 14, 28, 29, 58, 15, 30, 31, 62, 30, 60, 61, 122, + 2, 4, 5, 10, 4, 8, 9, 18, 5, 10, 11, 22, 10, 20, 21, 42, + 5, 10, 11, 22, 10, 20, 21, 42, 11, 22, 23, 46, 22, 44, 45, 90, + 5, 10, 11, 22, 10, 20, 21, 42, 11, 22, 23, 46, 22, 44, 45, 90, + 11, 22, 23, 46, 22, 44, 45, 90, 23, 46, 47, 94, 46, 92, 93, 186, + }, { + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 3, 7, 7, 15, 6, 13, 13, 27, 7, 15, 15, 31, 14, 29, 29, 59, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 3, 7, 7, 15, 6, 13, 13, 27, 7, 15, 15, 31, 14, 29, 29, 59, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 3, 7, 7, 15, 6, 13, 13, 27, 7, 15, 15, 31, 14, 29, 29, 59, + 3, 7, 7, 15, 6, 13, 13, 27, 7, 15, 15, 31, 14, 29, 29, 59, + 7, 15, 15, 31, 14, 29, 29, 59, 15, 31, 31, 63, 30, 61, 61, 123, + 2, 5, 5, 11, 4, 9, 9, 19, 5, 11, 11, 23, 10, 21, 21, 43, + 5, 11, 11, 23, 10, 21, 21, 43, 11, 23, 23, 47, 22, 45, 45, 91, + 5, 11, 11, 23, 10, 21, 21, 43, 11, 23, 23, 47, 22, 45, 45, 91, + 11, 23, 23, 47, 22, 45, 45, 91, 23, 47, 47, 95, 46, 93, 93, 187, + }, + { + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 3, 6, 6, 12, 7, 14, 14, 28, 7, 14, 14, 28, 15, 30, 30, 60, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 3, 6, 6, 12, 7, 14, 14, 28, 7, 14, 14, 28, 15, 30, 30, 60, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 3, 6, 6, 12, 7, 14, 14, 28, 7, 14, 14, 28, 15, 30, 30, 60, + 3, 6, 6, 12, 7, 14, 14, 28, 7, 14, 14, 28, 15, 30, 30, 60, + 7, 14, 14, 28, 15, 30, 30, 60, 15, 30, 30, 60, 31, 62, 62, 124, + 2, 4, 4, 8, 5, 10, 10, 20, 5, 10, 10, 20, 11, 22, 22, 44, + 5, 10, 10, 20, 11, 22, 22, 44, 11, 22, 22, 44, 23, 46, 46, 92, + 5, 10, 10, 20, 11, 22, 22, 44, 11, 22, 22, 44, 23, 46, 46, 92, + 11, 22, 22, 44, 23, 46, 46, 92, 23, 46, 46, 92, 47, 94, 94, 188, + }, { + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 3, 7, 6, 13, 7, 15, 14, 29, 7, 15, 14, 29, 15, 31, 30, 61, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 3, 7, 6, 13, 7, 15, 14, 29, 7, 15, 14, 29, 15, 31, 30, 61, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 3, 7, 6, 13, 7, 15, 14, 29, 7, 15, 14, 29, 15, 31, 30, 61, + 3, 7, 6, 13, 7, 15, 14, 29, 7, 15, 14, 29, 15, 31, 30, 61, + 7, 15, 14, 29, 15, 31, 30, 61, 15, 31, 30, 61, 31, 63, 62, 125, + 2, 5, 4, 9, 5, 11, 10, 21, 5, 11, 10, 21, 11, 23, 22, 45, + 5, 11, 10, 21, 11, 23, 22, 45, 11, 23, 22, 45, 23, 47, 46, 93, + 5, 11, 10, 21, 11, 23, 22, 45, 11, 23, 22, 45, 23, 47, 46, 93, + 11, 23, 22, 45, 23, 47, 46, 93, 23, 47, 46, 93, 47, 95, 94, 189, + }, { + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 3, 6, 7, 14, 7, 14, 15, 30, 7, 14, 15, 30, 15, 30, 31, 62, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 3, 6, 7, 14, 7, 14, 15, 30, 7, 14, 15, 30, 15, 30, 31, 62, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 3, 6, 7, 14, 7, 14, 15, 30, 7, 14, 15, 30, 15, 30, 31, 62, + 3, 6, 7, 14, 7, 14, 15, 30, 7, 14, 15, 30, 15, 30, 31, 62, + 7, 14, 15, 30, 15, 30, 31, 62, 15, 30, 31, 62, 31, 62, 63, 126, + 2, 4, 5, 10, 5, 10, 11, 22, 5, 10, 11, 22, 11, 22, 23, 46, + 5, 10, 11, 22, 11, 22, 23, 46, 11, 22, 23, 46, 23, 46, 47, 94, + 5, 10, 11, 22, 11, 22, 23, 46, 11, 22, 23, 46, 23, 46, 47, 94, + 11, 22, 23, 46, 23, 46, 47, 94, 23, 46, 47, 94, 47, 94, 95, 190, + }, { + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 3, 7, 7, 15, 7, 15, 15, 31, 7, 15, 15, 31, 15, 31, 31, 63, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 3, 7, 7, 15, 7, 15, 15, 31, 7, 15, 15, 31, 15, 31, 31, 63, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 3, 7, 7, 15, 7, 15, 15, 31, 7, 15, 15, 31, 15, 31, 31, 63, + 3, 7, 7, 15, 7, 15, 15, 31, 7, 15, 15, 31, 15, 31, 31, 63, + 7, 15, 15, 31, 15, 31, 31, 63, 15, 31, 31, 63, 31, 63, 63, 127, + 2, 5, 5, 11, 5, 11, 11, 23, 5, 11, 11, 23, 11, 23, 23, 47, + 5, 11, 11, 23, 11, 23, 23, 47, 11, 23, 23, 47, 23, 47, 47, 95, + 5, 11, 11, 23, 11, 23, 23, 47, 11, 23, 23, 47, 23, 47, 47, 95, + 11, 23, 23, 47, 23, 47, 47, 95, 23, 47, 47, 95, 47, 95, 95, 191, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 2, 4, 4, 8, 4, 8, 8, 16, 4, 8, 8, 16, 8, 16, 16, 32, + 2, 4, 4, 8, 4, 8, 8, 16, 4, 8, 8, 16, 8, 16, 16, 32, + 4, 8, 8, 16, 8, 16, 16, 32, 8, 16, 16, 32, 16, 32, 32, 64, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 2, 4, 4, 8, 4, 8, 8, 16, 4, 8, 8, 16, 8, 16, 16, 32, + 2, 4, 4, 8, 4, 8, 8, 16, 4, 8, 8, 16, 8, 16, 16, 32, + 4, 8, 8, 16, 8, 16, 16, 32, 8, 16, 16, 32, 16, 32, 32, 64, + 3, 6, 6, 12, 6, 12, 12, 24, 6, 12, 12, 24, 12, 24, 24, 48, + 6, 12, 12, 24, 12, 24, 24, 48, 12, 24, 24, 48, 24, 48, 48, 96, + 6, 12, 12, 24, 12, 24, 24, 48, 12, 24, 24, 48, 24, 48, 48, 96, + 12, 24, 24, 48, 24, 48, 48, 96, 24, 48, 48, 96, 48, 96, 96, 192, + }, { + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 2, 5, 4, 9, 4, 9, 8, 17, 4, 9, 8, 17, 8, 17, 16, 33, + 2, 5, 4, 9, 4, 9, 8, 17, 4, 9, 8, 17, 8, 17, 16, 33, + 4, 9, 8, 17, 8, 17, 16, 33, 8, 17, 16, 33, 16, 33, 32, 65, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 2, 5, 4, 9, 4, 9, 8, 17, 4, 9, 8, 17, 8, 17, 16, 33, + 2, 5, 4, 9, 4, 9, 8, 17, 4, 9, 8, 17, 8, 17, 16, 33, + 4, 9, 8, 17, 8, 17, 16, 33, 8, 17, 16, 33, 16, 33, 32, 65, + 3, 7, 6, 13, 6, 13, 12, 25, 6, 13, 12, 25, 12, 25, 24, 49, + 6, 13, 12, 25, 12, 25, 24, 49, 12, 25, 24, 49, 24, 49, 48, 97, + 6, 13, 12, 25, 12, 25, 24, 49, 12, 25, 24, 49, 24, 49, 48, 97, + 12, 25, 24, 49, 24, 49, 48, 97, 24, 49, 48, 97, 48, 97, 96, 193, + }, { + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 2, 4, 5, 10, 4, 8, 9, 18, 4, 8, 9, 18, 8, 16, 17, 34, + 2, 4, 5, 10, 4, 8, 9, 18, 4, 8, 9, 18, 8, 16, 17, 34, + 4, 8, 9, 18, 8, 16, 17, 34, 8, 16, 17, 34, 16, 32, 33, 66, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 2, 4, 5, 10, 4, 8, 9, 18, 4, 8, 9, 18, 8, 16, 17, 34, + 2, 4, 5, 10, 4, 8, 9, 18, 4, 8, 9, 18, 8, 16, 17, 34, + 4, 8, 9, 18, 8, 16, 17, 34, 8, 16, 17, 34, 16, 32, 33, 66, + 3, 6, 7, 14, 6, 12, 13, 26, 6, 12, 13, 26, 12, 24, 25, 50, + 6, 12, 13, 26, 12, 24, 25, 50, 12, 24, 25, 50, 24, 48, 49, 98, + 6, 12, 13, 26, 12, 24, 25, 50, 12, 24, 25, 50, 24, 48, 49, 98, + 12, 24, 25, 50, 24, 48, 49, 98, 24, 48, 49, 98, 48, 96, 97, 194, + }, { + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 2, 5, 5, 11, 4, 9, 9, 19, 4, 9, 9, 19, 8, 17, 17, 35, + 2, 5, 5, 11, 4, 9, 9, 19, 4, 9, 9, 19, 8, 17, 17, 35, + 4, 9, 9, 19, 8, 17, 17, 35, 8, 17, 17, 35, 16, 33, 33, 67, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 2, 5, 5, 11, 4, 9, 9, 19, 4, 9, 9, 19, 8, 17, 17, 35, + 2, 5, 5, 11, 4, 9, 9, 19, 4, 9, 9, 19, 8, 17, 17, 35, + 4, 9, 9, 19, 8, 17, 17, 35, 8, 17, 17, 35, 16, 33, 33, 67, + 3, 7, 7, 15, 6, 13, 13, 27, 6, 13, 13, 27, 12, 25, 25, 51, + 6, 13, 13, 27, 12, 25, 25, 51, 12, 25, 25, 51, 24, 49, 49, 99, + 6, 13, 13, 27, 12, 25, 25, 51, 12, 25, 25, 51, 24, 49, 49, 99, + 12, 25, 25, 51, 24, 49, 49, 99, 24, 49, 49, 99, 48, 97, 97, 195, + }, + { + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 2, 4, 4, 8, 5, 10, 10, 20, 4, 8, 8, 16, 9, 18, 18, 36, + 2, 4, 4, 8, 5, 10, 10, 20, 4, 8, 8, 16, 9, 18, 18, 36, + 4, 8, 8, 16, 9, 18, 18, 36, 8, 16, 16, 32, 17, 34, 34, 68, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 2, 4, 4, 8, 5, 10, 10, 20, 4, 8, 8, 16, 9, 18, 18, 36, + 2, 4, 4, 8, 5, 10, 10, 20, 4, 8, 8, 16, 9, 18, 18, 36, + 4, 8, 8, 16, 9, 18, 18, 36, 8, 16, 16, 32, 17, 34, 34, 68, + 3, 6, 6, 12, 7, 14, 14, 28, 6, 12, 12, 24, 13, 26, 26, 52, + 6, 12, 12, 24, 13, 26, 26, 52, 12, 24, 24, 48, 25, 50, 50, 100, + 6, 12, 12, 24, 13, 26, 26, 52, 12, 24, 24, 48, 25, 50, 50, 100, + 12, 24, 24, 48, 25, 50, 50, 100, 24, 48, 48, 96, 49, 98, 98, 196, + }, { + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 2, 5, 4, 9, 5, 11, 10, 21, 4, 9, 8, 17, 9, 19, 18, 37, + 2, 5, 4, 9, 5, 11, 10, 21, 4, 9, 8, 17, 9, 19, 18, 37, + 4, 9, 8, 17, 9, 19, 18, 37, 8, 17, 16, 33, 17, 35, 34, 69, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 2, 5, 4, 9, 5, 11, 10, 21, 4, 9, 8, 17, 9, 19, 18, 37, + 2, 5, 4, 9, 5, 11, 10, 21, 4, 9, 8, 17, 9, 19, 18, 37, + 4, 9, 8, 17, 9, 19, 18, 37, 8, 17, 16, 33, 17, 35, 34, 69, + 3, 7, 6, 13, 7, 15, 14, 29, 6, 13, 12, 25, 13, 27, 26, 53, + 6, 13, 12, 25, 13, 27, 26, 53, 12, 25, 24, 49, 25, 51, 50, 101, + 6, 13, 12, 25, 13, 27, 26, 53, 12, 25, 24, 49, 25, 51, 50, 101, + 12, 25, 24, 49, 25, 51, 50, 101, 24, 49, 48, 97, 49, 99, 98, 197, + }, { + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 2, 4, 5, 10, 5, 10, 11, 22, 4, 8, 9, 18, 9, 18, 19, 38, + 2, 4, 5, 10, 5, 10, 11, 22, 4, 8, 9, 18, 9, 18, 19, 38, + 4, 8, 9, 18, 9, 18, 19, 38, 8, 16, 17, 34, 17, 34, 35, 70, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 2, 4, 5, 10, 5, 10, 11, 22, 4, 8, 9, 18, 9, 18, 19, 38, + 2, 4, 5, 10, 5, 10, 11, 22, 4, 8, 9, 18, 9, 18, 19, 38, + 4, 8, 9, 18, 9, 18, 19, 38, 8, 16, 17, 34, 17, 34, 35, 70, + 3, 6, 7, 14, 7, 14, 15, 30, 6, 12, 13, 26, 13, 26, 27, 54, + 6, 12, 13, 26, 13, 26, 27, 54, 12, 24, 25, 50, 25, 50, 51, 102, + 6, 12, 13, 26, 13, 26, 27, 54, 12, 24, 25, 50, 25, 50, 51, 102, + 12, 24, 25, 50, 25, 50, 51, 102, 24, 48, 49, 98, 49, 98, 99, 198, + }, { + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 2, 5, 5, 11, 5, 11, 11, 23, 4, 9, 9, 19, 9, 19, 19, 39, + 2, 5, 5, 11, 5, 11, 11, 23, 4, 9, 9, 19, 9, 19, 19, 39, + 4, 9, 9, 19, 9, 19, 19, 39, 8, 17, 17, 35, 17, 35, 35, 71, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 2, 5, 5, 11, 5, 11, 11, 23, 4, 9, 9, 19, 9, 19, 19, 39, + 2, 5, 5, 11, 5, 11, 11, 23, 4, 9, 9, 19, 9, 19, 19, 39, + 4, 9, 9, 19, 9, 19, 19, 39, 8, 17, 17, 35, 17, 35, 35, 71, + 3, 7, 7, 15, 7, 15, 15, 31, 6, 13, 13, 27, 13, 27, 27, 55, + 6, 13, 13, 27, 13, 27, 27, 55, 12, 25, 25, 51, 25, 51, 51, 103, + 6, 13, 13, 27, 13, 27, 27, 55, 12, 25, 25, 51, 25, 51, 51, 103, + 12, 25, 25, 51, 25, 51, 51, 103, 24, 49, 49, 99, 49, 99, 99, 199, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 2, 4, 4, 8, 4, 8, 8, 16, 5, 10, 10, 20, 10, 20, 20, 40, + 2, 4, 4, 8, 4, 8, 8, 16, 5, 10, 10, 20, 10, 20, 20, 40, + 4, 8, 8, 16, 8, 16, 16, 32, 9, 18, 18, 36, 18, 36, 36, 72, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 2, 4, 4, 8, 4, 8, 8, 16, 5, 10, 10, 20, 10, 20, 20, 40, + 2, 4, 4, 8, 4, 8, 8, 16, 5, 10, 10, 20, 10, 20, 20, 40, + 4, 8, 8, 16, 8, 16, 16, 32, 9, 18, 18, 36, 18, 36, 36, 72, + 3, 6, 6, 12, 6, 12, 12, 24, 7, 14, 14, 28, 14, 28, 28, 56, + 6, 12, 12, 24, 12, 24, 24, 48, 13, 26, 26, 52, 26, 52, 52, 104, + 6, 12, 12, 24, 12, 24, 24, 48, 13, 26, 26, 52, 26, 52, 52, 104, + 12, 24, 24, 48, 24, 48, 48, 96, 25, 50, 50, 100, 50, 100, 100, 200, + }, { + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 2, 5, 4, 9, 4, 9, 8, 17, 5, 11, 10, 21, 10, 21, 20, 41, + 2, 5, 4, 9, 4, 9, 8, 17, 5, 11, 10, 21, 10, 21, 20, 41, + 4, 9, 8, 17, 8, 17, 16, 33, 9, 19, 18, 37, 18, 37, 36, 73, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 2, 5, 4, 9, 4, 9, 8, 17, 5, 11, 10, 21, 10, 21, 20, 41, + 2, 5, 4, 9, 4, 9, 8, 17, 5, 11, 10, 21, 10, 21, 20, 41, + 4, 9, 8, 17, 8, 17, 16, 33, 9, 19, 18, 37, 18, 37, 36, 73, + 3, 7, 6, 13, 6, 13, 12, 25, 7, 15, 14, 29, 14, 29, 28, 57, + 6, 13, 12, 25, 12, 25, 24, 49, 13, 27, 26, 53, 26, 53, 52, 105, + 6, 13, 12, 25, 12, 25, 24, 49, 13, 27, 26, 53, 26, 53, 52, 105, + 12, 25, 24, 49, 24, 49, 48, 97, 25, 51, 50, 101, 50, 101, 100, 201, + }, { + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 2, 4, 5, 10, 4, 8, 9, 18, 5, 10, 11, 22, 10, 20, 21, 42, + 2, 4, 5, 10, 4, 8, 9, 18, 5, 10, 11, 22, 10, 20, 21, 42, + 4, 8, 9, 18, 8, 16, 17, 34, 9, 18, 19, 38, 18, 36, 37, 74, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 2, 4, 5, 10, 4, 8, 9, 18, 5, 10, 11, 22, 10, 20, 21, 42, + 2, 4, 5, 10, 4, 8, 9, 18, 5, 10, 11, 22, 10, 20, 21, 42, + 4, 8, 9, 18, 8, 16, 17, 34, 9, 18, 19, 38, 18, 36, 37, 74, + 3, 6, 7, 14, 6, 12, 13, 26, 7, 14, 15, 30, 14, 28, 29, 58, + 6, 12, 13, 26, 12, 24, 25, 50, 13, 26, 27, 54, 26, 52, 53, 106, + 6, 12, 13, 26, 12, 24, 25, 50, 13, 26, 27, 54, 26, 52, 53, 106, + 12, 24, 25, 50, 24, 48, 49, 98, 25, 50, 51, 102, 50, 100, 101, 202, + }, { + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 2, 5, 5, 11, 4, 9, 9, 19, 5, 11, 11, 23, 10, 21, 21, 43, + 2, 5, 5, 11, 4, 9, 9, 19, 5, 11, 11, 23, 10, 21, 21, 43, + 4, 9, 9, 19, 8, 17, 17, 35, 9, 19, 19, 39, 18, 37, 37, 75, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 2, 5, 5, 11, 4, 9, 9, 19, 5, 11, 11, 23, 10, 21, 21, 43, + 2, 5, 5, 11, 4, 9, 9, 19, 5, 11, 11, 23, 10, 21, 21, 43, + 4, 9, 9, 19, 8, 17, 17, 35, 9, 19, 19, 39, 18, 37, 37, 75, + 3, 7, 7, 15, 6, 13, 13, 27, 7, 15, 15, 31, 14, 29, 29, 59, + 6, 13, 13, 27, 12, 25, 25, 51, 13, 27, 27, 55, 26, 53, 53, 107, + 6, 13, 13, 27, 12, 25, 25, 51, 13, 27, 27, 55, 26, 53, 53, 107, + 12, 25, 25, 51, 24, 49, 49, 99, 25, 51, 51, 103, 50, 101, 101, 203, + }, + { + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 2, 4, 4, 8, 5, 10, 10, 20, 5, 10, 10, 20, 11, 22, 22, 44, + 2, 4, 4, 8, 5, 10, 10, 20, 5, 10, 10, 20, 11, 22, 22, 44, + 4, 8, 8, 16, 9, 18, 18, 36, 9, 18, 18, 36, 19, 38, 38, 76, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 2, 4, 4, 8, 5, 10, 10, 20, 5, 10, 10, 20, 11, 22, 22, 44, + 2, 4, 4, 8, 5, 10, 10, 20, 5, 10, 10, 20, 11, 22, 22, 44, + 4, 8, 8, 16, 9, 18, 18, 36, 9, 18, 18, 36, 19, 38, 38, 76, + 3, 6, 6, 12, 7, 14, 14, 28, 7, 14, 14, 28, 15, 30, 30, 60, + 6, 12, 12, 24, 13, 26, 26, 52, 13, 26, 26, 52, 27, 54, 54, 108, + 6, 12, 12, 24, 13, 26, 26, 52, 13, 26, 26, 52, 27, 54, 54, 108, + 12, 24, 24, 48, 25, 50, 50, 100, 25, 50, 50, 100, 51, 102, 102, 204, + }, { + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 2, 5, 4, 9, 5, 11, 10, 21, 5, 11, 10, 21, 11, 23, 22, 45, + 2, 5, 4, 9, 5, 11, 10, 21, 5, 11, 10, 21, 11, 23, 22, 45, + 4, 9, 8, 17, 9, 19, 18, 37, 9, 19, 18, 37, 19, 39, 38, 77, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 2, 5, 4, 9, 5, 11, 10, 21, 5, 11, 10, 21, 11, 23, 22, 45, + 2, 5, 4, 9, 5, 11, 10, 21, 5, 11, 10, 21, 11, 23, 22, 45, + 4, 9, 8, 17, 9, 19, 18, 37, 9, 19, 18, 37, 19, 39, 38, 77, + 3, 7, 6, 13, 7, 15, 14, 29, 7, 15, 14, 29, 15, 31, 30, 61, + 6, 13, 12, 25, 13, 27, 26, 53, 13, 27, 26, 53, 27, 55, 54, 109, + 6, 13, 12, 25, 13, 27, 26, 53, 13, 27, 26, 53, 27, 55, 54, 109, + 12, 25, 24, 49, 25, 51, 50, 101, 25, 51, 50, 101, 51, 103, 102, 205, + }, { + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 2, 4, 5, 10, 5, 10, 11, 22, 5, 10, 11, 22, 11, 22, 23, 46, + 2, 4, 5, 10, 5, 10, 11, 22, 5, 10, 11, 22, 11, 22, 23, 46, + 4, 8, 9, 18, 9, 18, 19, 38, 9, 18, 19, 38, 19, 38, 39, 78, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 2, 4, 5, 10, 5, 10, 11, 22, 5, 10, 11, 22, 11, 22, 23, 46, + 2, 4, 5, 10, 5, 10, 11, 22, 5, 10, 11, 22, 11, 22, 23, 46, + 4, 8, 9, 18, 9, 18, 19, 38, 9, 18, 19, 38, 19, 38, 39, 78, + 3, 6, 7, 14, 7, 14, 15, 30, 7, 14, 15, 30, 15, 30, 31, 62, + 6, 12, 13, 26, 13, 26, 27, 54, 13, 26, 27, 54, 27, 54, 55, 110, + 6, 12, 13, 26, 13, 26, 27, 54, 13, 26, 27, 54, 27, 54, 55, 110, + 12, 24, 25, 50, 25, 50, 51, 102, 25, 50, 51, 102, 51, 102, 103, 206, + }, { + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 2, 5, 5, 11, 5, 11, 11, 23, 5, 11, 11, 23, 11, 23, 23, 47, + 2, 5, 5, 11, 5, 11, 11, 23, 5, 11, 11, 23, 11, 23, 23, 47, + 4, 9, 9, 19, 9, 19, 19, 39, 9, 19, 19, 39, 19, 39, 39, 79, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 2, 5, 5, 11, 5, 11, 11, 23, 5, 11, 11, 23, 11, 23, 23, 47, + 2, 5, 5, 11, 5, 11, 11, 23, 5, 11, 11, 23, 11, 23, 23, 47, + 4, 9, 9, 19, 9, 19, 19, 39, 9, 19, 19, 39, 19, 39, 39, 79, + 3, 7, 7, 15, 7, 15, 15, 31, 7, 15, 15, 31, 15, 31, 31, 63, + 6, 13, 13, 27, 13, 27, 27, 55, 13, 27, 27, 55, 27, 55, 55, 111, + 6, 13, 13, 27, 13, 27, 27, 55, 13, 27, 27, 55, 27, 55, 55, 111, + 12, 25, 25, 51, 25, 51, 51, 103, 25, 51, 51, 103, 51, 103, 103, 207, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 3, 6, 6, 12, 6, 12, 12, 24, 6, 12, 12, 24, 12, 24, 24, 48, + 2, 4, 4, 8, 4, 8, 8, 16, 4, 8, 8, 16, 8, 16, 16, 32, + 5, 10, 10, 20, 10, 20, 20, 40, 10, 20, 20, 40, 20, 40, 40, 80, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 3, 6, 6, 12, 6, 12, 12, 24, 6, 12, 12, 24, 12, 24, 24, 48, + 2, 4, 4, 8, 4, 8, 8, 16, 4, 8, 8, 16, 8, 16, 16, 32, + 5, 10, 10, 20, 10, 20, 20, 40, 10, 20, 20, 40, 20, 40, 40, 80, + 3, 6, 6, 12, 6, 12, 12, 24, 6, 12, 12, 24, 12, 24, 24, 48, + 7, 14, 14, 28, 14, 28, 28, 56, 14, 28, 28, 56, 28, 56, 56, 112, + 6, 12, 12, 24, 12, 24, 24, 48, 12, 24, 24, 48, 24, 48, 48, 96, + 13, 26, 26, 52, 26, 52, 52, 104, 26, 52, 52, 104, 52, 104, 104, 208, + }, { + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 3, 7, 6, 13, 6, 13, 12, 25, 6, 13, 12, 25, 12, 25, 24, 49, + 2, 5, 4, 9, 4, 9, 8, 17, 4, 9, 8, 17, 8, 17, 16, 33, + 5, 11, 10, 21, 10, 21, 20, 41, 10, 21, 20, 41, 20, 41, 40, 81, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 3, 7, 6, 13, 6, 13, 12, 25, 6, 13, 12, 25, 12, 25, 24, 49, + 2, 5, 4, 9, 4, 9, 8, 17, 4, 9, 8, 17, 8, 17, 16, 33, + 5, 11, 10, 21, 10, 21, 20, 41, 10, 21, 20, 41, 20, 41, 40, 81, + 3, 7, 6, 13, 6, 13, 12, 25, 6, 13, 12, 25, 12, 25, 24, 49, + 7, 15, 14, 29, 14, 29, 28, 57, 14, 29, 28, 57, 28, 57, 56, 113, + 6, 13, 12, 25, 12, 25, 24, 49, 12, 25, 24, 49, 24, 49, 48, 97, + 13, 27, 26, 53, 26, 53, 52, 105, 26, 53, 52, 105, 52, 105, 104, 209, + }, { + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 3, 6, 7, 14, 6, 12, 13, 26, 6, 12, 13, 26, 12, 24, 25, 50, + 2, 4, 5, 10, 4, 8, 9, 18, 4, 8, 9, 18, 8, 16, 17, 34, + 5, 10, 11, 22, 10, 20, 21, 42, 10, 20, 21, 42, 20, 40, 41, 82, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 3, 6, 7, 14, 6, 12, 13, 26, 6, 12, 13, 26, 12, 24, 25, 50, + 2, 4, 5, 10, 4, 8, 9, 18, 4, 8, 9, 18, 8, 16, 17, 34, + 5, 10, 11, 22, 10, 20, 21, 42, 10, 20, 21, 42, 20, 40, 41, 82, + 3, 6, 7, 14, 6, 12, 13, 26, 6, 12, 13, 26, 12, 24, 25, 50, + 7, 14, 15, 30, 14, 28, 29, 58, 14, 28, 29, 58, 28, 56, 57, 114, + 6, 12, 13, 26, 12, 24, 25, 50, 12, 24, 25, 50, 24, 48, 49, 98, + 13, 26, 27, 54, 26, 52, 53, 106, 26, 52, 53, 106, 52, 104, 105, 210, + }, { + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 3, 7, 7, 15, 6, 13, 13, 27, 6, 13, 13, 27, 12, 25, 25, 51, + 2, 5, 5, 11, 4, 9, 9, 19, 4, 9, 9, 19, 8, 17, 17, 35, + 5, 11, 11, 23, 10, 21, 21, 43, 10, 21, 21, 43, 20, 41, 41, 83, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 3, 7, 7, 15, 6, 13, 13, 27, 6, 13, 13, 27, 12, 25, 25, 51, + 2, 5, 5, 11, 4, 9, 9, 19, 4, 9, 9, 19, 8, 17, 17, 35, + 5, 11, 11, 23, 10, 21, 21, 43, 10, 21, 21, 43, 20, 41, 41, 83, + 3, 7, 7, 15, 6, 13, 13, 27, 6, 13, 13, 27, 12, 25, 25, 51, + 7, 15, 15, 31, 14, 29, 29, 59, 14, 29, 29, 59, 28, 57, 57, 115, + 6, 13, 13, 27, 12, 25, 25, 51, 12, 25, 25, 51, 24, 49, 49, 99, + 13, 27, 27, 55, 26, 53, 53, 107, 26, 53, 53, 107, 52, 105, 105, 211, + }, + { + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 3, 6, 6, 12, 7, 14, 14, 28, 6, 12, 12, 24, 13, 26, 26, 52, + 2, 4, 4, 8, 5, 10, 10, 20, 4, 8, 8, 16, 9, 18, 18, 36, + 5, 10, 10, 20, 11, 22, 22, 44, 10, 20, 20, 40, 21, 42, 42, 84, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 3, 6, 6, 12, 7, 14, 14, 28, 6, 12, 12, 24, 13, 26, 26, 52, + 2, 4, 4, 8, 5, 10, 10, 20, 4, 8, 8, 16, 9, 18, 18, 36, + 5, 10, 10, 20, 11, 22, 22, 44, 10, 20, 20, 40, 21, 42, 42, 84, + 3, 6, 6, 12, 7, 14, 14, 28, 6, 12, 12, 24, 13, 26, 26, 52, + 7, 14, 14, 28, 15, 30, 30, 60, 14, 28, 28, 56, 29, 58, 58, 116, + 6, 12, 12, 24, 13, 26, 26, 52, 12, 24, 24, 48, 25, 50, 50, 100, + 13, 26, 26, 52, 27, 54, 54, 108, 26, 52, 52, 104, 53, 106, 106, 212, + }, { + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 3, 7, 6, 13, 7, 15, 14, 29, 6, 13, 12, 25, 13, 27, 26, 53, + 2, 5, 4, 9, 5, 11, 10, 21, 4, 9, 8, 17, 9, 19, 18, 37, + 5, 11, 10, 21, 11, 23, 22, 45, 10, 21, 20, 41, 21, 43, 42, 85, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 3, 7, 6, 13, 7, 15, 14, 29, 6, 13, 12, 25, 13, 27, 26, 53, + 2, 5, 4, 9, 5, 11, 10, 21, 4, 9, 8, 17, 9, 19, 18, 37, + 5, 11, 10, 21, 11, 23, 22, 45, 10, 21, 20, 41, 21, 43, 42, 85, + 3, 7, 6, 13, 7, 15, 14, 29, 6, 13, 12, 25, 13, 27, 26, 53, + 7, 15, 14, 29, 15, 31, 30, 61, 14, 29, 28, 57, 29, 59, 58, 117, + 6, 13, 12, 25, 13, 27, 26, 53, 12, 25, 24, 49, 25, 51, 50, 101, + 13, 27, 26, 53, 27, 55, 54, 109, 26, 53, 52, 105, 53, 107, 106, 213, + }, { + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 3, 6, 7, 14, 7, 14, 15, 30, 6, 12, 13, 26, 13, 26, 27, 54, + 2, 4, 5, 10, 5, 10, 11, 22, 4, 8, 9, 18, 9, 18, 19, 38, + 5, 10, 11, 22, 11, 22, 23, 46, 10, 20, 21, 42, 21, 42, 43, 86, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 3, 6, 7, 14, 7, 14, 15, 30, 6, 12, 13, 26, 13, 26, 27, 54, + 2, 4, 5, 10, 5, 10, 11, 22, 4, 8, 9, 18, 9, 18, 19, 38, + 5, 10, 11, 22, 11, 22, 23, 46, 10, 20, 21, 42, 21, 42, 43, 86, + 3, 6, 7, 14, 7, 14, 15, 30, 6, 12, 13, 26, 13, 26, 27, 54, + 7, 14, 15, 30, 15, 30, 31, 62, 14, 28, 29, 58, 29, 58, 59, 118, + 6, 12, 13, 26, 13, 26, 27, 54, 12, 24, 25, 50, 25, 50, 51, 102, + 13, 26, 27, 54, 27, 54, 55, 110, 26, 52, 53, 106, 53, 106, 107, 214, + }, { + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 3, 7, 7, 15, 7, 15, 15, 31, 6, 13, 13, 27, 13, 27, 27, 55, + 2, 5, 5, 11, 5, 11, 11, 23, 4, 9, 9, 19, 9, 19, 19, 39, + 5, 11, 11, 23, 11, 23, 23, 47, 10, 21, 21, 43, 21, 43, 43, 87, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 3, 7, 7, 15, 7, 15, 15, 31, 6, 13, 13, 27, 13, 27, 27, 55, + 2, 5, 5, 11, 5, 11, 11, 23, 4, 9, 9, 19, 9, 19, 19, 39, + 5, 11, 11, 23, 11, 23, 23, 47, 10, 21, 21, 43, 21, 43, 43, 87, + 3, 7, 7, 15, 7, 15, 15, 31, 6, 13, 13, 27, 13, 27, 27, 55, + 7, 15, 15, 31, 15, 31, 31, 63, 14, 29, 29, 59, 29, 59, 59, 119, + 6, 13, 13, 27, 13, 27, 27, 55, 12, 25, 25, 51, 25, 51, 51, 103, + 13, 27, 27, 55, 27, 55, 55, 111, 26, 53, 53, 107, 53, 107, 107, 215, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 3, 6, 6, 12, 6, 12, 12, 24, 7, 14, 14, 28, 14, 28, 28, 56, + 2, 4, 4, 8, 4, 8, 8, 16, 5, 10, 10, 20, 10, 20, 20, 40, + 5, 10, 10, 20, 10, 20, 20, 40, 11, 22, 22, 44, 22, 44, 44, 88, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 3, 6, 6, 12, 6, 12, 12, 24, 7, 14, 14, 28, 14, 28, 28, 56, + 2, 4, 4, 8, 4, 8, 8, 16, 5, 10, 10, 20, 10, 20, 20, 40, + 5, 10, 10, 20, 10, 20, 20, 40, 11, 22, 22, 44, 22, 44, 44, 88, + 3, 6, 6, 12, 6, 12, 12, 24, 7, 14, 14, 28, 14, 28, 28, 56, + 7, 14, 14, 28, 14, 28, 28, 56, 15, 30, 30, 60, 30, 60, 60, 120, + 6, 12, 12, 24, 12, 24, 24, 48, 13, 26, 26, 52, 26, 52, 52, 104, + 13, 26, 26, 52, 26, 52, 52, 104, 27, 54, 54, 108, 54, 108, 108, 216, + }, { + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 3, 7, 6, 13, 6, 13, 12, 25, 7, 15, 14, 29, 14, 29, 28, 57, + 2, 5, 4, 9, 4, 9, 8, 17, 5, 11, 10, 21, 10, 21, 20, 41, + 5, 11, 10, 21, 10, 21, 20, 41, 11, 23, 22, 45, 22, 45, 44, 89, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 3, 7, 6, 13, 6, 13, 12, 25, 7, 15, 14, 29, 14, 29, 28, 57, + 2, 5, 4, 9, 4, 9, 8, 17, 5, 11, 10, 21, 10, 21, 20, 41, + 5, 11, 10, 21, 10, 21, 20, 41, 11, 23, 22, 45, 22, 45, 44, 89, + 3, 7, 6, 13, 6, 13, 12, 25, 7, 15, 14, 29, 14, 29, 28, 57, + 7, 15, 14, 29, 14, 29, 28, 57, 15, 31, 30, 61, 30, 61, 60, 121, + 6, 13, 12, 25, 12, 25, 24, 49, 13, 27, 26, 53, 26, 53, 52, 105, + 13, 27, 26, 53, 26, 53, 52, 105, 27, 55, 54, 109, 54, 109, 108, 217, + }, { + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 3, 6, 7, 14, 6, 12, 13, 26, 7, 14, 15, 30, 14, 28, 29, 58, + 2, 4, 5, 10, 4, 8, 9, 18, 5, 10, 11, 22, 10, 20, 21, 42, + 5, 10, 11, 22, 10, 20, 21, 42, 11, 22, 23, 46, 22, 44, 45, 90, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 3, 6, 7, 14, 6, 12, 13, 26, 7, 14, 15, 30, 14, 28, 29, 58, + 2, 4, 5, 10, 4, 8, 9, 18, 5, 10, 11, 22, 10, 20, 21, 42, + 5, 10, 11, 22, 10, 20, 21, 42, 11, 22, 23, 46, 22, 44, 45, 90, + 3, 6, 7, 14, 6, 12, 13, 26, 7, 14, 15, 30, 14, 28, 29, 58, + 7, 14, 15, 30, 14, 28, 29, 58, 15, 30, 31, 62, 30, 60, 61, 122, + 6, 12, 13, 26, 12, 24, 25, 50, 13, 26, 27, 54, 26, 52, 53, 106, + 13, 26, 27, 54, 26, 52, 53, 106, 27, 54, 55, 110, 54, 108, 109, 218, + }, { + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 3, 7, 7, 15, 6, 13, 13, 27, 7, 15, 15, 31, 14, 29, 29, 59, + 2, 5, 5, 11, 4, 9, 9, 19, 5, 11, 11, 23, 10, 21, 21, 43, + 5, 11, 11, 23, 10, 21, 21, 43, 11, 23, 23, 47, 22, 45, 45, 91, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 3, 7, 7, 15, 6, 13, 13, 27, 7, 15, 15, 31, 14, 29, 29, 59, + 2, 5, 5, 11, 4, 9, 9, 19, 5, 11, 11, 23, 10, 21, 21, 43, + 5, 11, 11, 23, 10, 21, 21, 43, 11, 23, 23, 47, 22, 45, 45, 91, + 3, 7, 7, 15, 6, 13, 13, 27, 7, 15, 15, 31, 14, 29, 29, 59, + 7, 15, 15, 31, 14, 29, 29, 59, 15, 31, 31, 63, 30, 61, 61, 123, + 6, 13, 13, 27, 12, 25, 25, 51, 13, 27, 27, 55, 26, 53, 53, 107, + 13, 27, 27, 55, 26, 53, 53, 107, 27, 55, 55, 111, 54, 109, 109, 219, + }, + { + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 3, 6, 6, 12, 7, 14, 14, 28, 7, 14, 14, 28, 15, 30, 30, 60, + 2, 4, 4, 8, 5, 10, 10, 20, 5, 10, 10, 20, 11, 22, 22, 44, + 5, 10, 10, 20, 11, 22, 22, 44, 11, 22, 22, 44, 23, 46, 46, 92, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 3, 6, 6, 12, 7, 14, 14, 28, 7, 14, 14, 28, 15, 30, 30, 60, + 2, 4, 4, 8, 5, 10, 10, 20, 5, 10, 10, 20, 11, 22, 22, 44, + 5, 10, 10, 20, 11, 22, 22, 44, 11, 22, 22, 44, 23, 46, 46, 92, + 3, 6, 6, 12, 7, 14, 14, 28, 7, 14, 14, 28, 15, 30, 30, 60, + 7, 14, 14, 28, 15, 30, 30, 60, 15, 30, 30, 60, 31, 62, 62, 124, + 6, 12, 12, 24, 13, 26, 26, 52, 13, 26, 26, 52, 27, 54, 54, 108, + 13, 26, 26, 52, 27, 54, 54, 108, 27, 54, 54, 108, 55, 110, 110, 220, + }, { + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 3, 7, 6, 13, 7, 15, 14, 29, 7, 15, 14, 29, 15, 31, 30, 61, + 2, 5, 4, 9, 5, 11, 10, 21, 5, 11, 10, 21, 11, 23, 22, 45, + 5, 11, 10, 21, 11, 23, 22, 45, 11, 23, 22, 45, 23, 47, 46, 93, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 3, 7, 6, 13, 7, 15, 14, 29, 7, 15, 14, 29, 15, 31, 30, 61, + 2, 5, 4, 9, 5, 11, 10, 21, 5, 11, 10, 21, 11, 23, 22, 45, + 5, 11, 10, 21, 11, 23, 22, 45, 11, 23, 22, 45, 23, 47, 46, 93, + 3, 7, 6, 13, 7, 15, 14, 29, 7, 15, 14, 29, 15, 31, 30, 61, + 7, 15, 14, 29, 15, 31, 30, 61, 15, 31, 30, 61, 31, 63, 62, 125, + 6, 13, 12, 25, 13, 27, 26, 53, 13, 27, 26, 53, 27, 55, 54, 109, + 13, 27, 26, 53, 27, 55, 54, 109, 27, 55, 54, 109, 55, 111, 110, 221, + }, { + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 3, 6, 7, 14, 7, 14, 15, 30, 7, 14, 15, 30, 15, 30, 31, 62, + 2, 4, 5, 10, 5, 10, 11, 22, 5, 10, 11, 22, 11, 22, 23, 46, + 5, 10, 11, 22, 11, 22, 23, 46, 11, 22, 23, 46, 23, 46, 47, 94, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 3, 6, 7, 14, 7, 14, 15, 30, 7, 14, 15, 30, 15, 30, 31, 62, + 2, 4, 5, 10, 5, 10, 11, 22, 5, 10, 11, 22, 11, 22, 23, 46, + 5, 10, 11, 22, 11, 22, 23, 46, 11, 22, 23, 46, 23, 46, 47, 94, + 3, 6, 7, 14, 7, 14, 15, 30, 7, 14, 15, 30, 15, 30, 31, 62, + 7, 14, 15, 30, 15, 30, 31, 62, 15, 30, 31, 62, 31, 62, 63, 126, + 6, 12, 13, 26, 13, 26, 27, 54, 13, 26, 27, 54, 27, 54, 55, 110, + 13, 26, 27, 54, 27, 54, 55, 110, 27, 54, 55, 110, 55, 110, 111, 222, + }, { + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 3, 7, 7, 15, 7, 15, 15, 31, 7, 15, 15, 31, 15, 31, 31, 63, + 2, 5, 5, 11, 5, 11, 11, 23, 5, 11, 11, 23, 11, 23, 23, 47, + 5, 11, 11, 23, 11, 23, 23, 47, 11, 23, 23, 47, 23, 47, 47, 95, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 3, 7, 7, 15, 7, 15, 15, 31, 7, 15, 15, 31, 15, 31, 31, 63, + 2, 5, 5, 11, 5, 11, 11, 23, 5, 11, 11, 23, 11, 23, 23, 47, + 5, 11, 11, 23, 11, 23, 23, 47, 11, 23, 23, 47, 23, 47, 47, 95, + 3, 7, 7, 15, 7, 15, 15, 31, 7, 15, 15, 31, 15, 31, 31, 63, + 7, 15, 15, 31, 15, 31, 31, 63, 15, 31, 31, 63, 31, 63, 63, 127, + 6, 13, 13, 27, 13, 27, 27, 55, 13, 27, 27, 55, 27, 55, 55, 111, + 13, 27, 27, 55, 27, 55, 55, 111, 27, 55, 55, 111, 55, 111, 111, 223, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 2, 4, 4, 8, 4, 8, 8, 16, 4, 8, 8, 16, 8, 16, 16, 32, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 2, 4, 4, 8, 4, 8, 8, 16, 4, 8, 8, 16, 8, 16, 16, 32, + 3, 6, 6, 12, 6, 12, 12, 24, 6, 12, 12, 24, 12, 24, 24, 48, + 6, 12, 12, 24, 12, 24, 24, 48, 12, 24, 24, 48, 24, 48, 48, 96, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 2, 4, 4, 8, 4, 8, 8, 16, 4, 8, 8, 16, 8, 16, 16, 32, + 3, 6, 6, 12, 6, 12, 12, 24, 6, 12, 12, 24, 12, 24, 24, 48, + 6, 12, 12, 24, 12, 24, 24, 48, 12, 24, 24, 48, 24, 48, 48, 96, + 3, 6, 6, 12, 6, 12, 12, 24, 6, 12, 12, 24, 12, 24, 24, 48, + 6, 12, 12, 24, 12, 24, 24, 48, 12, 24, 24, 48, 24, 48, 48, 96, + 7, 14, 14, 28, 14, 28, 28, 56, 14, 28, 28, 56, 28, 56, 56, 112, + 14, 28, 28, 56, 28, 56, 56, 112, 28, 56, 56, 112, 56, 112, 112, 224, + }, { + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 2, 5, 4, 9, 4, 9, 8, 17, 4, 9, 8, 17, 8, 17, 16, 33, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 2, 5, 4, 9, 4, 9, 8, 17, 4, 9, 8, 17, 8, 17, 16, 33, + 3, 7, 6, 13, 6, 13, 12, 25, 6, 13, 12, 25, 12, 25, 24, 49, + 6, 13, 12, 25, 12, 25, 24, 49, 12, 25, 24, 49, 24, 49, 48, 97, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 2, 5, 4, 9, 4, 9, 8, 17, 4, 9, 8, 17, 8, 17, 16, 33, + 3, 7, 6, 13, 6, 13, 12, 25, 6, 13, 12, 25, 12, 25, 24, 49, + 6, 13, 12, 25, 12, 25, 24, 49, 12, 25, 24, 49, 24, 49, 48, 97, + 3, 7, 6, 13, 6, 13, 12, 25, 6, 13, 12, 25, 12, 25, 24, 49, + 6, 13, 12, 25, 12, 25, 24, 49, 12, 25, 24, 49, 24, 49, 48, 97, + 7, 15, 14, 29, 14, 29, 28, 57, 14, 29, 28, 57, 28, 57, 56, 113, + 14, 29, 28, 57, 28, 57, 56, 113, 28, 57, 56, 113, 56, 113, 112, 225, + }, { + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 2, 4, 5, 10, 4, 8, 9, 18, 4, 8, 9, 18, 8, 16, 17, 34, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 2, 4, 5, 10, 4, 8, 9, 18, 4, 8, 9, 18, 8, 16, 17, 34, + 3, 6, 7, 14, 6, 12, 13, 26, 6, 12, 13, 26, 12, 24, 25, 50, + 6, 12, 13, 26, 12, 24, 25, 50, 12, 24, 25, 50, 24, 48, 49, 98, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 2, 4, 5, 10, 4, 8, 9, 18, 4, 8, 9, 18, 8, 16, 17, 34, + 3, 6, 7, 14, 6, 12, 13, 26, 6, 12, 13, 26, 12, 24, 25, 50, + 6, 12, 13, 26, 12, 24, 25, 50, 12, 24, 25, 50, 24, 48, 49, 98, + 3, 6, 7, 14, 6, 12, 13, 26, 6, 12, 13, 26, 12, 24, 25, 50, + 6, 12, 13, 26, 12, 24, 25, 50, 12, 24, 25, 50, 24, 48, 49, 98, + 7, 14, 15, 30, 14, 28, 29, 58, 14, 28, 29, 58, 28, 56, 57, 114, + 14, 28, 29, 58, 28, 56, 57, 114, 28, 56, 57, 114, 56, 112, 113, 226, + }, { + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 2, 5, 5, 11, 4, 9, 9, 19, 4, 9, 9, 19, 8, 17, 17, 35, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 2, 5, 5, 11, 4, 9, 9, 19, 4, 9, 9, 19, 8, 17, 17, 35, + 3, 7, 7, 15, 6, 13, 13, 27, 6, 13, 13, 27, 12, 25, 25, 51, + 6, 13, 13, 27, 12, 25, 25, 51, 12, 25, 25, 51, 24, 49, 49, 99, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 2, 5, 5, 11, 4, 9, 9, 19, 4, 9, 9, 19, 8, 17, 17, 35, + 3, 7, 7, 15, 6, 13, 13, 27, 6, 13, 13, 27, 12, 25, 25, 51, + 6, 13, 13, 27, 12, 25, 25, 51, 12, 25, 25, 51, 24, 49, 49, 99, + 3, 7, 7, 15, 6, 13, 13, 27, 6, 13, 13, 27, 12, 25, 25, 51, + 6, 13, 13, 27, 12, 25, 25, 51, 12, 25, 25, 51, 24, 49, 49, 99, + 7, 15, 15, 31, 14, 29, 29, 59, 14, 29, 29, 59, 28, 57, 57, 115, + 14, 29, 29, 59, 28, 57, 57, 115, 28, 57, 57, 115, 56, 113, 113, 227, + }, + { + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 2, 4, 4, 8, 5, 10, 10, 20, 4, 8, 8, 16, 9, 18, 18, 36, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 2, 4, 4, 8, 5, 10, 10, 20, 4, 8, 8, 16, 9, 18, 18, 36, + 3, 6, 6, 12, 7, 14, 14, 28, 6, 12, 12, 24, 13, 26, 26, 52, + 6, 12, 12, 24, 13, 26, 26, 52, 12, 24, 24, 48, 25, 50, 50, 100, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 2, 4, 4, 8, 5, 10, 10, 20, 4, 8, 8, 16, 9, 18, 18, 36, + 3, 6, 6, 12, 7, 14, 14, 28, 6, 12, 12, 24, 13, 26, 26, 52, + 6, 12, 12, 24, 13, 26, 26, 52, 12, 24, 24, 48, 25, 50, 50, 100, + 3, 6, 6, 12, 7, 14, 14, 28, 6, 12, 12, 24, 13, 26, 26, 52, + 6, 12, 12, 24, 13, 26, 26, 52, 12, 24, 24, 48, 25, 50, 50, 100, + 7, 14, 14, 28, 15, 30, 30, 60, 14, 28, 28, 56, 29, 58, 58, 116, + 14, 28, 28, 56, 29, 58, 58, 116, 28, 56, 56, 112, 57, 114, 114, 228, + }, { + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 2, 5, 4, 9, 5, 11, 10, 21, 4, 9, 8, 17, 9, 19, 18, 37, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 2, 5, 4, 9, 5, 11, 10, 21, 4, 9, 8, 17, 9, 19, 18, 37, + 3, 7, 6, 13, 7, 15, 14, 29, 6, 13, 12, 25, 13, 27, 26, 53, + 6, 13, 12, 25, 13, 27, 26, 53, 12, 25, 24, 49, 25, 51, 50, 101, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 2, 5, 4, 9, 5, 11, 10, 21, 4, 9, 8, 17, 9, 19, 18, 37, + 3, 7, 6, 13, 7, 15, 14, 29, 6, 13, 12, 25, 13, 27, 26, 53, + 6, 13, 12, 25, 13, 27, 26, 53, 12, 25, 24, 49, 25, 51, 50, 101, + 3, 7, 6, 13, 7, 15, 14, 29, 6, 13, 12, 25, 13, 27, 26, 53, + 6, 13, 12, 25, 13, 27, 26, 53, 12, 25, 24, 49, 25, 51, 50, 101, + 7, 15, 14, 29, 15, 31, 30, 61, 14, 29, 28, 57, 29, 59, 58, 117, + 14, 29, 28, 57, 29, 59, 58, 117, 28, 57, 56, 113, 57, 115, 114, 229, + }, { + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 2, 4, 5, 10, 5, 10, 11, 22, 4, 8, 9, 18, 9, 18, 19, 38, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 2, 4, 5, 10, 5, 10, 11, 22, 4, 8, 9, 18, 9, 18, 19, 38, + 3, 6, 7, 14, 7, 14, 15, 30, 6, 12, 13, 26, 13, 26, 27, 54, + 6, 12, 13, 26, 13, 26, 27, 54, 12, 24, 25, 50, 25, 50, 51, 102, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 2, 4, 5, 10, 5, 10, 11, 22, 4, 8, 9, 18, 9, 18, 19, 38, + 3, 6, 7, 14, 7, 14, 15, 30, 6, 12, 13, 26, 13, 26, 27, 54, + 6, 12, 13, 26, 13, 26, 27, 54, 12, 24, 25, 50, 25, 50, 51, 102, + 3, 6, 7, 14, 7, 14, 15, 30, 6, 12, 13, 26, 13, 26, 27, 54, + 6, 12, 13, 26, 13, 26, 27, 54, 12, 24, 25, 50, 25, 50, 51, 102, + 7, 14, 15, 30, 15, 30, 31, 62, 14, 28, 29, 58, 29, 58, 59, 118, + 14, 28, 29, 58, 29, 58, 59, 118, 28, 56, 57, 114, 57, 114, 115, 230, + }, { + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 2, 5, 5, 11, 5, 11, 11, 23, 4, 9, 9, 19, 9, 19, 19, 39, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 2, 5, 5, 11, 5, 11, 11, 23, 4, 9, 9, 19, 9, 19, 19, 39, + 3, 7, 7, 15, 7, 15, 15, 31, 6, 13, 13, 27, 13, 27, 27, 55, + 6, 13, 13, 27, 13, 27, 27, 55, 12, 25, 25, 51, 25, 51, 51, 103, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 2, 5, 5, 11, 5, 11, 11, 23, 4, 9, 9, 19, 9, 19, 19, 39, + 3, 7, 7, 15, 7, 15, 15, 31, 6, 13, 13, 27, 13, 27, 27, 55, + 6, 13, 13, 27, 13, 27, 27, 55, 12, 25, 25, 51, 25, 51, 51, 103, + 3, 7, 7, 15, 7, 15, 15, 31, 6, 13, 13, 27, 13, 27, 27, 55, + 6, 13, 13, 27, 13, 27, 27, 55, 12, 25, 25, 51, 25, 51, 51, 103, + 7, 15, 15, 31, 15, 31, 31, 63, 14, 29, 29, 59, 29, 59, 59, 119, + 14, 29, 29, 59, 29, 59, 59, 119, 28, 57, 57, 115, 57, 115, 115, 231, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 2, 4, 4, 8, 4, 8, 8, 16, 5, 10, 10, 20, 10, 20, 20, 40, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 2, 4, 4, 8, 4, 8, 8, 16, 5, 10, 10, 20, 10, 20, 20, 40, + 3, 6, 6, 12, 6, 12, 12, 24, 7, 14, 14, 28, 14, 28, 28, 56, + 6, 12, 12, 24, 12, 24, 24, 48, 13, 26, 26, 52, 26, 52, 52, 104, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 2, 4, 4, 8, 4, 8, 8, 16, 5, 10, 10, 20, 10, 20, 20, 40, + 3, 6, 6, 12, 6, 12, 12, 24, 7, 14, 14, 28, 14, 28, 28, 56, + 6, 12, 12, 24, 12, 24, 24, 48, 13, 26, 26, 52, 26, 52, 52, 104, + 3, 6, 6, 12, 6, 12, 12, 24, 7, 14, 14, 28, 14, 28, 28, 56, + 6, 12, 12, 24, 12, 24, 24, 48, 13, 26, 26, 52, 26, 52, 52, 104, + 7, 14, 14, 28, 14, 28, 28, 56, 15, 30, 30, 60, 30, 60, 60, 120, + 14, 28, 28, 56, 28, 56, 56, 112, 29, 58, 58, 116, 58, 116, 116, 232, + }, { + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 2, 5, 4, 9, 4, 9, 8, 17, 5, 11, 10, 21, 10, 21, 20, 41, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 2, 5, 4, 9, 4, 9, 8, 17, 5, 11, 10, 21, 10, 21, 20, 41, + 3, 7, 6, 13, 6, 13, 12, 25, 7, 15, 14, 29, 14, 29, 28, 57, + 6, 13, 12, 25, 12, 25, 24, 49, 13, 27, 26, 53, 26, 53, 52, 105, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 2, 5, 4, 9, 4, 9, 8, 17, 5, 11, 10, 21, 10, 21, 20, 41, + 3, 7, 6, 13, 6, 13, 12, 25, 7, 15, 14, 29, 14, 29, 28, 57, + 6, 13, 12, 25, 12, 25, 24, 49, 13, 27, 26, 53, 26, 53, 52, 105, + 3, 7, 6, 13, 6, 13, 12, 25, 7, 15, 14, 29, 14, 29, 28, 57, + 6, 13, 12, 25, 12, 25, 24, 49, 13, 27, 26, 53, 26, 53, 52, 105, + 7, 15, 14, 29, 14, 29, 28, 57, 15, 31, 30, 61, 30, 61, 60, 121, + 14, 29, 28, 57, 28, 57, 56, 113, 29, 59, 58, 117, 58, 117, 116, 233, + }, { + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 2, 4, 5, 10, 4, 8, 9, 18, 5, 10, 11, 22, 10, 20, 21, 42, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 2, 4, 5, 10, 4, 8, 9, 18, 5, 10, 11, 22, 10, 20, 21, 42, + 3, 6, 7, 14, 6, 12, 13, 26, 7, 14, 15, 30, 14, 28, 29, 58, + 6, 12, 13, 26, 12, 24, 25, 50, 13, 26, 27, 54, 26, 52, 53, 106, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 2, 4, 5, 10, 4, 8, 9, 18, 5, 10, 11, 22, 10, 20, 21, 42, + 3, 6, 7, 14, 6, 12, 13, 26, 7, 14, 15, 30, 14, 28, 29, 58, + 6, 12, 13, 26, 12, 24, 25, 50, 13, 26, 27, 54, 26, 52, 53, 106, + 3, 6, 7, 14, 6, 12, 13, 26, 7, 14, 15, 30, 14, 28, 29, 58, + 6, 12, 13, 26, 12, 24, 25, 50, 13, 26, 27, 54, 26, 52, 53, 106, + 7, 14, 15, 30, 14, 28, 29, 58, 15, 30, 31, 62, 30, 60, 61, 122, + 14, 28, 29, 58, 28, 56, 57, 114, 29, 58, 59, 118, 58, 116, 117, 234, + }, { + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 2, 5, 5, 11, 4, 9, 9, 19, 5, 11, 11, 23, 10, 21, 21, 43, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 2, 5, 5, 11, 4, 9, 9, 19, 5, 11, 11, 23, 10, 21, 21, 43, + 3, 7, 7, 15, 6, 13, 13, 27, 7, 15, 15, 31, 14, 29, 29, 59, + 6, 13, 13, 27, 12, 25, 25, 51, 13, 27, 27, 55, 26, 53, 53, 107, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 2, 5, 5, 11, 4, 9, 9, 19, 5, 11, 11, 23, 10, 21, 21, 43, + 3, 7, 7, 15, 6, 13, 13, 27, 7, 15, 15, 31, 14, 29, 29, 59, + 6, 13, 13, 27, 12, 25, 25, 51, 13, 27, 27, 55, 26, 53, 53, 107, + 3, 7, 7, 15, 6, 13, 13, 27, 7, 15, 15, 31, 14, 29, 29, 59, + 6, 13, 13, 27, 12, 25, 25, 51, 13, 27, 27, 55, 26, 53, 53, 107, + 7, 15, 15, 31, 14, 29, 29, 59, 15, 31, 31, 63, 30, 61, 61, 123, + 14, 29, 29, 59, 28, 57, 57, 115, 29, 59, 59, 119, 58, 117, 117, 235, + }, + { + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 2, 4, 4, 8, 5, 10, 10, 20, 5, 10, 10, 20, 11, 22, 22, 44, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 2, 4, 4, 8, 5, 10, 10, 20, 5, 10, 10, 20, 11, 22, 22, 44, + 3, 6, 6, 12, 7, 14, 14, 28, 7, 14, 14, 28, 15, 30, 30, 60, + 6, 12, 12, 24, 13, 26, 26, 52, 13, 26, 26, 52, 27, 54, 54, 108, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 2, 4, 4, 8, 5, 10, 10, 20, 5, 10, 10, 20, 11, 22, 22, 44, + 3, 6, 6, 12, 7, 14, 14, 28, 7, 14, 14, 28, 15, 30, 30, 60, + 6, 12, 12, 24, 13, 26, 26, 52, 13, 26, 26, 52, 27, 54, 54, 108, + 3, 6, 6, 12, 7, 14, 14, 28, 7, 14, 14, 28, 15, 30, 30, 60, + 6, 12, 12, 24, 13, 26, 26, 52, 13, 26, 26, 52, 27, 54, 54, 108, + 7, 14, 14, 28, 15, 30, 30, 60, 15, 30, 30, 60, 31, 62, 62, 124, + 14, 28, 28, 56, 29, 58, 58, 116, 29, 58, 58, 116, 59, 118, 118, 236, + }, { + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 2, 5, 4, 9, 5, 11, 10, 21, 5, 11, 10, 21, 11, 23, 22, 45, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 2, 5, 4, 9, 5, 11, 10, 21, 5, 11, 10, 21, 11, 23, 22, 45, + 3, 7, 6, 13, 7, 15, 14, 29, 7, 15, 14, 29, 15, 31, 30, 61, + 6, 13, 12, 25, 13, 27, 26, 53, 13, 27, 26, 53, 27, 55, 54, 109, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 2, 5, 4, 9, 5, 11, 10, 21, 5, 11, 10, 21, 11, 23, 22, 45, + 3, 7, 6, 13, 7, 15, 14, 29, 7, 15, 14, 29, 15, 31, 30, 61, + 6, 13, 12, 25, 13, 27, 26, 53, 13, 27, 26, 53, 27, 55, 54, 109, + 3, 7, 6, 13, 7, 15, 14, 29, 7, 15, 14, 29, 15, 31, 30, 61, + 6, 13, 12, 25, 13, 27, 26, 53, 13, 27, 26, 53, 27, 55, 54, 109, + 7, 15, 14, 29, 15, 31, 30, 61, 15, 31, 30, 61, 31, 63, 62, 125, + 14, 29, 28, 57, 29, 59, 58, 117, 29, 59, 58, 117, 59, 119, 118, 237, + }, { + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 2, 4, 5, 10, 5, 10, 11, 22, 5, 10, 11, 22, 11, 22, 23, 46, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 2, 4, 5, 10, 5, 10, 11, 22, 5, 10, 11, 22, 11, 22, 23, 46, + 3, 6, 7, 14, 7, 14, 15, 30, 7, 14, 15, 30, 15, 30, 31, 62, + 6, 12, 13, 26, 13, 26, 27, 54, 13, 26, 27, 54, 27, 54, 55, 110, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 2, 4, 5, 10, 5, 10, 11, 22, 5, 10, 11, 22, 11, 22, 23, 46, + 3, 6, 7, 14, 7, 14, 15, 30, 7, 14, 15, 30, 15, 30, 31, 62, + 6, 12, 13, 26, 13, 26, 27, 54, 13, 26, 27, 54, 27, 54, 55, 110, + 3, 6, 7, 14, 7, 14, 15, 30, 7, 14, 15, 30, 15, 30, 31, 62, + 6, 12, 13, 26, 13, 26, 27, 54, 13, 26, 27, 54, 27, 54, 55, 110, + 7, 14, 15, 30, 15, 30, 31, 62, 15, 30, 31, 62, 31, 62, 63, 126, + 14, 28, 29, 58, 29, 58, 59, 118, 29, 58, 59, 118, 59, 118, 119, 238, + }, { + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 2, 5, 5, 11, 5, 11, 11, 23, 5, 11, 11, 23, 11, 23, 23, 47, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 2, 5, 5, 11, 5, 11, 11, 23, 5, 11, 11, 23, 11, 23, 23, 47, + 3, 7, 7, 15, 7, 15, 15, 31, 7, 15, 15, 31, 15, 31, 31, 63, + 6, 13, 13, 27, 13, 27, 27, 55, 13, 27, 27, 55, 27, 55, 55, 111, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 2, 5, 5, 11, 5, 11, 11, 23, 5, 11, 11, 23, 11, 23, 23, 47, + 3, 7, 7, 15, 7, 15, 15, 31, 7, 15, 15, 31, 15, 31, 31, 63, + 6, 13, 13, 27, 13, 27, 27, 55, 13, 27, 27, 55, 27, 55, 55, 111, + 3, 7, 7, 15, 7, 15, 15, 31, 7, 15, 15, 31, 15, 31, 31, 63, + 6, 13, 13, 27, 13, 27, 27, 55, 13, 27, 27, 55, 27, 55, 55, 111, + 7, 15, 15, 31, 15, 31, 31, 63, 15, 31, 31, 63, 31, 63, 63, 127, + 14, 29, 29, 59, 29, 59, 59, 119, 29, 59, 59, 119, 59, 119, 119, 239, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 3, 6, 6, 12, 6, 12, 12, 24, 6, 12, 12, 24, 12, 24, 24, 48, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 3, 6, 6, 12, 6, 12, 12, 24, 6, 12, 12, 24, 12, 24, 24, 48, + 3, 6, 6, 12, 6, 12, 12, 24, 6, 12, 12, 24, 12, 24, 24, 48, + 7, 14, 14, 28, 14, 28, 28, 56, 14, 28, 28, 56, 28, 56, 56, 112, + 1, 2, 2, 4, 2, 4, 4, 8, 2, 4, 4, 8, 4, 8, 8, 16, + 3, 6, 6, 12, 6, 12, 12, 24, 6, 12, 12, 24, 12, 24, 24, 48, + 3, 6, 6, 12, 6, 12, 12, 24, 6, 12, 12, 24, 12, 24, 24, 48, + 7, 14, 14, 28, 14, 28, 28, 56, 14, 28, 28, 56, 28, 56, 56, 112, + 3, 6, 6, 12, 6, 12, 12, 24, 6, 12, 12, 24, 12, 24, 24, 48, + 7, 14, 14, 28, 14, 28, 28, 56, 14, 28, 28, 56, 28, 56, 56, 112, + 7, 14, 14, 28, 14, 28, 28, 56, 14, 28, 28, 56, 28, 56, 56, 112, + 15, 30, 30, 60, 30, 60, 60, 120, 30, 60, 60, 120, 60, 120, 120, 240, + }, { + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 3, 7, 6, 13, 6, 13, 12, 25, 6, 13, 12, 25, 12, 25, 24, 49, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 3, 7, 6, 13, 6, 13, 12, 25, 6, 13, 12, 25, 12, 25, 24, 49, + 3, 7, 6, 13, 6, 13, 12, 25, 6, 13, 12, 25, 12, 25, 24, 49, + 7, 15, 14, 29, 14, 29, 28, 57, 14, 29, 28, 57, 28, 57, 56, 113, + 1, 3, 2, 5, 2, 5, 4, 9, 2, 5, 4, 9, 4, 9, 8, 17, + 3, 7, 6, 13, 6, 13, 12, 25, 6, 13, 12, 25, 12, 25, 24, 49, + 3, 7, 6, 13, 6, 13, 12, 25, 6, 13, 12, 25, 12, 25, 24, 49, + 7, 15, 14, 29, 14, 29, 28, 57, 14, 29, 28, 57, 28, 57, 56, 113, + 3, 7, 6, 13, 6, 13, 12, 25, 6, 13, 12, 25, 12, 25, 24, 49, + 7, 15, 14, 29, 14, 29, 28, 57, 14, 29, 28, 57, 28, 57, 56, 113, + 7, 15, 14, 29, 14, 29, 28, 57, 14, 29, 28, 57, 28, 57, 56, 113, + 15, 31, 30, 61, 30, 61, 60, 121, 30, 61, 60, 121, 60, 121, 120, 241, + }, { + 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 3, 6, 7, 14, 6, 12, 13, 26, 6, 12, 13, 26, 12, 24, 25, 50, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 3, 6, 7, 14, 6, 12, 13, 26, 6, 12, 13, 26, 12, 24, 25, 50, + 3, 6, 7, 14, 6, 12, 13, 26, 6, 12, 13, 26, 12, 24, 25, 50, + 7, 14, 15, 30, 14, 28, 29, 58, 14, 28, 29, 58, 28, 56, 57, 114, + 1, 2, 3, 6, 2, 4, 5, 10, 2, 4, 5, 10, 4, 8, 9, 18, + 3, 6, 7, 14, 6, 12, 13, 26, 6, 12, 13, 26, 12, 24, 25, 50, + 3, 6, 7, 14, 6, 12, 13, 26, 6, 12, 13, 26, 12, 24, 25, 50, + 7, 14, 15, 30, 14, 28, 29, 58, 14, 28, 29, 58, 28, 56, 57, 114, + 3, 6, 7, 14, 6, 12, 13, 26, 6, 12, 13, 26, 12, 24, 25, 50, + 7, 14, 15, 30, 14, 28, 29, 58, 14, 28, 29, 58, 28, 56, 57, 114, + 7, 14, 15, 30, 14, 28, 29, 58, 14, 28, 29, 58, 28, 56, 57, 114, + 15, 30, 31, 62, 30, 60, 61, 122, 30, 60, 61, 122, 60, 120, 121, 242, + }, { + 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 3, 7, 7, 15, 6, 13, 13, 27, 6, 13, 13, 27, 12, 25, 25, 51, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 3, 7, 7, 15, 6, 13, 13, 27, 6, 13, 13, 27, 12, 25, 25, 51, + 3, 7, 7, 15, 6, 13, 13, 27, 6, 13, 13, 27, 12, 25, 25, 51, + 7, 15, 15, 31, 14, 29, 29, 59, 14, 29, 29, 59, 28, 57, 57, 115, + 1, 3, 3, 7, 2, 5, 5, 11, 2, 5, 5, 11, 4, 9, 9, 19, + 3, 7, 7, 15, 6, 13, 13, 27, 6, 13, 13, 27, 12, 25, 25, 51, + 3, 7, 7, 15, 6, 13, 13, 27, 6, 13, 13, 27, 12, 25, 25, 51, + 7, 15, 15, 31, 14, 29, 29, 59, 14, 29, 29, 59, 28, 57, 57, 115, + 3, 7, 7, 15, 6, 13, 13, 27, 6, 13, 13, 27, 12, 25, 25, 51, + 7, 15, 15, 31, 14, 29, 29, 59, 14, 29, 29, 59, 28, 57, 57, 115, + 7, 15, 15, 31, 14, 29, 29, 59, 14, 29, 29, 59, 28, 57, 57, 115, + 15, 31, 31, 63, 30, 61, 61, 123, 30, 61, 61, 123, 60, 121, 121, 243, + }, + { + 0, 0, 0, 0, 1, 2, 2, 4, 0, 0, 0, 0, 1, 2, 2, 4, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 3, 6, 6, 12, 7, 14, 14, 28, 6, 12, 12, 24, 13, 26, 26, 52, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 3, 6, 6, 12, 7, 14, 14, 28, 6, 12, 12, 24, 13, 26, 26, 52, + 3, 6, 6, 12, 7, 14, 14, 28, 6, 12, 12, 24, 13, 26, 26, 52, + 7, 14, 14, 28, 15, 30, 30, 60, 14, 28, 28, 56, 29, 58, 58, 116, + 1, 2, 2, 4, 3, 6, 6, 12, 2, 4, 4, 8, 5, 10, 10, 20, + 3, 6, 6, 12, 7, 14, 14, 28, 6, 12, 12, 24, 13, 26, 26, 52, + 3, 6, 6, 12, 7, 14, 14, 28, 6, 12, 12, 24, 13, 26, 26, 52, + 7, 14, 14, 28, 15, 30, 30, 60, 14, 28, 28, 56, 29, 58, 58, 116, + 3, 6, 6, 12, 7, 14, 14, 28, 6, 12, 12, 24, 13, 26, 26, 52, + 7, 14, 14, 28, 15, 30, 30, 60, 14, 28, 28, 56, 29, 58, 58, 116, + 7, 14, 14, 28, 15, 30, 30, 60, 14, 28, 28, 56, 29, 58, 58, 116, + 15, 30, 30, 60, 31, 62, 62, 124, 30, 60, 60, 120, 61, 122, 122, 244, + }, { + 0, 1, 0, 1, 1, 3, 2, 5, 0, 1, 0, 1, 1, 3, 2, 5, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 3, 7, 6, 13, 7, 15, 14, 29, 6, 13, 12, 25, 13, 27, 26, 53, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 3, 7, 6, 13, 7, 15, 14, 29, 6, 13, 12, 25, 13, 27, 26, 53, + 3, 7, 6, 13, 7, 15, 14, 29, 6, 13, 12, 25, 13, 27, 26, 53, + 7, 15, 14, 29, 15, 31, 30, 61, 14, 29, 28, 57, 29, 59, 58, 117, + 1, 3, 2, 5, 3, 7, 6, 13, 2, 5, 4, 9, 5, 11, 10, 21, + 3, 7, 6, 13, 7, 15, 14, 29, 6, 13, 12, 25, 13, 27, 26, 53, + 3, 7, 6, 13, 7, 15, 14, 29, 6, 13, 12, 25, 13, 27, 26, 53, + 7, 15, 14, 29, 15, 31, 30, 61, 14, 29, 28, 57, 29, 59, 58, 117, + 3, 7, 6, 13, 7, 15, 14, 29, 6, 13, 12, 25, 13, 27, 26, 53, + 7, 15, 14, 29, 15, 31, 30, 61, 14, 29, 28, 57, 29, 59, 58, 117, + 7, 15, 14, 29, 15, 31, 30, 61, 14, 29, 28, 57, 29, 59, 58, 117, + 15, 31, 30, 61, 31, 63, 62, 125, 30, 61, 60, 121, 61, 123, 122, 245, + }, { + 0, 0, 1, 2, 1, 2, 3, 6, 0, 0, 1, 2, 1, 2, 3, 6, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 3, 6, 7, 14, 7, 14, 15, 30, 6, 12, 13, 26, 13, 26, 27, 54, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 3, 6, 7, 14, 7, 14, 15, 30, 6, 12, 13, 26, 13, 26, 27, 54, + 3, 6, 7, 14, 7, 14, 15, 30, 6, 12, 13, 26, 13, 26, 27, 54, + 7, 14, 15, 30, 15, 30, 31, 62, 14, 28, 29, 58, 29, 58, 59, 118, + 1, 2, 3, 6, 3, 6, 7, 14, 2, 4, 5, 10, 5, 10, 11, 22, + 3, 6, 7, 14, 7, 14, 15, 30, 6, 12, 13, 26, 13, 26, 27, 54, + 3, 6, 7, 14, 7, 14, 15, 30, 6, 12, 13, 26, 13, 26, 27, 54, + 7, 14, 15, 30, 15, 30, 31, 62, 14, 28, 29, 58, 29, 58, 59, 118, + 3, 6, 7, 14, 7, 14, 15, 30, 6, 12, 13, 26, 13, 26, 27, 54, + 7, 14, 15, 30, 15, 30, 31, 62, 14, 28, 29, 58, 29, 58, 59, 118, + 7, 14, 15, 30, 15, 30, 31, 62, 14, 28, 29, 58, 29, 58, 59, 118, + 15, 30, 31, 62, 31, 62, 63, 126, 30, 60, 61, 122, 61, 122, 123, 246, + }, { + 0, 1, 1, 3, 1, 3, 3, 7, 0, 1, 1, 3, 1, 3, 3, 7, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 3, 7, 7, 15, 7, 15, 15, 31, 6, 13, 13, 27, 13, 27, 27, 55, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 3, 7, 7, 15, 7, 15, 15, 31, 6, 13, 13, 27, 13, 27, 27, 55, + 3, 7, 7, 15, 7, 15, 15, 31, 6, 13, 13, 27, 13, 27, 27, 55, + 7, 15, 15, 31, 15, 31, 31, 63, 14, 29, 29, 59, 29, 59, 59, 119, + 1, 3, 3, 7, 3, 7, 7, 15, 2, 5, 5, 11, 5, 11, 11, 23, + 3, 7, 7, 15, 7, 15, 15, 31, 6, 13, 13, 27, 13, 27, 27, 55, + 3, 7, 7, 15, 7, 15, 15, 31, 6, 13, 13, 27, 13, 27, 27, 55, + 7, 15, 15, 31, 15, 31, 31, 63, 14, 29, 29, 59, 29, 59, 59, 119, + 3, 7, 7, 15, 7, 15, 15, 31, 6, 13, 13, 27, 13, 27, 27, 55, + 7, 15, 15, 31, 15, 31, 31, 63, 14, 29, 29, 59, 29, 59, 59, 119, + 7, 15, 15, 31, 15, 31, 31, 63, 14, 29, 29, 59, 29, 59, 59, 119, + 15, 31, 31, 63, 31, 63, 63, 127, 30, 61, 61, 123, 61, 123, 123, 247, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 2, 4, 4, 8, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 3, 6, 6, 12, 6, 12, 12, 24, 7, 14, 14, 28, 14, 28, 28, 56, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 3, 6, 6, 12, 6, 12, 12, 24, 7, 14, 14, 28, 14, 28, 28, 56, + 3, 6, 6, 12, 6, 12, 12, 24, 7, 14, 14, 28, 14, 28, 28, 56, + 7, 14, 14, 28, 14, 28, 28, 56, 15, 30, 30, 60, 30, 60, 60, 120, + 1, 2, 2, 4, 2, 4, 4, 8, 3, 6, 6, 12, 6, 12, 12, 24, + 3, 6, 6, 12, 6, 12, 12, 24, 7, 14, 14, 28, 14, 28, 28, 56, + 3, 6, 6, 12, 6, 12, 12, 24, 7, 14, 14, 28, 14, 28, 28, 56, + 7, 14, 14, 28, 14, 28, 28, 56, 15, 30, 30, 60, 30, 60, 60, 120, + 3, 6, 6, 12, 6, 12, 12, 24, 7, 14, 14, 28, 14, 28, 28, 56, + 7, 14, 14, 28, 14, 28, 28, 56, 15, 30, 30, 60, 30, 60, 60, 120, + 7, 14, 14, 28, 14, 28, 28, 56, 15, 30, 30, 60, 30, 60, 60, 120, + 15, 30, 30, 60, 30, 60, 60, 120, 31, 62, 62, 124, 62, 124, 124, 248, + }, { + 0, 1, 0, 1, 0, 1, 0, 1, 1, 3, 2, 5, 2, 5, 4, 9, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 3, 7, 6, 13, 6, 13, 12, 25, 7, 15, 14, 29, 14, 29, 28, 57, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 3, 7, 6, 13, 6, 13, 12, 25, 7, 15, 14, 29, 14, 29, 28, 57, + 3, 7, 6, 13, 6, 13, 12, 25, 7, 15, 14, 29, 14, 29, 28, 57, + 7, 15, 14, 29, 14, 29, 28, 57, 15, 31, 30, 61, 30, 61, 60, 121, + 1, 3, 2, 5, 2, 5, 4, 9, 3, 7, 6, 13, 6, 13, 12, 25, + 3, 7, 6, 13, 6, 13, 12, 25, 7, 15, 14, 29, 14, 29, 28, 57, + 3, 7, 6, 13, 6, 13, 12, 25, 7, 15, 14, 29, 14, 29, 28, 57, + 7, 15, 14, 29, 14, 29, 28, 57, 15, 31, 30, 61, 30, 61, 60, 121, + 3, 7, 6, 13, 6, 13, 12, 25, 7, 15, 14, 29, 14, 29, 28, 57, + 7, 15, 14, 29, 14, 29, 28, 57, 15, 31, 30, 61, 30, 61, 60, 121, + 7, 15, 14, 29, 14, 29, 28, 57, 15, 31, 30, 61, 30, 61, 60, 121, + 15, 31, 30, 61, 30, 61, 60, 121, 31, 63, 62, 125, 62, 125, 124, 249, + }, { + 0, 0, 1, 2, 0, 0, 1, 2, 1, 2, 3, 6, 2, 4, 5, 10, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 3, 6, 7, 14, 6, 12, 13, 26, 7, 14, 15, 30, 14, 28, 29, 58, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 3, 6, 7, 14, 6, 12, 13, 26, 7, 14, 15, 30, 14, 28, 29, 58, + 3, 6, 7, 14, 6, 12, 13, 26, 7, 14, 15, 30, 14, 28, 29, 58, + 7, 14, 15, 30, 14, 28, 29, 58, 15, 30, 31, 62, 30, 60, 61, 122, + 1, 2, 3, 6, 2, 4, 5, 10, 3, 6, 7, 14, 6, 12, 13, 26, + 3, 6, 7, 14, 6, 12, 13, 26, 7, 14, 15, 30, 14, 28, 29, 58, + 3, 6, 7, 14, 6, 12, 13, 26, 7, 14, 15, 30, 14, 28, 29, 58, + 7, 14, 15, 30, 14, 28, 29, 58, 15, 30, 31, 62, 30, 60, 61, 122, + 3, 6, 7, 14, 6, 12, 13, 26, 7, 14, 15, 30, 14, 28, 29, 58, + 7, 14, 15, 30, 14, 28, 29, 58, 15, 30, 31, 62, 30, 60, 61, 122, + 7, 14, 15, 30, 14, 28, 29, 58, 15, 30, 31, 62, 30, 60, 61, 122, + 15, 30, 31, 62, 30, 60, 61, 122, 31, 62, 63, 126, 62, 124, 125, 250, + }, { + 0, 1, 1, 3, 0, 1, 1, 3, 1, 3, 3, 7, 2, 5, 5, 11, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 3, 7, 7, 15, 6, 13, 13, 27, 7, 15, 15, 31, 14, 29, 29, 59, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 3, 7, 7, 15, 6, 13, 13, 27, 7, 15, 15, 31, 14, 29, 29, 59, + 3, 7, 7, 15, 6, 13, 13, 27, 7, 15, 15, 31, 14, 29, 29, 59, + 7, 15, 15, 31, 14, 29, 29, 59, 15, 31, 31, 63, 30, 61, 61, 123, + 1, 3, 3, 7, 2, 5, 5, 11, 3, 7, 7, 15, 6, 13, 13, 27, + 3, 7, 7, 15, 6, 13, 13, 27, 7, 15, 15, 31, 14, 29, 29, 59, + 3, 7, 7, 15, 6, 13, 13, 27, 7, 15, 15, 31, 14, 29, 29, 59, + 7, 15, 15, 31, 14, 29, 29, 59, 15, 31, 31, 63, 30, 61, 61, 123, + 3, 7, 7, 15, 6, 13, 13, 27, 7, 15, 15, 31, 14, 29, 29, 59, + 7, 15, 15, 31, 14, 29, 29, 59, 15, 31, 31, 63, 30, 61, 61, 123, + 7, 15, 15, 31, 14, 29, 29, 59, 15, 31, 31, 63, 30, 61, 61, 123, + 15, 31, 31, 63, 30, 61, 61, 123, 31, 63, 63, 127, 62, 125, 125, 251, + }, + { + 0, 0, 0, 0, 1, 2, 2, 4, 1, 2, 2, 4, 3, 6, 6, 12, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 3, 6, 6, 12, 7, 14, 14, 28, 7, 14, 14, 28, 15, 30, 30, 60, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 3, 6, 6, 12, 7, 14, 14, 28, 7, 14, 14, 28, 15, 30, 30, 60, + 3, 6, 6, 12, 7, 14, 14, 28, 7, 14, 14, 28, 15, 30, 30, 60, + 7, 14, 14, 28, 15, 30, 30, 60, 15, 30, 30, 60, 31, 62, 62, 124, + 1, 2, 2, 4, 3, 6, 6, 12, 3, 6, 6, 12, 7, 14, 14, 28, + 3, 6, 6, 12, 7, 14, 14, 28, 7, 14, 14, 28, 15, 30, 30, 60, + 3, 6, 6, 12, 7, 14, 14, 28, 7, 14, 14, 28, 15, 30, 30, 60, + 7, 14, 14, 28, 15, 30, 30, 60, 15, 30, 30, 60, 31, 62, 62, 124, + 3, 6, 6, 12, 7, 14, 14, 28, 7, 14, 14, 28, 15, 30, 30, 60, + 7, 14, 14, 28, 15, 30, 30, 60, 15, 30, 30, 60, 31, 62, 62, 124, + 7, 14, 14, 28, 15, 30, 30, 60, 15, 30, 30, 60, 31, 62, 62, 124, + 15, 30, 30, 60, 31, 62, 62, 124, 31, 62, 62, 124, 63, 126, 126, 252, + }, { + 0, 1, 0, 1, 1, 3, 2, 5, 1, 3, 2, 5, 3, 7, 6, 13, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 3, 7, 6, 13, 7, 15, 14, 29, 7, 15, 14, 29, 15, 31, 30, 61, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 3, 7, 6, 13, 7, 15, 14, 29, 7, 15, 14, 29, 15, 31, 30, 61, + 3, 7, 6, 13, 7, 15, 14, 29, 7, 15, 14, 29, 15, 31, 30, 61, + 7, 15, 14, 29, 15, 31, 30, 61, 15, 31, 30, 61, 31, 63, 62, 125, + 1, 3, 2, 5, 3, 7, 6, 13, 3, 7, 6, 13, 7, 15, 14, 29, + 3, 7, 6, 13, 7, 15, 14, 29, 7, 15, 14, 29, 15, 31, 30, 61, + 3, 7, 6, 13, 7, 15, 14, 29, 7, 15, 14, 29, 15, 31, 30, 61, + 7, 15, 14, 29, 15, 31, 30, 61, 15, 31, 30, 61, 31, 63, 62, 125, + 3, 7, 6, 13, 7, 15, 14, 29, 7, 15, 14, 29, 15, 31, 30, 61, + 7, 15, 14, 29, 15, 31, 30, 61, 15, 31, 30, 61, 31, 63, 62, 125, + 7, 15, 14, 29, 15, 31, 30, 61, 15, 31, 30, 61, 31, 63, 62, 125, + 15, 31, 30, 61, 31, 63, 62, 125, 31, 63, 62, 125, 63, 127, 126, 253, + }, { + 0, 0, 1, 2, 1, 2, 3, 6, 1, 2, 3, 6, 3, 6, 7, 14, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 3, 6, 7, 14, 7, 14, 15, 30, 7, 14, 15, 30, 15, 30, 31, 62, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 3, 6, 7, 14, 7, 14, 15, 30, 7, 14, 15, 30, 15, 30, 31, 62, + 3, 6, 7, 14, 7, 14, 15, 30, 7, 14, 15, 30, 15, 30, 31, 62, + 7, 14, 15, 30, 15, 30, 31, 62, 15, 30, 31, 62, 31, 62, 63, 126, + 1, 2, 3, 6, 3, 6, 7, 14, 3, 6, 7, 14, 7, 14, 15, 30, + 3, 6, 7, 14, 7, 14, 15, 30, 7, 14, 15, 30, 15, 30, 31, 62, + 3, 6, 7, 14, 7, 14, 15, 30, 7, 14, 15, 30, 15, 30, 31, 62, + 7, 14, 15, 30, 15, 30, 31, 62, 15, 30, 31, 62, 31, 62, 63, 126, + 3, 6, 7, 14, 7, 14, 15, 30, 7, 14, 15, 30, 15, 30, 31, 62, + 7, 14, 15, 30, 15, 30, 31, 62, 15, 30, 31, 62, 31, 62, 63, 126, + 7, 14, 15, 30, 15, 30, 31, 62, 15, 30, 31, 62, 31, 62, 63, 126, + 15, 30, 31, 62, 31, 62, 63, 126, 31, 62, 63, 126, 63, 126, 127, 254, + }, { + 0, 1, 1, 3, 1, 3, 3, 7, 1, 3, 3, 7, 3, 7, 7, 15, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 3, 7, 7, 15, 7, 15, 15, 31, 7, 15, 15, 31, 15, 31, 31, 63, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 3, 7, 7, 15, 7, 15, 15, 31, 7, 15, 15, 31, 15, 31, 31, 63, + 3, 7, 7, 15, 7, 15, 15, 31, 7, 15, 15, 31, 15, 31, 31, 63, + 7, 15, 15, 31, 15, 31, 31, 63, 15, 31, 31, 63, 31, 63, 63, 127, + 1, 3, 3, 7, 3, 7, 7, 15, 3, 7, 7, 15, 7, 15, 15, 31, + 3, 7, 7, 15, 7, 15, 15, 31, 7, 15, 15, 31, 15, 31, 31, 63, + 3, 7, 7, 15, 7, 15, 15, 31, 7, 15, 15, 31, 15, 31, 31, 63, + 7, 15, 15, 31, 15, 31, 31, 63, 15, 31, 31, 63, 31, 63, 63, 127, + 3, 7, 7, 15, 7, 15, 15, 31, 7, 15, 15, 31, 15, 31, 31, 63, + 7, 15, 15, 31, 15, 31, 31, 63, 15, 31, 31, 63, 31, 63, 63, 127, + 7, 15, 15, 31, 15, 31, 31, 63, 15, 31, 31, 63, 31, 63, 63, 127, + 15, 31, 31, 63, 31, 63, 63, 127, 31, 63, 63, 127, 63, 127, 127, 255, + }, +} + +// pdepLUT contains pre-computed parallel bit deposit results +var pdepLUT = [256][256]uint8{ + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, { + 0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 64, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 128, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 64, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + }, { + 0, 0, 0, 2, 0, 4, 4, 2, 0, 8, 8, 2, 8, 4, 4, 2, + 0, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 2, + 0, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 2, + 32, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 2, + 0, 64, 64, 2, 64, 4, 4, 2, 64, 8, 8, 2, 8, 4, 4, 2, + 64, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 2, + 64, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 2, + 32, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 2, + 0, 128, 128, 2, 128, 4, 4, 2, 128, 8, 8, 2, 8, 4, 4, 2, + 128, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 2, + 128, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 2, + 32, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 2, + 128, 64, 64, 2, 64, 4, 4, 2, 64, 8, 8, 2, 8, 4, 4, 2, + 64, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 2, + 64, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 2, + 32, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 2, + }, { + 0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 10, 3, 12, 5, 6, 3, + 16, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 3, + 32, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 3, + 48, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 3, + 64, 65, 66, 3, 68, 5, 6, 3, 72, 9, 10, 3, 12, 5, 6, 3, + 80, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 3, + 96, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 3, + 48, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 3, + 128, 129, 130, 3, 132, 5, 6, 3, 136, 9, 10, 3, 12, 5, 6, 3, + 144, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 3, + 160, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 3, + 48, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 3, + 192, 65, 66, 3, 68, 5, 6, 3, 72, 9, 10, 3, 12, 5, 6, 3, + 80, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 3, + 96, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 3, + 48, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 3, + }, + { + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 8, 8, 4, + 0, 0, 0, 16, 0, 16, 16, 4, 0, 16, 16, 8, 16, 8, 8, 4, + 0, 0, 0, 32, 0, 32, 32, 4, 0, 32, 32, 8, 32, 8, 8, 4, + 0, 32, 32, 16, 32, 16, 16, 4, 32, 16, 16, 8, 16, 8, 8, 4, + 0, 0, 0, 64, 0, 64, 64, 4, 0, 64, 64, 8, 64, 8, 8, 4, + 0, 64, 64, 16, 64, 16, 16, 4, 64, 16, 16, 8, 16, 8, 8, 4, + 0, 64, 64, 32, 64, 32, 32, 4, 64, 32, 32, 8, 32, 8, 8, 4, + 64, 32, 32, 16, 32, 16, 16, 4, 32, 16, 16, 8, 16, 8, 8, 4, + 0, 0, 0, 128, 0, 128, 128, 4, 0, 128, 128, 8, 128, 8, 8, 4, + 0, 128, 128, 16, 128, 16, 16, 4, 128, 16, 16, 8, 16, 8, 8, 4, + 0, 128, 128, 32, 128, 32, 32, 4, 128, 32, 32, 8, 32, 8, 8, 4, + 128, 32, 32, 16, 32, 16, 16, 4, 32, 16, 16, 8, 16, 8, 8, 4, + 0, 128, 128, 64, 128, 64, 64, 4, 128, 64, 64, 8, 64, 8, 8, 4, + 128, 64, 64, 16, 64, 16, 16, 4, 64, 16, 16, 8, 16, 8, 8, 4, + 128, 64, 64, 32, 64, 32, 32, 4, 64, 32, 32, 8, 32, 8, 8, 4, + 64, 32, 32, 16, 32, 16, 16, 4, 32, 16, 16, 8, 16, 8, 8, 4, + }, { + 0, 1, 2, 1, 4, 1, 2, 5, 8, 1, 2, 9, 4, 9, 10, 5, + 16, 1, 2, 17, 4, 17, 18, 5, 8, 17, 18, 9, 20, 9, 10, 5, + 32, 1, 2, 33, 4, 33, 34, 5, 8, 33, 34, 9, 36, 9, 10, 5, + 16, 33, 34, 17, 36, 17, 18, 5, 40, 17, 18, 9, 20, 9, 10, 5, + 64, 1, 2, 65, 4, 65, 66, 5, 8, 65, 66, 9, 68, 9, 10, 5, + 16, 65, 66, 17, 68, 17, 18, 5, 72, 17, 18, 9, 20, 9, 10, 5, + 32, 65, 66, 33, 68, 33, 34, 5, 72, 33, 34, 9, 36, 9, 10, 5, + 80, 33, 34, 17, 36, 17, 18, 5, 40, 17, 18, 9, 20, 9, 10, 5, + 128, 1, 2, 129, 4, 129, 130, 5, 8, 129, 130, 9, 132, 9, 10, 5, + 16, 129, 130, 17, 132, 17, 18, 5, 136, 17, 18, 9, 20, 9, 10, 5, + 32, 129, 130, 33, 132, 33, 34, 5, 136, 33, 34, 9, 36, 9, 10, 5, + 144, 33, 34, 17, 36, 17, 18, 5, 40, 17, 18, 9, 20, 9, 10, 5, + 64, 129, 130, 65, 132, 65, 66, 5, 136, 65, 66, 9, 68, 9, 10, 5, + 144, 65, 66, 17, 68, 17, 18, 5, 72, 17, 18, 9, 20, 9, 10, 5, + 160, 65, 66, 33, 68, 33, 34, 5, 72, 33, 34, 9, 36, 9, 10, 5, + 80, 33, 34, 17, 36, 17, 18, 5, 40, 17, 18, 9, 20, 9, 10, 5, + }, { + 0, 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10, 8, 12, 12, 6, + 0, 16, 16, 18, 16, 20, 20, 6, 16, 24, 24, 10, 24, 12, 12, 6, + 0, 32, 32, 34, 32, 36, 36, 6, 32, 40, 40, 10, 40, 12, 12, 6, + 32, 48, 48, 18, 48, 20, 20, 6, 48, 24, 24, 10, 24, 12, 12, 6, + 0, 64, 64, 66, 64, 68, 68, 6, 64, 72, 72, 10, 72, 12, 12, 6, + 64, 80, 80, 18, 80, 20, 20, 6, 80, 24, 24, 10, 24, 12, 12, 6, + 64, 96, 96, 34, 96, 36, 36, 6, 96, 40, 40, 10, 40, 12, 12, 6, + 96, 48, 48, 18, 48, 20, 20, 6, 48, 24, 24, 10, 24, 12, 12, 6, + 0, 128, 128, 130, 128, 132, 132, 6, 128, 136, 136, 10, 136, 12, 12, 6, + 128, 144, 144, 18, 144, 20, 20, 6, 144, 24, 24, 10, 24, 12, 12, 6, + 128, 160, 160, 34, 160, 36, 36, 6, 160, 40, 40, 10, 40, 12, 12, 6, + 160, 48, 48, 18, 48, 20, 20, 6, 48, 24, 24, 10, 24, 12, 12, 6, + 128, 192, 192, 66, 192, 68, 68, 6, 192, 72, 72, 10, 72, 12, 12, 6, + 192, 80, 80, 18, 80, 20, 20, 6, 80, 24, 24, 10, 24, 12, 12, 6, + 192, 96, 96, 34, 96, 36, 36, 6, 96, 40, 40, 10, 40, 12, 12, 6, + 96, 48, 48, 18, 48, 20, 20, 6, 48, 24, 24, 10, 24, 12, 12, 6, + }, { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 7, + 16, 17, 18, 19, 20, 21, 22, 7, 24, 25, 26, 11, 28, 13, 14, 7, + 32, 33, 34, 35, 36, 37, 38, 7, 40, 41, 42, 11, 44, 13, 14, 7, + 48, 49, 50, 19, 52, 21, 22, 7, 56, 25, 26, 11, 28, 13, 14, 7, + 64, 65, 66, 67, 68, 69, 70, 7, 72, 73, 74, 11, 76, 13, 14, 7, + 80, 81, 82, 19, 84, 21, 22, 7, 88, 25, 26, 11, 28, 13, 14, 7, + 96, 97, 98, 35, 100, 37, 38, 7, 104, 41, 42, 11, 44, 13, 14, 7, + 112, 49, 50, 19, 52, 21, 22, 7, 56, 25, 26, 11, 28, 13, 14, 7, + 128, 129, 130, 131, 132, 133, 134, 7, 136, 137, 138, 11, 140, 13, 14, 7, + 144, 145, 146, 19, 148, 21, 22, 7, 152, 25, 26, 11, 28, 13, 14, 7, + 160, 161, 162, 35, 164, 37, 38, 7, 168, 41, 42, 11, 44, 13, 14, 7, + 176, 49, 50, 19, 52, 21, 22, 7, 56, 25, 26, 11, 28, 13, 14, 7, + 192, 193, 194, 67, 196, 69, 70, 7, 200, 73, 74, 11, 76, 13, 14, 7, + 208, 81, 82, 19, 84, 21, 22, 7, 88, 25, 26, 11, 28, 13, 14, 7, + 224, 97, 98, 35, 100, 37, 38, 7, 104, 41, 42, 11, 44, 13, 14, 7, + 112, 49, 50, 19, 52, 21, 22, 7, 56, 25, 26, 11, 28, 13, 14, 7, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, + 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 16, 0, 16, 16, 8, + 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 32, 0, 32, 32, 8, + 0, 0, 0, 32, 0, 32, 32, 16, 0, 32, 32, 16, 32, 16, 16, 8, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 8, + 0, 0, 0, 64, 0, 64, 64, 16, 0, 64, 64, 16, 64, 16, 16, 8, + 0, 0, 0, 64, 0, 64, 64, 32, 0, 64, 64, 32, 64, 32, 32, 8, + 0, 64, 64, 32, 64, 32, 32, 16, 64, 32, 32, 16, 32, 16, 16, 8, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 8, + 0, 0, 0, 128, 0, 128, 128, 16, 0, 128, 128, 16, 128, 16, 16, 8, + 0, 0, 0, 128, 0, 128, 128, 32, 0, 128, 128, 32, 128, 32, 32, 8, + 0, 128, 128, 32, 128, 32, 32, 16, 128, 32, 32, 16, 32, 16, 16, 8, + 0, 0, 0, 128, 0, 128, 128, 64, 0, 128, 128, 64, 128, 64, 64, 8, + 0, 128, 128, 64, 128, 64, 64, 16, 128, 64, 64, 16, 64, 16, 16, 8, + 0, 128, 128, 64, 128, 64, 64, 32, 128, 64, 64, 32, 64, 32, 32, 8, + 128, 64, 64, 32, 64, 32, 32, 16, 64, 32, 32, 16, 32, 16, 16, 8, + }, { + 0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 9, + 16, 1, 2, 1, 4, 1, 2, 17, 8, 1, 2, 17, 4, 17, 18, 9, + 32, 1, 2, 1, 4, 1, 2, 33, 8, 1, 2, 33, 4, 33, 34, 9, + 16, 1, 2, 33, 4, 33, 34, 17, 8, 33, 34, 17, 36, 17, 18, 9, + 64, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 9, + 16, 1, 2, 65, 4, 65, 66, 17, 8, 65, 66, 17, 68, 17, 18, 9, + 32, 1, 2, 65, 4, 65, 66, 33, 8, 65, 66, 33, 68, 33, 34, 9, + 16, 65, 66, 33, 68, 33, 34, 17, 72, 33, 34, 17, 36, 17, 18, 9, + 128, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 9, + 16, 1, 2, 129, 4, 129, 130, 17, 8, 129, 130, 17, 132, 17, 18, 9, + 32, 1, 2, 129, 4, 129, 130, 33, 8, 129, 130, 33, 132, 33, 34, 9, + 16, 129, 130, 33, 132, 33, 34, 17, 136, 33, 34, 17, 36, 17, 18, 9, + 64, 1, 2, 129, 4, 129, 130, 65, 8, 129, 130, 65, 132, 65, 66, 9, + 16, 129, 130, 65, 132, 65, 66, 17, 136, 65, 66, 17, 68, 17, 18, 9, + 32, 129, 130, 65, 132, 65, 66, 33, 136, 65, 66, 33, 68, 33, 34, 9, + 144, 65, 66, 33, 68, 33, 34, 17, 72, 33, 34, 17, 36, 17, 18, 9, + }, { + 0, 0, 0, 2, 0, 4, 4, 2, 0, 8, 8, 2, 8, 4, 4, 10, + 0, 16, 16, 2, 16, 4, 4, 18, 16, 8, 8, 18, 8, 20, 20, 10, + 0, 32, 32, 2, 32, 4, 4, 34, 32, 8, 8, 34, 8, 36, 36, 10, + 32, 16, 16, 34, 16, 36, 36, 18, 16, 40, 40, 18, 40, 20, 20, 10, + 0, 64, 64, 2, 64, 4, 4, 66, 64, 8, 8, 66, 8, 68, 68, 10, + 64, 16, 16, 66, 16, 68, 68, 18, 16, 72, 72, 18, 72, 20, 20, 10, + 64, 32, 32, 66, 32, 68, 68, 34, 32, 72, 72, 34, 72, 36, 36, 10, + 32, 80, 80, 34, 80, 36, 36, 18, 80, 40, 40, 18, 40, 20, 20, 10, + 0, 128, 128, 2, 128, 4, 4, 130, 128, 8, 8, 130, 8, 132, 132, 10, + 128, 16, 16, 130, 16, 132, 132, 18, 16, 136, 136, 18, 136, 20, 20, 10, + 128, 32, 32, 130, 32, 132, 132, 34, 32, 136, 136, 34, 136, 36, 36, 10, + 32, 144, 144, 34, 144, 36, 36, 18, 144, 40, 40, 18, 40, 20, 20, 10, + 128, 64, 64, 130, 64, 132, 132, 66, 64, 136, 136, 66, 136, 68, 68, 10, + 64, 144, 144, 66, 144, 68, 68, 18, 144, 72, 72, 18, 72, 20, 20, 10, + 64, 160, 160, 66, 160, 68, 68, 34, 160, 72, 72, 34, 72, 36, 36, 10, + 160, 80, 80, 34, 80, 36, 36, 18, 80, 40, 40, 18, 40, 20, 20, 10, + }, { + 0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 10, 3, 12, 5, 6, 11, + 16, 17, 18, 3, 20, 5, 6, 19, 24, 9, 10, 19, 12, 21, 22, 11, + 32, 33, 34, 3, 36, 5, 6, 35, 40, 9, 10, 35, 12, 37, 38, 11, + 48, 17, 18, 35, 20, 37, 38, 19, 24, 41, 42, 19, 44, 21, 22, 11, + 64, 65, 66, 3, 68, 5, 6, 67, 72, 9, 10, 67, 12, 69, 70, 11, + 80, 17, 18, 67, 20, 69, 70, 19, 24, 73, 74, 19, 76, 21, 22, 11, + 96, 33, 34, 67, 36, 69, 70, 35, 40, 73, 74, 35, 76, 37, 38, 11, + 48, 81, 82, 35, 84, 37, 38, 19, 88, 41, 42, 19, 44, 21, 22, 11, + 128, 129, 130, 3, 132, 5, 6, 131, 136, 9, 10, 131, 12, 133, 134, 11, + 144, 17, 18, 131, 20, 133, 134, 19, 24, 137, 138, 19, 140, 21, 22, 11, + 160, 33, 34, 131, 36, 133, 134, 35, 40, 137, 138, 35, 140, 37, 38, 11, + 48, 145, 146, 35, 148, 37, 38, 19, 152, 41, 42, 19, 44, 21, 22, 11, + 192, 65, 66, 131, 68, 133, 134, 67, 72, 137, 138, 67, 140, 69, 70, 11, + 80, 145, 146, 67, 148, 69, 70, 19, 152, 73, 74, 19, 76, 21, 22, 11, + 96, 161, 162, 67, 164, 69, 70, 35, 168, 73, 74, 35, 76, 37, 38, 11, + 176, 81, 82, 35, 84, 37, 38, 19, 88, 41, 42, 19, 44, 21, 22, 11, + }, + { + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 8, 8, 12, + 0, 0, 0, 16, 0, 16, 16, 20, 0, 16, 16, 24, 16, 24, 24, 12, + 0, 0, 0, 32, 0, 32, 32, 36, 0, 32, 32, 40, 32, 40, 40, 12, + 0, 32, 32, 48, 32, 48, 48, 20, 32, 48, 48, 24, 48, 24, 24, 12, + 0, 0, 0, 64, 0, 64, 64, 68, 0, 64, 64, 72, 64, 72, 72, 12, + 0, 64, 64, 80, 64, 80, 80, 20, 64, 80, 80, 24, 80, 24, 24, 12, + 0, 64, 64, 96, 64, 96, 96, 36, 64, 96, 96, 40, 96, 40, 40, 12, + 64, 96, 96, 48, 96, 48, 48, 20, 96, 48, 48, 24, 48, 24, 24, 12, + 0, 0, 0, 128, 0, 128, 128, 132, 0, 128, 128, 136, 128, 136, 136, 12, + 0, 128, 128, 144, 128, 144, 144, 20, 128, 144, 144, 24, 144, 24, 24, 12, + 0, 128, 128, 160, 128, 160, 160, 36, 128, 160, 160, 40, 160, 40, 40, 12, + 128, 160, 160, 48, 160, 48, 48, 20, 160, 48, 48, 24, 48, 24, 24, 12, + 0, 128, 128, 192, 128, 192, 192, 68, 128, 192, 192, 72, 192, 72, 72, 12, + 128, 192, 192, 80, 192, 80, 80, 20, 192, 80, 80, 24, 80, 24, 24, 12, + 128, 192, 192, 96, 192, 96, 96, 36, 192, 96, 96, 40, 96, 40, 40, 12, + 192, 96, 96, 48, 96, 48, 48, 20, 96, 48, 48, 24, 48, 24, 24, 12, + }, { + 0, 1, 2, 1, 4, 1, 2, 5, 8, 1, 2, 9, 4, 9, 10, 13, + 16, 1, 2, 17, 4, 17, 18, 21, 8, 17, 18, 25, 20, 25, 26, 13, + 32, 1, 2, 33, 4, 33, 34, 37, 8, 33, 34, 41, 36, 41, 42, 13, + 16, 33, 34, 49, 36, 49, 50, 21, 40, 49, 50, 25, 52, 25, 26, 13, + 64, 1, 2, 65, 4, 65, 66, 69, 8, 65, 66, 73, 68, 73, 74, 13, + 16, 65, 66, 81, 68, 81, 82, 21, 72, 81, 82, 25, 84, 25, 26, 13, + 32, 65, 66, 97, 68, 97, 98, 37, 72, 97, 98, 41, 100, 41, 42, 13, + 80, 97, 98, 49, 100, 49, 50, 21, 104, 49, 50, 25, 52, 25, 26, 13, + 128, 1, 2, 129, 4, 129, 130, 133, 8, 129, 130, 137, 132, 137, 138, 13, + 16, 129, 130, 145, 132, 145, 146, 21, 136, 145, 146, 25, 148, 25, 26, 13, + 32, 129, 130, 161, 132, 161, 162, 37, 136, 161, 162, 41, 164, 41, 42, 13, + 144, 161, 162, 49, 164, 49, 50, 21, 168, 49, 50, 25, 52, 25, 26, 13, + 64, 129, 130, 193, 132, 193, 194, 69, 136, 193, 194, 73, 196, 73, 74, 13, + 144, 193, 194, 81, 196, 81, 82, 21, 200, 81, 82, 25, 84, 25, 26, 13, + 160, 193, 194, 97, 196, 97, 98, 37, 200, 97, 98, 41, 100, 41, 42, 13, + 208, 97, 98, 49, 100, 49, 50, 21, 104, 49, 50, 25, 52, 25, 26, 13, + }, { + 0, 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10, 8, 12, 12, 14, + 0, 16, 16, 18, 16, 20, 20, 22, 16, 24, 24, 26, 24, 28, 28, 14, + 0, 32, 32, 34, 32, 36, 36, 38, 32, 40, 40, 42, 40, 44, 44, 14, + 32, 48, 48, 50, 48, 52, 52, 22, 48, 56, 56, 26, 56, 28, 28, 14, + 0, 64, 64, 66, 64, 68, 68, 70, 64, 72, 72, 74, 72, 76, 76, 14, + 64, 80, 80, 82, 80, 84, 84, 22, 80, 88, 88, 26, 88, 28, 28, 14, + 64, 96, 96, 98, 96, 100, 100, 38, 96, 104, 104, 42, 104, 44, 44, 14, + 96, 112, 112, 50, 112, 52, 52, 22, 112, 56, 56, 26, 56, 28, 28, 14, + 0, 128, 128, 130, 128, 132, 132, 134, 128, 136, 136, 138, 136, 140, 140, 14, + 128, 144, 144, 146, 144, 148, 148, 22, 144, 152, 152, 26, 152, 28, 28, 14, + 128, 160, 160, 162, 160, 164, 164, 38, 160, 168, 168, 42, 168, 44, 44, 14, + 160, 176, 176, 50, 176, 52, 52, 22, 176, 56, 56, 26, 56, 28, 28, 14, + 128, 192, 192, 194, 192, 196, 196, 70, 192, 200, 200, 74, 200, 76, 76, 14, + 192, 208, 208, 82, 208, 84, 84, 22, 208, 88, 88, 26, 88, 28, 28, 14, + 192, 224, 224, 98, 224, 100, 100, 38, 224, 104, 104, 42, 104, 44, 44, 14, + 224, 112, 112, 50, 112, 52, 52, 22, 112, 56, 56, 26, 56, 28, 28, 14, + }, { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 15, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 15, + 48, 49, 50, 51, 52, 53, 54, 23, 56, 57, 58, 27, 60, 29, 30, 15, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 15, + 80, 81, 82, 83, 84, 85, 86, 23, 88, 89, 90, 27, 92, 29, 30, 15, + 96, 97, 98, 99, 100, 101, 102, 39, 104, 105, 106, 43, 108, 45, 46, 15, + 112, 113, 114, 51, 116, 53, 54, 23, 120, 57, 58, 27, 60, 29, 30, 15, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 15, + 144, 145, 146, 147, 148, 149, 150, 23, 152, 153, 154, 27, 156, 29, 30, 15, + 160, 161, 162, 163, 164, 165, 166, 39, 168, 169, 170, 43, 172, 45, 46, 15, + 176, 177, 178, 51, 180, 53, 54, 23, 184, 57, 58, 27, 60, 29, 30, 15, + 192, 193, 194, 195, 196, 197, 198, 71, 200, 201, 202, 75, 204, 77, 78, 15, + 208, 209, 210, 83, 212, 85, 86, 23, 216, 89, 90, 27, 92, 29, 30, 15, + 224, 225, 226, 99, 228, 101, 102, 39, 232, 105, 106, 43, 108, 45, 46, 15, + 240, 113, 114, 51, 116, 53, 54, 23, 120, 57, 58, 27, 60, 29, 30, 15, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, + 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 32, 0, 32, 32, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 16, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 32, + 0, 0, 0, 64, 0, 64, 64, 32, 0, 64, 64, 32, 64, 32, 32, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 16, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 32, + 0, 0, 0, 128, 0, 128, 128, 32, 0, 128, 128, 32, 128, 32, 32, 16, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 64, + 0, 0, 0, 128, 0, 128, 128, 64, 0, 128, 128, 64, 128, 64, 64, 16, + 0, 0, 0, 128, 0, 128, 128, 64, 0, 128, 128, 64, 128, 64, 64, 32, + 0, 128, 128, 64, 128, 64, 64, 32, 128, 64, 64, 32, 64, 32, 32, 16, + }, { + 0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 17, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 33, + 16, 1, 2, 1, 4, 1, 2, 33, 8, 1, 2, 33, 4, 33, 34, 17, + 64, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 65, + 16, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 17, + 32, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 33, + 16, 1, 2, 65, 4, 65, 66, 33, 8, 65, 66, 33, 68, 33, 34, 17, + 128, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 129, + 16, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 17, + 32, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 33, + 16, 1, 2, 129, 4, 129, 130, 33, 8, 129, 130, 33, 132, 33, 34, 17, + 64, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 65, + 16, 1, 2, 129, 4, 129, 130, 65, 8, 129, 130, 65, 132, 65, 66, 17, + 32, 1, 2, 129, 4, 129, 130, 65, 8, 129, 130, 65, 132, 65, 66, 33, + 16, 129, 130, 65, 132, 65, 66, 33, 136, 65, 66, 33, 68, 33, 34, 17, + }, { + 0, 0, 0, 2, 0, 4, 4, 2, 0, 8, 8, 2, 8, 4, 4, 2, + 0, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 18, + 0, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 34, + 32, 16, 16, 2, 16, 4, 4, 34, 16, 8, 8, 34, 8, 36, 36, 18, + 0, 64, 64, 2, 64, 4, 4, 2, 64, 8, 8, 2, 8, 4, 4, 66, + 64, 16, 16, 2, 16, 4, 4, 66, 16, 8, 8, 66, 8, 68, 68, 18, + 64, 32, 32, 2, 32, 4, 4, 66, 32, 8, 8, 66, 8, 68, 68, 34, + 32, 16, 16, 66, 16, 68, 68, 34, 16, 72, 72, 34, 72, 36, 36, 18, + 0, 128, 128, 2, 128, 4, 4, 2, 128, 8, 8, 2, 8, 4, 4, 130, + 128, 16, 16, 2, 16, 4, 4, 130, 16, 8, 8, 130, 8, 132, 132, 18, + 128, 32, 32, 2, 32, 4, 4, 130, 32, 8, 8, 130, 8, 132, 132, 34, + 32, 16, 16, 130, 16, 132, 132, 34, 16, 136, 136, 34, 136, 36, 36, 18, + 128, 64, 64, 2, 64, 4, 4, 130, 64, 8, 8, 130, 8, 132, 132, 66, + 64, 16, 16, 130, 16, 132, 132, 66, 16, 136, 136, 66, 136, 68, 68, 18, + 64, 32, 32, 130, 32, 132, 132, 66, 32, 136, 136, 66, 136, 68, 68, 34, + 32, 144, 144, 66, 144, 68, 68, 34, 144, 72, 72, 34, 72, 36, 36, 18, + }, { + 0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 10, 3, 12, 5, 6, 3, + 16, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 19, + 32, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 35, + 48, 17, 18, 3, 20, 5, 6, 35, 24, 9, 10, 35, 12, 37, 38, 19, + 64, 65, 66, 3, 68, 5, 6, 3, 72, 9, 10, 3, 12, 5, 6, 67, + 80, 17, 18, 3, 20, 5, 6, 67, 24, 9, 10, 67, 12, 69, 70, 19, + 96, 33, 34, 3, 36, 5, 6, 67, 40, 9, 10, 67, 12, 69, 70, 35, + 48, 17, 18, 67, 20, 69, 70, 35, 24, 73, 74, 35, 76, 37, 38, 19, + 128, 129, 130, 3, 132, 5, 6, 3, 136, 9, 10, 3, 12, 5, 6, 131, + 144, 17, 18, 3, 20, 5, 6, 131, 24, 9, 10, 131, 12, 133, 134, 19, + 160, 33, 34, 3, 36, 5, 6, 131, 40, 9, 10, 131, 12, 133, 134, 35, + 48, 17, 18, 131, 20, 133, 134, 35, 24, 137, 138, 35, 140, 37, 38, 19, + 192, 65, 66, 3, 68, 5, 6, 131, 72, 9, 10, 131, 12, 133, 134, 67, + 80, 17, 18, 131, 20, 133, 134, 67, 24, 137, 138, 67, 140, 69, 70, 19, + 96, 33, 34, 131, 36, 133, 134, 67, 40, 137, 138, 67, 140, 69, 70, 35, + 48, 145, 146, 67, 148, 69, 70, 35, 152, 73, 74, 35, 76, 37, 38, 19, + }, + { + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 8, 8, 4, + 0, 0, 0, 16, 0, 16, 16, 4, 0, 16, 16, 8, 16, 8, 8, 20, + 0, 0, 0, 32, 0, 32, 32, 4, 0, 32, 32, 8, 32, 8, 8, 36, + 0, 32, 32, 16, 32, 16, 16, 36, 32, 16, 16, 40, 16, 40, 40, 20, + 0, 0, 0, 64, 0, 64, 64, 4, 0, 64, 64, 8, 64, 8, 8, 68, + 0, 64, 64, 16, 64, 16, 16, 68, 64, 16, 16, 72, 16, 72, 72, 20, + 0, 64, 64, 32, 64, 32, 32, 68, 64, 32, 32, 72, 32, 72, 72, 36, + 64, 32, 32, 80, 32, 80, 80, 36, 32, 80, 80, 40, 80, 40, 40, 20, + 0, 0, 0, 128, 0, 128, 128, 4, 0, 128, 128, 8, 128, 8, 8, 132, + 0, 128, 128, 16, 128, 16, 16, 132, 128, 16, 16, 136, 16, 136, 136, 20, + 0, 128, 128, 32, 128, 32, 32, 132, 128, 32, 32, 136, 32, 136, 136, 36, + 128, 32, 32, 144, 32, 144, 144, 36, 32, 144, 144, 40, 144, 40, 40, 20, + 0, 128, 128, 64, 128, 64, 64, 132, 128, 64, 64, 136, 64, 136, 136, 68, + 128, 64, 64, 144, 64, 144, 144, 68, 64, 144, 144, 72, 144, 72, 72, 20, + 128, 64, 64, 160, 64, 160, 160, 68, 64, 160, 160, 72, 160, 72, 72, 36, + 64, 160, 160, 80, 160, 80, 80, 36, 160, 80, 80, 40, 80, 40, 40, 20, + }, { + 0, 1, 2, 1, 4, 1, 2, 5, 8, 1, 2, 9, 4, 9, 10, 5, + 16, 1, 2, 17, 4, 17, 18, 5, 8, 17, 18, 9, 20, 9, 10, 21, + 32, 1, 2, 33, 4, 33, 34, 5, 8, 33, 34, 9, 36, 9, 10, 37, + 16, 33, 34, 17, 36, 17, 18, 37, 40, 17, 18, 41, 20, 41, 42, 21, + 64, 1, 2, 65, 4, 65, 66, 5, 8, 65, 66, 9, 68, 9, 10, 69, + 16, 65, 66, 17, 68, 17, 18, 69, 72, 17, 18, 73, 20, 73, 74, 21, + 32, 65, 66, 33, 68, 33, 34, 69, 72, 33, 34, 73, 36, 73, 74, 37, + 80, 33, 34, 81, 36, 81, 82, 37, 40, 81, 82, 41, 84, 41, 42, 21, + 128, 1, 2, 129, 4, 129, 130, 5, 8, 129, 130, 9, 132, 9, 10, 133, + 16, 129, 130, 17, 132, 17, 18, 133, 136, 17, 18, 137, 20, 137, 138, 21, + 32, 129, 130, 33, 132, 33, 34, 133, 136, 33, 34, 137, 36, 137, 138, 37, + 144, 33, 34, 145, 36, 145, 146, 37, 40, 145, 146, 41, 148, 41, 42, 21, + 64, 129, 130, 65, 132, 65, 66, 133, 136, 65, 66, 137, 68, 137, 138, 69, + 144, 65, 66, 145, 68, 145, 146, 69, 72, 145, 146, 73, 148, 73, 74, 21, + 160, 65, 66, 161, 68, 161, 162, 69, 72, 161, 162, 73, 164, 73, 74, 37, + 80, 161, 162, 81, 164, 81, 82, 37, 168, 81, 82, 41, 84, 41, 42, 21, + }, { + 0, 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10, 8, 12, 12, 6, + 0, 16, 16, 18, 16, 20, 20, 6, 16, 24, 24, 10, 24, 12, 12, 22, + 0, 32, 32, 34, 32, 36, 36, 6, 32, 40, 40, 10, 40, 12, 12, 38, + 32, 48, 48, 18, 48, 20, 20, 38, 48, 24, 24, 42, 24, 44, 44, 22, + 0, 64, 64, 66, 64, 68, 68, 6, 64, 72, 72, 10, 72, 12, 12, 70, + 64, 80, 80, 18, 80, 20, 20, 70, 80, 24, 24, 74, 24, 76, 76, 22, + 64, 96, 96, 34, 96, 36, 36, 70, 96, 40, 40, 74, 40, 76, 76, 38, + 96, 48, 48, 82, 48, 84, 84, 38, 48, 88, 88, 42, 88, 44, 44, 22, + 0, 128, 128, 130, 128, 132, 132, 6, 128, 136, 136, 10, 136, 12, 12, 134, + 128, 144, 144, 18, 144, 20, 20, 134, 144, 24, 24, 138, 24, 140, 140, 22, + 128, 160, 160, 34, 160, 36, 36, 134, 160, 40, 40, 138, 40, 140, 140, 38, + 160, 48, 48, 146, 48, 148, 148, 38, 48, 152, 152, 42, 152, 44, 44, 22, + 128, 192, 192, 66, 192, 68, 68, 134, 192, 72, 72, 138, 72, 140, 140, 70, + 192, 80, 80, 146, 80, 148, 148, 70, 80, 152, 152, 74, 152, 76, 76, 22, + 192, 96, 96, 162, 96, 164, 164, 70, 96, 168, 168, 74, 168, 76, 76, 38, + 96, 176, 176, 82, 176, 84, 84, 38, 176, 88, 88, 42, 88, 44, 44, 22, + }, { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 7, + 16, 17, 18, 19, 20, 21, 22, 7, 24, 25, 26, 11, 28, 13, 14, 23, + 32, 33, 34, 35, 36, 37, 38, 7, 40, 41, 42, 11, 44, 13, 14, 39, + 48, 49, 50, 19, 52, 21, 22, 39, 56, 25, 26, 43, 28, 45, 46, 23, + 64, 65, 66, 67, 68, 69, 70, 7, 72, 73, 74, 11, 76, 13, 14, 71, + 80, 81, 82, 19, 84, 21, 22, 71, 88, 25, 26, 75, 28, 77, 78, 23, + 96, 97, 98, 35, 100, 37, 38, 71, 104, 41, 42, 75, 44, 77, 78, 39, + 112, 49, 50, 83, 52, 85, 86, 39, 56, 89, 90, 43, 92, 45, 46, 23, + 128, 129, 130, 131, 132, 133, 134, 7, 136, 137, 138, 11, 140, 13, 14, 135, + 144, 145, 146, 19, 148, 21, 22, 135, 152, 25, 26, 139, 28, 141, 142, 23, + 160, 161, 162, 35, 164, 37, 38, 135, 168, 41, 42, 139, 44, 141, 142, 39, + 176, 49, 50, 147, 52, 149, 150, 39, 56, 153, 154, 43, 156, 45, 46, 23, + 192, 193, 194, 67, 196, 69, 70, 135, 200, 73, 74, 139, 76, 141, 142, 71, + 208, 81, 82, 147, 84, 149, 150, 71, 88, 153, 154, 75, 156, 77, 78, 23, + 224, 97, 98, 163, 100, 165, 166, 71, 104, 169, 170, 75, 172, 77, 78, 39, + 112, 177, 178, 83, 180, 85, 86, 39, 184, 89, 90, 43, 92, 45, 46, 23, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, + 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 16, 0, 16, 16, 24, + 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 32, 0, 32, 32, 40, + 0, 0, 0, 32, 0, 32, 32, 48, 0, 32, 32, 48, 32, 48, 48, 24, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 72, + 0, 0, 0, 64, 0, 64, 64, 80, 0, 64, 64, 80, 64, 80, 80, 24, + 0, 0, 0, 64, 0, 64, 64, 96, 0, 64, 64, 96, 64, 96, 96, 40, + 0, 64, 64, 96, 64, 96, 96, 48, 64, 96, 96, 48, 96, 48, 48, 24, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 136, + 0, 0, 0, 128, 0, 128, 128, 144, 0, 128, 128, 144, 128, 144, 144, 24, + 0, 0, 0, 128, 0, 128, 128, 160, 0, 128, 128, 160, 128, 160, 160, 40, + 0, 128, 128, 160, 128, 160, 160, 48, 128, 160, 160, 48, 160, 48, 48, 24, + 0, 0, 0, 128, 0, 128, 128, 192, 0, 128, 128, 192, 128, 192, 192, 72, + 0, 128, 128, 192, 128, 192, 192, 80, 128, 192, 192, 80, 192, 80, 80, 24, + 0, 128, 128, 192, 128, 192, 192, 96, 128, 192, 192, 96, 192, 96, 96, 40, + 128, 192, 192, 96, 192, 96, 96, 48, 192, 96, 96, 48, 96, 48, 48, 24, + }, { + 0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 9, + 16, 1, 2, 1, 4, 1, 2, 17, 8, 1, 2, 17, 4, 17, 18, 25, + 32, 1, 2, 1, 4, 1, 2, 33, 8, 1, 2, 33, 4, 33, 34, 41, + 16, 1, 2, 33, 4, 33, 34, 49, 8, 33, 34, 49, 36, 49, 50, 25, + 64, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 73, + 16, 1, 2, 65, 4, 65, 66, 81, 8, 65, 66, 81, 68, 81, 82, 25, + 32, 1, 2, 65, 4, 65, 66, 97, 8, 65, 66, 97, 68, 97, 98, 41, + 16, 65, 66, 97, 68, 97, 98, 49, 72, 97, 98, 49, 100, 49, 50, 25, + 128, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 137, + 16, 1, 2, 129, 4, 129, 130, 145, 8, 129, 130, 145, 132, 145, 146, 25, + 32, 1, 2, 129, 4, 129, 130, 161, 8, 129, 130, 161, 132, 161, 162, 41, + 16, 129, 130, 161, 132, 161, 162, 49, 136, 161, 162, 49, 164, 49, 50, 25, + 64, 1, 2, 129, 4, 129, 130, 193, 8, 129, 130, 193, 132, 193, 194, 73, + 16, 129, 130, 193, 132, 193, 194, 81, 136, 193, 194, 81, 196, 81, 82, 25, + 32, 129, 130, 193, 132, 193, 194, 97, 136, 193, 194, 97, 196, 97, 98, 41, + 144, 193, 194, 97, 196, 97, 98, 49, 200, 97, 98, 49, 100, 49, 50, 25, + }, { + 0, 0, 0, 2, 0, 4, 4, 2, 0, 8, 8, 2, 8, 4, 4, 10, + 0, 16, 16, 2, 16, 4, 4, 18, 16, 8, 8, 18, 8, 20, 20, 26, + 0, 32, 32, 2, 32, 4, 4, 34, 32, 8, 8, 34, 8, 36, 36, 42, + 32, 16, 16, 34, 16, 36, 36, 50, 16, 40, 40, 50, 40, 52, 52, 26, + 0, 64, 64, 2, 64, 4, 4, 66, 64, 8, 8, 66, 8, 68, 68, 74, + 64, 16, 16, 66, 16, 68, 68, 82, 16, 72, 72, 82, 72, 84, 84, 26, + 64, 32, 32, 66, 32, 68, 68, 98, 32, 72, 72, 98, 72, 100, 100, 42, + 32, 80, 80, 98, 80, 100, 100, 50, 80, 104, 104, 50, 104, 52, 52, 26, + 0, 128, 128, 2, 128, 4, 4, 130, 128, 8, 8, 130, 8, 132, 132, 138, + 128, 16, 16, 130, 16, 132, 132, 146, 16, 136, 136, 146, 136, 148, 148, 26, + 128, 32, 32, 130, 32, 132, 132, 162, 32, 136, 136, 162, 136, 164, 164, 42, + 32, 144, 144, 162, 144, 164, 164, 50, 144, 168, 168, 50, 168, 52, 52, 26, + 128, 64, 64, 130, 64, 132, 132, 194, 64, 136, 136, 194, 136, 196, 196, 74, + 64, 144, 144, 194, 144, 196, 196, 82, 144, 200, 200, 82, 200, 84, 84, 26, + 64, 160, 160, 194, 160, 196, 196, 98, 160, 200, 200, 98, 200, 100, 100, 42, + 160, 208, 208, 98, 208, 100, 100, 50, 208, 104, 104, 50, 104, 52, 52, 26, + }, { + 0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 10, 3, 12, 5, 6, 11, + 16, 17, 18, 3, 20, 5, 6, 19, 24, 9, 10, 19, 12, 21, 22, 27, + 32, 33, 34, 3, 36, 5, 6, 35, 40, 9, 10, 35, 12, 37, 38, 43, + 48, 17, 18, 35, 20, 37, 38, 51, 24, 41, 42, 51, 44, 53, 54, 27, + 64, 65, 66, 3, 68, 5, 6, 67, 72, 9, 10, 67, 12, 69, 70, 75, + 80, 17, 18, 67, 20, 69, 70, 83, 24, 73, 74, 83, 76, 85, 86, 27, + 96, 33, 34, 67, 36, 69, 70, 99, 40, 73, 74, 99, 76, 101, 102, 43, + 48, 81, 82, 99, 84, 101, 102, 51, 88, 105, 106, 51, 108, 53, 54, 27, + 128, 129, 130, 3, 132, 5, 6, 131, 136, 9, 10, 131, 12, 133, 134, 139, + 144, 17, 18, 131, 20, 133, 134, 147, 24, 137, 138, 147, 140, 149, 150, 27, + 160, 33, 34, 131, 36, 133, 134, 163, 40, 137, 138, 163, 140, 165, 166, 43, + 48, 145, 146, 163, 148, 165, 166, 51, 152, 169, 170, 51, 172, 53, 54, 27, + 192, 65, 66, 131, 68, 133, 134, 195, 72, 137, 138, 195, 140, 197, 198, 75, + 80, 145, 146, 195, 148, 197, 198, 83, 152, 201, 202, 83, 204, 85, 86, 27, + 96, 161, 162, 195, 164, 197, 198, 99, 168, 201, 202, 99, 204, 101, 102, 43, + 176, 209, 210, 99, 212, 101, 102, 51, 216, 105, 106, 51, 108, 53, 54, 27, + }, + { + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 8, 8, 12, + 0, 0, 0, 16, 0, 16, 16, 20, 0, 16, 16, 24, 16, 24, 24, 28, + 0, 0, 0, 32, 0, 32, 32, 36, 0, 32, 32, 40, 32, 40, 40, 44, + 0, 32, 32, 48, 32, 48, 48, 52, 32, 48, 48, 56, 48, 56, 56, 28, + 0, 0, 0, 64, 0, 64, 64, 68, 0, 64, 64, 72, 64, 72, 72, 76, + 0, 64, 64, 80, 64, 80, 80, 84, 64, 80, 80, 88, 80, 88, 88, 28, + 0, 64, 64, 96, 64, 96, 96, 100, 64, 96, 96, 104, 96, 104, 104, 44, + 64, 96, 96, 112, 96, 112, 112, 52, 96, 112, 112, 56, 112, 56, 56, 28, + 0, 0, 0, 128, 0, 128, 128, 132, 0, 128, 128, 136, 128, 136, 136, 140, + 0, 128, 128, 144, 128, 144, 144, 148, 128, 144, 144, 152, 144, 152, 152, 28, + 0, 128, 128, 160, 128, 160, 160, 164, 128, 160, 160, 168, 160, 168, 168, 44, + 128, 160, 160, 176, 160, 176, 176, 52, 160, 176, 176, 56, 176, 56, 56, 28, + 0, 128, 128, 192, 128, 192, 192, 196, 128, 192, 192, 200, 192, 200, 200, 76, + 128, 192, 192, 208, 192, 208, 208, 84, 192, 208, 208, 88, 208, 88, 88, 28, + 128, 192, 192, 224, 192, 224, 224, 100, 192, 224, 224, 104, 224, 104, 104, 44, + 192, 224, 224, 112, 224, 112, 112, 52, 224, 112, 112, 56, 112, 56, 56, 28, + }, { + 0, 1, 2, 1, 4, 1, 2, 5, 8, 1, 2, 9, 4, 9, 10, 13, + 16, 1, 2, 17, 4, 17, 18, 21, 8, 17, 18, 25, 20, 25, 26, 29, + 32, 1, 2, 33, 4, 33, 34, 37, 8, 33, 34, 41, 36, 41, 42, 45, + 16, 33, 34, 49, 36, 49, 50, 53, 40, 49, 50, 57, 52, 57, 58, 29, + 64, 1, 2, 65, 4, 65, 66, 69, 8, 65, 66, 73, 68, 73, 74, 77, + 16, 65, 66, 81, 68, 81, 82, 85, 72, 81, 82, 89, 84, 89, 90, 29, + 32, 65, 66, 97, 68, 97, 98, 101, 72, 97, 98, 105, 100, 105, 106, 45, + 80, 97, 98, 113, 100, 113, 114, 53, 104, 113, 114, 57, 116, 57, 58, 29, + 128, 1, 2, 129, 4, 129, 130, 133, 8, 129, 130, 137, 132, 137, 138, 141, + 16, 129, 130, 145, 132, 145, 146, 149, 136, 145, 146, 153, 148, 153, 154, 29, + 32, 129, 130, 161, 132, 161, 162, 165, 136, 161, 162, 169, 164, 169, 170, 45, + 144, 161, 162, 177, 164, 177, 178, 53, 168, 177, 178, 57, 180, 57, 58, 29, + 64, 129, 130, 193, 132, 193, 194, 197, 136, 193, 194, 201, 196, 201, 202, 77, + 144, 193, 194, 209, 196, 209, 210, 85, 200, 209, 210, 89, 212, 89, 90, 29, + 160, 193, 194, 225, 196, 225, 226, 101, 200, 225, 226, 105, 228, 105, 106, 45, + 208, 225, 226, 113, 228, 113, 114, 53, 232, 113, 114, 57, 116, 57, 58, 29, + }, { + 0, 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10, 8, 12, 12, 14, + 0, 16, 16, 18, 16, 20, 20, 22, 16, 24, 24, 26, 24, 28, 28, 30, + 0, 32, 32, 34, 32, 36, 36, 38, 32, 40, 40, 42, 40, 44, 44, 46, + 32, 48, 48, 50, 48, 52, 52, 54, 48, 56, 56, 58, 56, 60, 60, 30, + 0, 64, 64, 66, 64, 68, 68, 70, 64, 72, 72, 74, 72, 76, 76, 78, + 64, 80, 80, 82, 80, 84, 84, 86, 80, 88, 88, 90, 88, 92, 92, 30, + 64, 96, 96, 98, 96, 100, 100, 102, 96, 104, 104, 106, 104, 108, 108, 46, + 96, 112, 112, 114, 112, 116, 116, 54, 112, 120, 120, 58, 120, 60, 60, 30, + 0, 128, 128, 130, 128, 132, 132, 134, 128, 136, 136, 138, 136, 140, 140, 142, + 128, 144, 144, 146, 144, 148, 148, 150, 144, 152, 152, 154, 152, 156, 156, 30, + 128, 160, 160, 162, 160, 164, 164, 166, 160, 168, 168, 170, 168, 172, 172, 46, + 160, 176, 176, 178, 176, 180, 180, 54, 176, 184, 184, 58, 184, 60, 60, 30, + 128, 192, 192, 194, 192, 196, 196, 198, 192, 200, 200, 202, 200, 204, 204, 78, + 192, 208, 208, 210, 208, 212, 212, 86, 208, 216, 216, 90, 216, 92, 92, 30, + 192, 224, 224, 226, 224, 228, 228, 102, 224, 232, 232, 106, 232, 108, 108, 46, + 224, 240, 240, 114, 240, 116, 116, 54, 240, 120, 120, 58, 120, 60, 60, 30, + }, { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 31, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 31, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 47, + 112, 113, 114, 115, 116, 117, 118, 55, 120, 121, 122, 59, 124, 61, 62, 31, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, + 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 31, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 47, + 176, 177, 178, 179, 180, 181, 182, 55, 184, 185, 186, 59, 188, 61, 62, 31, + 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 79, + 208, 209, 210, 211, 212, 213, 214, 87, 216, 217, 218, 91, 220, 93, 94, 31, + 224, 225, 226, 227, 228, 229, 230, 103, 232, 233, 234, 107, 236, 109, 110, 47, + 240, 241, 242, 115, 244, 117, 118, 55, 248, 121, 122, 59, 124, 61, 62, 31, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 32, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 32, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 64, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 64, + 0, 0, 0, 128, 0, 128, 128, 64, 0, 128, 128, 64, 128, 64, 64, 32, + }, { + 0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 33, + 64, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 65, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 65, + 16, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 33, + 128, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 129, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 129, + 16, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 33, + 64, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 129, + 16, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 65, + 32, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 65, + 16, 1, 2, 129, 4, 129, 130, 65, 8, 129, 130, 65, 132, 65, 66, 33, + }, { + 0, 0, 0, 2, 0, 4, 4, 2, 0, 8, 8, 2, 8, 4, 4, 2, + 0, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 2, + 0, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 2, + 32, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 34, + 0, 64, 64, 2, 64, 4, 4, 2, 64, 8, 8, 2, 8, 4, 4, 2, + 64, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 66, + 64, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 66, + 32, 16, 16, 2, 16, 4, 4, 66, 16, 8, 8, 66, 8, 68, 68, 34, + 0, 128, 128, 2, 128, 4, 4, 2, 128, 8, 8, 2, 8, 4, 4, 2, + 128, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 130, + 128, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 130, + 32, 16, 16, 2, 16, 4, 4, 130, 16, 8, 8, 130, 8, 132, 132, 34, + 128, 64, 64, 2, 64, 4, 4, 2, 64, 8, 8, 2, 8, 4, 4, 130, + 64, 16, 16, 2, 16, 4, 4, 130, 16, 8, 8, 130, 8, 132, 132, 66, + 64, 32, 32, 2, 32, 4, 4, 130, 32, 8, 8, 130, 8, 132, 132, 66, + 32, 16, 16, 130, 16, 132, 132, 66, 16, 136, 136, 66, 136, 68, 68, 34, + }, { + 0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 10, 3, 12, 5, 6, 3, + 16, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 3, + 32, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 3, + 48, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 35, + 64, 65, 66, 3, 68, 5, 6, 3, 72, 9, 10, 3, 12, 5, 6, 3, + 80, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 67, + 96, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 67, + 48, 17, 18, 3, 20, 5, 6, 67, 24, 9, 10, 67, 12, 69, 70, 35, + 128, 129, 130, 3, 132, 5, 6, 3, 136, 9, 10, 3, 12, 5, 6, 3, + 144, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 131, + 160, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 131, + 48, 17, 18, 3, 20, 5, 6, 131, 24, 9, 10, 131, 12, 133, 134, 35, + 192, 65, 66, 3, 68, 5, 6, 3, 72, 9, 10, 3, 12, 5, 6, 131, + 80, 17, 18, 3, 20, 5, 6, 131, 24, 9, 10, 131, 12, 133, 134, 67, + 96, 33, 34, 3, 36, 5, 6, 131, 40, 9, 10, 131, 12, 133, 134, 67, + 48, 17, 18, 131, 20, 133, 134, 67, 24, 137, 138, 67, 140, 69, 70, 35, + }, + { + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 8, 8, 4, + 0, 0, 0, 16, 0, 16, 16, 4, 0, 16, 16, 8, 16, 8, 8, 4, + 0, 0, 0, 32, 0, 32, 32, 4, 0, 32, 32, 8, 32, 8, 8, 4, + 0, 32, 32, 16, 32, 16, 16, 4, 32, 16, 16, 8, 16, 8, 8, 36, + 0, 0, 0, 64, 0, 64, 64, 4, 0, 64, 64, 8, 64, 8, 8, 4, + 0, 64, 64, 16, 64, 16, 16, 4, 64, 16, 16, 8, 16, 8, 8, 68, + 0, 64, 64, 32, 64, 32, 32, 4, 64, 32, 32, 8, 32, 8, 8, 68, + 64, 32, 32, 16, 32, 16, 16, 68, 32, 16, 16, 72, 16, 72, 72, 36, + 0, 0, 0, 128, 0, 128, 128, 4, 0, 128, 128, 8, 128, 8, 8, 4, + 0, 128, 128, 16, 128, 16, 16, 4, 128, 16, 16, 8, 16, 8, 8, 132, + 0, 128, 128, 32, 128, 32, 32, 4, 128, 32, 32, 8, 32, 8, 8, 132, + 128, 32, 32, 16, 32, 16, 16, 132, 32, 16, 16, 136, 16, 136, 136, 36, + 0, 128, 128, 64, 128, 64, 64, 4, 128, 64, 64, 8, 64, 8, 8, 132, + 128, 64, 64, 16, 64, 16, 16, 132, 64, 16, 16, 136, 16, 136, 136, 68, + 128, 64, 64, 32, 64, 32, 32, 132, 64, 32, 32, 136, 32, 136, 136, 68, + 64, 32, 32, 144, 32, 144, 144, 68, 32, 144, 144, 72, 144, 72, 72, 36, + }, { + 0, 1, 2, 1, 4, 1, 2, 5, 8, 1, 2, 9, 4, 9, 10, 5, + 16, 1, 2, 17, 4, 17, 18, 5, 8, 17, 18, 9, 20, 9, 10, 5, + 32, 1, 2, 33, 4, 33, 34, 5, 8, 33, 34, 9, 36, 9, 10, 5, + 16, 33, 34, 17, 36, 17, 18, 5, 40, 17, 18, 9, 20, 9, 10, 37, + 64, 1, 2, 65, 4, 65, 66, 5, 8, 65, 66, 9, 68, 9, 10, 5, + 16, 65, 66, 17, 68, 17, 18, 5, 72, 17, 18, 9, 20, 9, 10, 69, + 32, 65, 66, 33, 68, 33, 34, 5, 72, 33, 34, 9, 36, 9, 10, 69, + 80, 33, 34, 17, 36, 17, 18, 69, 40, 17, 18, 73, 20, 73, 74, 37, + 128, 1, 2, 129, 4, 129, 130, 5, 8, 129, 130, 9, 132, 9, 10, 5, + 16, 129, 130, 17, 132, 17, 18, 5, 136, 17, 18, 9, 20, 9, 10, 133, + 32, 129, 130, 33, 132, 33, 34, 5, 136, 33, 34, 9, 36, 9, 10, 133, + 144, 33, 34, 17, 36, 17, 18, 133, 40, 17, 18, 137, 20, 137, 138, 37, + 64, 129, 130, 65, 132, 65, 66, 5, 136, 65, 66, 9, 68, 9, 10, 133, + 144, 65, 66, 17, 68, 17, 18, 133, 72, 17, 18, 137, 20, 137, 138, 69, + 160, 65, 66, 33, 68, 33, 34, 133, 72, 33, 34, 137, 36, 137, 138, 69, + 80, 33, 34, 145, 36, 145, 146, 69, 40, 145, 146, 73, 148, 73, 74, 37, + }, { + 0, 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10, 8, 12, 12, 6, + 0, 16, 16, 18, 16, 20, 20, 6, 16, 24, 24, 10, 24, 12, 12, 6, + 0, 32, 32, 34, 32, 36, 36, 6, 32, 40, 40, 10, 40, 12, 12, 6, + 32, 48, 48, 18, 48, 20, 20, 6, 48, 24, 24, 10, 24, 12, 12, 38, + 0, 64, 64, 66, 64, 68, 68, 6, 64, 72, 72, 10, 72, 12, 12, 6, + 64, 80, 80, 18, 80, 20, 20, 6, 80, 24, 24, 10, 24, 12, 12, 70, + 64, 96, 96, 34, 96, 36, 36, 6, 96, 40, 40, 10, 40, 12, 12, 70, + 96, 48, 48, 18, 48, 20, 20, 70, 48, 24, 24, 74, 24, 76, 76, 38, + 0, 128, 128, 130, 128, 132, 132, 6, 128, 136, 136, 10, 136, 12, 12, 6, + 128, 144, 144, 18, 144, 20, 20, 6, 144, 24, 24, 10, 24, 12, 12, 134, + 128, 160, 160, 34, 160, 36, 36, 6, 160, 40, 40, 10, 40, 12, 12, 134, + 160, 48, 48, 18, 48, 20, 20, 134, 48, 24, 24, 138, 24, 140, 140, 38, + 128, 192, 192, 66, 192, 68, 68, 6, 192, 72, 72, 10, 72, 12, 12, 134, + 192, 80, 80, 18, 80, 20, 20, 134, 80, 24, 24, 138, 24, 140, 140, 70, + 192, 96, 96, 34, 96, 36, 36, 134, 96, 40, 40, 138, 40, 140, 140, 70, + 96, 48, 48, 146, 48, 148, 148, 70, 48, 152, 152, 74, 152, 76, 76, 38, + }, { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 7, + 16, 17, 18, 19, 20, 21, 22, 7, 24, 25, 26, 11, 28, 13, 14, 7, + 32, 33, 34, 35, 36, 37, 38, 7, 40, 41, 42, 11, 44, 13, 14, 7, + 48, 49, 50, 19, 52, 21, 22, 7, 56, 25, 26, 11, 28, 13, 14, 39, + 64, 65, 66, 67, 68, 69, 70, 7, 72, 73, 74, 11, 76, 13, 14, 7, + 80, 81, 82, 19, 84, 21, 22, 7, 88, 25, 26, 11, 28, 13, 14, 71, + 96, 97, 98, 35, 100, 37, 38, 7, 104, 41, 42, 11, 44, 13, 14, 71, + 112, 49, 50, 19, 52, 21, 22, 71, 56, 25, 26, 75, 28, 77, 78, 39, + 128, 129, 130, 131, 132, 133, 134, 7, 136, 137, 138, 11, 140, 13, 14, 7, + 144, 145, 146, 19, 148, 21, 22, 7, 152, 25, 26, 11, 28, 13, 14, 135, + 160, 161, 162, 35, 164, 37, 38, 7, 168, 41, 42, 11, 44, 13, 14, 135, + 176, 49, 50, 19, 52, 21, 22, 135, 56, 25, 26, 139, 28, 141, 142, 39, + 192, 193, 194, 67, 196, 69, 70, 7, 200, 73, 74, 11, 76, 13, 14, 135, + 208, 81, 82, 19, 84, 21, 22, 135, 88, 25, 26, 139, 28, 141, 142, 71, + 224, 97, 98, 35, 100, 37, 38, 135, 104, 41, 42, 139, 44, 141, 142, 71, + 112, 49, 50, 147, 52, 149, 150, 71, 56, 153, 154, 75, 156, 77, 78, 39, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, + 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 16, 0, 16, 16, 8, + 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 32, 0, 32, 32, 8, + 0, 0, 0, 32, 0, 32, 32, 16, 0, 32, 32, 16, 32, 16, 16, 40, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 8, + 0, 0, 0, 64, 0, 64, 64, 16, 0, 64, 64, 16, 64, 16, 16, 72, + 0, 0, 0, 64, 0, 64, 64, 32, 0, 64, 64, 32, 64, 32, 32, 72, + 0, 64, 64, 32, 64, 32, 32, 80, 64, 32, 32, 80, 32, 80, 80, 40, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 8, + 0, 0, 0, 128, 0, 128, 128, 16, 0, 128, 128, 16, 128, 16, 16, 136, + 0, 0, 0, 128, 0, 128, 128, 32, 0, 128, 128, 32, 128, 32, 32, 136, + 0, 128, 128, 32, 128, 32, 32, 144, 128, 32, 32, 144, 32, 144, 144, 40, + 0, 0, 0, 128, 0, 128, 128, 64, 0, 128, 128, 64, 128, 64, 64, 136, + 0, 128, 128, 64, 128, 64, 64, 144, 128, 64, 64, 144, 64, 144, 144, 72, + 0, 128, 128, 64, 128, 64, 64, 160, 128, 64, 64, 160, 64, 160, 160, 72, + 128, 64, 64, 160, 64, 160, 160, 80, 64, 160, 160, 80, 160, 80, 80, 40, + }, { + 0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 9, + 16, 1, 2, 1, 4, 1, 2, 17, 8, 1, 2, 17, 4, 17, 18, 9, + 32, 1, 2, 1, 4, 1, 2, 33, 8, 1, 2, 33, 4, 33, 34, 9, + 16, 1, 2, 33, 4, 33, 34, 17, 8, 33, 34, 17, 36, 17, 18, 41, + 64, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 9, + 16, 1, 2, 65, 4, 65, 66, 17, 8, 65, 66, 17, 68, 17, 18, 73, + 32, 1, 2, 65, 4, 65, 66, 33, 8, 65, 66, 33, 68, 33, 34, 73, + 16, 65, 66, 33, 68, 33, 34, 81, 72, 33, 34, 81, 36, 81, 82, 41, + 128, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 9, + 16, 1, 2, 129, 4, 129, 130, 17, 8, 129, 130, 17, 132, 17, 18, 137, + 32, 1, 2, 129, 4, 129, 130, 33, 8, 129, 130, 33, 132, 33, 34, 137, + 16, 129, 130, 33, 132, 33, 34, 145, 136, 33, 34, 145, 36, 145, 146, 41, + 64, 1, 2, 129, 4, 129, 130, 65, 8, 129, 130, 65, 132, 65, 66, 137, + 16, 129, 130, 65, 132, 65, 66, 145, 136, 65, 66, 145, 68, 145, 146, 73, + 32, 129, 130, 65, 132, 65, 66, 161, 136, 65, 66, 161, 68, 161, 162, 73, + 144, 65, 66, 161, 68, 161, 162, 81, 72, 161, 162, 81, 164, 81, 82, 41, + }, { + 0, 0, 0, 2, 0, 4, 4, 2, 0, 8, 8, 2, 8, 4, 4, 10, + 0, 16, 16, 2, 16, 4, 4, 18, 16, 8, 8, 18, 8, 20, 20, 10, + 0, 32, 32, 2, 32, 4, 4, 34, 32, 8, 8, 34, 8, 36, 36, 10, + 32, 16, 16, 34, 16, 36, 36, 18, 16, 40, 40, 18, 40, 20, 20, 42, + 0, 64, 64, 2, 64, 4, 4, 66, 64, 8, 8, 66, 8, 68, 68, 10, + 64, 16, 16, 66, 16, 68, 68, 18, 16, 72, 72, 18, 72, 20, 20, 74, + 64, 32, 32, 66, 32, 68, 68, 34, 32, 72, 72, 34, 72, 36, 36, 74, + 32, 80, 80, 34, 80, 36, 36, 82, 80, 40, 40, 82, 40, 84, 84, 42, + 0, 128, 128, 2, 128, 4, 4, 130, 128, 8, 8, 130, 8, 132, 132, 10, + 128, 16, 16, 130, 16, 132, 132, 18, 16, 136, 136, 18, 136, 20, 20, 138, + 128, 32, 32, 130, 32, 132, 132, 34, 32, 136, 136, 34, 136, 36, 36, 138, + 32, 144, 144, 34, 144, 36, 36, 146, 144, 40, 40, 146, 40, 148, 148, 42, + 128, 64, 64, 130, 64, 132, 132, 66, 64, 136, 136, 66, 136, 68, 68, 138, + 64, 144, 144, 66, 144, 68, 68, 146, 144, 72, 72, 146, 72, 148, 148, 74, + 64, 160, 160, 66, 160, 68, 68, 162, 160, 72, 72, 162, 72, 164, 164, 74, + 160, 80, 80, 162, 80, 164, 164, 82, 80, 168, 168, 82, 168, 84, 84, 42, + }, { + 0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 10, 3, 12, 5, 6, 11, + 16, 17, 18, 3, 20, 5, 6, 19, 24, 9, 10, 19, 12, 21, 22, 11, + 32, 33, 34, 3, 36, 5, 6, 35, 40, 9, 10, 35, 12, 37, 38, 11, + 48, 17, 18, 35, 20, 37, 38, 19, 24, 41, 42, 19, 44, 21, 22, 43, + 64, 65, 66, 3, 68, 5, 6, 67, 72, 9, 10, 67, 12, 69, 70, 11, + 80, 17, 18, 67, 20, 69, 70, 19, 24, 73, 74, 19, 76, 21, 22, 75, + 96, 33, 34, 67, 36, 69, 70, 35, 40, 73, 74, 35, 76, 37, 38, 75, + 48, 81, 82, 35, 84, 37, 38, 83, 88, 41, 42, 83, 44, 85, 86, 43, + 128, 129, 130, 3, 132, 5, 6, 131, 136, 9, 10, 131, 12, 133, 134, 11, + 144, 17, 18, 131, 20, 133, 134, 19, 24, 137, 138, 19, 140, 21, 22, 139, + 160, 33, 34, 131, 36, 133, 134, 35, 40, 137, 138, 35, 140, 37, 38, 139, + 48, 145, 146, 35, 148, 37, 38, 147, 152, 41, 42, 147, 44, 149, 150, 43, + 192, 65, 66, 131, 68, 133, 134, 67, 72, 137, 138, 67, 140, 69, 70, 139, + 80, 145, 146, 67, 148, 69, 70, 147, 152, 73, 74, 147, 76, 149, 150, 75, + 96, 161, 162, 67, 164, 69, 70, 163, 168, 73, 74, 163, 76, 165, 166, 75, + 176, 81, 82, 163, 84, 165, 166, 83, 88, 169, 170, 83, 172, 85, 86, 43, + }, + { + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 8, 8, 12, + 0, 0, 0, 16, 0, 16, 16, 20, 0, 16, 16, 24, 16, 24, 24, 12, + 0, 0, 0, 32, 0, 32, 32, 36, 0, 32, 32, 40, 32, 40, 40, 12, + 0, 32, 32, 48, 32, 48, 48, 20, 32, 48, 48, 24, 48, 24, 24, 44, + 0, 0, 0, 64, 0, 64, 64, 68, 0, 64, 64, 72, 64, 72, 72, 12, + 0, 64, 64, 80, 64, 80, 80, 20, 64, 80, 80, 24, 80, 24, 24, 76, + 0, 64, 64, 96, 64, 96, 96, 36, 64, 96, 96, 40, 96, 40, 40, 76, + 64, 96, 96, 48, 96, 48, 48, 84, 96, 48, 48, 88, 48, 88, 88, 44, + 0, 0, 0, 128, 0, 128, 128, 132, 0, 128, 128, 136, 128, 136, 136, 12, + 0, 128, 128, 144, 128, 144, 144, 20, 128, 144, 144, 24, 144, 24, 24, 140, + 0, 128, 128, 160, 128, 160, 160, 36, 128, 160, 160, 40, 160, 40, 40, 140, + 128, 160, 160, 48, 160, 48, 48, 148, 160, 48, 48, 152, 48, 152, 152, 44, + 0, 128, 128, 192, 128, 192, 192, 68, 128, 192, 192, 72, 192, 72, 72, 140, + 128, 192, 192, 80, 192, 80, 80, 148, 192, 80, 80, 152, 80, 152, 152, 76, + 128, 192, 192, 96, 192, 96, 96, 164, 192, 96, 96, 168, 96, 168, 168, 76, + 192, 96, 96, 176, 96, 176, 176, 84, 96, 176, 176, 88, 176, 88, 88, 44, + }, { + 0, 1, 2, 1, 4, 1, 2, 5, 8, 1, 2, 9, 4, 9, 10, 13, + 16, 1, 2, 17, 4, 17, 18, 21, 8, 17, 18, 25, 20, 25, 26, 13, + 32, 1, 2, 33, 4, 33, 34, 37, 8, 33, 34, 41, 36, 41, 42, 13, + 16, 33, 34, 49, 36, 49, 50, 21, 40, 49, 50, 25, 52, 25, 26, 45, + 64, 1, 2, 65, 4, 65, 66, 69, 8, 65, 66, 73, 68, 73, 74, 13, + 16, 65, 66, 81, 68, 81, 82, 21, 72, 81, 82, 25, 84, 25, 26, 77, + 32, 65, 66, 97, 68, 97, 98, 37, 72, 97, 98, 41, 100, 41, 42, 77, + 80, 97, 98, 49, 100, 49, 50, 85, 104, 49, 50, 89, 52, 89, 90, 45, + 128, 1, 2, 129, 4, 129, 130, 133, 8, 129, 130, 137, 132, 137, 138, 13, + 16, 129, 130, 145, 132, 145, 146, 21, 136, 145, 146, 25, 148, 25, 26, 141, + 32, 129, 130, 161, 132, 161, 162, 37, 136, 161, 162, 41, 164, 41, 42, 141, + 144, 161, 162, 49, 164, 49, 50, 149, 168, 49, 50, 153, 52, 153, 154, 45, + 64, 129, 130, 193, 132, 193, 194, 69, 136, 193, 194, 73, 196, 73, 74, 141, + 144, 193, 194, 81, 196, 81, 82, 149, 200, 81, 82, 153, 84, 153, 154, 77, + 160, 193, 194, 97, 196, 97, 98, 165, 200, 97, 98, 169, 100, 169, 170, 77, + 208, 97, 98, 177, 100, 177, 178, 85, 104, 177, 178, 89, 180, 89, 90, 45, + }, { + 0, 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10, 8, 12, 12, 14, + 0, 16, 16, 18, 16, 20, 20, 22, 16, 24, 24, 26, 24, 28, 28, 14, + 0, 32, 32, 34, 32, 36, 36, 38, 32, 40, 40, 42, 40, 44, 44, 14, + 32, 48, 48, 50, 48, 52, 52, 22, 48, 56, 56, 26, 56, 28, 28, 46, + 0, 64, 64, 66, 64, 68, 68, 70, 64, 72, 72, 74, 72, 76, 76, 14, + 64, 80, 80, 82, 80, 84, 84, 22, 80, 88, 88, 26, 88, 28, 28, 78, + 64, 96, 96, 98, 96, 100, 100, 38, 96, 104, 104, 42, 104, 44, 44, 78, + 96, 112, 112, 50, 112, 52, 52, 86, 112, 56, 56, 90, 56, 92, 92, 46, + 0, 128, 128, 130, 128, 132, 132, 134, 128, 136, 136, 138, 136, 140, 140, 14, + 128, 144, 144, 146, 144, 148, 148, 22, 144, 152, 152, 26, 152, 28, 28, 142, + 128, 160, 160, 162, 160, 164, 164, 38, 160, 168, 168, 42, 168, 44, 44, 142, + 160, 176, 176, 50, 176, 52, 52, 150, 176, 56, 56, 154, 56, 156, 156, 46, + 128, 192, 192, 194, 192, 196, 196, 70, 192, 200, 200, 74, 200, 76, 76, 142, + 192, 208, 208, 82, 208, 84, 84, 150, 208, 88, 88, 154, 88, 156, 156, 78, + 192, 224, 224, 98, 224, 100, 100, 166, 224, 104, 104, 170, 104, 172, 172, 78, + 224, 112, 112, 178, 112, 180, 180, 86, 112, 184, 184, 90, 184, 92, 92, 46, + }, { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 15, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 15, + 48, 49, 50, 51, 52, 53, 54, 23, 56, 57, 58, 27, 60, 29, 30, 47, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 15, + 80, 81, 82, 83, 84, 85, 86, 23, 88, 89, 90, 27, 92, 29, 30, 79, + 96, 97, 98, 99, 100, 101, 102, 39, 104, 105, 106, 43, 108, 45, 46, 79, + 112, 113, 114, 51, 116, 53, 54, 87, 120, 57, 58, 91, 60, 93, 94, 47, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 15, + 144, 145, 146, 147, 148, 149, 150, 23, 152, 153, 154, 27, 156, 29, 30, 143, + 160, 161, 162, 163, 164, 165, 166, 39, 168, 169, 170, 43, 172, 45, 46, 143, + 176, 177, 178, 51, 180, 53, 54, 151, 184, 57, 58, 155, 60, 157, 158, 47, + 192, 193, 194, 195, 196, 197, 198, 71, 200, 201, 202, 75, 204, 77, 78, 143, + 208, 209, 210, 83, 212, 85, 86, 151, 216, 89, 90, 155, 92, 157, 158, 79, + 224, 225, 226, 99, 228, 101, 102, 167, 232, 105, 106, 171, 108, 173, 174, 79, + 240, 113, 114, 179, 116, 181, 182, 87, 120, 185, 186, 91, 188, 93, 94, 47, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, + 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 32, 0, 32, 32, 48, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 80, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 96, + 0, 0, 0, 64, 0, 64, 64, 96, 0, 64, 64, 96, 64, 96, 96, 48, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 144, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 160, + 0, 0, 0, 128, 0, 128, 128, 160, 0, 128, 128, 160, 128, 160, 160, 48, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 192, + 0, 0, 0, 128, 0, 128, 128, 192, 0, 128, 128, 192, 128, 192, 192, 80, + 0, 0, 0, 128, 0, 128, 128, 192, 0, 128, 128, 192, 128, 192, 192, 96, + 0, 128, 128, 192, 128, 192, 192, 96, 128, 192, 192, 96, 192, 96, 96, 48, + }, { + 0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 17, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 33, + 16, 1, 2, 1, 4, 1, 2, 33, 8, 1, 2, 33, 4, 33, 34, 49, + 64, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 65, + 16, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 81, + 32, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 97, + 16, 1, 2, 65, 4, 65, 66, 97, 8, 65, 66, 97, 68, 97, 98, 49, + 128, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 129, + 16, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 145, + 32, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 161, + 16, 1, 2, 129, 4, 129, 130, 161, 8, 129, 130, 161, 132, 161, 162, 49, + 64, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 193, + 16, 1, 2, 129, 4, 129, 130, 193, 8, 129, 130, 193, 132, 193, 194, 81, + 32, 1, 2, 129, 4, 129, 130, 193, 8, 129, 130, 193, 132, 193, 194, 97, + 16, 129, 130, 193, 132, 193, 194, 97, 136, 193, 194, 97, 196, 97, 98, 49, + }, { + 0, 0, 0, 2, 0, 4, 4, 2, 0, 8, 8, 2, 8, 4, 4, 2, + 0, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 18, + 0, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 34, + 32, 16, 16, 2, 16, 4, 4, 34, 16, 8, 8, 34, 8, 36, 36, 50, + 0, 64, 64, 2, 64, 4, 4, 2, 64, 8, 8, 2, 8, 4, 4, 66, + 64, 16, 16, 2, 16, 4, 4, 66, 16, 8, 8, 66, 8, 68, 68, 82, + 64, 32, 32, 2, 32, 4, 4, 66, 32, 8, 8, 66, 8, 68, 68, 98, + 32, 16, 16, 66, 16, 68, 68, 98, 16, 72, 72, 98, 72, 100, 100, 50, + 0, 128, 128, 2, 128, 4, 4, 2, 128, 8, 8, 2, 8, 4, 4, 130, + 128, 16, 16, 2, 16, 4, 4, 130, 16, 8, 8, 130, 8, 132, 132, 146, + 128, 32, 32, 2, 32, 4, 4, 130, 32, 8, 8, 130, 8, 132, 132, 162, + 32, 16, 16, 130, 16, 132, 132, 162, 16, 136, 136, 162, 136, 164, 164, 50, + 128, 64, 64, 2, 64, 4, 4, 130, 64, 8, 8, 130, 8, 132, 132, 194, + 64, 16, 16, 130, 16, 132, 132, 194, 16, 136, 136, 194, 136, 196, 196, 82, + 64, 32, 32, 130, 32, 132, 132, 194, 32, 136, 136, 194, 136, 196, 196, 98, + 32, 144, 144, 194, 144, 196, 196, 98, 144, 200, 200, 98, 200, 100, 100, 50, + }, { + 0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 10, 3, 12, 5, 6, 3, + 16, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 19, + 32, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 35, + 48, 17, 18, 3, 20, 5, 6, 35, 24, 9, 10, 35, 12, 37, 38, 51, + 64, 65, 66, 3, 68, 5, 6, 3, 72, 9, 10, 3, 12, 5, 6, 67, + 80, 17, 18, 3, 20, 5, 6, 67, 24, 9, 10, 67, 12, 69, 70, 83, + 96, 33, 34, 3, 36, 5, 6, 67, 40, 9, 10, 67, 12, 69, 70, 99, + 48, 17, 18, 67, 20, 69, 70, 99, 24, 73, 74, 99, 76, 101, 102, 51, + 128, 129, 130, 3, 132, 5, 6, 3, 136, 9, 10, 3, 12, 5, 6, 131, + 144, 17, 18, 3, 20, 5, 6, 131, 24, 9, 10, 131, 12, 133, 134, 147, + 160, 33, 34, 3, 36, 5, 6, 131, 40, 9, 10, 131, 12, 133, 134, 163, + 48, 17, 18, 131, 20, 133, 134, 163, 24, 137, 138, 163, 140, 165, 166, 51, + 192, 65, 66, 3, 68, 5, 6, 131, 72, 9, 10, 131, 12, 133, 134, 195, + 80, 17, 18, 131, 20, 133, 134, 195, 24, 137, 138, 195, 140, 197, 198, 83, + 96, 33, 34, 131, 36, 133, 134, 195, 40, 137, 138, 195, 140, 197, 198, 99, + 48, 145, 146, 195, 148, 197, 198, 99, 152, 201, 202, 99, 204, 101, 102, 51, + }, + { + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 8, 8, 4, + 0, 0, 0, 16, 0, 16, 16, 4, 0, 16, 16, 8, 16, 8, 8, 20, + 0, 0, 0, 32, 0, 32, 32, 4, 0, 32, 32, 8, 32, 8, 8, 36, + 0, 32, 32, 16, 32, 16, 16, 36, 32, 16, 16, 40, 16, 40, 40, 52, + 0, 0, 0, 64, 0, 64, 64, 4, 0, 64, 64, 8, 64, 8, 8, 68, + 0, 64, 64, 16, 64, 16, 16, 68, 64, 16, 16, 72, 16, 72, 72, 84, + 0, 64, 64, 32, 64, 32, 32, 68, 64, 32, 32, 72, 32, 72, 72, 100, + 64, 32, 32, 80, 32, 80, 80, 100, 32, 80, 80, 104, 80, 104, 104, 52, + 0, 0, 0, 128, 0, 128, 128, 4, 0, 128, 128, 8, 128, 8, 8, 132, + 0, 128, 128, 16, 128, 16, 16, 132, 128, 16, 16, 136, 16, 136, 136, 148, + 0, 128, 128, 32, 128, 32, 32, 132, 128, 32, 32, 136, 32, 136, 136, 164, + 128, 32, 32, 144, 32, 144, 144, 164, 32, 144, 144, 168, 144, 168, 168, 52, + 0, 128, 128, 64, 128, 64, 64, 132, 128, 64, 64, 136, 64, 136, 136, 196, + 128, 64, 64, 144, 64, 144, 144, 196, 64, 144, 144, 200, 144, 200, 200, 84, + 128, 64, 64, 160, 64, 160, 160, 196, 64, 160, 160, 200, 160, 200, 200, 100, + 64, 160, 160, 208, 160, 208, 208, 100, 160, 208, 208, 104, 208, 104, 104, 52, + }, { + 0, 1, 2, 1, 4, 1, 2, 5, 8, 1, 2, 9, 4, 9, 10, 5, + 16, 1, 2, 17, 4, 17, 18, 5, 8, 17, 18, 9, 20, 9, 10, 21, + 32, 1, 2, 33, 4, 33, 34, 5, 8, 33, 34, 9, 36, 9, 10, 37, + 16, 33, 34, 17, 36, 17, 18, 37, 40, 17, 18, 41, 20, 41, 42, 53, + 64, 1, 2, 65, 4, 65, 66, 5, 8, 65, 66, 9, 68, 9, 10, 69, + 16, 65, 66, 17, 68, 17, 18, 69, 72, 17, 18, 73, 20, 73, 74, 85, + 32, 65, 66, 33, 68, 33, 34, 69, 72, 33, 34, 73, 36, 73, 74, 101, + 80, 33, 34, 81, 36, 81, 82, 101, 40, 81, 82, 105, 84, 105, 106, 53, + 128, 1, 2, 129, 4, 129, 130, 5, 8, 129, 130, 9, 132, 9, 10, 133, + 16, 129, 130, 17, 132, 17, 18, 133, 136, 17, 18, 137, 20, 137, 138, 149, + 32, 129, 130, 33, 132, 33, 34, 133, 136, 33, 34, 137, 36, 137, 138, 165, + 144, 33, 34, 145, 36, 145, 146, 165, 40, 145, 146, 169, 148, 169, 170, 53, + 64, 129, 130, 65, 132, 65, 66, 133, 136, 65, 66, 137, 68, 137, 138, 197, + 144, 65, 66, 145, 68, 145, 146, 197, 72, 145, 146, 201, 148, 201, 202, 85, + 160, 65, 66, 161, 68, 161, 162, 197, 72, 161, 162, 201, 164, 201, 202, 101, + 80, 161, 162, 209, 164, 209, 210, 101, 168, 209, 210, 105, 212, 105, 106, 53, + }, { + 0, 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10, 8, 12, 12, 6, + 0, 16, 16, 18, 16, 20, 20, 6, 16, 24, 24, 10, 24, 12, 12, 22, + 0, 32, 32, 34, 32, 36, 36, 6, 32, 40, 40, 10, 40, 12, 12, 38, + 32, 48, 48, 18, 48, 20, 20, 38, 48, 24, 24, 42, 24, 44, 44, 54, + 0, 64, 64, 66, 64, 68, 68, 6, 64, 72, 72, 10, 72, 12, 12, 70, + 64, 80, 80, 18, 80, 20, 20, 70, 80, 24, 24, 74, 24, 76, 76, 86, + 64, 96, 96, 34, 96, 36, 36, 70, 96, 40, 40, 74, 40, 76, 76, 102, + 96, 48, 48, 82, 48, 84, 84, 102, 48, 88, 88, 106, 88, 108, 108, 54, + 0, 128, 128, 130, 128, 132, 132, 6, 128, 136, 136, 10, 136, 12, 12, 134, + 128, 144, 144, 18, 144, 20, 20, 134, 144, 24, 24, 138, 24, 140, 140, 150, + 128, 160, 160, 34, 160, 36, 36, 134, 160, 40, 40, 138, 40, 140, 140, 166, + 160, 48, 48, 146, 48, 148, 148, 166, 48, 152, 152, 170, 152, 172, 172, 54, + 128, 192, 192, 66, 192, 68, 68, 134, 192, 72, 72, 138, 72, 140, 140, 198, + 192, 80, 80, 146, 80, 148, 148, 198, 80, 152, 152, 202, 152, 204, 204, 86, + 192, 96, 96, 162, 96, 164, 164, 198, 96, 168, 168, 202, 168, 204, 204, 102, + 96, 176, 176, 210, 176, 212, 212, 102, 176, 216, 216, 106, 216, 108, 108, 54, + }, { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 7, + 16, 17, 18, 19, 20, 21, 22, 7, 24, 25, 26, 11, 28, 13, 14, 23, + 32, 33, 34, 35, 36, 37, 38, 7, 40, 41, 42, 11, 44, 13, 14, 39, + 48, 49, 50, 19, 52, 21, 22, 39, 56, 25, 26, 43, 28, 45, 46, 55, + 64, 65, 66, 67, 68, 69, 70, 7, 72, 73, 74, 11, 76, 13, 14, 71, + 80, 81, 82, 19, 84, 21, 22, 71, 88, 25, 26, 75, 28, 77, 78, 87, + 96, 97, 98, 35, 100, 37, 38, 71, 104, 41, 42, 75, 44, 77, 78, 103, + 112, 49, 50, 83, 52, 85, 86, 103, 56, 89, 90, 107, 92, 109, 110, 55, + 128, 129, 130, 131, 132, 133, 134, 7, 136, 137, 138, 11, 140, 13, 14, 135, + 144, 145, 146, 19, 148, 21, 22, 135, 152, 25, 26, 139, 28, 141, 142, 151, + 160, 161, 162, 35, 164, 37, 38, 135, 168, 41, 42, 139, 44, 141, 142, 167, + 176, 49, 50, 147, 52, 149, 150, 167, 56, 153, 154, 171, 156, 173, 174, 55, + 192, 193, 194, 67, 196, 69, 70, 135, 200, 73, 74, 139, 76, 141, 142, 199, + 208, 81, 82, 147, 84, 149, 150, 199, 88, 153, 154, 203, 156, 205, 206, 87, + 224, 97, 98, 163, 100, 165, 166, 199, 104, 169, 170, 203, 172, 205, 206, 103, + 112, 177, 178, 211, 180, 213, 214, 103, 184, 217, 218, 107, 220, 109, 110, 55, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, + 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 16, 0, 16, 16, 24, + 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 32, 0, 32, 32, 40, + 0, 0, 0, 32, 0, 32, 32, 48, 0, 32, 32, 48, 32, 48, 48, 56, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 72, + 0, 0, 0, 64, 0, 64, 64, 80, 0, 64, 64, 80, 64, 80, 80, 88, + 0, 0, 0, 64, 0, 64, 64, 96, 0, 64, 64, 96, 64, 96, 96, 104, + 0, 64, 64, 96, 64, 96, 96, 112, 64, 96, 96, 112, 96, 112, 112, 56, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 136, + 0, 0, 0, 128, 0, 128, 128, 144, 0, 128, 128, 144, 128, 144, 144, 152, + 0, 0, 0, 128, 0, 128, 128, 160, 0, 128, 128, 160, 128, 160, 160, 168, + 0, 128, 128, 160, 128, 160, 160, 176, 128, 160, 160, 176, 160, 176, 176, 56, + 0, 0, 0, 128, 0, 128, 128, 192, 0, 128, 128, 192, 128, 192, 192, 200, + 0, 128, 128, 192, 128, 192, 192, 208, 128, 192, 192, 208, 192, 208, 208, 88, + 0, 128, 128, 192, 128, 192, 192, 224, 128, 192, 192, 224, 192, 224, 224, 104, + 128, 192, 192, 224, 192, 224, 224, 112, 192, 224, 224, 112, 224, 112, 112, 56, + }, { + 0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 9, + 16, 1, 2, 1, 4, 1, 2, 17, 8, 1, 2, 17, 4, 17, 18, 25, + 32, 1, 2, 1, 4, 1, 2, 33, 8, 1, 2, 33, 4, 33, 34, 41, + 16, 1, 2, 33, 4, 33, 34, 49, 8, 33, 34, 49, 36, 49, 50, 57, + 64, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 73, + 16, 1, 2, 65, 4, 65, 66, 81, 8, 65, 66, 81, 68, 81, 82, 89, + 32, 1, 2, 65, 4, 65, 66, 97, 8, 65, 66, 97, 68, 97, 98, 105, + 16, 65, 66, 97, 68, 97, 98, 113, 72, 97, 98, 113, 100, 113, 114, 57, + 128, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 137, + 16, 1, 2, 129, 4, 129, 130, 145, 8, 129, 130, 145, 132, 145, 146, 153, + 32, 1, 2, 129, 4, 129, 130, 161, 8, 129, 130, 161, 132, 161, 162, 169, + 16, 129, 130, 161, 132, 161, 162, 177, 136, 161, 162, 177, 164, 177, 178, 57, + 64, 1, 2, 129, 4, 129, 130, 193, 8, 129, 130, 193, 132, 193, 194, 201, + 16, 129, 130, 193, 132, 193, 194, 209, 136, 193, 194, 209, 196, 209, 210, 89, + 32, 129, 130, 193, 132, 193, 194, 225, 136, 193, 194, 225, 196, 225, 226, 105, + 144, 193, 194, 225, 196, 225, 226, 113, 200, 225, 226, 113, 228, 113, 114, 57, + }, { + 0, 0, 0, 2, 0, 4, 4, 2, 0, 8, 8, 2, 8, 4, 4, 10, + 0, 16, 16, 2, 16, 4, 4, 18, 16, 8, 8, 18, 8, 20, 20, 26, + 0, 32, 32, 2, 32, 4, 4, 34, 32, 8, 8, 34, 8, 36, 36, 42, + 32, 16, 16, 34, 16, 36, 36, 50, 16, 40, 40, 50, 40, 52, 52, 58, + 0, 64, 64, 2, 64, 4, 4, 66, 64, 8, 8, 66, 8, 68, 68, 74, + 64, 16, 16, 66, 16, 68, 68, 82, 16, 72, 72, 82, 72, 84, 84, 90, + 64, 32, 32, 66, 32, 68, 68, 98, 32, 72, 72, 98, 72, 100, 100, 106, + 32, 80, 80, 98, 80, 100, 100, 114, 80, 104, 104, 114, 104, 116, 116, 58, + 0, 128, 128, 2, 128, 4, 4, 130, 128, 8, 8, 130, 8, 132, 132, 138, + 128, 16, 16, 130, 16, 132, 132, 146, 16, 136, 136, 146, 136, 148, 148, 154, + 128, 32, 32, 130, 32, 132, 132, 162, 32, 136, 136, 162, 136, 164, 164, 170, + 32, 144, 144, 162, 144, 164, 164, 178, 144, 168, 168, 178, 168, 180, 180, 58, + 128, 64, 64, 130, 64, 132, 132, 194, 64, 136, 136, 194, 136, 196, 196, 202, + 64, 144, 144, 194, 144, 196, 196, 210, 144, 200, 200, 210, 200, 212, 212, 90, + 64, 160, 160, 194, 160, 196, 196, 226, 160, 200, 200, 226, 200, 228, 228, 106, + 160, 208, 208, 226, 208, 228, 228, 114, 208, 232, 232, 114, 232, 116, 116, 58, + }, { + 0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 10, 3, 12, 5, 6, 11, + 16, 17, 18, 3, 20, 5, 6, 19, 24, 9, 10, 19, 12, 21, 22, 27, + 32, 33, 34, 3, 36, 5, 6, 35, 40, 9, 10, 35, 12, 37, 38, 43, + 48, 17, 18, 35, 20, 37, 38, 51, 24, 41, 42, 51, 44, 53, 54, 59, + 64, 65, 66, 3, 68, 5, 6, 67, 72, 9, 10, 67, 12, 69, 70, 75, + 80, 17, 18, 67, 20, 69, 70, 83, 24, 73, 74, 83, 76, 85, 86, 91, + 96, 33, 34, 67, 36, 69, 70, 99, 40, 73, 74, 99, 76, 101, 102, 107, + 48, 81, 82, 99, 84, 101, 102, 115, 88, 105, 106, 115, 108, 117, 118, 59, + 128, 129, 130, 3, 132, 5, 6, 131, 136, 9, 10, 131, 12, 133, 134, 139, + 144, 17, 18, 131, 20, 133, 134, 147, 24, 137, 138, 147, 140, 149, 150, 155, + 160, 33, 34, 131, 36, 133, 134, 163, 40, 137, 138, 163, 140, 165, 166, 171, + 48, 145, 146, 163, 148, 165, 166, 179, 152, 169, 170, 179, 172, 181, 182, 59, + 192, 65, 66, 131, 68, 133, 134, 195, 72, 137, 138, 195, 140, 197, 198, 203, + 80, 145, 146, 195, 148, 197, 198, 211, 152, 201, 202, 211, 204, 213, 214, 91, + 96, 161, 162, 195, 164, 197, 198, 227, 168, 201, 202, 227, 204, 229, 230, 107, + 176, 209, 210, 227, 212, 229, 230, 115, 216, 233, 234, 115, 236, 117, 118, 59, + }, + { + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 8, 8, 12, + 0, 0, 0, 16, 0, 16, 16, 20, 0, 16, 16, 24, 16, 24, 24, 28, + 0, 0, 0, 32, 0, 32, 32, 36, 0, 32, 32, 40, 32, 40, 40, 44, + 0, 32, 32, 48, 32, 48, 48, 52, 32, 48, 48, 56, 48, 56, 56, 60, + 0, 0, 0, 64, 0, 64, 64, 68, 0, 64, 64, 72, 64, 72, 72, 76, + 0, 64, 64, 80, 64, 80, 80, 84, 64, 80, 80, 88, 80, 88, 88, 92, + 0, 64, 64, 96, 64, 96, 96, 100, 64, 96, 96, 104, 96, 104, 104, 108, + 64, 96, 96, 112, 96, 112, 112, 116, 96, 112, 112, 120, 112, 120, 120, 60, + 0, 0, 0, 128, 0, 128, 128, 132, 0, 128, 128, 136, 128, 136, 136, 140, + 0, 128, 128, 144, 128, 144, 144, 148, 128, 144, 144, 152, 144, 152, 152, 156, + 0, 128, 128, 160, 128, 160, 160, 164, 128, 160, 160, 168, 160, 168, 168, 172, + 128, 160, 160, 176, 160, 176, 176, 180, 160, 176, 176, 184, 176, 184, 184, 60, + 0, 128, 128, 192, 128, 192, 192, 196, 128, 192, 192, 200, 192, 200, 200, 204, + 128, 192, 192, 208, 192, 208, 208, 212, 192, 208, 208, 216, 208, 216, 216, 92, + 128, 192, 192, 224, 192, 224, 224, 228, 192, 224, 224, 232, 224, 232, 232, 108, + 192, 224, 224, 240, 224, 240, 240, 116, 224, 240, 240, 120, 240, 120, 120, 60, + }, { + 0, 1, 2, 1, 4, 1, 2, 5, 8, 1, 2, 9, 4, 9, 10, 13, + 16, 1, 2, 17, 4, 17, 18, 21, 8, 17, 18, 25, 20, 25, 26, 29, + 32, 1, 2, 33, 4, 33, 34, 37, 8, 33, 34, 41, 36, 41, 42, 45, + 16, 33, 34, 49, 36, 49, 50, 53, 40, 49, 50, 57, 52, 57, 58, 61, + 64, 1, 2, 65, 4, 65, 66, 69, 8, 65, 66, 73, 68, 73, 74, 77, + 16, 65, 66, 81, 68, 81, 82, 85, 72, 81, 82, 89, 84, 89, 90, 93, + 32, 65, 66, 97, 68, 97, 98, 101, 72, 97, 98, 105, 100, 105, 106, 109, + 80, 97, 98, 113, 100, 113, 114, 117, 104, 113, 114, 121, 116, 121, 122, 61, + 128, 1, 2, 129, 4, 129, 130, 133, 8, 129, 130, 137, 132, 137, 138, 141, + 16, 129, 130, 145, 132, 145, 146, 149, 136, 145, 146, 153, 148, 153, 154, 157, + 32, 129, 130, 161, 132, 161, 162, 165, 136, 161, 162, 169, 164, 169, 170, 173, + 144, 161, 162, 177, 164, 177, 178, 181, 168, 177, 178, 185, 180, 185, 186, 61, + 64, 129, 130, 193, 132, 193, 194, 197, 136, 193, 194, 201, 196, 201, 202, 205, + 144, 193, 194, 209, 196, 209, 210, 213, 200, 209, 210, 217, 212, 217, 218, 93, + 160, 193, 194, 225, 196, 225, 226, 229, 200, 225, 226, 233, 228, 233, 234, 109, + 208, 225, 226, 241, 228, 241, 242, 117, 232, 241, 242, 121, 244, 121, 122, 61, + }, { + 0, 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10, 8, 12, 12, 14, + 0, 16, 16, 18, 16, 20, 20, 22, 16, 24, 24, 26, 24, 28, 28, 30, + 0, 32, 32, 34, 32, 36, 36, 38, 32, 40, 40, 42, 40, 44, 44, 46, + 32, 48, 48, 50, 48, 52, 52, 54, 48, 56, 56, 58, 56, 60, 60, 62, + 0, 64, 64, 66, 64, 68, 68, 70, 64, 72, 72, 74, 72, 76, 76, 78, + 64, 80, 80, 82, 80, 84, 84, 86, 80, 88, 88, 90, 88, 92, 92, 94, + 64, 96, 96, 98, 96, 100, 100, 102, 96, 104, 104, 106, 104, 108, 108, 110, + 96, 112, 112, 114, 112, 116, 116, 118, 112, 120, 120, 122, 120, 124, 124, 62, + 0, 128, 128, 130, 128, 132, 132, 134, 128, 136, 136, 138, 136, 140, 140, 142, + 128, 144, 144, 146, 144, 148, 148, 150, 144, 152, 152, 154, 152, 156, 156, 158, + 128, 160, 160, 162, 160, 164, 164, 166, 160, 168, 168, 170, 168, 172, 172, 174, + 160, 176, 176, 178, 176, 180, 180, 182, 176, 184, 184, 186, 184, 188, 188, 62, + 128, 192, 192, 194, 192, 196, 196, 198, 192, 200, 200, 202, 200, 204, 204, 206, + 192, 208, 208, 210, 208, 212, 212, 214, 208, 216, 216, 218, 216, 220, 220, 94, + 192, 224, 224, 226, 224, 228, 228, 230, 224, 232, 232, 234, 232, 236, 236, 110, + 224, 240, 240, 242, 240, 244, 244, 118, 240, 248, 248, 122, 248, 124, 124, 62, + }, { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 63, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, + 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, + 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 63, + 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, + 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 95, + 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 111, + 240, 241, 242, 243, 244, 245, 246, 119, 248, 249, 250, 123, 252, 125, 126, 63, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 64, + }, { + 0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 64, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 65, + 128, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 129, + 64, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 129, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 129, + 16, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 65, + }, { + 0, 0, 0, 2, 0, 4, 4, 2, 0, 8, 8, 2, 8, 4, 4, 2, + 0, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 2, + 0, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 2, + 32, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 2, + 0, 64, 64, 2, 64, 4, 4, 2, 64, 8, 8, 2, 8, 4, 4, 2, + 64, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 2, + 64, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 2, + 32, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 66, + 0, 128, 128, 2, 128, 4, 4, 2, 128, 8, 8, 2, 8, 4, 4, 2, + 128, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 2, + 128, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 2, + 32, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 130, + 128, 64, 64, 2, 64, 4, 4, 2, 64, 8, 8, 2, 8, 4, 4, 2, + 64, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 130, + 64, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 130, + 32, 16, 16, 2, 16, 4, 4, 130, 16, 8, 8, 130, 8, 132, 132, 66, + }, { + 0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 10, 3, 12, 5, 6, 3, + 16, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 3, + 32, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 3, + 48, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 3, + 64, 65, 66, 3, 68, 5, 6, 3, 72, 9, 10, 3, 12, 5, 6, 3, + 80, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 3, + 96, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 3, + 48, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 67, + 128, 129, 130, 3, 132, 5, 6, 3, 136, 9, 10, 3, 12, 5, 6, 3, + 144, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 3, + 160, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 3, + 48, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 131, + 192, 65, 66, 3, 68, 5, 6, 3, 72, 9, 10, 3, 12, 5, 6, 3, + 80, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 131, + 96, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 131, + 48, 17, 18, 3, 20, 5, 6, 131, 24, 9, 10, 131, 12, 133, 134, 67, + }, + { + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 8, 8, 4, + 0, 0, 0, 16, 0, 16, 16, 4, 0, 16, 16, 8, 16, 8, 8, 4, + 0, 0, 0, 32, 0, 32, 32, 4, 0, 32, 32, 8, 32, 8, 8, 4, + 0, 32, 32, 16, 32, 16, 16, 4, 32, 16, 16, 8, 16, 8, 8, 4, + 0, 0, 0, 64, 0, 64, 64, 4, 0, 64, 64, 8, 64, 8, 8, 4, + 0, 64, 64, 16, 64, 16, 16, 4, 64, 16, 16, 8, 16, 8, 8, 4, + 0, 64, 64, 32, 64, 32, 32, 4, 64, 32, 32, 8, 32, 8, 8, 4, + 64, 32, 32, 16, 32, 16, 16, 4, 32, 16, 16, 8, 16, 8, 8, 68, + 0, 0, 0, 128, 0, 128, 128, 4, 0, 128, 128, 8, 128, 8, 8, 4, + 0, 128, 128, 16, 128, 16, 16, 4, 128, 16, 16, 8, 16, 8, 8, 4, + 0, 128, 128, 32, 128, 32, 32, 4, 128, 32, 32, 8, 32, 8, 8, 4, + 128, 32, 32, 16, 32, 16, 16, 4, 32, 16, 16, 8, 16, 8, 8, 132, + 0, 128, 128, 64, 128, 64, 64, 4, 128, 64, 64, 8, 64, 8, 8, 4, + 128, 64, 64, 16, 64, 16, 16, 4, 64, 16, 16, 8, 16, 8, 8, 132, + 128, 64, 64, 32, 64, 32, 32, 4, 64, 32, 32, 8, 32, 8, 8, 132, + 64, 32, 32, 16, 32, 16, 16, 132, 32, 16, 16, 136, 16, 136, 136, 68, + }, { + 0, 1, 2, 1, 4, 1, 2, 5, 8, 1, 2, 9, 4, 9, 10, 5, + 16, 1, 2, 17, 4, 17, 18, 5, 8, 17, 18, 9, 20, 9, 10, 5, + 32, 1, 2, 33, 4, 33, 34, 5, 8, 33, 34, 9, 36, 9, 10, 5, + 16, 33, 34, 17, 36, 17, 18, 5, 40, 17, 18, 9, 20, 9, 10, 5, + 64, 1, 2, 65, 4, 65, 66, 5, 8, 65, 66, 9, 68, 9, 10, 5, + 16, 65, 66, 17, 68, 17, 18, 5, 72, 17, 18, 9, 20, 9, 10, 5, + 32, 65, 66, 33, 68, 33, 34, 5, 72, 33, 34, 9, 36, 9, 10, 5, + 80, 33, 34, 17, 36, 17, 18, 5, 40, 17, 18, 9, 20, 9, 10, 69, + 128, 1, 2, 129, 4, 129, 130, 5, 8, 129, 130, 9, 132, 9, 10, 5, + 16, 129, 130, 17, 132, 17, 18, 5, 136, 17, 18, 9, 20, 9, 10, 5, + 32, 129, 130, 33, 132, 33, 34, 5, 136, 33, 34, 9, 36, 9, 10, 5, + 144, 33, 34, 17, 36, 17, 18, 5, 40, 17, 18, 9, 20, 9, 10, 133, + 64, 129, 130, 65, 132, 65, 66, 5, 136, 65, 66, 9, 68, 9, 10, 5, + 144, 65, 66, 17, 68, 17, 18, 5, 72, 17, 18, 9, 20, 9, 10, 133, + 160, 65, 66, 33, 68, 33, 34, 5, 72, 33, 34, 9, 36, 9, 10, 133, + 80, 33, 34, 17, 36, 17, 18, 133, 40, 17, 18, 137, 20, 137, 138, 69, + }, { + 0, 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10, 8, 12, 12, 6, + 0, 16, 16, 18, 16, 20, 20, 6, 16, 24, 24, 10, 24, 12, 12, 6, + 0, 32, 32, 34, 32, 36, 36, 6, 32, 40, 40, 10, 40, 12, 12, 6, + 32, 48, 48, 18, 48, 20, 20, 6, 48, 24, 24, 10, 24, 12, 12, 6, + 0, 64, 64, 66, 64, 68, 68, 6, 64, 72, 72, 10, 72, 12, 12, 6, + 64, 80, 80, 18, 80, 20, 20, 6, 80, 24, 24, 10, 24, 12, 12, 6, + 64, 96, 96, 34, 96, 36, 36, 6, 96, 40, 40, 10, 40, 12, 12, 6, + 96, 48, 48, 18, 48, 20, 20, 6, 48, 24, 24, 10, 24, 12, 12, 70, + 0, 128, 128, 130, 128, 132, 132, 6, 128, 136, 136, 10, 136, 12, 12, 6, + 128, 144, 144, 18, 144, 20, 20, 6, 144, 24, 24, 10, 24, 12, 12, 6, + 128, 160, 160, 34, 160, 36, 36, 6, 160, 40, 40, 10, 40, 12, 12, 6, + 160, 48, 48, 18, 48, 20, 20, 6, 48, 24, 24, 10, 24, 12, 12, 134, + 128, 192, 192, 66, 192, 68, 68, 6, 192, 72, 72, 10, 72, 12, 12, 6, + 192, 80, 80, 18, 80, 20, 20, 6, 80, 24, 24, 10, 24, 12, 12, 134, + 192, 96, 96, 34, 96, 36, 36, 6, 96, 40, 40, 10, 40, 12, 12, 134, + 96, 48, 48, 18, 48, 20, 20, 134, 48, 24, 24, 138, 24, 140, 140, 70, + }, { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 7, + 16, 17, 18, 19, 20, 21, 22, 7, 24, 25, 26, 11, 28, 13, 14, 7, + 32, 33, 34, 35, 36, 37, 38, 7, 40, 41, 42, 11, 44, 13, 14, 7, + 48, 49, 50, 19, 52, 21, 22, 7, 56, 25, 26, 11, 28, 13, 14, 7, + 64, 65, 66, 67, 68, 69, 70, 7, 72, 73, 74, 11, 76, 13, 14, 7, + 80, 81, 82, 19, 84, 21, 22, 7, 88, 25, 26, 11, 28, 13, 14, 7, + 96, 97, 98, 35, 100, 37, 38, 7, 104, 41, 42, 11, 44, 13, 14, 7, + 112, 49, 50, 19, 52, 21, 22, 7, 56, 25, 26, 11, 28, 13, 14, 71, + 128, 129, 130, 131, 132, 133, 134, 7, 136, 137, 138, 11, 140, 13, 14, 7, + 144, 145, 146, 19, 148, 21, 22, 7, 152, 25, 26, 11, 28, 13, 14, 7, + 160, 161, 162, 35, 164, 37, 38, 7, 168, 41, 42, 11, 44, 13, 14, 7, + 176, 49, 50, 19, 52, 21, 22, 7, 56, 25, 26, 11, 28, 13, 14, 135, + 192, 193, 194, 67, 196, 69, 70, 7, 200, 73, 74, 11, 76, 13, 14, 7, + 208, 81, 82, 19, 84, 21, 22, 7, 88, 25, 26, 11, 28, 13, 14, 135, + 224, 97, 98, 35, 100, 37, 38, 7, 104, 41, 42, 11, 44, 13, 14, 135, + 112, 49, 50, 19, 52, 21, 22, 135, 56, 25, 26, 139, 28, 141, 142, 71, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, + 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 16, 0, 16, 16, 8, + 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 32, 0, 32, 32, 8, + 0, 0, 0, 32, 0, 32, 32, 16, 0, 32, 32, 16, 32, 16, 16, 8, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 8, + 0, 0, 0, 64, 0, 64, 64, 16, 0, 64, 64, 16, 64, 16, 16, 8, + 0, 0, 0, 64, 0, 64, 64, 32, 0, 64, 64, 32, 64, 32, 32, 8, + 0, 64, 64, 32, 64, 32, 32, 16, 64, 32, 32, 16, 32, 16, 16, 72, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 8, + 0, 0, 0, 128, 0, 128, 128, 16, 0, 128, 128, 16, 128, 16, 16, 8, + 0, 0, 0, 128, 0, 128, 128, 32, 0, 128, 128, 32, 128, 32, 32, 8, + 0, 128, 128, 32, 128, 32, 32, 16, 128, 32, 32, 16, 32, 16, 16, 136, + 0, 0, 0, 128, 0, 128, 128, 64, 0, 128, 128, 64, 128, 64, 64, 8, + 0, 128, 128, 64, 128, 64, 64, 16, 128, 64, 64, 16, 64, 16, 16, 136, + 0, 128, 128, 64, 128, 64, 64, 32, 128, 64, 64, 32, 64, 32, 32, 136, + 128, 64, 64, 32, 64, 32, 32, 144, 64, 32, 32, 144, 32, 144, 144, 72, + }, { + 0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 9, + 16, 1, 2, 1, 4, 1, 2, 17, 8, 1, 2, 17, 4, 17, 18, 9, + 32, 1, 2, 1, 4, 1, 2, 33, 8, 1, 2, 33, 4, 33, 34, 9, + 16, 1, 2, 33, 4, 33, 34, 17, 8, 33, 34, 17, 36, 17, 18, 9, + 64, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 9, + 16, 1, 2, 65, 4, 65, 66, 17, 8, 65, 66, 17, 68, 17, 18, 9, + 32, 1, 2, 65, 4, 65, 66, 33, 8, 65, 66, 33, 68, 33, 34, 9, + 16, 65, 66, 33, 68, 33, 34, 17, 72, 33, 34, 17, 36, 17, 18, 73, + 128, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 9, + 16, 1, 2, 129, 4, 129, 130, 17, 8, 129, 130, 17, 132, 17, 18, 9, + 32, 1, 2, 129, 4, 129, 130, 33, 8, 129, 130, 33, 132, 33, 34, 9, + 16, 129, 130, 33, 132, 33, 34, 17, 136, 33, 34, 17, 36, 17, 18, 137, + 64, 1, 2, 129, 4, 129, 130, 65, 8, 129, 130, 65, 132, 65, 66, 9, + 16, 129, 130, 65, 132, 65, 66, 17, 136, 65, 66, 17, 68, 17, 18, 137, + 32, 129, 130, 65, 132, 65, 66, 33, 136, 65, 66, 33, 68, 33, 34, 137, + 144, 65, 66, 33, 68, 33, 34, 145, 72, 33, 34, 145, 36, 145, 146, 73, + }, { + 0, 0, 0, 2, 0, 4, 4, 2, 0, 8, 8, 2, 8, 4, 4, 10, + 0, 16, 16, 2, 16, 4, 4, 18, 16, 8, 8, 18, 8, 20, 20, 10, + 0, 32, 32, 2, 32, 4, 4, 34, 32, 8, 8, 34, 8, 36, 36, 10, + 32, 16, 16, 34, 16, 36, 36, 18, 16, 40, 40, 18, 40, 20, 20, 10, + 0, 64, 64, 2, 64, 4, 4, 66, 64, 8, 8, 66, 8, 68, 68, 10, + 64, 16, 16, 66, 16, 68, 68, 18, 16, 72, 72, 18, 72, 20, 20, 10, + 64, 32, 32, 66, 32, 68, 68, 34, 32, 72, 72, 34, 72, 36, 36, 10, + 32, 80, 80, 34, 80, 36, 36, 18, 80, 40, 40, 18, 40, 20, 20, 74, + 0, 128, 128, 2, 128, 4, 4, 130, 128, 8, 8, 130, 8, 132, 132, 10, + 128, 16, 16, 130, 16, 132, 132, 18, 16, 136, 136, 18, 136, 20, 20, 10, + 128, 32, 32, 130, 32, 132, 132, 34, 32, 136, 136, 34, 136, 36, 36, 10, + 32, 144, 144, 34, 144, 36, 36, 18, 144, 40, 40, 18, 40, 20, 20, 138, + 128, 64, 64, 130, 64, 132, 132, 66, 64, 136, 136, 66, 136, 68, 68, 10, + 64, 144, 144, 66, 144, 68, 68, 18, 144, 72, 72, 18, 72, 20, 20, 138, + 64, 160, 160, 66, 160, 68, 68, 34, 160, 72, 72, 34, 72, 36, 36, 138, + 160, 80, 80, 34, 80, 36, 36, 146, 80, 40, 40, 146, 40, 148, 148, 74, + }, { + 0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 10, 3, 12, 5, 6, 11, + 16, 17, 18, 3, 20, 5, 6, 19, 24, 9, 10, 19, 12, 21, 22, 11, + 32, 33, 34, 3, 36, 5, 6, 35, 40, 9, 10, 35, 12, 37, 38, 11, + 48, 17, 18, 35, 20, 37, 38, 19, 24, 41, 42, 19, 44, 21, 22, 11, + 64, 65, 66, 3, 68, 5, 6, 67, 72, 9, 10, 67, 12, 69, 70, 11, + 80, 17, 18, 67, 20, 69, 70, 19, 24, 73, 74, 19, 76, 21, 22, 11, + 96, 33, 34, 67, 36, 69, 70, 35, 40, 73, 74, 35, 76, 37, 38, 11, + 48, 81, 82, 35, 84, 37, 38, 19, 88, 41, 42, 19, 44, 21, 22, 75, + 128, 129, 130, 3, 132, 5, 6, 131, 136, 9, 10, 131, 12, 133, 134, 11, + 144, 17, 18, 131, 20, 133, 134, 19, 24, 137, 138, 19, 140, 21, 22, 11, + 160, 33, 34, 131, 36, 133, 134, 35, 40, 137, 138, 35, 140, 37, 38, 11, + 48, 145, 146, 35, 148, 37, 38, 19, 152, 41, 42, 19, 44, 21, 22, 139, + 192, 65, 66, 131, 68, 133, 134, 67, 72, 137, 138, 67, 140, 69, 70, 11, + 80, 145, 146, 67, 148, 69, 70, 19, 152, 73, 74, 19, 76, 21, 22, 139, + 96, 161, 162, 67, 164, 69, 70, 35, 168, 73, 74, 35, 76, 37, 38, 139, + 176, 81, 82, 35, 84, 37, 38, 147, 88, 41, 42, 147, 44, 149, 150, 75, + }, + { + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 8, 8, 12, + 0, 0, 0, 16, 0, 16, 16, 20, 0, 16, 16, 24, 16, 24, 24, 12, + 0, 0, 0, 32, 0, 32, 32, 36, 0, 32, 32, 40, 32, 40, 40, 12, + 0, 32, 32, 48, 32, 48, 48, 20, 32, 48, 48, 24, 48, 24, 24, 12, + 0, 0, 0, 64, 0, 64, 64, 68, 0, 64, 64, 72, 64, 72, 72, 12, + 0, 64, 64, 80, 64, 80, 80, 20, 64, 80, 80, 24, 80, 24, 24, 12, + 0, 64, 64, 96, 64, 96, 96, 36, 64, 96, 96, 40, 96, 40, 40, 12, + 64, 96, 96, 48, 96, 48, 48, 20, 96, 48, 48, 24, 48, 24, 24, 76, + 0, 0, 0, 128, 0, 128, 128, 132, 0, 128, 128, 136, 128, 136, 136, 12, + 0, 128, 128, 144, 128, 144, 144, 20, 128, 144, 144, 24, 144, 24, 24, 12, + 0, 128, 128, 160, 128, 160, 160, 36, 128, 160, 160, 40, 160, 40, 40, 12, + 128, 160, 160, 48, 160, 48, 48, 20, 160, 48, 48, 24, 48, 24, 24, 140, + 0, 128, 128, 192, 128, 192, 192, 68, 128, 192, 192, 72, 192, 72, 72, 12, + 128, 192, 192, 80, 192, 80, 80, 20, 192, 80, 80, 24, 80, 24, 24, 140, + 128, 192, 192, 96, 192, 96, 96, 36, 192, 96, 96, 40, 96, 40, 40, 140, + 192, 96, 96, 48, 96, 48, 48, 148, 96, 48, 48, 152, 48, 152, 152, 76, + }, { + 0, 1, 2, 1, 4, 1, 2, 5, 8, 1, 2, 9, 4, 9, 10, 13, + 16, 1, 2, 17, 4, 17, 18, 21, 8, 17, 18, 25, 20, 25, 26, 13, + 32, 1, 2, 33, 4, 33, 34, 37, 8, 33, 34, 41, 36, 41, 42, 13, + 16, 33, 34, 49, 36, 49, 50, 21, 40, 49, 50, 25, 52, 25, 26, 13, + 64, 1, 2, 65, 4, 65, 66, 69, 8, 65, 66, 73, 68, 73, 74, 13, + 16, 65, 66, 81, 68, 81, 82, 21, 72, 81, 82, 25, 84, 25, 26, 13, + 32, 65, 66, 97, 68, 97, 98, 37, 72, 97, 98, 41, 100, 41, 42, 13, + 80, 97, 98, 49, 100, 49, 50, 21, 104, 49, 50, 25, 52, 25, 26, 77, + 128, 1, 2, 129, 4, 129, 130, 133, 8, 129, 130, 137, 132, 137, 138, 13, + 16, 129, 130, 145, 132, 145, 146, 21, 136, 145, 146, 25, 148, 25, 26, 13, + 32, 129, 130, 161, 132, 161, 162, 37, 136, 161, 162, 41, 164, 41, 42, 13, + 144, 161, 162, 49, 164, 49, 50, 21, 168, 49, 50, 25, 52, 25, 26, 141, + 64, 129, 130, 193, 132, 193, 194, 69, 136, 193, 194, 73, 196, 73, 74, 13, + 144, 193, 194, 81, 196, 81, 82, 21, 200, 81, 82, 25, 84, 25, 26, 141, + 160, 193, 194, 97, 196, 97, 98, 37, 200, 97, 98, 41, 100, 41, 42, 141, + 208, 97, 98, 49, 100, 49, 50, 149, 104, 49, 50, 153, 52, 153, 154, 77, + }, { + 0, 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10, 8, 12, 12, 14, + 0, 16, 16, 18, 16, 20, 20, 22, 16, 24, 24, 26, 24, 28, 28, 14, + 0, 32, 32, 34, 32, 36, 36, 38, 32, 40, 40, 42, 40, 44, 44, 14, + 32, 48, 48, 50, 48, 52, 52, 22, 48, 56, 56, 26, 56, 28, 28, 14, + 0, 64, 64, 66, 64, 68, 68, 70, 64, 72, 72, 74, 72, 76, 76, 14, + 64, 80, 80, 82, 80, 84, 84, 22, 80, 88, 88, 26, 88, 28, 28, 14, + 64, 96, 96, 98, 96, 100, 100, 38, 96, 104, 104, 42, 104, 44, 44, 14, + 96, 112, 112, 50, 112, 52, 52, 22, 112, 56, 56, 26, 56, 28, 28, 78, + 0, 128, 128, 130, 128, 132, 132, 134, 128, 136, 136, 138, 136, 140, 140, 14, + 128, 144, 144, 146, 144, 148, 148, 22, 144, 152, 152, 26, 152, 28, 28, 14, + 128, 160, 160, 162, 160, 164, 164, 38, 160, 168, 168, 42, 168, 44, 44, 14, + 160, 176, 176, 50, 176, 52, 52, 22, 176, 56, 56, 26, 56, 28, 28, 142, + 128, 192, 192, 194, 192, 196, 196, 70, 192, 200, 200, 74, 200, 76, 76, 14, + 192, 208, 208, 82, 208, 84, 84, 22, 208, 88, 88, 26, 88, 28, 28, 142, + 192, 224, 224, 98, 224, 100, 100, 38, 224, 104, 104, 42, 104, 44, 44, 142, + 224, 112, 112, 50, 112, 52, 52, 150, 112, 56, 56, 154, 56, 156, 156, 78, + }, { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 15, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 15, + 48, 49, 50, 51, 52, 53, 54, 23, 56, 57, 58, 27, 60, 29, 30, 15, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 15, + 80, 81, 82, 83, 84, 85, 86, 23, 88, 89, 90, 27, 92, 29, 30, 15, + 96, 97, 98, 99, 100, 101, 102, 39, 104, 105, 106, 43, 108, 45, 46, 15, + 112, 113, 114, 51, 116, 53, 54, 23, 120, 57, 58, 27, 60, 29, 30, 79, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 15, + 144, 145, 146, 147, 148, 149, 150, 23, 152, 153, 154, 27, 156, 29, 30, 15, + 160, 161, 162, 163, 164, 165, 166, 39, 168, 169, 170, 43, 172, 45, 46, 15, + 176, 177, 178, 51, 180, 53, 54, 23, 184, 57, 58, 27, 60, 29, 30, 143, + 192, 193, 194, 195, 196, 197, 198, 71, 200, 201, 202, 75, 204, 77, 78, 15, + 208, 209, 210, 83, 212, 85, 86, 23, 216, 89, 90, 27, 92, 29, 30, 143, + 224, 225, 226, 99, 228, 101, 102, 39, 232, 105, 106, 43, 108, 45, 46, 143, + 240, 113, 114, 51, 116, 53, 54, 151, 120, 57, 58, 155, 60, 157, 158, 79, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, + 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 32, 0, 32, 32, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 16, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 32, + 0, 0, 0, 64, 0, 64, 64, 32, 0, 64, 64, 32, 64, 32, 32, 80, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 16, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 32, + 0, 0, 0, 128, 0, 128, 128, 32, 0, 128, 128, 32, 128, 32, 32, 144, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 64, + 0, 0, 0, 128, 0, 128, 128, 64, 0, 128, 128, 64, 128, 64, 64, 144, + 0, 0, 0, 128, 0, 128, 128, 64, 0, 128, 128, 64, 128, 64, 64, 160, + 0, 128, 128, 64, 128, 64, 64, 160, 128, 64, 64, 160, 64, 160, 160, 80, + }, { + 0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 17, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 33, + 16, 1, 2, 1, 4, 1, 2, 33, 8, 1, 2, 33, 4, 33, 34, 17, + 64, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 65, + 16, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 17, + 32, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 33, + 16, 1, 2, 65, 4, 65, 66, 33, 8, 65, 66, 33, 68, 33, 34, 81, + 128, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 129, + 16, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 17, + 32, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 33, + 16, 1, 2, 129, 4, 129, 130, 33, 8, 129, 130, 33, 132, 33, 34, 145, + 64, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 65, + 16, 1, 2, 129, 4, 129, 130, 65, 8, 129, 130, 65, 132, 65, 66, 145, + 32, 1, 2, 129, 4, 129, 130, 65, 8, 129, 130, 65, 132, 65, 66, 161, + 16, 129, 130, 65, 132, 65, 66, 161, 136, 65, 66, 161, 68, 161, 162, 81, + }, { + 0, 0, 0, 2, 0, 4, 4, 2, 0, 8, 8, 2, 8, 4, 4, 2, + 0, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 18, + 0, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 34, + 32, 16, 16, 2, 16, 4, 4, 34, 16, 8, 8, 34, 8, 36, 36, 18, + 0, 64, 64, 2, 64, 4, 4, 2, 64, 8, 8, 2, 8, 4, 4, 66, + 64, 16, 16, 2, 16, 4, 4, 66, 16, 8, 8, 66, 8, 68, 68, 18, + 64, 32, 32, 2, 32, 4, 4, 66, 32, 8, 8, 66, 8, 68, 68, 34, + 32, 16, 16, 66, 16, 68, 68, 34, 16, 72, 72, 34, 72, 36, 36, 82, + 0, 128, 128, 2, 128, 4, 4, 2, 128, 8, 8, 2, 8, 4, 4, 130, + 128, 16, 16, 2, 16, 4, 4, 130, 16, 8, 8, 130, 8, 132, 132, 18, + 128, 32, 32, 2, 32, 4, 4, 130, 32, 8, 8, 130, 8, 132, 132, 34, + 32, 16, 16, 130, 16, 132, 132, 34, 16, 136, 136, 34, 136, 36, 36, 146, + 128, 64, 64, 2, 64, 4, 4, 130, 64, 8, 8, 130, 8, 132, 132, 66, + 64, 16, 16, 130, 16, 132, 132, 66, 16, 136, 136, 66, 136, 68, 68, 146, + 64, 32, 32, 130, 32, 132, 132, 66, 32, 136, 136, 66, 136, 68, 68, 162, + 32, 144, 144, 66, 144, 68, 68, 162, 144, 72, 72, 162, 72, 164, 164, 82, + }, { + 0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 10, 3, 12, 5, 6, 3, + 16, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 19, + 32, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 35, + 48, 17, 18, 3, 20, 5, 6, 35, 24, 9, 10, 35, 12, 37, 38, 19, + 64, 65, 66, 3, 68, 5, 6, 3, 72, 9, 10, 3, 12, 5, 6, 67, + 80, 17, 18, 3, 20, 5, 6, 67, 24, 9, 10, 67, 12, 69, 70, 19, + 96, 33, 34, 3, 36, 5, 6, 67, 40, 9, 10, 67, 12, 69, 70, 35, + 48, 17, 18, 67, 20, 69, 70, 35, 24, 73, 74, 35, 76, 37, 38, 83, + 128, 129, 130, 3, 132, 5, 6, 3, 136, 9, 10, 3, 12, 5, 6, 131, + 144, 17, 18, 3, 20, 5, 6, 131, 24, 9, 10, 131, 12, 133, 134, 19, + 160, 33, 34, 3, 36, 5, 6, 131, 40, 9, 10, 131, 12, 133, 134, 35, + 48, 17, 18, 131, 20, 133, 134, 35, 24, 137, 138, 35, 140, 37, 38, 147, + 192, 65, 66, 3, 68, 5, 6, 131, 72, 9, 10, 131, 12, 133, 134, 67, + 80, 17, 18, 131, 20, 133, 134, 67, 24, 137, 138, 67, 140, 69, 70, 147, + 96, 33, 34, 131, 36, 133, 134, 67, 40, 137, 138, 67, 140, 69, 70, 163, + 48, 145, 146, 67, 148, 69, 70, 163, 152, 73, 74, 163, 76, 165, 166, 83, + }, + { + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 8, 8, 4, + 0, 0, 0, 16, 0, 16, 16, 4, 0, 16, 16, 8, 16, 8, 8, 20, + 0, 0, 0, 32, 0, 32, 32, 4, 0, 32, 32, 8, 32, 8, 8, 36, + 0, 32, 32, 16, 32, 16, 16, 36, 32, 16, 16, 40, 16, 40, 40, 20, + 0, 0, 0, 64, 0, 64, 64, 4, 0, 64, 64, 8, 64, 8, 8, 68, + 0, 64, 64, 16, 64, 16, 16, 68, 64, 16, 16, 72, 16, 72, 72, 20, + 0, 64, 64, 32, 64, 32, 32, 68, 64, 32, 32, 72, 32, 72, 72, 36, + 64, 32, 32, 80, 32, 80, 80, 36, 32, 80, 80, 40, 80, 40, 40, 84, + 0, 0, 0, 128, 0, 128, 128, 4, 0, 128, 128, 8, 128, 8, 8, 132, + 0, 128, 128, 16, 128, 16, 16, 132, 128, 16, 16, 136, 16, 136, 136, 20, + 0, 128, 128, 32, 128, 32, 32, 132, 128, 32, 32, 136, 32, 136, 136, 36, + 128, 32, 32, 144, 32, 144, 144, 36, 32, 144, 144, 40, 144, 40, 40, 148, + 0, 128, 128, 64, 128, 64, 64, 132, 128, 64, 64, 136, 64, 136, 136, 68, + 128, 64, 64, 144, 64, 144, 144, 68, 64, 144, 144, 72, 144, 72, 72, 148, + 128, 64, 64, 160, 64, 160, 160, 68, 64, 160, 160, 72, 160, 72, 72, 164, + 64, 160, 160, 80, 160, 80, 80, 164, 160, 80, 80, 168, 80, 168, 168, 84, + }, { + 0, 1, 2, 1, 4, 1, 2, 5, 8, 1, 2, 9, 4, 9, 10, 5, + 16, 1, 2, 17, 4, 17, 18, 5, 8, 17, 18, 9, 20, 9, 10, 21, + 32, 1, 2, 33, 4, 33, 34, 5, 8, 33, 34, 9, 36, 9, 10, 37, + 16, 33, 34, 17, 36, 17, 18, 37, 40, 17, 18, 41, 20, 41, 42, 21, + 64, 1, 2, 65, 4, 65, 66, 5, 8, 65, 66, 9, 68, 9, 10, 69, + 16, 65, 66, 17, 68, 17, 18, 69, 72, 17, 18, 73, 20, 73, 74, 21, + 32, 65, 66, 33, 68, 33, 34, 69, 72, 33, 34, 73, 36, 73, 74, 37, + 80, 33, 34, 81, 36, 81, 82, 37, 40, 81, 82, 41, 84, 41, 42, 85, + 128, 1, 2, 129, 4, 129, 130, 5, 8, 129, 130, 9, 132, 9, 10, 133, + 16, 129, 130, 17, 132, 17, 18, 133, 136, 17, 18, 137, 20, 137, 138, 21, + 32, 129, 130, 33, 132, 33, 34, 133, 136, 33, 34, 137, 36, 137, 138, 37, + 144, 33, 34, 145, 36, 145, 146, 37, 40, 145, 146, 41, 148, 41, 42, 149, + 64, 129, 130, 65, 132, 65, 66, 133, 136, 65, 66, 137, 68, 137, 138, 69, + 144, 65, 66, 145, 68, 145, 146, 69, 72, 145, 146, 73, 148, 73, 74, 149, + 160, 65, 66, 161, 68, 161, 162, 69, 72, 161, 162, 73, 164, 73, 74, 165, + 80, 161, 162, 81, 164, 81, 82, 165, 168, 81, 82, 169, 84, 169, 170, 85, + }, { + 0, 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10, 8, 12, 12, 6, + 0, 16, 16, 18, 16, 20, 20, 6, 16, 24, 24, 10, 24, 12, 12, 22, + 0, 32, 32, 34, 32, 36, 36, 6, 32, 40, 40, 10, 40, 12, 12, 38, + 32, 48, 48, 18, 48, 20, 20, 38, 48, 24, 24, 42, 24, 44, 44, 22, + 0, 64, 64, 66, 64, 68, 68, 6, 64, 72, 72, 10, 72, 12, 12, 70, + 64, 80, 80, 18, 80, 20, 20, 70, 80, 24, 24, 74, 24, 76, 76, 22, + 64, 96, 96, 34, 96, 36, 36, 70, 96, 40, 40, 74, 40, 76, 76, 38, + 96, 48, 48, 82, 48, 84, 84, 38, 48, 88, 88, 42, 88, 44, 44, 86, + 0, 128, 128, 130, 128, 132, 132, 6, 128, 136, 136, 10, 136, 12, 12, 134, + 128, 144, 144, 18, 144, 20, 20, 134, 144, 24, 24, 138, 24, 140, 140, 22, + 128, 160, 160, 34, 160, 36, 36, 134, 160, 40, 40, 138, 40, 140, 140, 38, + 160, 48, 48, 146, 48, 148, 148, 38, 48, 152, 152, 42, 152, 44, 44, 150, + 128, 192, 192, 66, 192, 68, 68, 134, 192, 72, 72, 138, 72, 140, 140, 70, + 192, 80, 80, 146, 80, 148, 148, 70, 80, 152, 152, 74, 152, 76, 76, 150, + 192, 96, 96, 162, 96, 164, 164, 70, 96, 168, 168, 74, 168, 76, 76, 166, + 96, 176, 176, 82, 176, 84, 84, 166, 176, 88, 88, 170, 88, 172, 172, 86, + }, { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 7, + 16, 17, 18, 19, 20, 21, 22, 7, 24, 25, 26, 11, 28, 13, 14, 23, + 32, 33, 34, 35, 36, 37, 38, 7, 40, 41, 42, 11, 44, 13, 14, 39, + 48, 49, 50, 19, 52, 21, 22, 39, 56, 25, 26, 43, 28, 45, 46, 23, + 64, 65, 66, 67, 68, 69, 70, 7, 72, 73, 74, 11, 76, 13, 14, 71, + 80, 81, 82, 19, 84, 21, 22, 71, 88, 25, 26, 75, 28, 77, 78, 23, + 96, 97, 98, 35, 100, 37, 38, 71, 104, 41, 42, 75, 44, 77, 78, 39, + 112, 49, 50, 83, 52, 85, 86, 39, 56, 89, 90, 43, 92, 45, 46, 87, + 128, 129, 130, 131, 132, 133, 134, 7, 136, 137, 138, 11, 140, 13, 14, 135, + 144, 145, 146, 19, 148, 21, 22, 135, 152, 25, 26, 139, 28, 141, 142, 23, + 160, 161, 162, 35, 164, 37, 38, 135, 168, 41, 42, 139, 44, 141, 142, 39, + 176, 49, 50, 147, 52, 149, 150, 39, 56, 153, 154, 43, 156, 45, 46, 151, + 192, 193, 194, 67, 196, 69, 70, 135, 200, 73, 74, 139, 76, 141, 142, 71, + 208, 81, 82, 147, 84, 149, 150, 71, 88, 153, 154, 75, 156, 77, 78, 151, + 224, 97, 98, 163, 100, 165, 166, 71, 104, 169, 170, 75, 172, 77, 78, 167, + 112, 177, 178, 83, 180, 85, 86, 167, 184, 89, 90, 171, 92, 173, 174, 87, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, + 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 16, 0, 16, 16, 24, + 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 32, 0, 32, 32, 40, + 0, 0, 0, 32, 0, 32, 32, 48, 0, 32, 32, 48, 32, 48, 48, 24, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 72, + 0, 0, 0, 64, 0, 64, 64, 80, 0, 64, 64, 80, 64, 80, 80, 24, + 0, 0, 0, 64, 0, 64, 64, 96, 0, 64, 64, 96, 64, 96, 96, 40, + 0, 64, 64, 96, 64, 96, 96, 48, 64, 96, 96, 48, 96, 48, 48, 88, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 136, + 0, 0, 0, 128, 0, 128, 128, 144, 0, 128, 128, 144, 128, 144, 144, 24, + 0, 0, 0, 128, 0, 128, 128, 160, 0, 128, 128, 160, 128, 160, 160, 40, + 0, 128, 128, 160, 128, 160, 160, 48, 128, 160, 160, 48, 160, 48, 48, 152, + 0, 0, 0, 128, 0, 128, 128, 192, 0, 128, 128, 192, 128, 192, 192, 72, + 0, 128, 128, 192, 128, 192, 192, 80, 128, 192, 192, 80, 192, 80, 80, 152, + 0, 128, 128, 192, 128, 192, 192, 96, 128, 192, 192, 96, 192, 96, 96, 168, + 128, 192, 192, 96, 192, 96, 96, 176, 192, 96, 96, 176, 96, 176, 176, 88, + }, { + 0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 9, + 16, 1, 2, 1, 4, 1, 2, 17, 8, 1, 2, 17, 4, 17, 18, 25, + 32, 1, 2, 1, 4, 1, 2, 33, 8, 1, 2, 33, 4, 33, 34, 41, + 16, 1, 2, 33, 4, 33, 34, 49, 8, 33, 34, 49, 36, 49, 50, 25, + 64, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 73, + 16, 1, 2, 65, 4, 65, 66, 81, 8, 65, 66, 81, 68, 81, 82, 25, + 32, 1, 2, 65, 4, 65, 66, 97, 8, 65, 66, 97, 68, 97, 98, 41, + 16, 65, 66, 97, 68, 97, 98, 49, 72, 97, 98, 49, 100, 49, 50, 89, + 128, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 137, + 16, 1, 2, 129, 4, 129, 130, 145, 8, 129, 130, 145, 132, 145, 146, 25, + 32, 1, 2, 129, 4, 129, 130, 161, 8, 129, 130, 161, 132, 161, 162, 41, + 16, 129, 130, 161, 132, 161, 162, 49, 136, 161, 162, 49, 164, 49, 50, 153, + 64, 1, 2, 129, 4, 129, 130, 193, 8, 129, 130, 193, 132, 193, 194, 73, + 16, 129, 130, 193, 132, 193, 194, 81, 136, 193, 194, 81, 196, 81, 82, 153, + 32, 129, 130, 193, 132, 193, 194, 97, 136, 193, 194, 97, 196, 97, 98, 169, + 144, 193, 194, 97, 196, 97, 98, 177, 200, 97, 98, 177, 100, 177, 178, 89, + }, { + 0, 0, 0, 2, 0, 4, 4, 2, 0, 8, 8, 2, 8, 4, 4, 10, + 0, 16, 16, 2, 16, 4, 4, 18, 16, 8, 8, 18, 8, 20, 20, 26, + 0, 32, 32, 2, 32, 4, 4, 34, 32, 8, 8, 34, 8, 36, 36, 42, + 32, 16, 16, 34, 16, 36, 36, 50, 16, 40, 40, 50, 40, 52, 52, 26, + 0, 64, 64, 2, 64, 4, 4, 66, 64, 8, 8, 66, 8, 68, 68, 74, + 64, 16, 16, 66, 16, 68, 68, 82, 16, 72, 72, 82, 72, 84, 84, 26, + 64, 32, 32, 66, 32, 68, 68, 98, 32, 72, 72, 98, 72, 100, 100, 42, + 32, 80, 80, 98, 80, 100, 100, 50, 80, 104, 104, 50, 104, 52, 52, 90, + 0, 128, 128, 2, 128, 4, 4, 130, 128, 8, 8, 130, 8, 132, 132, 138, + 128, 16, 16, 130, 16, 132, 132, 146, 16, 136, 136, 146, 136, 148, 148, 26, + 128, 32, 32, 130, 32, 132, 132, 162, 32, 136, 136, 162, 136, 164, 164, 42, + 32, 144, 144, 162, 144, 164, 164, 50, 144, 168, 168, 50, 168, 52, 52, 154, + 128, 64, 64, 130, 64, 132, 132, 194, 64, 136, 136, 194, 136, 196, 196, 74, + 64, 144, 144, 194, 144, 196, 196, 82, 144, 200, 200, 82, 200, 84, 84, 154, + 64, 160, 160, 194, 160, 196, 196, 98, 160, 200, 200, 98, 200, 100, 100, 170, + 160, 208, 208, 98, 208, 100, 100, 178, 208, 104, 104, 178, 104, 180, 180, 90, + }, { + 0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 10, 3, 12, 5, 6, 11, + 16, 17, 18, 3, 20, 5, 6, 19, 24, 9, 10, 19, 12, 21, 22, 27, + 32, 33, 34, 3, 36, 5, 6, 35, 40, 9, 10, 35, 12, 37, 38, 43, + 48, 17, 18, 35, 20, 37, 38, 51, 24, 41, 42, 51, 44, 53, 54, 27, + 64, 65, 66, 3, 68, 5, 6, 67, 72, 9, 10, 67, 12, 69, 70, 75, + 80, 17, 18, 67, 20, 69, 70, 83, 24, 73, 74, 83, 76, 85, 86, 27, + 96, 33, 34, 67, 36, 69, 70, 99, 40, 73, 74, 99, 76, 101, 102, 43, + 48, 81, 82, 99, 84, 101, 102, 51, 88, 105, 106, 51, 108, 53, 54, 91, + 128, 129, 130, 3, 132, 5, 6, 131, 136, 9, 10, 131, 12, 133, 134, 139, + 144, 17, 18, 131, 20, 133, 134, 147, 24, 137, 138, 147, 140, 149, 150, 27, + 160, 33, 34, 131, 36, 133, 134, 163, 40, 137, 138, 163, 140, 165, 166, 43, + 48, 145, 146, 163, 148, 165, 166, 51, 152, 169, 170, 51, 172, 53, 54, 155, + 192, 65, 66, 131, 68, 133, 134, 195, 72, 137, 138, 195, 140, 197, 198, 75, + 80, 145, 146, 195, 148, 197, 198, 83, 152, 201, 202, 83, 204, 85, 86, 155, + 96, 161, 162, 195, 164, 197, 198, 99, 168, 201, 202, 99, 204, 101, 102, 171, + 176, 209, 210, 99, 212, 101, 102, 179, 216, 105, 106, 179, 108, 181, 182, 91, + }, + { + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 8, 8, 12, + 0, 0, 0, 16, 0, 16, 16, 20, 0, 16, 16, 24, 16, 24, 24, 28, + 0, 0, 0, 32, 0, 32, 32, 36, 0, 32, 32, 40, 32, 40, 40, 44, + 0, 32, 32, 48, 32, 48, 48, 52, 32, 48, 48, 56, 48, 56, 56, 28, + 0, 0, 0, 64, 0, 64, 64, 68, 0, 64, 64, 72, 64, 72, 72, 76, + 0, 64, 64, 80, 64, 80, 80, 84, 64, 80, 80, 88, 80, 88, 88, 28, + 0, 64, 64, 96, 64, 96, 96, 100, 64, 96, 96, 104, 96, 104, 104, 44, + 64, 96, 96, 112, 96, 112, 112, 52, 96, 112, 112, 56, 112, 56, 56, 92, + 0, 0, 0, 128, 0, 128, 128, 132, 0, 128, 128, 136, 128, 136, 136, 140, + 0, 128, 128, 144, 128, 144, 144, 148, 128, 144, 144, 152, 144, 152, 152, 28, + 0, 128, 128, 160, 128, 160, 160, 164, 128, 160, 160, 168, 160, 168, 168, 44, + 128, 160, 160, 176, 160, 176, 176, 52, 160, 176, 176, 56, 176, 56, 56, 156, + 0, 128, 128, 192, 128, 192, 192, 196, 128, 192, 192, 200, 192, 200, 200, 76, + 128, 192, 192, 208, 192, 208, 208, 84, 192, 208, 208, 88, 208, 88, 88, 156, + 128, 192, 192, 224, 192, 224, 224, 100, 192, 224, 224, 104, 224, 104, 104, 172, + 192, 224, 224, 112, 224, 112, 112, 180, 224, 112, 112, 184, 112, 184, 184, 92, + }, { + 0, 1, 2, 1, 4, 1, 2, 5, 8, 1, 2, 9, 4, 9, 10, 13, + 16, 1, 2, 17, 4, 17, 18, 21, 8, 17, 18, 25, 20, 25, 26, 29, + 32, 1, 2, 33, 4, 33, 34, 37, 8, 33, 34, 41, 36, 41, 42, 45, + 16, 33, 34, 49, 36, 49, 50, 53, 40, 49, 50, 57, 52, 57, 58, 29, + 64, 1, 2, 65, 4, 65, 66, 69, 8, 65, 66, 73, 68, 73, 74, 77, + 16, 65, 66, 81, 68, 81, 82, 85, 72, 81, 82, 89, 84, 89, 90, 29, + 32, 65, 66, 97, 68, 97, 98, 101, 72, 97, 98, 105, 100, 105, 106, 45, + 80, 97, 98, 113, 100, 113, 114, 53, 104, 113, 114, 57, 116, 57, 58, 93, + 128, 1, 2, 129, 4, 129, 130, 133, 8, 129, 130, 137, 132, 137, 138, 141, + 16, 129, 130, 145, 132, 145, 146, 149, 136, 145, 146, 153, 148, 153, 154, 29, + 32, 129, 130, 161, 132, 161, 162, 165, 136, 161, 162, 169, 164, 169, 170, 45, + 144, 161, 162, 177, 164, 177, 178, 53, 168, 177, 178, 57, 180, 57, 58, 157, + 64, 129, 130, 193, 132, 193, 194, 197, 136, 193, 194, 201, 196, 201, 202, 77, + 144, 193, 194, 209, 196, 209, 210, 85, 200, 209, 210, 89, 212, 89, 90, 157, + 160, 193, 194, 225, 196, 225, 226, 101, 200, 225, 226, 105, 228, 105, 106, 173, + 208, 225, 226, 113, 228, 113, 114, 181, 232, 113, 114, 185, 116, 185, 186, 93, + }, { + 0, 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10, 8, 12, 12, 14, + 0, 16, 16, 18, 16, 20, 20, 22, 16, 24, 24, 26, 24, 28, 28, 30, + 0, 32, 32, 34, 32, 36, 36, 38, 32, 40, 40, 42, 40, 44, 44, 46, + 32, 48, 48, 50, 48, 52, 52, 54, 48, 56, 56, 58, 56, 60, 60, 30, + 0, 64, 64, 66, 64, 68, 68, 70, 64, 72, 72, 74, 72, 76, 76, 78, + 64, 80, 80, 82, 80, 84, 84, 86, 80, 88, 88, 90, 88, 92, 92, 30, + 64, 96, 96, 98, 96, 100, 100, 102, 96, 104, 104, 106, 104, 108, 108, 46, + 96, 112, 112, 114, 112, 116, 116, 54, 112, 120, 120, 58, 120, 60, 60, 94, + 0, 128, 128, 130, 128, 132, 132, 134, 128, 136, 136, 138, 136, 140, 140, 142, + 128, 144, 144, 146, 144, 148, 148, 150, 144, 152, 152, 154, 152, 156, 156, 30, + 128, 160, 160, 162, 160, 164, 164, 166, 160, 168, 168, 170, 168, 172, 172, 46, + 160, 176, 176, 178, 176, 180, 180, 54, 176, 184, 184, 58, 184, 60, 60, 158, + 128, 192, 192, 194, 192, 196, 196, 198, 192, 200, 200, 202, 200, 204, 204, 78, + 192, 208, 208, 210, 208, 212, 212, 86, 208, 216, 216, 90, 216, 92, 92, 158, + 192, 224, 224, 226, 224, 228, 228, 102, 224, 232, 232, 106, 232, 108, 108, 174, + 224, 240, 240, 114, 240, 116, 116, 182, 240, 120, 120, 186, 120, 188, 188, 94, + }, { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 31, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 31, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 47, + 112, 113, 114, 115, 116, 117, 118, 55, 120, 121, 122, 59, 124, 61, 62, 95, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, + 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 31, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 47, + 176, 177, 178, 179, 180, 181, 182, 55, 184, 185, 186, 59, 188, 61, 62, 159, + 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 79, + 208, 209, 210, 211, 212, 213, 214, 87, 216, 217, 218, 91, 220, 93, 94, 159, + 224, 225, 226, 227, 228, 229, 230, 103, 232, 233, 234, 107, 236, 109, 110, 175, + 240, 241, 242, 115, 244, 117, 118, 183, 248, 121, 122, 187, 124, 189, 190, 95, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 96, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 160, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 192, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 192, + 0, 0, 0, 128, 0, 128, 128, 192, 0, 128, 128, 192, 128, 192, 192, 96, + }, { + 0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 33, + 64, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 65, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 65, + 16, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 97, + 128, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 129, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 129, + 16, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 161, + 64, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 129, + 16, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 193, + 32, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 193, + 16, 1, 2, 129, 4, 129, 130, 193, 8, 129, 130, 193, 132, 193, 194, 97, + }, { + 0, 0, 0, 2, 0, 4, 4, 2, 0, 8, 8, 2, 8, 4, 4, 2, + 0, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 2, + 0, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 2, + 32, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 34, + 0, 64, 64, 2, 64, 4, 4, 2, 64, 8, 8, 2, 8, 4, 4, 2, + 64, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 66, + 64, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 66, + 32, 16, 16, 2, 16, 4, 4, 66, 16, 8, 8, 66, 8, 68, 68, 98, + 0, 128, 128, 2, 128, 4, 4, 2, 128, 8, 8, 2, 8, 4, 4, 2, + 128, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 130, + 128, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 130, + 32, 16, 16, 2, 16, 4, 4, 130, 16, 8, 8, 130, 8, 132, 132, 162, + 128, 64, 64, 2, 64, 4, 4, 2, 64, 8, 8, 2, 8, 4, 4, 130, + 64, 16, 16, 2, 16, 4, 4, 130, 16, 8, 8, 130, 8, 132, 132, 194, + 64, 32, 32, 2, 32, 4, 4, 130, 32, 8, 8, 130, 8, 132, 132, 194, + 32, 16, 16, 130, 16, 132, 132, 194, 16, 136, 136, 194, 136, 196, 196, 98, + }, { + 0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 10, 3, 12, 5, 6, 3, + 16, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 3, + 32, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 3, + 48, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 35, + 64, 65, 66, 3, 68, 5, 6, 3, 72, 9, 10, 3, 12, 5, 6, 3, + 80, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 67, + 96, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 67, + 48, 17, 18, 3, 20, 5, 6, 67, 24, 9, 10, 67, 12, 69, 70, 99, + 128, 129, 130, 3, 132, 5, 6, 3, 136, 9, 10, 3, 12, 5, 6, 3, + 144, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 131, + 160, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 131, + 48, 17, 18, 3, 20, 5, 6, 131, 24, 9, 10, 131, 12, 133, 134, 163, + 192, 65, 66, 3, 68, 5, 6, 3, 72, 9, 10, 3, 12, 5, 6, 131, + 80, 17, 18, 3, 20, 5, 6, 131, 24, 9, 10, 131, 12, 133, 134, 195, + 96, 33, 34, 3, 36, 5, 6, 131, 40, 9, 10, 131, 12, 133, 134, 195, + 48, 17, 18, 131, 20, 133, 134, 195, 24, 137, 138, 195, 140, 197, 198, 99, + }, + { + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 8, 8, 4, + 0, 0, 0, 16, 0, 16, 16, 4, 0, 16, 16, 8, 16, 8, 8, 4, + 0, 0, 0, 32, 0, 32, 32, 4, 0, 32, 32, 8, 32, 8, 8, 4, + 0, 32, 32, 16, 32, 16, 16, 4, 32, 16, 16, 8, 16, 8, 8, 36, + 0, 0, 0, 64, 0, 64, 64, 4, 0, 64, 64, 8, 64, 8, 8, 4, + 0, 64, 64, 16, 64, 16, 16, 4, 64, 16, 16, 8, 16, 8, 8, 68, + 0, 64, 64, 32, 64, 32, 32, 4, 64, 32, 32, 8, 32, 8, 8, 68, + 64, 32, 32, 16, 32, 16, 16, 68, 32, 16, 16, 72, 16, 72, 72, 100, + 0, 0, 0, 128, 0, 128, 128, 4, 0, 128, 128, 8, 128, 8, 8, 4, + 0, 128, 128, 16, 128, 16, 16, 4, 128, 16, 16, 8, 16, 8, 8, 132, + 0, 128, 128, 32, 128, 32, 32, 4, 128, 32, 32, 8, 32, 8, 8, 132, + 128, 32, 32, 16, 32, 16, 16, 132, 32, 16, 16, 136, 16, 136, 136, 164, + 0, 128, 128, 64, 128, 64, 64, 4, 128, 64, 64, 8, 64, 8, 8, 132, + 128, 64, 64, 16, 64, 16, 16, 132, 64, 16, 16, 136, 16, 136, 136, 196, + 128, 64, 64, 32, 64, 32, 32, 132, 64, 32, 32, 136, 32, 136, 136, 196, + 64, 32, 32, 144, 32, 144, 144, 196, 32, 144, 144, 200, 144, 200, 200, 100, + }, { + 0, 1, 2, 1, 4, 1, 2, 5, 8, 1, 2, 9, 4, 9, 10, 5, + 16, 1, 2, 17, 4, 17, 18, 5, 8, 17, 18, 9, 20, 9, 10, 5, + 32, 1, 2, 33, 4, 33, 34, 5, 8, 33, 34, 9, 36, 9, 10, 5, + 16, 33, 34, 17, 36, 17, 18, 5, 40, 17, 18, 9, 20, 9, 10, 37, + 64, 1, 2, 65, 4, 65, 66, 5, 8, 65, 66, 9, 68, 9, 10, 5, + 16, 65, 66, 17, 68, 17, 18, 5, 72, 17, 18, 9, 20, 9, 10, 69, + 32, 65, 66, 33, 68, 33, 34, 5, 72, 33, 34, 9, 36, 9, 10, 69, + 80, 33, 34, 17, 36, 17, 18, 69, 40, 17, 18, 73, 20, 73, 74, 101, + 128, 1, 2, 129, 4, 129, 130, 5, 8, 129, 130, 9, 132, 9, 10, 5, + 16, 129, 130, 17, 132, 17, 18, 5, 136, 17, 18, 9, 20, 9, 10, 133, + 32, 129, 130, 33, 132, 33, 34, 5, 136, 33, 34, 9, 36, 9, 10, 133, + 144, 33, 34, 17, 36, 17, 18, 133, 40, 17, 18, 137, 20, 137, 138, 165, + 64, 129, 130, 65, 132, 65, 66, 5, 136, 65, 66, 9, 68, 9, 10, 133, + 144, 65, 66, 17, 68, 17, 18, 133, 72, 17, 18, 137, 20, 137, 138, 197, + 160, 65, 66, 33, 68, 33, 34, 133, 72, 33, 34, 137, 36, 137, 138, 197, + 80, 33, 34, 145, 36, 145, 146, 197, 40, 145, 146, 201, 148, 201, 202, 101, + }, { + 0, 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10, 8, 12, 12, 6, + 0, 16, 16, 18, 16, 20, 20, 6, 16, 24, 24, 10, 24, 12, 12, 6, + 0, 32, 32, 34, 32, 36, 36, 6, 32, 40, 40, 10, 40, 12, 12, 6, + 32, 48, 48, 18, 48, 20, 20, 6, 48, 24, 24, 10, 24, 12, 12, 38, + 0, 64, 64, 66, 64, 68, 68, 6, 64, 72, 72, 10, 72, 12, 12, 6, + 64, 80, 80, 18, 80, 20, 20, 6, 80, 24, 24, 10, 24, 12, 12, 70, + 64, 96, 96, 34, 96, 36, 36, 6, 96, 40, 40, 10, 40, 12, 12, 70, + 96, 48, 48, 18, 48, 20, 20, 70, 48, 24, 24, 74, 24, 76, 76, 102, + 0, 128, 128, 130, 128, 132, 132, 6, 128, 136, 136, 10, 136, 12, 12, 6, + 128, 144, 144, 18, 144, 20, 20, 6, 144, 24, 24, 10, 24, 12, 12, 134, + 128, 160, 160, 34, 160, 36, 36, 6, 160, 40, 40, 10, 40, 12, 12, 134, + 160, 48, 48, 18, 48, 20, 20, 134, 48, 24, 24, 138, 24, 140, 140, 166, + 128, 192, 192, 66, 192, 68, 68, 6, 192, 72, 72, 10, 72, 12, 12, 134, + 192, 80, 80, 18, 80, 20, 20, 134, 80, 24, 24, 138, 24, 140, 140, 198, + 192, 96, 96, 34, 96, 36, 36, 134, 96, 40, 40, 138, 40, 140, 140, 198, + 96, 48, 48, 146, 48, 148, 148, 198, 48, 152, 152, 202, 152, 204, 204, 102, + }, { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 7, + 16, 17, 18, 19, 20, 21, 22, 7, 24, 25, 26, 11, 28, 13, 14, 7, + 32, 33, 34, 35, 36, 37, 38, 7, 40, 41, 42, 11, 44, 13, 14, 7, + 48, 49, 50, 19, 52, 21, 22, 7, 56, 25, 26, 11, 28, 13, 14, 39, + 64, 65, 66, 67, 68, 69, 70, 7, 72, 73, 74, 11, 76, 13, 14, 7, + 80, 81, 82, 19, 84, 21, 22, 7, 88, 25, 26, 11, 28, 13, 14, 71, + 96, 97, 98, 35, 100, 37, 38, 7, 104, 41, 42, 11, 44, 13, 14, 71, + 112, 49, 50, 19, 52, 21, 22, 71, 56, 25, 26, 75, 28, 77, 78, 103, + 128, 129, 130, 131, 132, 133, 134, 7, 136, 137, 138, 11, 140, 13, 14, 7, + 144, 145, 146, 19, 148, 21, 22, 7, 152, 25, 26, 11, 28, 13, 14, 135, + 160, 161, 162, 35, 164, 37, 38, 7, 168, 41, 42, 11, 44, 13, 14, 135, + 176, 49, 50, 19, 52, 21, 22, 135, 56, 25, 26, 139, 28, 141, 142, 167, + 192, 193, 194, 67, 196, 69, 70, 7, 200, 73, 74, 11, 76, 13, 14, 135, + 208, 81, 82, 19, 84, 21, 22, 135, 88, 25, 26, 139, 28, 141, 142, 199, + 224, 97, 98, 35, 100, 37, 38, 135, 104, 41, 42, 139, 44, 141, 142, 199, + 112, 49, 50, 147, 52, 149, 150, 199, 56, 153, 154, 203, 156, 205, 206, 103, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, + 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 16, 0, 16, 16, 8, + 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 32, 0, 32, 32, 8, + 0, 0, 0, 32, 0, 32, 32, 16, 0, 32, 32, 16, 32, 16, 16, 40, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 8, + 0, 0, 0, 64, 0, 64, 64, 16, 0, 64, 64, 16, 64, 16, 16, 72, + 0, 0, 0, 64, 0, 64, 64, 32, 0, 64, 64, 32, 64, 32, 32, 72, + 0, 64, 64, 32, 64, 32, 32, 80, 64, 32, 32, 80, 32, 80, 80, 104, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 8, + 0, 0, 0, 128, 0, 128, 128, 16, 0, 128, 128, 16, 128, 16, 16, 136, + 0, 0, 0, 128, 0, 128, 128, 32, 0, 128, 128, 32, 128, 32, 32, 136, + 0, 128, 128, 32, 128, 32, 32, 144, 128, 32, 32, 144, 32, 144, 144, 168, + 0, 0, 0, 128, 0, 128, 128, 64, 0, 128, 128, 64, 128, 64, 64, 136, + 0, 128, 128, 64, 128, 64, 64, 144, 128, 64, 64, 144, 64, 144, 144, 200, + 0, 128, 128, 64, 128, 64, 64, 160, 128, 64, 64, 160, 64, 160, 160, 200, + 128, 64, 64, 160, 64, 160, 160, 208, 64, 160, 160, 208, 160, 208, 208, 104, + }, { + 0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 9, + 16, 1, 2, 1, 4, 1, 2, 17, 8, 1, 2, 17, 4, 17, 18, 9, + 32, 1, 2, 1, 4, 1, 2, 33, 8, 1, 2, 33, 4, 33, 34, 9, + 16, 1, 2, 33, 4, 33, 34, 17, 8, 33, 34, 17, 36, 17, 18, 41, + 64, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 9, + 16, 1, 2, 65, 4, 65, 66, 17, 8, 65, 66, 17, 68, 17, 18, 73, + 32, 1, 2, 65, 4, 65, 66, 33, 8, 65, 66, 33, 68, 33, 34, 73, + 16, 65, 66, 33, 68, 33, 34, 81, 72, 33, 34, 81, 36, 81, 82, 105, + 128, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 9, + 16, 1, 2, 129, 4, 129, 130, 17, 8, 129, 130, 17, 132, 17, 18, 137, + 32, 1, 2, 129, 4, 129, 130, 33, 8, 129, 130, 33, 132, 33, 34, 137, + 16, 129, 130, 33, 132, 33, 34, 145, 136, 33, 34, 145, 36, 145, 146, 169, + 64, 1, 2, 129, 4, 129, 130, 65, 8, 129, 130, 65, 132, 65, 66, 137, + 16, 129, 130, 65, 132, 65, 66, 145, 136, 65, 66, 145, 68, 145, 146, 201, + 32, 129, 130, 65, 132, 65, 66, 161, 136, 65, 66, 161, 68, 161, 162, 201, + 144, 65, 66, 161, 68, 161, 162, 209, 72, 161, 162, 209, 164, 209, 210, 105, + }, { + 0, 0, 0, 2, 0, 4, 4, 2, 0, 8, 8, 2, 8, 4, 4, 10, + 0, 16, 16, 2, 16, 4, 4, 18, 16, 8, 8, 18, 8, 20, 20, 10, + 0, 32, 32, 2, 32, 4, 4, 34, 32, 8, 8, 34, 8, 36, 36, 10, + 32, 16, 16, 34, 16, 36, 36, 18, 16, 40, 40, 18, 40, 20, 20, 42, + 0, 64, 64, 2, 64, 4, 4, 66, 64, 8, 8, 66, 8, 68, 68, 10, + 64, 16, 16, 66, 16, 68, 68, 18, 16, 72, 72, 18, 72, 20, 20, 74, + 64, 32, 32, 66, 32, 68, 68, 34, 32, 72, 72, 34, 72, 36, 36, 74, + 32, 80, 80, 34, 80, 36, 36, 82, 80, 40, 40, 82, 40, 84, 84, 106, + 0, 128, 128, 2, 128, 4, 4, 130, 128, 8, 8, 130, 8, 132, 132, 10, + 128, 16, 16, 130, 16, 132, 132, 18, 16, 136, 136, 18, 136, 20, 20, 138, + 128, 32, 32, 130, 32, 132, 132, 34, 32, 136, 136, 34, 136, 36, 36, 138, + 32, 144, 144, 34, 144, 36, 36, 146, 144, 40, 40, 146, 40, 148, 148, 170, + 128, 64, 64, 130, 64, 132, 132, 66, 64, 136, 136, 66, 136, 68, 68, 138, + 64, 144, 144, 66, 144, 68, 68, 146, 144, 72, 72, 146, 72, 148, 148, 202, + 64, 160, 160, 66, 160, 68, 68, 162, 160, 72, 72, 162, 72, 164, 164, 202, + 160, 80, 80, 162, 80, 164, 164, 210, 80, 168, 168, 210, 168, 212, 212, 106, + }, { + 0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 10, 3, 12, 5, 6, 11, + 16, 17, 18, 3, 20, 5, 6, 19, 24, 9, 10, 19, 12, 21, 22, 11, + 32, 33, 34, 3, 36, 5, 6, 35, 40, 9, 10, 35, 12, 37, 38, 11, + 48, 17, 18, 35, 20, 37, 38, 19, 24, 41, 42, 19, 44, 21, 22, 43, + 64, 65, 66, 3, 68, 5, 6, 67, 72, 9, 10, 67, 12, 69, 70, 11, + 80, 17, 18, 67, 20, 69, 70, 19, 24, 73, 74, 19, 76, 21, 22, 75, + 96, 33, 34, 67, 36, 69, 70, 35, 40, 73, 74, 35, 76, 37, 38, 75, + 48, 81, 82, 35, 84, 37, 38, 83, 88, 41, 42, 83, 44, 85, 86, 107, + 128, 129, 130, 3, 132, 5, 6, 131, 136, 9, 10, 131, 12, 133, 134, 11, + 144, 17, 18, 131, 20, 133, 134, 19, 24, 137, 138, 19, 140, 21, 22, 139, + 160, 33, 34, 131, 36, 133, 134, 35, 40, 137, 138, 35, 140, 37, 38, 139, + 48, 145, 146, 35, 148, 37, 38, 147, 152, 41, 42, 147, 44, 149, 150, 171, + 192, 65, 66, 131, 68, 133, 134, 67, 72, 137, 138, 67, 140, 69, 70, 139, + 80, 145, 146, 67, 148, 69, 70, 147, 152, 73, 74, 147, 76, 149, 150, 203, + 96, 161, 162, 67, 164, 69, 70, 163, 168, 73, 74, 163, 76, 165, 166, 203, + 176, 81, 82, 163, 84, 165, 166, 211, 88, 169, 170, 211, 172, 213, 214, 107, + }, + { + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 8, 8, 12, + 0, 0, 0, 16, 0, 16, 16, 20, 0, 16, 16, 24, 16, 24, 24, 12, + 0, 0, 0, 32, 0, 32, 32, 36, 0, 32, 32, 40, 32, 40, 40, 12, + 0, 32, 32, 48, 32, 48, 48, 20, 32, 48, 48, 24, 48, 24, 24, 44, + 0, 0, 0, 64, 0, 64, 64, 68, 0, 64, 64, 72, 64, 72, 72, 12, + 0, 64, 64, 80, 64, 80, 80, 20, 64, 80, 80, 24, 80, 24, 24, 76, + 0, 64, 64, 96, 64, 96, 96, 36, 64, 96, 96, 40, 96, 40, 40, 76, + 64, 96, 96, 48, 96, 48, 48, 84, 96, 48, 48, 88, 48, 88, 88, 108, + 0, 0, 0, 128, 0, 128, 128, 132, 0, 128, 128, 136, 128, 136, 136, 12, + 0, 128, 128, 144, 128, 144, 144, 20, 128, 144, 144, 24, 144, 24, 24, 140, + 0, 128, 128, 160, 128, 160, 160, 36, 128, 160, 160, 40, 160, 40, 40, 140, + 128, 160, 160, 48, 160, 48, 48, 148, 160, 48, 48, 152, 48, 152, 152, 172, + 0, 128, 128, 192, 128, 192, 192, 68, 128, 192, 192, 72, 192, 72, 72, 140, + 128, 192, 192, 80, 192, 80, 80, 148, 192, 80, 80, 152, 80, 152, 152, 204, + 128, 192, 192, 96, 192, 96, 96, 164, 192, 96, 96, 168, 96, 168, 168, 204, + 192, 96, 96, 176, 96, 176, 176, 212, 96, 176, 176, 216, 176, 216, 216, 108, + }, { + 0, 1, 2, 1, 4, 1, 2, 5, 8, 1, 2, 9, 4, 9, 10, 13, + 16, 1, 2, 17, 4, 17, 18, 21, 8, 17, 18, 25, 20, 25, 26, 13, + 32, 1, 2, 33, 4, 33, 34, 37, 8, 33, 34, 41, 36, 41, 42, 13, + 16, 33, 34, 49, 36, 49, 50, 21, 40, 49, 50, 25, 52, 25, 26, 45, + 64, 1, 2, 65, 4, 65, 66, 69, 8, 65, 66, 73, 68, 73, 74, 13, + 16, 65, 66, 81, 68, 81, 82, 21, 72, 81, 82, 25, 84, 25, 26, 77, + 32, 65, 66, 97, 68, 97, 98, 37, 72, 97, 98, 41, 100, 41, 42, 77, + 80, 97, 98, 49, 100, 49, 50, 85, 104, 49, 50, 89, 52, 89, 90, 109, + 128, 1, 2, 129, 4, 129, 130, 133, 8, 129, 130, 137, 132, 137, 138, 13, + 16, 129, 130, 145, 132, 145, 146, 21, 136, 145, 146, 25, 148, 25, 26, 141, + 32, 129, 130, 161, 132, 161, 162, 37, 136, 161, 162, 41, 164, 41, 42, 141, + 144, 161, 162, 49, 164, 49, 50, 149, 168, 49, 50, 153, 52, 153, 154, 173, + 64, 129, 130, 193, 132, 193, 194, 69, 136, 193, 194, 73, 196, 73, 74, 141, + 144, 193, 194, 81, 196, 81, 82, 149, 200, 81, 82, 153, 84, 153, 154, 205, + 160, 193, 194, 97, 196, 97, 98, 165, 200, 97, 98, 169, 100, 169, 170, 205, + 208, 97, 98, 177, 100, 177, 178, 213, 104, 177, 178, 217, 180, 217, 218, 109, + }, { + 0, 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10, 8, 12, 12, 14, + 0, 16, 16, 18, 16, 20, 20, 22, 16, 24, 24, 26, 24, 28, 28, 14, + 0, 32, 32, 34, 32, 36, 36, 38, 32, 40, 40, 42, 40, 44, 44, 14, + 32, 48, 48, 50, 48, 52, 52, 22, 48, 56, 56, 26, 56, 28, 28, 46, + 0, 64, 64, 66, 64, 68, 68, 70, 64, 72, 72, 74, 72, 76, 76, 14, + 64, 80, 80, 82, 80, 84, 84, 22, 80, 88, 88, 26, 88, 28, 28, 78, + 64, 96, 96, 98, 96, 100, 100, 38, 96, 104, 104, 42, 104, 44, 44, 78, + 96, 112, 112, 50, 112, 52, 52, 86, 112, 56, 56, 90, 56, 92, 92, 110, + 0, 128, 128, 130, 128, 132, 132, 134, 128, 136, 136, 138, 136, 140, 140, 14, + 128, 144, 144, 146, 144, 148, 148, 22, 144, 152, 152, 26, 152, 28, 28, 142, + 128, 160, 160, 162, 160, 164, 164, 38, 160, 168, 168, 42, 168, 44, 44, 142, + 160, 176, 176, 50, 176, 52, 52, 150, 176, 56, 56, 154, 56, 156, 156, 174, + 128, 192, 192, 194, 192, 196, 196, 70, 192, 200, 200, 74, 200, 76, 76, 142, + 192, 208, 208, 82, 208, 84, 84, 150, 208, 88, 88, 154, 88, 156, 156, 206, + 192, 224, 224, 98, 224, 100, 100, 166, 224, 104, 104, 170, 104, 172, 172, 206, + 224, 112, 112, 178, 112, 180, 180, 214, 112, 184, 184, 218, 184, 220, 220, 110, + }, { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 15, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 15, + 48, 49, 50, 51, 52, 53, 54, 23, 56, 57, 58, 27, 60, 29, 30, 47, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 15, + 80, 81, 82, 83, 84, 85, 86, 23, 88, 89, 90, 27, 92, 29, 30, 79, + 96, 97, 98, 99, 100, 101, 102, 39, 104, 105, 106, 43, 108, 45, 46, 79, + 112, 113, 114, 51, 116, 53, 54, 87, 120, 57, 58, 91, 60, 93, 94, 111, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 15, + 144, 145, 146, 147, 148, 149, 150, 23, 152, 153, 154, 27, 156, 29, 30, 143, + 160, 161, 162, 163, 164, 165, 166, 39, 168, 169, 170, 43, 172, 45, 46, 143, + 176, 177, 178, 51, 180, 53, 54, 151, 184, 57, 58, 155, 60, 157, 158, 175, + 192, 193, 194, 195, 196, 197, 198, 71, 200, 201, 202, 75, 204, 77, 78, 143, + 208, 209, 210, 83, 212, 85, 86, 151, 216, 89, 90, 155, 92, 157, 158, 207, + 224, 225, 226, 99, 228, 101, 102, 167, 232, 105, 106, 171, 108, 173, 174, 207, + 240, 113, 114, 179, 116, 181, 182, 215, 120, 185, 186, 219, 188, 221, 222, 111, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, + 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 32, 0, 32, 32, 48, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 80, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 96, + 0, 0, 0, 64, 0, 64, 64, 96, 0, 64, 64, 96, 64, 96, 96, 112, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 144, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 160, + 0, 0, 0, 128, 0, 128, 128, 160, 0, 128, 128, 160, 128, 160, 160, 176, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 192, + 0, 0, 0, 128, 0, 128, 128, 192, 0, 128, 128, 192, 128, 192, 192, 208, + 0, 0, 0, 128, 0, 128, 128, 192, 0, 128, 128, 192, 128, 192, 192, 224, + 0, 128, 128, 192, 128, 192, 192, 224, 128, 192, 192, 224, 192, 224, 224, 112, + }, { + 0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 17, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 33, + 16, 1, 2, 1, 4, 1, 2, 33, 8, 1, 2, 33, 4, 33, 34, 49, + 64, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 65, + 16, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 81, + 32, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 97, + 16, 1, 2, 65, 4, 65, 66, 97, 8, 65, 66, 97, 68, 97, 98, 113, + 128, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 129, + 16, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 145, + 32, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 161, + 16, 1, 2, 129, 4, 129, 130, 161, 8, 129, 130, 161, 132, 161, 162, 177, + 64, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 193, + 16, 1, 2, 129, 4, 129, 130, 193, 8, 129, 130, 193, 132, 193, 194, 209, + 32, 1, 2, 129, 4, 129, 130, 193, 8, 129, 130, 193, 132, 193, 194, 225, + 16, 129, 130, 193, 132, 193, 194, 225, 136, 193, 194, 225, 196, 225, 226, 113, + }, { + 0, 0, 0, 2, 0, 4, 4, 2, 0, 8, 8, 2, 8, 4, 4, 2, + 0, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 18, + 0, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 34, + 32, 16, 16, 2, 16, 4, 4, 34, 16, 8, 8, 34, 8, 36, 36, 50, + 0, 64, 64, 2, 64, 4, 4, 2, 64, 8, 8, 2, 8, 4, 4, 66, + 64, 16, 16, 2, 16, 4, 4, 66, 16, 8, 8, 66, 8, 68, 68, 82, + 64, 32, 32, 2, 32, 4, 4, 66, 32, 8, 8, 66, 8, 68, 68, 98, + 32, 16, 16, 66, 16, 68, 68, 98, 16, 72, 72, 98, 72, 100, 100, 114, + 0, 128, 128, 2, 128, 4, 4, 2, 128, 8, 8, 2, 8, 4, 4, 130, + 128, 16, 16, 2, 16, 4, 4, 130, 16, 8, 8, 130, 8, 132, 132, 146, + 128, 32, 32, 2, 32, 4, 4, 130, 32, 8, 8, 130, 8, 132, 132, 162, + 32, 16, 16, 130, 16, 132, 132, 162, 16, 136, 136, 162, 136, 164, 164, 178, + 128, 64, 64, 2, 64, 4, 4, 130, 64, 8, 8, 130, 8, 132, 132, 194, + 64, 16, 16, 130, 16, 132, 132, 194, 16, 136, 136, 194, 136, 196, 196, 210, + 64, 32, 32, 130, 32, 132, 132, 194, 32, 136, 136, 194, 136, 196, 196, 226, + 32, 144, 144, 194, 144, 196, 196, 226, 144, 200, 200, 226, 200, 228, 228, 114, + }, { + 0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 10, 3, 12, 5, 6, 3, + 16, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 19, + 32, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 35, + 48, 17, 18, 3, 20, 5, 6, 35, 24, 9, 10, 35, 12, 37, 38, 51, + 64, 65, 66, 3, 68, 5, 6, 3, 72, 9, 10, 3, 12, 5, 6, 67, + 80, 17, 18, 3, 20, 5, 6, 67, 24, 9, 10, 67, 12, 69, 70, 83, + 96, 33, 34, 3, 36, 5, 6, 67, 40, 9, 10, 67, 12, 69, 70, 99, + 48, 17, 18, 67, 20, 69, 70, 99, 24, 73, 74, 99, 76, 101, 102, 115, + 128, 129, 130, 3, 132, 5, 6, 3, 136, 9, 10, 3, 12, 5, 6, 131, + 144, 17, 18, 3, 20, 5, 6, 131, 24, 9, 10, 131, 12, 133, 134, 147, + 160, 33, 34, 3, 36, 5, 6, 131, 40, 9, 10, 131, 12, 133, 134, 163, + 48, 17, 18, 131, 20, 133, 134, 163, 24, 137, 138, 163, 140, 165, 166, 179, + 192, 65, 66, 3, 68, 5, 6, 131, 72, 9, 10, 131, 12, 133, 134, 195, + 80, 17, 18, 131, 20, 133, 134, 195, 24, 137, 138, 195, 140, 197, 198, 211, + 96, 33, 34, 131, 36, 133, 134, 195, 40, 137, 138, 195, 140, 197, 198, 227, + 48, 145, 146, 195, 148, 197, 198, 227, 152, 201, 202, 227, 204, 229, 230, 115, + }, + { + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 8, 8, 4, + 0, 0, 0, 16, 0, 16, 16, 4, 0, 16, 16, 8, 16, 8, 8, 20, + 0, 0, 0, 32, 0, 32, 32, 4, 0, 32, 32, 8, 32, 8, 8, 36, + 0, 32, 32, 16, 32, 16, 16, 36, 32, 16, 16, 40, 16, 40, 40, 52, + 0, 0, 0, 64, 0, 64, 64, 4, 0, 64, 64, 8, 64, 8, 8, 68, + 0, 64, 64, 16, 64, 16, 16, 68, 64, 16, 16, 72, 16, 72, 72, 84, + 0, 64, 64, 32, 64, 32, 32, 68, 64, 32, 32, 72, 32, 72, 72, 100, + 64, 32, 32, 80, 32, 80, 80, 100, 32, 80, 80, 104, 80, 104, 104, 116, + 0, 0, 0, 128, 0, 128, 128, 4, 0, 128, 128, 8, 128, 8, 8, 132, + 0, 128, 128, 16, 128, 16, 16, 132, 128, 16, 16, 136, 16, 136, 136, 148, + 0, 128, 128, 32, 128, 32, 32, 132, 128, 32, 32, 136, 32, 136, 136, 164, + 128, 32, 32, 144, 32, 144, 144, 164, 32, 144, 144, 168, 144, 168, 168, 180, + 0, 128, 128, 64, 128, 64, 64, 132, 128, 64, 64, 136, 64, 136, 136, 196, + 128, 64, 64, 144, 64, 144, 144, 196, 64, 144, 144, 200, 144, 200, 200, 212, + 128, 64, 64, 160, 64, 160, 160, 196, 64, 160, 160, 200, 160, 200, 200, 228, + 64, 160, 160, 208, 160, 208, 208, 228, 160, 208, 208, 232, 208, 232, 232, 116, + }, { + 0, 1, 2, 1, 4, 1, 2, 5, 8, 1, 2, 9, 4, 9, 10, 5, + 16, 1, 2, 17, 4, 17, 18, 5, 8, 17, 18, 9, 20, 9, 10, 21, + 32, 1, 2, 33, 4, 33, 34, 5, 8, 33, 34, 9, 36, 9, 10, 37, + 16, 33, 34, 17, 36, 17, 18, 37, 40, 17, 18, 41, 20, 41, 42, 53, + 64, 1, 2, 65, 4, 65, 66, 5, 8, 65, 66, 9, 68, 9, 10, 69, + 16, 65, 66, 17, 68, 17, 18, 69, 72, 17, 18, 73, 20, 73, 74, 85, + 32, 65, 66, 33, 68, 33, 34, 69, 72, 33, 34, 73, 36, 73, 74, 101, + 80, 33, 34, 81, 36, 81, 82, 101, 40, 81, 82, 105, 84, 105, 106, 117, + 128, 1, 2, 129, 4, 129, 130, 5, 8, 129, 130, 9, 132, 9, 10, 133, + 16, 129, 130, 17, 132, 17, 18, 133, 136, 17, 18, 137, 20, 137, 138, 149, + 32, 129, 130, 33, 132, 33, 34, 133, 136, 33, 34, 137, 36, 137, 138, 165, + 144, 33, 34, 145, 36, 145, 146, 165, 40, 145, 146, 169, 148, 169, 170, 181, + 64, 129, 130, 65, 132, 65, 66, 133, 136, 65, 66, 137, 68, 137, 138, 197, + 144, 65, 66, 145, 68, 145, 146, 197, 72, 145, 146, 201, 148, 201, 202, 213, + 160, 65, 66, 161, 68, 161, 162, 197, 72, 161, 162, 201, 164, 201, 202, 229, + 80, 161, 162, 209, 164, 209, 210, 229, 168, 209, 210, 233, 212, 233, 234, 117, + }, { + 0, 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10, 8, 12, 12, 6, + 0, 16, 16, 18, 16, 20, 20, 6, 16, 24, 24, 10, 24, 12, 12, 22, + 0, 32, 32, 34, 32, 36, 36, 6, 32, 40, 40, 10, 40, 12, 12, 38, + 32, 48, 48, 18, 48, 20, 20, 38, 48, 24, 24, 42, 24, 44, 44, 54, + 0, 64, 64, 66, 64, 68, 68, 6, 64, 72, 72, 10, 72, 12, 12, 70, + 64, 80, 80, 18, 80, 20, 20, 70, 80, 24, 24, 74, 24, 76, 76, 86, + 64, 96, 96, 34, 96, 36, 36, 70, 96, 40, 40, 74, 40, 76, 76, 102, + 96, 48, 48, 82, 48, 84, 84, 102, 48, 88, 88, 106, 88, 108, 108, 118, + 0, 128, 128, 130, 128, 132, 132, 6, 128, 136, 136, 10, 136, 12, 12, 134, + 128, 144, 144, 18, 144, 20, 20, 134, 144, 24, 24, 138, 24, 140, 140, 150, + 128, 160, 160, 34, 160, 36, 36, 134, 160, 40, 40, 138, 40, 140, 140, 166, + 160, 48, 48, 146, 48, 148, 148, 166, 48, 152, 152, 170, 152, 172, 172, 182, + 128, 192, 192, 66, 192, 68, 68, 134, 192, 72, 72, 138, 72, 140, 140, 198, + 192, 80, 80, 146, 80, 148, 148, 198, 80, 152, 152, 202, 152, 204, 204, 214, + 192, 96, 96, 162, 96, 164, 164, 198, 96, 168, 168, 202, 168, 204, 204, 230, + 96, 176, 176, 210, 176, 212, 212, 230, 176, 216, 216, 234, 216, 236, 236, 118, + }, { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 7, + 16, 17, 18, 19, 20, 21, 22, 7, 24, 25, 26, 11, 28, 13, 14, 23, + 32, 33, 34, 35, 36, 37, 38, 7, 40, 41, 42, 11, 44, 13, 14, 39, + 48, 49, 50, 19, 52, 21, 22, 39, 56, 25, 26, 43, 28, 45, 46, 55, + 64, 65, 66, 67, 68, 69, 70, 7, 72, 73, 74, 11, 76, 13, 14, 71, + 80, 81, 82, 19, 84, 21, 22, 71, 88, 25, 26, 75, 28, 77, 78, 87, + 96, 97, 98, 35, 100, 37, 38, 71, 104, 41, 42, 75, 44, 77, 78, 103, + 112, 49, 50, 83, 52, 85, 86, 103, 56, 89, 90, 107, 92, 109, 110, 119, + 128, 129, 130, 131, 132, 133, 134, 7, 136, 137, 138, 11, 140, 13, 14, 135, + 144, 145, 146, 19, 148, 21, 22, 135, 152, 25, 26, 139, 28, 141, 142, 151, + 160, 161, 162, 35, 164, 37, 38, 135, 168, 41, 42, 139, 44, 141, 142, 167, + 176, 49, 50, 147, 52, 149, 150, 167, 56, 153, 154, 171, 156, 173, 174, 183, + 192, 193, 194, 67, 196, 69, 70, 135, 200, 73, 74, 139, 76, 141, 142, 199, + 208, 81, 82, 147, 84, 149, 150, 199, 88, 153, 154, 203, 156, 205, 206, 215, + 224, 97, 98, 163, 100, 165, 166, 199, 104, 169, 170, 203, 172, 205, 206, 231, + 112, 177, 178, 211, 180, 213, 214, 231, 184, 217, 218, 235, 220, 237, 238, 119, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, + 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 16, 0, 16, 16, 24, + 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 32, 0, 32, 32, 40, + 0, 0, 0, 32, 0, 32, 32, 48, 0, 32, 32, 48, 32, 48, 48, 56, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 72, + 0, 0, 0, 64, 0, 64, 64, 80, 0, 64, 64, 80, 64, 80, 80, 88, + 0, 0, 0, 64, 0, 64, 64, 96, 0, 64, 64, 96, 64, 96, 96, 104, + 0, 64, 64, 96, 64, 96, 96, 112, 64, 96, 96, 112, 96, 112, 112, 120, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 136, + 0, 0, 0, 128, 0, 128, 128, 144, 0, 128, 128, 144, 128, 144, 144, 152, + 0, 0, 0, 128, 0, 128, 128, 160, 0, 128, 128, 160, 128, 160, 160, 168, + 0, 128, 128, 160, 128, 160, 160, 176, 128, 160, 160, 176, 160, 176, 176, 184, + 0, 0, 0, 128, 0, 128, 128, 192, 0, 128, 128, 192, 128, 192, 192, 200, + 0, 128, 128, 192, 128, 192, 192, 208, 128, 192, 192, 208, 192, 208, 208, 216, + 0, 128, 128, 192, 128, 192, 192, 224, 128, 192, 192, 224, 192, 224, 224, 232, + 128, 192, 192, 224, 192, 224, 224, 240, 192, 224, 224, 240, 224, 240, 240, 120, + }, { + 0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 9, + 16, 1, 2, 1, 4, 1, 2, 17, 8, 1, 2, 17, 4, 17, 18, 25, + 32, 1, 2, 1, 4, 1, 2, 33, 8, 1, 2, 33, 4, 33, 34, 41, + 16, 1, 2, 33, 4, 33, 34, 49, 8, 33, 34, 49, 36, 49, 50, 57, + 64, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 73, + 16, 1, 2, 65, 4, 65, 66, 81, 8, 65, 66, 81, 68, 81, 82, 89, + 32, 1, 2, 65, 4, 65, 66, 97, 8, 65, 66, 97, 68, 97, 98, 105, + 16, 65, 66, 97, 68, 97, 98, 113, 72, 97, 98, 113, 100, 113, 114, 121, + 128, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 137, + 16, 1, 2, 129, 4, 129, 130, 145, 8, 129, 130, 145, 132, 145, 146, 153, + 32, 1, 2, 129, 4, 129, 130, 161, 8, 129, 130, 161, 132, 161, 162, 169, + 16, 129, 130, 161, 132, 161, 162, 177, 136, 161, 162, 177, 164, 177, 178, 185, + 64, 1, 2, 129, 4, 129, 130, 193, 8, 129, 130, 193, 132, 193, 194, 201, + 16, 129, 130, 193, 132, 193, 194, 209, 136, 193, 194, 209, 196, 209, 210, 217, + 32, 129, 130, 193, 132, 193, 194, 225, 136, 193, 194, 225, 196, 225, 226, 233, + 144, 193, 194, 225, 196, 225, 226, 241, 200, 225, 226, 241, 228, 241, 242, 121, + }, { + 0, 0, 0, 2, 0, 4, 4, 2, 0, 8, 8, 2, 8, 4, 4, 10, + 0, 16, 16, 2, 16, 4, 4, 18, 16, 8, 8, 18, 8, 20, 20, 26, + 0, 32, 32, 2, 32, 4, 4, 34, 32, 8, 8, 34, 8, 36, 36, 42, + 32, 16, 16, 34, 16, 36, 36, 50, 16, 40, 40, 50, 40, 52, 52, 58, + 0, 64, 64, 2, 64, 4, 4, 66, 64, 8, 8, 66, 8, 68, 68, 74, + 64, 16, 16, 66, 16, 68, 68, 82, 16, 72, 72, 82, 72, 84, 84, 90, + 64, 32, 32, 66, 32, 68, 68, 98, 32, 72, 72, 98, 72, 100, 100, 106, + 32, 80, 80, 98, 80, 100, 100, 114, 80, 104, 104, 114, 104, 116, 116, 122, + 0, 128, 128, 2, 128, 4, 4, 130, 128, 8, 8, 130, 8, 132, 132, 138, + 128, 16, 16, 130, 16, 132, 132, 146, 16, 136, 136, 146, 136, 148, 148, 154, + 128, 32, 32, 130, 32, 132, 132, 162, 32, 136, 136, 162, 136, 164, 164, 170, + 32, 144, 144, 162, 144, 164, 164, 178, 144, 168, 168, 178, 168, 180, 180, 186, + 128, 64, 64, 130, 64, 132, 132, 194, 64, 136, 136, 194, 136, 196, 196, 202, + 64, 144, 144, 194, 144, 196, 196, 210, 144, 200, 200, 210, 200, 212, 212, 218, + 64, 160, 160, 194, 160, 196, 196, 226, 160, 200, 200, 226, 200, 228, 228, 234, + 160, 208, 208, 226, 208, 228, 228, 242, 208, 232, 232, 242, 232, 244, 244, 122, + }, { + 0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 10, 3, 12, 5, 6, 11, + 16, 17, 18, 3, 20, 5, 6, 19, 24, 9, 10, 19, 12, 21, 22, 27, + 32, 33, 34, 3, 36, 5, 6, 35, 40, 9, 10, 35, 12, 37, 38, 43, + 48, 17, 18, 35, 20, 37, 38, 51, 24, 41, 42, 51, 44, 53, 54, 59, + 64, 65, 66, 3, 68, 5, 6, 67, 72, 9, 10, 67, 12, 69, 70, 75, + 80, 17, 18, 67, 20, 69, 70, 83, 24, 73, 74, 83, 76, 85, 86, 91, + 96, 33, 34, 67, 36, 69, 70, 99, 40, 73, 74, 99, 76, 101, 102, 107, + 48, 81, 82, 99, 84, 101, 102, 115, 88, 105, 106, 115, 108, 117, 118, 123, + 128, 129, 130, 3, 132, 5, 6, 131, 136, 9, 10, 131, 12, 133, 134, 139, + 144, 17, 18, 131, 20, 133, 134, 147, 24, 137, 138, 147, 140, 149, 150, 155, + 160, 33, 34, 131, 36, 133, 134, 163, 40, 137, 138, 163, 140, 165, 166, 171, + 48, 145, 146, 163, 148, 165, 166, 179, 152, 169, 170, 179, 172, 181, 182, 187, + 192, 65, 66, 131, 68, 133, 134, 195, 72, 137, 138, 195, 140, 197, 198, 203, + 80, 145, 146, 195, 148, 197, 198, 211, 152, 201, 202, 211, 204, 213, 214, 219, + 96, 161, 162, 195, 164, 197, 198, 227, 168, 201, 202, 227, 204, 229, 230, 235, + 176, 209, 210, 227, 212, 229, 230, 243, 216, 233, 234, 243, 236, 245, 246, 123, + }, + { + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 8, 8, 12, + 0, 0, 0, 16, 0, 16, 16, 20, 0, 16, 16, 24, 16, 24, 24, 28, + 0, 0, 0, 32, 0, 32, 32, 36, 0, 32, 32, 40, 32, 40, 40, 44, + 0, 32, 32, 48, 32, 48, 48, 52, 32, 48, 48, 56, 48, 56, 56, 60, + 0, 0, 0, 64, 0, 64, 64, 68, 0, 64, 64, 72, 64, 72, 72, 76, + 0, 64, 64, 80, 64, 80, 80, 84, 64, 80, 80, 88, 80, 88, 88, 92, + 0, 64, 64, 96, 64, 96, 96, 100, 64, 96, 96, 104, 96, 104, 104, 108, + 64, 96, 96, 112, 96, 112, 112, 116, 96, 112, 112, 120, 112, 120, 120, 124, + 0, 0, 0, 128, 0, 128, 128, 132, 0, 128, 128, 136, 128, 136, 136, 140, + 0, 128, 128, 144, 128, 144, 144, 148, 128, 144, 144, 152, 144, 152, 152, 156, + 0, 128, 128, 160, 128, 160, 160, 164, 128, 160, 160, 168, 160, 168, 168, 172, + 128, 160, 160, 176, 160, 176, 176, 180, 160, 176, 176, 184, 176, 184, 184, 188, + 0, 128, 128, 192, 128, 192, 192, 196, 128, 192, 192, 200, 192, 200, 200, 204, + 128, 192, 192, 208, 192, 208, 208, 212, 192, 208, 208, 216, 208, 216, 216, 220, + 128, 192, 192, 224, 192, 224, 224, 228, 192, 224, 224, 232, 224, 232, 232, 236, + 192, 224, 224, 240, 224, 240, 240, 244, 224, 240, 240, 248, 240, 248, 248, 124, + }, { + 0, 1, 2, 1, 4, 1, 2, 5, 8, 1, 2, 9, 4, 9, 10, 13, + 16, 1, 2, 17, 4, 17, 18, 21, 8, 17, 18, 25, 20, 25, 26, 29, + 32, 1, 2, 33, 4, 33, 34, 37, 8, 33, 34, 41, 36, 41, 42, 45, + 16, 33, 34, 49, 36, 49, 50, 53, 40, 49, 50, 57, 52, 57, 58, 61, + 64, 1, 2, 65, 4, 65, 66, 69, 8, 65, 66, 73, 68, 73, 74, 77, + 16, 65, 66, 81, 68, 81, 82, 85, 72, 81, 82, 89, 84, 89, 90, 93, + 32, 65, 66, 97, 68, 97, 98, 101, 72, 97, 98, 105, 100, 105, 106, 109, + 80, 97, 98, 113, 100, 113, 114, 117, 104, 113, 114, 121, 116, 121, 122, 125, + 128, 1, 2, 129, 4, 129, 130, 133, 8, 129, 130, 137, 132, 137, 138, 141, + 16, 129, 130, 145, 132, 145, 146, 149, 136, 145, 146, 153, 148, 153, 154, 157, + 32, 129, 130, 161, 132, 161, 162, 165, 136, 161, 162, 169, 164, 169, 170, 173, + 144, 161, 162, 177, 164, 177, 178, 181, 168, 177, 178, 185, 180, 185, 186, 189, + 64, 129, 130, 193, 132, 193, 194, 197, 136, 193, 194, 201, 196, 201, 202, 205, + 144, 193, 194, 209, 196, 209, 210, 213, 200, 209, 210, 217, 212, 217, 218, 221, + 160, 193, 194, 225, 196, 225, 226, 229, 200, 225, 226, 233, 228, 233, 234, 237, + 208, 225, 226, 241, 228, 241, 242, 245, 232, 241, 242, 249, 244, 249, 250, 125, + }, { + 0, 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10, 8, 12, 12, 14, + 0, 16, 16, 18, 16, 20, 20, 22, 16, 24, 24, 26, 24, 28, 28, 30, + 0, 32, 32, 34, 32, 36, 36, 38, 32, 40, 40, 42, 40, 44, 44, 46, + 32, 48, 48, 50, 48, 52, 52, 54, 48, 56, 56, 58, 56, 60, 60, 62, + 0, 64, 64, 66, 64, 68, 68, 70, 64, 72, 72, 74, 72, 76, 76, 78, + 64, 80, 80, 82, 80, 84, 84, 86, 80, 88, 88, 90, 88, 92, 92, 94, + 64, 96, 96, 98, 96, 100, 100, 102, 96, 104, 104, 106, 104, 108, 108, 110, + 96, 112, 112, 114, 112, 116, 116, 118, 112, 120, 120, 122, 120, 124, 124, 126, + 0, 128, 128, 130, 128, 132, 132, 134, 128, 136, 136, 138, 136, 140, 140, 142, + 128, 144, 144, 146, 144, 148, 148, 150, 144, 152, 152, 154, 152, 156, 156, 158, + 128, 160, 160, 162, 160, 164, 164, 166, 160, 168, 168, 170, 168, 172, 172, 174, + 160, 176, 176, 178, 176, 180, 180, 182, 176, 184, 184, 186, 184, 188, 188, 190, + 128, 192, 192, 194, 192, 196, 196, 198, 192, 200, 200, 202, 200, 204, 204, 206, + 192, 208, 208, 210, 208, 212, 212, 214, 208, 216, 216, 218, 216, 220, 220, 222, + 192, 224, 224, 226, 224, 228, 228, 230, 224, 232, 232, 234, 232, 236, 236, 238, + 224, 240, 240, 242, 240, 244, 244, 246, 240, 248, 248, 250, 248, 252, 252, 126, + }, { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, + 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, + 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, + 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, + 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 127, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, + }, { + 0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 64, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 128, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 64, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 129, + }, { + 0, 0, 0, 2, 0, 4, 4, 2, 0, 8, 8, 2, 8, 4, 4, 2, + 0, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 2, + 0, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 2, + 32, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 2, + 0, 64, 64, 2, 64, 4, 4, 2, 64, 8, 8, 2, 8, 4, 4, 2, + 64, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 2, + 64, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 2, + 32, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 2, + 0, 128, 128, 2, 128, 4, 4, 2, 128, 8, 8, 2, 8, 4, 4, 2, + 128, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 2, + 128, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 2, + 32, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 2, + 128, 64, 64, 2, 64, 4, 4, 2, 64, 8, 8, 2, 8, 4, 4, 2, + 64, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 2, + 64, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 2, + 32, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 130, + }, { + 0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 10, 3, 12, 5, 6, 3, + 16, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 3, + 32, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 3, + 48, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 3, + 64, 65, 66, 3, 68, 5, 6, 3, 72, 9, 10, 3, 12, 5, 6, 3, + 80, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 3, + 96, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 3, + 48, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 3, + 128, 129, 130, 3, 132, 5, 6, 3, 136, 9, 10, 3, 12, 5, 6, 3, + 144, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 3, + 160, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 3, + 48, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 3, + 192, 65, 66, 3, 68, 5, 6, 3, 72, 9, 10, 3, 12, 5, 6, 3, + 80, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 3, + 96, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 3, + 48, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 131, + }, + { + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 8, 8, 4, + 0, 0, 0, 16, 0, 16, 16, 4, 0, 16, 16, 8, 16, 8, 8, 4, + 0, 0, 0, 32, 0, 32, 32, 4, 0, 32, 32, 8, 32, 8, 8, 4, + 0, 32, 32, 16, 32, 16, 16, 4, 32, 16, 16, 8, 16, 8, 8, 4, + 0, 0, 0, 64, 0, 64, 64, 4, 0, 64, 64, 8, 64, 8, 8, 4, + 0, 64, 64, 16, 64, 16, 16, 4, 64, 16, 16, 8, 16, 8, 8, 4, + 0, 64, 64, 32, 64, 32, 32, 4, 64, 32, 32, 8, 32, 8, 8, 4, + 64, 32, 32, 16, 32, 16, 16, 4, 32, 16, 16, 8, 16, 8, 8, 4, + 0, 0, 0, 128, 0, 128, 128, 4, 0, 128, 128, 8, 128, 8, 8, 4, + 0, 128, 128, 16, 128, 16, 16, 4, 128, 16, 16, 8, 16, 8, 8, 4, + 0, 128, 128, 32, 128, 32, 32, 4, 128, 32, 32, 8, 32, 8, 8, 4, + 128, 32, 32, 16, 32, 16, 16, 4, 32, 16, 16, 8, 16, 8, 8, 4, + 0, 128, 128, 64, 128, 64, 64, 4, 128, 64, 64, 8, 64, 8, 8, 4, + 128, 64, 64, 16, 64, 16, 16, 4, 64, 16, 16, 8, 16, 8, 8, 4, + 128, 64, 64, 32, 64, 32, 32, 4, 64, 32, 32, 8, 32, 8, 8, 4, + 64, 32, 32, 16, 32, 16, 16, 4, 32, 16, 16, 8, 16, 8, 8, 132, + }, { + 0, 1, 2, 1, 4, 1, 2, 5, 8, 1, 2, 9, 4, 9, 10, 5, + 16, 1, 2, 17, 4, 17, 18, 5, 8, 17, 18, 9, 20, 9, 10, 5, + 32, 1, 2, 33, 4, 33, 34, 5, 8, 33, 34, 9, 36, 9, 10, 5, + 16, 33, 34, 17, 36, 17, 18, 5, 40, 17, 18, 9, 20, 9, 10, 5, + 64, 1, 2, 65, 4, 65, 66, 5, 8, 65, 66, 9, 68, 9, 10, 5, + 16, 65, 66, 17, 68, 17, 18, 5, 72, 17, 18, 9, 20, 9, 10, 5, + 32, 65, 66, 33, 68, 33, 34, 5, 72, 33, 34, 9, 36, 9, 10, 5, + 80, 33, 34, 17, 36, 17, 18, 5, 40, 17, 18, 9, 20, 9, 10, 5, + 128, 1, 2, 129, 4, 129, 130, 5, 8, 129, 130, 9, 132, 9, 10, 5, + 16, 129, 130, 17, 132, 17, 18, 5, 136, 17, 18, 9, 20, 9, 10, 5, + 32, 129, 130, 33, 132, 33, 34, 5, 136, 33, 34, 9, 36, 9, 10, 5, + 144, 33, 34, 17, 36, 17, 18, 5, 40, 17, 18, 9, 20, 9, 10, 5, + 64, 129, 130, 65, 132, 65, 66, 5, 136, 65, 66, 9, 68, 9, 10, 5, + 144, 65, 66, 17, 68, 17, 18, 5, 72, 17, 18, 9, 20, 9, 10, 5, + 160, 65, 66, 33, 68, 33, 34, 5, 72, 33, 34, 9, 36, 9, 10, 5, + 80, 33, 34, 17, 36, 17, 18, 5, 40, 17, 18, 9, 20, 9, 10, 133, + }, { + 0, 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10, 8, 12, 12, 6, + 0, 16, 16, 18, 16, 20, 20, 6, 16, 24, 24, 10, 24, 12, 12, 6, + 0, 32, 32, 34, 32, 36, 36, 6, 32, 40, 40, 10, 40, 12, 12, 6, + 32, 48, 48, 18, 48, 20, 20, 6, 48, 24, 24, 10, 24, 12, 12, 6, + 0, 64, 64, 66, 64, 68, 68, 6, 64, 72, 72, 10, 72, 12, 12, 6, + 64, 80, 80, 18, 80, 20, 20, 6, 80, 24, 24, 10, 24, 12, 12, 6, + 64, 96, 96, 34, 96, 36, 36, 6, 96, 40, 40, 10, 40, 12, 12, 6, + 96, 48, 48, 18, 48, 20, 20, 6, 48, 24, 24, 10, 24, 12, 12, 6, + 0, 128, 128, 130, 128, 132, 132, 6, 128, 136, 136, 10, 136, 12, 12, 6, + 128, 144, 144, 18, 144, 20, 20, 6, 144, 24, 24, 10, 24, 12, 12, 6, + 128, 160, 160, 34, 160, 36, 36, 6, 160, 40, 40, 10, 40, 12, 12, 6, + 160, 48, 48, 18, 48, 20, 20, 6, 48, 24, 24, 10, 24, 12, 12, 6, + 128, 192, 192, 66, 192, 68, 68, 6, 192, 72, 72, 10, 72, 12, 12, 6, + 192, 80, 80, 18, 80, 20, 20, 6, 80, 24, 24, 10, 24, 12, 12, 6, + 192, 96, 96, 34, 96, 36, 36, 6, 96, 40, 40, 10, 40, 12, 12, 6, + 96, 48, 48, 18, 48, 20, 20, 6, 48, 24, 24, 10, 24, 12, 12, 134, + }, { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 7, + 16, 17, 18, 19, 20, 21, 22, 7, 24, 25, 26, 11, 28, 13, 14, 7, + 32, 33, 34, 35, 36, 37, 38, 7, 40, 41, 42, 11, 44, 13, 14, 7, + 48, 49, 50, 19, 52, 21, 22, 7, 56, 25, 26, 11, 28, 13, 14, 7, + 64, 65, 66, 67, 68, 69, 70, 7, 72, 73, 74, 11, 76, 13, 14, 7, + 80, 81, 82, 19, 84, 21, 22, 7, 88, 25, 26, 11, 28, 13, 14, 7, + 96, 97, 98, 35, 100, 37, 38, 7, 104, 41, 42, 11, 44, 13, 14, 7, + 112, 49, 50, 19, 52, 21, 22, 7, 56, 25, 26, 11, 28, 13, 14, 7, + 128, 129, 130, 131, 132, 133, 134, 7, 136, 137, 138, 11, 140, 13, 14, 7, + 144, 145, 146, 19, 148, 21, 22, 7, 152, 25, 26, 11, 28, 13, 14, 7, + 160, 161, 162, 35, 164, 37, 38, 7, 168, 41, 42, 11, 44, 13, 14, 7, + 176, 49, 50, 19, 52, 21, 22, 7, 56, 25, 26, 11, 28, 13, 14, 7, + 192, 193, 194, 67, 196, 69, 70, 7, 200, 73, 74, 11, 76, 13, 14, 7, + 208, 81, 82, 19, 84, 21, 22, 7, 88, 25, 26, 11, 28, 13, 14, 7, + 224, 97, 98, 35, 100, 37, 38, 7, 104, 41, 42, 11, 44, 13, 14, 7, + 112, 49, 50, 19, 52, 21, 22, 7, 56, 25, 26, 11, 28, 13, 14, 135, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, + 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 16, 0, 16, 16, 8, + 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 32, 0, 32, 32, 8, + 0, 0, 0, 32, 0, 32, 32, 16, 0, 32, 32, 16, 32, 16, 16, 8, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 8, + 0, 0, 0, 64, 0, 64, 64, 16, 0, 64, 64, 16, 64, 16, 16, 8, + 0, 0, 0, 64, 0, 64, 64, 32, 0, 64, 64, 32, 64, 32, 32, 8, + 0, 64, 64, 32, 64, 32, 32, 16, 64, 32, 32, 16, 32, 16, 16, 8, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 8, + 0, 0, 0, 128, 0, 128, 128, 16, 0, 128, 128, 16, 128, 16, 16, 8, + 0, 0, 0, 128, 0, 128, 128, 32, 0, 128, 128, 32, 128, 32, 32, 8, + 0, 128, 128, 32, 128, 32, 32, 16, 128, 32, 32, 16, 32, 16, 16, 8, + 0, 0, 0, 128, 0, 128, 128, 64, 0, 128, 128, 64, 128, 64, 64, 8, + 0, 128, 128, 64, 128, 64, 64, 16, 128, 64, 64, 16, 64, 16, 16, 8, + 0, 128, 128, 64, 128, 64, 64, 32, 128, 64, 64, 32, 64, 32, 32, 8, + 128, 64, 64, 32, 64, 32, 32, 16, 64, 32, 32, 16, 32, 16, 16, 136, + }, { + 0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 9, + 16, 1, 2, 1, 4, 1, 2, 17, 8, 1, 2, 17, 4, 17, 18, 9, + 32, 1, 2, 1, 4, 1, 2, 33, 8, 1, 2, 33, 4, 33, 34, 9, + 16, 1, 2, 33, 4, 33, 34, 17, 8, 33, 34, 17, 36, 17, 18, 9, + 64, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 9, + 16, 1, 2, 65, 4, 65, 66, 17, 8, 65, 66, 17, 68, 17, 18, 9, + 32, 1, 2, 65, 4, 65, 66, 33, 8, 65, 66, 33, 68, 33, 34, 9, + 16, 65, 66, 33, 68, 33, 34, 17, 72, 33, 34, 17, 36, 17, 18, 9, + 128, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 9, + 16, 1, 2, 129, 4, 129, 130, 17, 8, 129, 130, 17, 132, 17, 18, 9, + 32, 1, 2, 129, 4, 129, 130, 33, 8, 129, 130, 33, 132, 33, 34, 9, + 16, 129, 130, 33, 132, 33, 34, 17, 136, 33, 34, 17, 36, 17, 18, 9, + 64, 1, 2, 129, 4, 129, 130, 65, 8, 129, 130, 65, 132, 65, 66, 9, + 16, 129, 130, 65, 132, 65, 66, 17, 136, 65, 66, 17, 68, 17, 18, 9, + 32, 129, 130, 65, 132, 65, 66, 33, 136, 65, 66, 33, 68, 33, 34, 9, + 144, 65, 66, 33, 68, 33, 34, 17, 72, 33, 34, 17, 36, 17, 18, 137, + }, { + 0, 0, 0, 2, 0, 4, 4, 2, 0, 8, 8, 2, 8, 4, 4, 10, + 0, 16, 16, 2, 16, 4, 4, 18, 16, 8, 8, 18, 8, 20, 20, 10, + 0, 32, 32, 2, 32, 4, 4, 34, 32, 8, 8, 34, 8, 36, 36, 10, + 32, 16, 16, 34, 16, 36, 36, 18, 16, 40, 40, 18, 40, 20, 20, 10, + 0, 64, 64, 2, 64, 4, 4, 66, 64, 8, 8, 66, 8, 68, 68, 10, + 64, 16, 16, 66, 16, 68, 68, 18, 16, 72, 72, 18, 72, 20, 20, 10, + 64, 32, 32, 66, 32, 68, 68, 34, 32, 72, 72, 34, 72, 36, 36, 10, + 32, 80, 80, 34, 80, 36, 36, 18, 80, 40, 40, 18, 40, 20, 20, 10, + 0, 128, 128, 2, 128, 4, 4, 130, 128, 8, 8, 130, 8, 132, 132, 10, + 128, 16, 16, 130, 16, 132, 132, 18, 16, 136, 136, 18, 136, 20, 20, 10, + 128, 32, 32, 130, 32, 132, 132, 34, 32, 136, 136, 34, 136, 36, 36, 10, + 32, 144, 144, 34, 144, 36, 36, 18, 144, 40, 40, 18, 40, 20, 20, 10, + 128, 64, 64, 130, 64, 132, 132, 66, 64, 136, 136, 66, 136, 68, 68, 10, + 64, 144, 144, 66, 144, 68, 68, 18, 144, 72, 72, 18, 72, 20, 20, 10, + 64, 160, 160, 66, 160, 68, 68, 34, 160, 72, 72, 34, 72, 36, 36, 10, + 160, 80, 80, 34, 80, 36, 36, 18, 80, 40, 40, 18, 40, 20, 20, 138, + }, { + 0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 10, 3, 12, 5, 6, 11, + 16, 17, 18, 3, 20, 5, 6, 19, 24, 9, 10, 19, 12, 21, 22, 11, + 32, 33, 34, 3, 36, 5, 6, 35, 40, 9, 10, 35, 12, 37, 38, 11, + 48, 17, 18, 35, 20, 37, 38, 19, 24, 41, 42, 19, 44, 21, 22, 11, + 64, 65, 66, 3, 68, 5, 6, 67, 72, 9, 10, 67, 12, 69, 70, 11, + 80, 17, 18, 67, 20, 69, 70, 19, 24, 73, 74, 19, 76, 21, 22, 11, + 96, 33, 34, 67, 36, 69, 70, 35, 40, 73, 74, 35, 76, 37, 38, 11, + 48, 81, 82, 35, 84, 37, 38, 19, 88, 41, 42, 19, 44, 21, 22, 11, + 128, 129, 130, 3, 132, 5, 6, 131, 136, 9, 10, 131, 12, 133, 134, 11, + 144, 17, 18, 131, 20, 133, 134, 19, 24, 137, 138, 19, 140, 21, 22, 11, + 160, 33, 34, 131, 36, 133, 134, 35, 40, 137, 138, 35, 140, 37, 38, 11, + 48, 145, 146, 35, 148, 37, 38, 19, 152, 41, 42, 19, 44, 21, 22, 11, + 192, 65, 66, 131, 68, 133, 134, 67, 72, 137, 138, 67, 140, 69, 70, 11, + 80, 145, 146, 67, 148, 69, 70, 19, 152, 73, 74, 19, 76, 21, 22, 11, + 96, 161, 162, 67, 164, 69, 70, 35, 168, 73, 74, 35, 76, 37, 38, 11, + 176, 81, 82, 35, 84, 37, 38, 19, 88, 41, 42, 19, 44, 21, 22, 139, + }, + { + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 8, 8, 12, + 0, 0, 0, 16, 0, 16, 16, 20, 0, 16, 16, 24, 16, 24, 24, 12, + 0, 0, 0, 32, 0, 32, 32, 36, 0, 32, 32, 40, 32, 40, 40, 12, + 0, 32, 32, 48, 32, 48, 48, 20, 32, 48, 48, 24, 48, 24, 24, 12, + 0, 0, 0, 64, 0, 64, 64, 68, 0, 64, 64, 72, 64, 72, 72, 12, + 0, 64, 64, 80, 64, 80, 80, 20, 64, 80, 80, 24, 80, 24, 24, 12, + 0, 64, 64, 96, 64, 96, 96, 36, 64, 96, 96, 40, 96, 40, 40, 12, + 64, 96, 96, 48, 96, 48, 48, 20, 96, 48, 48, 24, 48, 24, 24, 12, + 0, 0, 0, 128, 0, 128, 128, 132, 0, 128, 128, 136, 128, 136, 136, 12, + 0, 128, 128, 144, 128, 144, 144, 20, 128, 144, 144, 24, 144, 24, 24, 12, + 0, 128, 128, 160, 128, 160, 160, 36, 128, 160, 160, 40, 160, 40, 40, 12, + 128, 160, 160, 48, 160, 48, 48, 20, 160, 48, 48, 24, 48, 24, 24, 12, + 0, 128, 128, 192, 128, 192, 192, 68, 128, 192, 192, 72, 192, 72, 72, 12, + 128, 192, 192, 80, 192, 80, 80, 20, 192, 80, 80, 24, 80, 24, 24, 12, + 128, 192, 192, 96, 192, 96, 96, 36, 192, 96, 96, 40, 96, 40, 40, 12, + 192, 96, 96, 48, 96, 48, 48, 20, 96, 48, 48, 24, 48, 24, 24, 140, + }, { + 0, 1, 2, 1, 4, 1, 2, 5, 8, 1, 2, 9, 4, 9, 10, 13, + 16, 1, 2, 17, 4, 17, 18, 21, 8, 17, 18, 25, 20, 25, 26, 13, + 32, 1, 2, 33, 4, 33, 34, 37, 8, 33, 34, 41, 36, 41, 42, 13, + 16, 33, 34, 49, 36, 49, 50, 21, 40, 49, 50, 25, 52, 25, 26, 13, + 64, 1, 2, 65, 4, 65, 66, 69, 8, 65, 66, 73, 68, 73, 74, 13, + 16, 65, 66, 81, 68, 81, 82, 21, 72, 81, 82, 25, 84, 25, 26, 13, + 32, 65, 66, 97, 68, 97, 98, 37, 72, 97, 98, 41, 100, 41, 42, 13, + 80, 97, 98, 49, 100, 49, 50, 21, 104, 49, 50, 25, 52, 25, 26, 13, + 128, 1, 2, 129, 4, 129, 130, 133, 8, 129, 130, 137, 132, 137, 138, 13, + 16, 129, 130, 145, 132, 145, 146, 21, 136, 145, 146, 25, 148, 25, 26, 13, + 32, 129, 130, 161, 132, 161, 162, 37, 136, 161, 162, 41, 164, 41, 42, 13, + 144, 161, 162, 49, 164, 49, 50, 21, 168, 49, 50, 25, 52, 25, 26, 13, + 64, 129, 130, 193, 132, 193, 194, 69, 136, 193, 194, 73, 196, 73, 74, 13, + 144, 193, 194, 81, 196, 81, 82, 21, 200, 81, 82, 25, 84, 25, 26, 13, + 160, 193, 194, 97, 196, 97, 98, 37, 200, 97, 98, 41, 100, 41, 42, 13, + 208, 97, 98, 49, 100, 49, 50, 21, 104, 49, 50, 25, 52, 25, 26, 141, + }, { + 0, 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10, 8, 12, 12, 14, + 0, 16, 16, 18, 16, 20, 20, 22, 16, 24, 24, 26, 24, 28, 28, 14, + 0, 32, 32, 34, 32, 36, 36, 38, 32, 40, 40, 42, 40, 44, 44, 14, + 32, 48, 48, 50, 48, 52, 52, 22, 48, 56, 56, 26, 56, 28, 28, 14, + 0, 64, 64, 66, 64, 68, 68, 70, 64, 72, 72, 74, 72, 76, 76, 14, + 64, 80, 80, 82, 80, 84, 84, 22, 80, 88, 88, 26, 88, 28, 28, 14, + 64, 96, 96, 98, 96, 100, 100, 38, 96, 104, 104, 42, 104, 44, 44, 14, + 96, 112, 112, 50, 112, 52, 52, 22, 112, 56, 56, 26, 56, 28, 28, 14, + 0, 128, 128, 130, 128, 132, 132, 134, 128, 136, 136, 138, 136, 140, 140, 14, + 128, 144, 144, 146, 144, 148, 148, 22, 144, 152, 152, 26, 152, 28, 28, 14, + 128, 160, 160, 162, 160, 164, 164, 38, 160, 168, 168, 42, 168, 44, 44, 14, + 160, 176, 176, 50, 176, 52, 52, 22, 176, 56, 56, 26, 56, 28, 28, 14, + 128, 192, 192, 194, 192, 196, 196, 70, 192, 200, 200, 74, 200, 76, 76, 14, + 192, 208, 208, 82, 208, 84, 84, 22, 208, 88, 88, 26, 88, 28, 28, 14, + 192, 224, 224, 98, 224, 100, 100, 38, 224, 104, 104, 42, 104, 44, 44, 14, + 224, 112, 112, 50, 112, 52, 52, 22, 112, 56, 56, 26, 56, 28, 28, 142, + }, { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 15, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 15, + 48, 49, 50, 51, 52, 53, 54, 23, 56, 57, 58, 27, 60, 29, 30, 15, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 15, + 80, 81, 82, 83, 84, 85, 86, 23, 88, 89, 90, 27, 92, 29, 30, 15, + 96, 97, 98, 99, 100, 101, 102, 39, 104, 105, 106, 43, 108, 45, 46, 15, + 112, 113, 114, 51, 116, 53, 54, 23, 120, 57, 58, 27, 60, 29, 30, 15, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 15, + 144, 145, 146, 147, 148, 149, 150, 23, 152, 153, 154, 27, 156, 29, 30, 15, + 160, 161, 162, 163, 164, 165, 166, 39, 168, 169, 170, 43, 172, 45, 46, 15, + 176, 177, 178, 51, 180, 53, 54, 23, 184, 57, 58, 27, 60, 29, 30, 15, + 192, 193, 194, 195, 196, 197, 198, 71, 200, 201, 202, 75, 204, 77, 78, 15, + 208, 209, 210, 83, 212, 85, 86, 23, 216, 89, 90, 27, 92, 29, 30, 15, + 224, 225, 226, 99, 228, 101, 102, 39, 232, 105, 106, 43, 108, 45, 46, 15, + 240, 113, 114, 51, 116, 53, 54, 23, 120, 57, 58, 27, 60, 29, 30, 143, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, + 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 32, 0, 32, 32, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 16, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 32, + 0, 0, 0, 64, 0, 64, 64, 32, 0, 64, 64, 32, 64, 32, 32, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 16, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 32, + 0, 0, 0, 128, 0, 128, 128, 32, 0, 128, 128, 32, 128, 32, 32, 16, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 64, + 0, 0, 0, 128, 0, 128, 128, 64, 0, 128, 128, 64, 128, 64, 64, 16, + 0, 0, 0, 128, 0, 128, 128, 64, 0, 128, 128, 64, 128, 64, 64, 32, + 0, 128, 128, 64, 128, 64, 64, 32, 128, 64, 64, 32, 64, 32, 32, 144, + }, { + 0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 17, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 33, + 16, 1, 2, 1, 4, 1, 2, 33, 8, 1, 2, 33, 4, 33, 34, 17, + 64, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 65, + 16, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 17, + 32, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 33, + 16, 1, 2, 65, 4, 65, 66, 33, 8, 65, 66, 33, 68, 33, 34, 17, + 128, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 129, + 16, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 17, + 32, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 33, + 16, 1, 2, 129, 4, 129, 130, 33, 8, 129, 130, 33, 132, 33, 34, 17, + 64, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 65, + 16, 1, 2, 129, 4, 129, 130, 65, 8, 129, 130, 65, 132, 65, 66, 17, + 32, 1, 2, 129, 4, 129, 130, 65, 8, 129, 130, 65, 132, 65, 66, 33, + 16, 129, 130, 65, 132, 65, 66, 33, 136, 65, 66, 33, 68, 33, 34, 145, + }, { + 0, 0, 0, 2, 0, 4, 4, 2, 0, 8, 8, 2, 8, 4, 4, 2, + 0, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 18, + 0, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 34, + 32, 16, 16, 2, 16, 4, 4, 34, 16, 8, 8, 34, 8, 36, 36, 18, + 0, 64, 64, 2, 64, 4, 4, 2, 64, 8, 8, 2, 8, 4, 4, 66, + 64, 16, 16, 2, 16, 4, 4, 66, 16, 8, 8, 66, 8, 68, 68, 18, + 64, 32, 32, 2, 32, 4, 4, 66, 32, 8, 8, 66, 8, 68, 68, 34, + 32, 16, 16, 66, 16, 68, 68, 34, 16, 72, 72, 34, 72, 36, 36, 18, + 0, 128, 128, 2, 128, 4, 4, 2, 128, 8, 8, 2, 8, 4, 4, 130, + 128, 16, 16, 2, 16, 4, 4, 130, 16, 8, 8, 130, 8, 132, 132, 18, + 128, 32, 32, 2, 32, 4, 4, 130, 32, 8, 8, 130, 8, 132, 132, 34, + 32, 16, 16, 130, 16, 132, 132, 34, 16, 136, 136, 34, 136, 36, 36, 18, + 128, 64, 64, 2, 64, 4, 4, 130, 64, 8, 8, 130, 8, 132, 132, 66, + 64, 16, 16, 130, 16, 132, 132, 66, 16, 136, 136, 66, 136, 68, 68, 18, + 64, 32, 32, 130, 32, 132, 132, 66, 32, 136, 136, 66, 136, 68, 68, 34, + 32, 144, 144, 66, 144, 68, 68, 34, 144, 72, 72, 34, 72, 36, 36, 146, + }, { + 0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 10, 3, 12, 5, 6, 3, + 16, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 19, + 32, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 35, + 48, 17, 18, 3, 20, 5, 6, 35, 24, 9, 10, 35, 12, 37, 38, 19, + 64, 65, 66, 3, 68, 5, 6, 3, 72, 9, 10, 3, 12, 5, 6, 67, + 80, 17, 18, 3, 20, 5, 6, 67, 24, 9, 10, 67, 12, 69, 70, 19, + 96, 33, 34, 3, 36, 5, 6, 67, 40, 9, 10, 67, 12, 69, 70, 35, + 48, 17, 18, 67, 20, 69, 70, 35, 24, 73, 74, 35, 76, 37, 38, 19, + 128, 129, 130, 3, 132, 5, 6, 3, 136, 9, 10, 3, 12, 5, 6, 131, + 144, 17, 18, 3, 20, 5, 6, 131, 24, 9, 10, 131, 12, 133, 134, 19, + 160, 33, 34, 3, 36, 5, 6, 131, 40, 9, 10, 131, 12, 133, 134, 35, + 48, 17, 18, 131, 20, 133, 134, 35, 24, 137, 138, 35, 140, 37, 38, 19, + 192, 65, 66, 3, 68, 5, 6, 131, 72, 9, 10, 131, 12, 133, 134, 67, + 80, 17, 18, 131, 20, 133, 134, 67, 24, 137, 138, 67, 140, 69, 70, 19, + 96, 33, 34, 131, 36, 133, 134, 67, 40, 137, 138, 67, 140, 69, 70, 35, + 48, 145, 146, 67, 148, 69, 70, 35, 152, 73, 74, 35, 76, 37, 38, 147, + }, + { + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 8, 8, 4, + 0, 0, 0, 16, 0, 16, 16, 4, 0, 16, 16, 8, 16, 8, 8, 20, + 0, 0, 0, 32, 0, 32, 32, 4, 0, 32, 32, 8, 32, 8, 8, 36, + 0, 32, 32, 16, 32, 16, 16, 36, 32, 16, 16, 40, 16, 40, 40, 20, + 0, 0, 0, 64, 0, 64, 64, 4, 0, 64, 64, 8, 64, 8, 8, 68, + 0, 64, 64, 16, 64, 16, 16, 68, 64, 16, 16, 72, 16, 72, 72, 20, + 0, 64, 64, 32, 64, 32, 32, 68, 64, 32, 32, 72, 32, 72, 72, 36, + 64, 32, 32, 80, 32, 80, 80, 36, 32, 80, 80, 40, 80, 40, 40, 20, + 0, 0, 0, 128, 0, 128, 128, 4, 0, 128, 128, 8, 128, 8, 8, 132, + 0, 128, 128, 16, 128, 16, 16, 132, 128, 16, 16, 136, 16, 136, 136, 20, + 0, 128, 128, 32, 128, 32, 32, 132, 128, 32, 32, 136, 32, 136, 136, 36, + 128, 32, 32, 144, 32, 144, 144, 36, 32, 144, 144, 40, 144, 40, 40, 20, + 0, 128, 128, 64, 128, 64, 64, 132, 128, 64, 64, 136, 64, 136, 136, 68, + 128, 64, 64, 144, 64, 144, 144, 68, 64, 144, 144, 72, 144, 72, 72, 20, + 128, 64, 64, 160, 64, 160, 160, 68, 64, 160, 160, 72, 160, 72, 72, 36, + 64, 160, 160, 80, 160, 80, 80, 36, 160, 80, 80, 40, 80, 40, 40, 148, + }, { + 0, 1, 2, 1, 4, 1, 2, 5, 8, 1, 2, 9, 4, 9, 10, 5, + 16, 1, 2, 17, 4, 17, 18, 5, 8, 17, 18, 9, 20, 9, 10, 21, + 32, 1, 2, 33, 4, 33, 34, 5, 8, 33, 34, 9, 36, 9, 10, 37, + 16, 33, 34, 17, 36, 17, 18, 37, 40, 17, 18, 41, 20, 41, 42, 21, + 64, 1, 2, 65, 4, 65, 66, 5, 8, 65, 66, 9, 68, 9, 10, 69, + 16, 65, 66, 17, 68, 17, 18, 69, 72, 17, 18, 73, 20, 73, 74, 21, + 32, 65, 66, 33, 68, 33, 34, 69, 72, 33, 34, 73, 36, 73, 74, 37, + 80, 33, 34, 81, 36, 81, 82, 37, 40, 81, 82, 41, 84, 41, 42, 21, + 128, 1, 2, 129, 4, 129, 130, 5, 8, 129, 130, 9, 132, 9, 10, 133, + 16, 129, 130, 17, 132, 17, 18, 133, 136, 17, 18, 137, 20, 137, 138, 21, + 32, 129, 130, 33, 132, 33, 34, 133, 136, 33, 34, 137, 36, 137, 138, 37, + 144, 33, 34, 145, 36, 145, 146, 37, 40, 145, 146, 41, 148, 41, 42, 21, + 64, 129, 130, 65, 132, 65, 66, 133, 136, 65, 66, 137, 68, 137, 138, 69, + 144, 65, 66, 145, 68, 145, 146, 69, 72, 145, 146, 73, 148, 73, 74, 21, + 160, 65, 66, 161, 68, 161, 162, 69, 72, 161, 162, 73, 164, 73, 74, 37, + 80, 161, 162, 81, 164, 81, 82, 37, 168, 81, 82, 41, 84, 41, 42, 149, + }, { + 0, 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10, 8, 12, 12, 6, + 0, 16, 16, 18, 16, 20, 20, 6, 16, 24, 24, 10, 24, 12, 12, 22, + 0, 32, 32, 34, 32, 36, 36, 6, 32, 40, 40, 10, 40, 12, 12, 38, + 32, 48, 48, 18, 48, 20, 20, 38, 48, 24, 24, 42, 24, 44, 44, 22, + 0, 64, 64, 66, 64, 68, 68, 6, 64, 72, 72, 10, 72, 12, 12, 70, + 64, 80, 80, 18, 80, 20, 20, 70, 80, 24, 24, 74, 24, 76, 76, 22, + 64, 96, 96, 34, 96, 36, 36, 70, 96, 40, 40, 74, 40, 76, 76, 38, + 96, 48, 48, 82, 48, 84, 84, 38, 48, 88, 88, 42, 88, 44, 44, 22, + 0, 128, 128, 130, 128, 132, 132, 6, 128, 136, 136, 10, 136, 12, 12, 134, + 128, 144, 144, 18, 144, 20, 20, 134, 144, 24, 24, 138, 24, 140, 140, 22, + 128, 160, 160, 34, 160, 36, 36, 134, 160, 40, 40, 138, 40, 140, 140, 38, + 160, 48, 48, 146, 48, 148, 148, 38, 48, 152, 152, 42, 152, 44, 44, 22, + 128, 192, 192, 66, 192, 68, 68, 134, 192, 72, 72, 138, 72, 140, 140, 70, + 192, 80, 80, 146, 80, 148, 148, 70, 80, 152, 152, 74, 152, 76, 76, 22, + 192, 96, 96, 162, 96, 164, 164, 70, 96, 168, 168, 74, 168, 76, 76, 38, + 96, 176, 176, 82, 176, 84, 84, 38, 176, 88, 88, 42, 88, 44, 44, 150, + }, { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 7, + 16, 17, 18, 19, 20, 21, 22, 7, 24, 25, 26, 11, 28, 13, 14, 23, + 32, 33, 34, 35, 36, 37, 38, 7, 40, 41, 42, 11, 44, 13, 14, 39, + 48, 49, 50, 19, 52, 21, 22, 39, 56, 25, 26, 43, 28, 45, 46, 23, + 64, 65, 66, 67, 68, 69, 70, 7, 72, 73, 74, 11, 76, 13, 14, 71, + 80, 81, 82, 19, 84, 21, 22, 71, 88, 25, 26, 75, 28, 77, 78, 23, + 96, 97, 98, 35, 100, 37, 38, 71, 104, 41, 42, 75, 44, 77, 78, 39, + 112, 49, 50, 83, 52, 85, 86, 39, 56, 89, 90, 43, 92, 45, 46, 23, + 128, 129, 130, 131, 132, 133, 134, 7, 136, 137, 138, 11, 140, 13, 14, 135, + 144, 145, 146, 19, 148, 21, 22, 135, 152, 25, 26, 139, 28, 141, 142, 23, + 160, 161, 162, 35, 164, 37, 38, 135, 168, 41, 42, 139, 44, 141, 142, 39, + 176, 49, 50, 147, 52, 149, 150, 39, 56, 153, 154, 43, 156, 45, 46, 23, + 192, 193, 194, 67, 196, 69, 70, 135, 200, 73, 74, 139, 76, 141, 142, 71, + 208, 81, 82, 147, 84, 149, 150, 71, 88, 153, 154, 75, 156, 77, 78, 23, + 224, 97, 98, 163, 100, 165, 166, 71, 104, 169, 170, 75, 172, 77, 78, 39, + 112, 177, 178, 83, 180, 85, 86, 39, 184, 89, 90, 43, 92, 45, 46, 151, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, + 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 16, 0, 16, 16, 24, + 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 32, 0, 32, 32, 40, + 0, 0, 0, 32, 0, 32, 32, 48, 0, 32, 32, 48, 32, 48, 48, 24, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 72, + 0, 0, 0, 64, 0, 64, 64, 80, 0, 64, 64, 80, 64, 80, 80, 24, + 0, 0, 0, 64, 0, 64, 64, 96, 0, 64, 64, 96, 64, 96, 96, 40, + 0, 64, 64, 96, 64, 96, 96, 48, 64, 96, 96, 48, 96, 48, 48, 24, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 136, + 0, 0, 0, 128, 0, 128, 128, 144, 0, 128, 128, 144, 128, 144, 144, 24, + 0, 0, 0, 128, 0, 128, 128, 160, 0, 128, 128, 160, 128, 160, 160, 40, + 0, 128, 128, 160, 128, 160, 160, 48, 128, 160, 160, 48, 160, 48, 48, 24, + 0, 0, 0, 128, 0, 128, 128, 192, 0, 128, 128, 192, 128, 192, 192, 72, + 0, 128, 128, 192, 128, 192, 192, 80, 128, 192, 192, 80, 192, 80, 80, 24, + 0, 128, 128, 192, 128, 192, 192, 96, 128, 192, 192, 96, 192, 96, 96, 40, + 128, 192, 192, 96, 192, 96, 96, 48, 192, 96, 96, 48, 96, 48, 48, 152, + }, { + 0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 9, + 16, 1, 2, 1, 4, 1, 2, 17, 8, 1, 2, 17, 4, 17, 18, 25, + 32, 1, 2, 1, 4, 1, 2, 33, 8, 1, 2, 33, 4, 33, 34, 41, + 16, 1, 2, 33, 4, 33, 34, 49, 8, 33, 34, 49, 36, 49, 50, 25, + 64, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 73, + 16, 1, 2, 65, 4, 65, 66, 81, 8, 65, 66, 81, 68, 81, 82, 25, + 32, 1, 2, 65, 4, 65, 66, 97, 8, 65, 66, 97, 68, 97, 98, 41, + 16, 65, 66, 97, 68, 97, 98, 49, 72, 97, 98, 49, 100, 49, 50, 25, + 128, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 137, + 16, 1, 2, 129, 4, 129, 130, 145, 8, 129, 130, 145, 132, 145, 146, 25, + 32, 1, 2, 129, 4, 129, 130, 161, 8, 129, 130, 161, 132, 161, 162, 41, + 16, 129, 130, 161, 132, 161, 162, 49, 136, 161, 162, 49, 164, 49, 50, 25, + 64, 1, 2, 129, 4, 129, 130, 193, 8, 129, 130, 193, 132, 193, 194, 73, + 16, 129, 130, 193, 132, 193, 194, 81, 136, 193, 194, 81, 196, 81, 82, 25, + 32, 129, 130, 193, 132, 193, 194, 97, 136, 193, 194, 97, 196, 97, 98, 41, + 144, 193, 194, 97, 196, 97, 98, 49, 200, 97, 98, 49, 100, 49, 50, 153, + }, { + 0, 0, 0, 2, 0, 4, 4, 2, 0, 8, 8, 2, 8, 4, 4, 10, + 0, 16, 16, 2, 16, 4, 4, 18, 16, 8, 8, 18, 8, 20, 20, 26, + 0, 32, 32, 2, 32, 4, 4, 34, 32, 8, 8, 34, 8, 36, 36, 42, + 32, 16, 16, 34, 16, 36, 36, 50, 16, 40, 40, 50, 40, 52, 52, 26, + 0, 64, 64, 2, 64, 4, 4, 66, 64, 8, 8, 66, 8, 68, 68, 74, + 64, 16, 16, 66, 16, 68, 68, 82, 16, 72, 72, 82, 72, 84, 84, 26, + 64, 32, 32, 66, 32, 68, 68, 98, 32, 72, 72, 98, 72, 100, 100, 42, + 32, 80, 80, 98, 80, 100, 100, 50, 80, 104, 104, 50, 104, 52, 52, 26, + 0, 128, 128, 2, 128, 4, 4, 130, 128, 8, 8, 130, 8, 132, 132, 138, + 128, 16, 16, 130, 16, 132, 132, 146, 16, 136, 136, 146, 136, 148, 148, 26, + 128, 32, 32, 130, 32, 132, 132, 162, 32, 136, 136, 162, 136, 164, 164, 42, + 32, 144, 144, 162, 144, 164, 164, 50, 144, 168, 168, 50, 168, 52, 52, 26, + 128, 64, 64, 130, 64, 132, 132, 194, 64, 136, 136, 194, 136, 196, 196, 74, + 64, 144, 144, 194, 144, 196, 196, 82, 144, 200, 200, 82, 200, 84, 84, 26, + 64, 160, 160, 194, 160, 196, 196, 98, 160, 200, 200, 98, 200, 100, 100, 42, + 160, 208, 208, 98, 208, 100, 100, 50, 208, 104, 104, 50, 104, 52, 52, 154, + }, { + 0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 10, 3, 12, 5, 6, 11, + 16, 17, 18, 3, 20, 5, 6, 19, 24, 9, 10, 19, 12, 21, 22, 27, + 32, 33, 34, 3, 36, 5, 6, 35, 40, 9, 10, 35, 12, 37, 38, 43, + 48, 17, 18, 35, 20, 37, 38, 51, 24, 41, 42, 51, 44, 53, 54, 27, + 64, 65, 66, 3, 68, 5, 6, 67, 72, 9, 10, 67, 12, 69, 70, 75, + 80, 17, 18, 67, 20, 69, 70, 83, 24, 73, 74, 83, 76, 85, 86, 27, + 96, 33, 34, 67, 36, 69, 70, 99, 40, 73, 74, 99, 76, 101, 102, 43, + 48, 81, 82, 99, 84, 101, 102, 51, 88, 105, 106, 51, 108, 53, 54, 27, + 128, 129, 130, 3, 132, 5, 6, 131, 136, 9, 10, 131, 12, 133, 134, 139, + 144, 17, 18, 131, 20, 133, 134, 147, 24, 137, 138, 147, 140, 149, 150, 27, + 160, 33, 34, 131, 36, 133, 134, 163, 40, 137, 138, 163, 140, 165, 166, 43, + 48, 145, 146, 163, 148, 165, 166, 51, 152, 169, 170, 51, 172, 53, 54, 27, + 192, 65, 66, 131, 68, 133, 134, 195, 72, 137, 138, 195, 140, 197, 198, 75, + 80, 145, 146, 195, 148, 197, 198, 83, 152, 201, 202, 83, 204, 85, 86, 27, + 96, 161, 162, 195, 164, 197, 198, 99, 168, 201, 202, 99, 204, 101, 102, 43, + 176, 209, 210, 99, 212, 101, 102, 51, 216, 105, 106, 51, 108, 53, 54, 155, + }, + { + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 8, 8, 12, + 0, 0, 0, 16, 0, 16, 16, 20, 0, 16, 16, 24, 16, 24, 24, 28, + 0, 0, 0, 32, 0, 32, 32, 36, 0, 32, 32, 40, 32, 40, 40, 44, + 0, 32, 32, 48, 32, 48, 48, 52, 32, 48, 48, 56, 48, 56, 56, 28, + 0, 0, 0, 64, 0, 64, 64, 68, 0, 64, 64, 72, 64, 72, 72, 76, + 0, 64, 64, 80, 64, 80, 80, 84, 64, 80, 80, 88, 80, 88, 88, 28, + 0, 64, 64, 96, 64, 96, 96, 100, 64, 96, 96, 104, 96, 104, 104, 44, + 64, 96, 96, 112, 96, 112, 112, 52, 96, 112, 112, 56, 112, 56, 56, 28, + 0, 0, 0, 128, 0, 128, 128, 132, 0, 128, 128, 136, 128, 136, 136, 140, + 0, 128, 128, 144, 128, 144, 144, 148, 128, 144, 144, 152, 144, 152, 152, 28, + 0, 128, 128, 160, 128, 160, 160, 164, 128, 160, 160, 168, 160, 168, 168, 44, + 128, 160, 160, 176, 160, 176, 176, 52, 160, 176, 176, 56, 176, 56, 56, 28, + 0, 128, 128, 192, 128, 192, 192, 196, 128, 192, 192, 200, 192, 200, 200, 76, + 128, 192, 192, 208, 192, 208, 208, 84, 192, 208, 208, 88, 208, 88, 88, 28, + 128, 192, 192, 224, 192, 224, 224, 100, 192, 224, 224, 104, 224, 104, 104, 44, + 192, 224, 224, 112, 224, 112, 112, 52, 224, 112, 112, 56, 112, 56, 56, 156, + }, { + 0, 1, 2, 1, 4, 1, 2, 5, 8, 1, 2, 9, 4, 9, 10, 13, + 16, 1, 2, 17, 4, 17, 18, 21, 8, 17, 18, 25, 20, 25, 26, 29, + 32, 1, 2, 33, 4, 33, 34, 37, 8, 33, 34, 41, 36, 41, 42, 45, + 16, 33, 34, 49, 36, 49, 50, 53, 40, 49, 50, 57, 52, 57, 58, 29, + 64, 1, 2, 65, 4, 65, 66, 69, 8, 65, 66, 73, 68, 73, 74, 77, + 16, 65, 66, 81, 68, 81, 82, 85, 72, 81, 82, 89, 84, 89, 90, 29, + 32, 65, 66, 97, 68, 97, 98, 101, 72, 97, 98, 105, 100, 105, 106, 45, + 80, 97, 98, 113, 100, 113, 114, 53, 104, 113, 114, 57, 116, 57, 58, 29, + 128, 1, 2, 129, 4, 129, 130, 133, 8, 129, 130, 137, 132, 137, 138, 141, + 16, 129, 130, 145, 132, 145, 146, 149, 136, 145, 146, 153, 148, 153, 154, 29, + 32, 129, 130, 161, 132, 161, 162, 165, 136, 161, 162, 169, 164, 169, 170, 45, + 144, 161, 162, 177, 164, 177, 178, 53, 168, 177, 178, 57, 180, 57, 58, 29, + 64, 129, 130, 193, 132, 193, 194, 197, 136, 193, 194, 201, 196, 201, 202, 77, + 144, 193, 194, 209, 196, 209, 210, 85, 200, 209, 210, 89, 212, 89, 90, 29, + 160, 193, 194, 225, 196, 225, 226, 101, 200, 225, 226, 105, 228, 105, 106, 45, + 208, 225, 226, 113, 228, 113, 114, 53, 232, 113, 114, 57, 116, 57, 58, 157, + }, { + 0, 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10, 8, 12, 12, 14, + 0, 16, 16, 18, 16, 20, 20, 22, 16, 24, 24, 26, 24, 28, 28, 30, + 0, 32, 32, 34, 32, 36, 36, 38, 32, 40, 40, 42, 40, 44, 44, 46, + 32, 48, 48, 50, 48, 52, 52, 54, 48, 56, 56, 58, 56, 60, 60, 30, + 0, 64, 64, 66, 64, 68, 68, 70, 64, 72, 72, 74, 72, 76, 76, 78, + 64, 80, 80, 82, 80, 84, 84, 86, 80, 88, 88, 90, 88, 92, 92, 30, + 64, 96, 96, 98, 96, 100, 100, 102, 96, 104, 104, 106, 104, 108, 108, 46, + 96, 112, 112, 114, 112, 116, 116, 54, 112, 120, 120, 58, 120, 60, 60, 30, + 0, 128, 128, 130, 128, 132, 132, 134, 128, 136, 136, 138, 136, 140, 140, 142, + 128, 144, 144, 146, 144, 148, 148, 150, 144, 152, 152, 154, 152, 156, 156, 30, + 128, 160, 160, 162, 160, 164, 164, 166, 160, 168, 168, 170, 168, 172, 172, 46, + 160, 176, 176, 178, 176, 180, 180, 54, 176, 184, 184, 58, 184, 60, 60, 30, + 128, 192, 192, 194, 192, 196, 196, 198, 192, 200, 200, 202, 200, 204, 204, 78, + 192, 208, 208, 210, 208, 212, 212, 86, 208, 216, 216, 90, 216, 92, 92, 30, + 192, 224, 224, 226, 224, 228, 228, 102, 224, 232, 232, 106, 232, 108, 108, 46, + 224, 240, 240, 114, 240, 116, 116, 54, 240, 120, 120, 58, 120, 60, 60, 158, + }, { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 31, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 31, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 47, + 112, 113, 114, 115, 116, 117, 118, 55, 120, 121, 122, 59, 124, 61, 62, 31, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, + 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 31, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 47, + 176, 177, 178, 179, 180, 181, 182, 55, 184, 185, 186, 59, 188, 61, 62, 31, + 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 79, + 208, 209, 210, 211, 212, 213, 214, 87, 216, 217, 218, 91, 220, 93, 94, 31, + 224, 225, 226, 227, 228, 229, 230, 103, 232, 233, 234, 107, 236, 109, 110, 47, + 240, 241, 242, 115, 244, 117, 118, 55, 248, 121, 122, 59, 124, 61, 62, 159, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 32, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 32, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 64, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 64, + 0, 0, 0, 128, 0, 128, 128, 64, 0, 128, 128, 64, 128, 64, 64, 160, + }, { + 0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 33, + 64, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 65, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 65, + 16, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 33, + 128, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 129, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 129, + 16, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 33, + 64, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 129, + 16, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 65, + 32, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 65, + 16, 1, 2, 129, 4, 129, 130, 65, 8, 129, 130, 65, 132, 65, 66, 161, + }, { + 0, 0, 0, 2, 0, 4, 4, 2, 0, 8, 8, 2, 8, 4, 4, 2, + 0, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 2, + 0, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 2, + 32, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 34, + 0, 64, 64, 2, 64, 4, 4, 2, 64, 8, 8, 2, 8, 4, 4, 2, + 64, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 66, + 64, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 66, + 32, 16, 16, 2, 16, 4, 4, 66, 16, 8, 8, 66, 8, 68, 68, 34, + 0, 128, 128, 2, 128, 4, 4, 2, 128, 8, 8, 2, 8, 4, 4, 2, + 128, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 130, + 128, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 130, + 32, 16, 16, 2, 16, 4, 4, 130, 16, 8, 8, 130, 8, 132, 132, 34, + 128, 64, 64, 2, 64, 4, 4, 2, 64, 8, 8, 2, 8, 4, 4, 130, + 64, 16, 16, 2, 16, 4, 4, 130, 16, 8, 8, 130, 8, 132, 132, 66, + 64, 32, 32, 2, 32, 4, 4, 130, 32, 8, 8, 130, 8, 132, 132, 66, + 32, 16, 16, 130, 16, 132, 132, 66, 16, 136, 136, 66, 136, 68, 68, 162, + }, { + 0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 10, 3, 12, 5, 6, 3, + 16, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 3, + 32, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 3, + 48, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 35, + 64, 65, 66, 3, 68, 5, 6, 3, 72, 9, 10, 3, 12, 5, 6, 3, + 80, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 67, + 96, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 67, + 48, 17, 18, 3, 20, 5, 6, 67, 24, 9, 10, 67, 12, 69, 70, 35, + 128, 129, 130, 3, 132, 5, 6, 3, 136, 9, 10, 3, 12, 5, 6, 3, + 144, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 131, + 160, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 131, + 48, 17, 18, 3, 20, 5, 6, 131, 24, 9, 10, 131, 12, 133, 134, 35, + 192, 65, 66, 3, 68, 5, 6, 3, 72, 9, 10, 3, 12, 5, 6, 131, + 80, 17, 18, 3, 20, 5, 6, 131, 24, 9, 10, 131, 12, 133, 134, 67, + 96, 33, 34, 3, 36, 5, 6, 131, 40, 9, 10, 131, 12, 133, 134, 67, + 48, 17, 18, 131, 20, 133, 134, 67, 24, 137, 138, 67, 140, 69, 70, 163, + }, + { + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 8, 8, 4, + 0, 0, 0, 16, 0, 16, 16, 4, 0, 16, 16, 8, 16, 8, 8, 4, + 0, 0, 0, 32, 0, 32, 32, 4, 0, 32, 32, 8, 32, 8, 8, 4, + 0, 32, 32, 16, 32, 16, 16, 4, 32, 16, 16, 8, 16, 8, 8, 36, + 0, 0, 0, 64, 0, 64, 64, 4, 0, 64, 64, 8, 64, 8, 8, 4, + 0, 64, 64, 16, 64, 16, 16, 4, 64, 16, 16, 8, 16, 8, 8, 68, + 0, 64, 64, 32, 64, 32, 32, 4, 64, 32, 32, 8, 32, 8, 8, 68, + 64, 32, 32, 16, 32, 16, 16, 68, 32, 16, 16, 72, 16, 72, 72, 36, + 0, 0, 0, 128, 0, 128, 128, 4, 0, 128, 128, 8, 128, 8, 8, 4, + 0, 128, 128, 16, 128, 16, 16, 4, 128, 16, 16, 8, 16, 8, 8, 132, + 0, 128, 128, 32, 128, 32, 32, 4, 128, 32, 32, 8, 32, 8, 8, 132, + 128, 32, 32, 16, 32, 16, 16, 132, 32, 16, 16, 136, 16, 136, 136, 36, + 0, 128, 128, 64, 128, 64, 64, 4, 128, 64, 64, 8, 64, 8, 8, 132, + 128, 64, 64, 16, 64, 16, 16, 132, 64, 16, 16, 136, 16, 136, 136, 68, + 128, 64, 64, 32, 64, 32, 32, 132, 64, 32, 32, 136, 32, 136, 136, 68, + 64, 32, 32, 144, 32, 144, 144, 68, 32, 144, 144, 72, 144, 72, 72, 164, + }, { + 0, 1, 2, 1, 4, 1, 2, 5, 8, 1, 2, 9, 4, 9, 10, 5, + 16, 1, 2, 17, 4, 17, 18, 5, 8, 17, 18, 9, 20, 9, 10, 5, + 32, 1, 2, 33, 4, 33, 34, 5, 8, 33, 34, 9, 36, 9, 10, 5, + 16, 33, 34, 17, 36, 17, 18, 5, 40, 17, 18, 9, 20, 9, 10, 37, + 64, 1, 2, 65, 4, 65, 66, 5, 8, 65, 66, 9, 68, 9, 10, 5, + 16, 65, 66, 17, 68, 17, 18, 5, 72, 17, 18, 9, 20, 9, 10, 69, + 32, 65, 66, 33, 68, 33, 34, 5, 72, 33, 34, 9, 36, 9, 10, 69, + 80, 33, 34, 17, 36, 17, 18, 69, 40, 17, 18, 73, 20, 73, 74, 37, + 128, 1, 2, 129, 4, 129, 130, 5, 8, 129, 130, 9, 132, 9, 10, 5, + 16, 129, 130, 17, 132, 17, 18, 5, 136, 17, 18, 9, 20, 9, 10, 133, + 32, 129, 130, 33, 132, 33, 34, 5, 136, 33, 34, 9, 36, 9, 10, 133, + 144, 33, 34, 17, 36, 17, 18, 133, 40, 17, 18, 137, 20, 137, 138, 37, + 64, 129, 130, 65, 132, 65, 66, 5, 136, 65, 66, 9, 68, 9, 10, 133, + 144, 65, 66, 17, 68, 17, 18, 133, 72, 17, 18, 137, 20, 137, 138, 69, + 160, 65, 66, 33, 68, 33, 34, 133, 72, 33, 34, 137, 36, 137, 138, 69, + 80, 33, 34, 145, 36, 145, 146, 69, 40, 145, 146, 73, 148, 73, 74, 165, + }, { + 0, 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10, 8, 12, 12, 6, + 0, 16, 16, 18, 16, 20, 20, 6, 16, 24, 24, 10, 24, 12, 12, 6, + 0, 32, 32, 34, 32, 36, 36, 6, 32, 40, 40, 10, 40, 12, 12, 6, + 32, 48, 48, 18, 48, 20, 20, 6, 48, 24, 24, 10, 24, 12, 12, 38, + 0, 64, 64, 66, 64, 68, 68, 6, 64, 72, 72, 10, 72, 12, 12, 6, + 64, 80, 80, 18, 80, 20, 20, 6, 80, 24, 24, 10, 24, 12, 12, 70, + 64, 96, 96, 34, 96, 36, 36, 6, 96, 40, 40, 10, 40, 12, 12, 70, + 96, 48, 48, 18, 48, 20, 20, 70, 48, 24, 24, 74, 24, 76, 76, 38, + 0, 128, 128, 130, 128, 132, 132, 6, 128, 136, 136, 10, 136, 12, 12, 6, + 128, 144, 144, 18, 144, 20, 20, 6, 144, 24, 24, 10, 24, 12, 12, 134, + 128, 160, 160, 34, 160, 36, 36, 6, 160, 40, 40, 10, 40, 12, 12, 134, + 160, 48, 48, 18, 48, 20, 20, 134, 48, 24, 24, 138, 24, 140, 140, 38, + 128, 192, 192, 66, 192, 68, 68, 6, 192, 72, 72, 10, 72, 12, 12, 134, + 192, 80, 80, 18, 80, 20, 20, 134, 80, 24, 24, 138, 24, 140, 140, 70, + 192, 96, 96, 34, 96, 36, 36, 134, 96, 40, 40, 138, 40, 140, 140, 70, + 96, 48, 48, 146, 48, 148, 148, 70, 48, 152, 152, 74, 152, 76, 76, 166, + }, { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 7, + 16, 17, 18, 19, 20, 21, 22, 7, 24, 25, 26, 11, 28, 13, 14, 7, + 32, 33, 34, 35, 36, 37, 38, 7, 40, 41, 42, 11, 44, 13, 14, 7, + 48, 49, 50, 19, 52, 21, 22, 7, 56, 25, 26, 11, 28, 13, 14, 39, + 64, 65, 66, 67, 68, 69, 70, 7, 72, 73, 74, 11, 76, 13, 14, 7, + 80, 81, 82, 19, 84, 21, 22, 7, 88, 25, 26, 11, 28, 13, 14, 71, + 96, 97, 98, 35, 100, 37, 38, 7, 104, 41, 42, 11, 44, 13, 14, 71, + 112, 49, 50, 19, 52, 21, 22, 71, 56, 25, 26, 75, 28, 77, 78, 39, + 128, 129, 130, 131, 132, 133, 134, 7, 136, 137, 138, 11, 140, 13, 14, 7, + 144, 145, 146, 19, 148, 21, 22, 7, 152, 25, 26, 11, 28, 13, 14, 135, + 160, 161, 162, 35, 164, 37, 38, 7, 168, 41, 42, 11, 44, 13, 14, 135, + 176, 49, 50, 19, 52, 21, 22, 135, 56, 25, 26, 139, 28, 141, 142, 39, + 192, 193, 194, 67, 196, 69, 70, 7, 200, 73, 74, 11, 76, 13, 14, 135, + 208, 81, 82, 19, 84, 21, 22, 135, 88, 25, 26, 139, 28, 141, 142, 71, + 224, 97, 98, 35, 100, 37, 38, 135, 104, 41, 42, 139, 44, 141, 142, 71, + 112, 49, 50, 147, 52, 149, 150, 71, 56, 153, 154, 75, 156, 77, 78, 167, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, + 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 16, 0, 16, 16, 8, + 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 32, 0, 32, 32, 8, + 0, 0, 0, 32, 0, 32, 32, 16, 0, 32, 32, 16, 32, 16, 16, 40, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 8, + 0, 0, 0, 64, 0, 64, 64, 16, 0, 64, 64, 16, 64, 16, 16, 72, + 0, 0, 0, 64, 0, 64, 64, 32, 0, 64, 64, 32, 64, 32, 32, 72, + 0, 64, 64, 32, 64, 32, 32, 80, 64, 32, 32, 80, 32, 80, 80, 40, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 8, + 0, 0, 0, 128, 0, 128, 128, 16, 0, 128, 128, 16, 128, 16, 16, 136, + 0, 0, 0, 128, 0, 128, 128, 32, 0, 128, 128, 32, 128, 32, 32, 136, + 0, 128, 128, 32, 128, 32, 32, 144, 128, 32, 32, 144, 32, 144, 144, 40, + 0, 0, 0, 128, 0, 128, 128, 64, 0, 128, 128, 64, 128, 64, 64, 136, + 0, 128, 128, 64, 128, 64, 64, 144, 128, 64, 64, 144, 64, 144, 144, 72, + 0, 128, 128, 64, 128, 64, 64, 160, 128, 64, 64, 160, 64, 160, 160, 72, + 128, 64, 64, 160, 64, 160, 160, 80, 64, 160, 160, 80, 160, 80, 80, 168, + }, { + 0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 9, + 16, 1, 2, 1, 4, 1, 2, 17, 8, 1, 2, 17, 4, 17, 18, 9, + 32, 1, 2, 1, 4, 1, 2, 33, 8, 1, 2, 33, 4, 33, 34, 9, + 16, 1, 2, 33, 4, 33, 34, 17, 8, 33, 34, 17, 36, 17, 18, 41, + 64, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 9, + 16, 1, 2, 65, 4, 65, 66, 17, 8, 65, 66, 17, 68, 17, 18, 73, + 32, 1, 2, 65, 4, 65, 66, 33, 8, 65, 66, 33, 68, 33, 34, 73, + 16, 65, 66, 33, 68, 33, 34, 81, 72, 33, 34, 81, 36, 81, 82, 41, + 128, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 9, + 16, 1, 2, 129, 4, 129, 130, 17, 8, 129, 130, 17, 132, 17, 18, 137, + 32, 1, 2, 129, 4, 129, 130, 33, 8, 129, 130, 33, 132, 33, 34, 137, + 16, 129, 130, 33, 132, 33, 34, 145, 136, 33, 34, 145, 36, 145, 146, 41, + 64, 1, 2, 129, 4, 129, 130, 65, 8, 129, 130, 65, 132, 65, 66, 137, + 16, 129, 130, 65, 132, 65, 66, 145, 136, 65, 66, 145, 68, 145, 146, 73, + 32, 129, 130, 65, 132, 65, 66, 161, 136, 65, 66, 161, 68, 161, 162, 73, + 144, 65, 66, 161, 68, 161, 162, 81, 72, 161, 162, 81, 164, 81, 82, 169, + }, { + 0, 0, 0, 2, 0, 4, 4, 2, 0, 8, 8, 2, 8, 4, 4, 10, + 0, 16, 16, 2, 16, 4, 4, 18, 16, 8, 8, 18, 8, 20, 20, 10, + 0, 32, 32, 2, 32, 4, 4, 34, 32, 8, 8, 34, 8, 36, 36, 10, + 32, 16, 16, 34, 16, 36, 36, 18, 16, 40, 40, 18, 40, 20, 20, 42, + 0, 64, 64, 2, 64, 4, 4, 66, 64, 8, 8, 66, 8, 68, 68, 10, + 64, 16, 16, 66, 16, 68, 68, 18, 16, 72, 72, 18, 72, 20, 20, 74, + 64, 32, 32, 66, 32, 68, 68, 34, 32, 72, 72, 34, 72, 36, 36, 74, + 32, 80, 80, 34, 80, 36, 36, 82, 80, 40, 40, 82, 40, 84, 84, 42, + 0, 128, 128, 2, 128, 4, 4, 130, 128, 8, 8, 130, 8, 132, 132, 10, + 128, 16, 16, 130, 16, 132, 132, 18, 16, 136, 136, 18, 136, 20, 20, 138, + 128, 32, 32, 130, 32, 132, 132, 34, 32, 136, 136, 34, 136, 36, 36, 138, + 32, 144, 144, 34, 144, 36, 36, 146, 144, 40, 40, 146, 40, 148, 148, 42, + 128, 64, 64, 130, 64, 132, 132, 66, 64, 136, 136, 66, 136, 68, 68, 138, + 64, 144, 144, 66, 144, 68, 68, 146, 144, 72, 72, 146, 72, 148, 148, 74, + 64, 160, 160, 66, 160, 68, 68, 162, 160, 72, 72, 162, 72, 164, 164, 74, + 160, 80, 80, 162, 80, 164, 164, 82, 80, 168, 168, 82, 168, 84, 84, 170, + }, { + 0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 10, 3, 12, 5, 6, 11, + 16, 17, 18, 3, 20, 5, 6, 19, 24, 9, 10, 19, 12, 21, 22, 11, + 32, 33, 34, 3, 36, 5, 6, 35, 40, 9, 10, 35, 12, 37, 38, 11, + 48, 17, 18, 35, 20, 37, 38, 19, 24, 41, 42, 19, 44, 21, 22, 43, + 64, 65, 66, 3, 68, 5, 6, 67, 72, 9, 10, 67, 12, 69, 70, 11, + 80, 17, 18, 67, 20, 69, 70, 19, 24, 73, 74, 19, 76, 21, 22, 75, + 96, 33, 34, 67, 36, 69, 70, 35, 40, 73, 74, 35, 76, 37, 38, 75, + 48, 81, 82, 35, 84, 37, 38, 83, 88, 41, 42, 83, 44, 85, 86, 43, + 128, 129, 130, 3, 132, 5, 6, 131, 136, 9, 10, 131, 12, 133, 134, 11, + 144, 17, 18, 131, 20, 133, 134, 19, 24, 137, 138, 19, 140, 21, 22, 139, + 160, 33, 34, 131, 36, 133, 134, 35, 40, 137, 138, 35, 140, 37, 38, 139, + 48, 145, 146, 35, 148, 37, 38, 147, 152, 41, 42, 147, 44, 149, 150, 43, + 192, 65, 66, 131, 68, 133, 134, 67, 72, 137, 138, 67, 140, 69, 70, 139, + 80, 145, 146, 67, 148, 69, 70, 147, 152, 73, 74, 147, 76, 149, 150, 75, + 96, 161, 162, 67, 164, 69, 70, 163, 168, 73, 74, 163, 76, 165, 166, 75, + 176, 81, 82, 163, 84, 165, 166, 83, 88, 169, 170, 83, 172, 85, 86, 171, + }, + { + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 8, 8, 12, + 0, 0, 0, 16, 0, 16, 16, 20, 0, 16, 16, 24, 16, 24, 24, 12, + 0, 0, 0, 32, 0, 32, 32, 36, 0, 32, 32, 40, 32, 40, 40, 12, + 0, 32, 32, 48, 32, 48, 48, 20, 32, 48, 48, 24, 48, 24, 24, 44, + 0, 0, 0, 64, 0, 64, 64, 68, 0, 64, 64, 72, 64, 72, 72, 12, + 0, 64, 64, 80, 64, 80, 80, 20, 64, 80, 80, 24, 80, 24, 24, 76, + 0, 64, 64, 96, 64, 96, 96, 36, 64, 96, 96, 40, 96, 40, 40, 76, + 64, 96, 96, 48, 96, 48, 48, 84, 96, 48, 48, 88, 48, 88, 88, 44, + 0, 0, 0, 128, 0, 128, 128, 132, 0, 128, 128, 136, 128, 136, 136, 12, + 0, 128, 128, 144, 128, 144, 144, 20, 128, 144, 144, 24, 144, 24, 24, 140, + 0, 128, 128, 160, 128, 160, 160, 36, 128, 160, 160, 40, 160, 40, 40, 140, + 128, 160, 160, 48, 160, 48, 48, 148, 160, 48, 48, 152, 48, 152, 152, 44, + 0, 128, 128, 192, 128, 192, 192, 68, 128, 192, 192, 72, 192, 72, 72, 140, + 128, 192, 192, 80, 192, 80, 80, 148, 192, 80, 80, 152, 80, 152, 152, 76, + 128, 192, 192, 96, 192, 96, 96, 164, 192, 96, 96, 168, 96, 168, 168, 76, + 192, 96, 96, 176, 96, 176, 176, 84, 96, 176, 176, 88, 176, 88, 88, 172, + }, { + 0, 1, 2, 1, 4, 1, 2, 5, 8, 1, 2, 9, 4, 9, 10, 13, + 16, 1, 2, 17, 4, 17, 18, 21, 8, 17, 18, 25, 20, 25, 26, 13, + 32, 1, 2, 33, 4, 33, 34, 37, 8, 33, 34, 41, 36, 41, 42, 13, + 16, 33, 34, 49, 36, 49, 50, 21, 40, 49, 50, 25, 52, 25, 26, 45, + 64, 1, 2, 65, 4, 65, 66, 69, 8, 65, 66, 73, 68, 73, 74, 13, + 16, 65, 66, 81, 68, 81, 82, 21, 72, 81, 82, 25, 84, 25, 26, 77, + 32, 65, 66, 97, 68, 97, 98, 37, 72, 97, 98, 41, 100, 41, 42, 77, + 80, 97, 98, 49, 100, 49, 50, 85, 104, 49, 50, 89, 52, 89, 90, 45, + 128, 1, 2, 129, 4, 129, 130, 133, 8, 129, 130, 137, 132, 137, 138, 13, + 16, 129, 130, 145, 132, 145, 146, 21, 136, 145, 146, 25, 148, 25, 26, 141, + 32, 129, 130, 161, 132, 161, 162, 37, 136, 161, 162, 41, 164, 41, 42, 141, + 144, 161, 162, 49, 164, 49, 50, 149, 168, 49, 50, 153, 52, 153, 154, 45, + 64, 129, 130, 193, 132, 193, 194, 69, 136, 193, 194, 73, 196, 73, 74, 141, + 144, 193, 194, 81, 196, 81, 82, 149, 200, 81, 82, 153, 84, 153, 154, 77, + 160, 193, 194, 97, 196, 97, 98, 165, 200, 97, 98, 169, 100, 169, 170, 77, + 208, 97, 98, 177, 100, 177, 178, 85, 104, 177, 178, 89, 180, 89, 90, 173, + }, { + 0, 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10, 8, 12, 12, 14, + 0, 16, 16, 18, 16, 20, 20, 22, 16, 24, 24, 26, 24, 28, 28, 14, + 0, 32, 32, 34, 32, 36, 36, 38, 32, 40, 40, 42, 40, 44, 44, 14, + 32, 48, 48, 50, 48, 52, 52, 22, 48, 56, 56, 26, 56, 28, 28, 46, + 0, 64, 64, 66, 64, 68, 68, 70, 64, 72, 72, 74, 72, 76, 76, 14, + 64, 80, 80, 82, 80, 84, 84, 22, 80, 88, 88, 26, 88, 28, 28, 78, + 64, 96, 96, 98, 96, 100, 100, 38, 96, 104, 104, 42, 104, 44, 44, 78, + 96, 112, 112, 50, 112, 52, 52, 86, 112, 56, 56, 90, 56, 92, 92, 46, + 0, 128, 128, 130, 128, 132, 132, 134, 128, 136, 136, 138, 136, 140, 140, 14, + 128, 144, 144, 146, 144, 148, 148, 22, 144, 152, 152, 26, 152, 28, 28, 142, + 128, 160, 160, 162, 160, 164, 164, 38, 160, 168, 168, 42, 168, 44, 44, 142, + 160, 176, 176, 50, 176, 52, 52, 150, 176, 56, 56, 154, 56, 156, 156, 46, + 128, 192, 192, 194, 192, 196, 196, 70, 192, 200, 200, 74, 200, 76, 76, 142, + 192, 208, 208, 82, 208, 84, 84, 150, 208, 88, 88, 154, 88, 156, 156, 78, + 192, 224, 224, 98, 224, 100, 100, 166, 224, 104, 104, 170, 104, 172, 172, 78, + 224, 112, 112, 178, 112, 180, 180, 86, 112, 184, 184, 90, 184, 92, 92, 174, + }, { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 15, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 15, + 48, 49, 50, 51, 52, 53, 54, 23, 56, 57, 58, 27, 60, 29, 30, 47, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 15, + 80, 81, 82, 83, 84, 85, 86, 23, 88, 89, 90, 27, 92, 29, 30, 79, + 96, 97, 98, 99, 100, 101, 102, 39, 104, 105, 106, 43, 108, 45, 46, 79, + 112, 113, 114, 51, 116, 53, 54, 87, 120, 57, 58, 91, 60, 93, 94, 47, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 15, + 144, 145, 146, 147, 148, 149, 150, 23, 152, 153, 154, 27, 156, 29, 30, 143, + 160, 161, 162, 163, 164, 165, 166, 39, 168, 169, 170, 43, 172, 45, 46, 143, + 176, 177, 178, 51, 180, 53, 54, 151, 184, 57, 58, 155, 60, 157, 158, 47, + 192, 193, 194, 195, 196, 197, 198, 71, 200, 201, 202, 75, 204, 77, 78, 143, + 208, 209, 210, 83, 212, 85, 86, 151, 216, 89, 90, 155, 92, 157, 158, 79, + 224, 225, 226, 99, 228, 101, 102, 167, 232, 105, 106, 171, 108, 173, 174, 79, + 240, 113, 114, 179, 116, 181, 182, 87, 120, 185, 186, 91, 188, 93, 94, 175, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, + 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 32, 0, 32, 32, 48, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 80, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 96, + 0, 0, 0, 64, 0, 64, 64, 96, 0, 64, 64, 96, 64, 96, 96, 48, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 144, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 160, + 0, 0, 0, 128, 0, 128, 128, 160, 0, 128, 128, 160, 128, 160, 160, 48, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 192, + 0, 0, 0, 128, 0, 128, 128, 192, 0, 128, 128, 192, 128, 192, 192, 80, + 0, 0, 0, 128, 0, 128, 128, 192, 0, 128, 128, 192, 128, 192, 192, 96, + 0, 128, 128, 192, 128, 192, 192, 96, 128, 192, 192, 96, 192, 96, 96, 176, + }, { + 0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 17, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 33, + 16, 1, 2, 1, 4, 1, 2, 33, 8, 1, 2, 33, 4, 33, 34, 49, + 64, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 65, + 16, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 81, + 32, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 97, + 16, 1, 2, 65, 4, 65, 66, 97, 8, 65, 66, 97, 68, 97, 98, 49, + 128, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 129, + 16, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 145, + 32, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 161, + 16, 1, 2, 129, 4, 129, 130, 161, 8, 129, 130, 161, 132, 161, 162, 49, + 64, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 193, + 16, 1, 2, 129, 4, 129, 130, 193, 8, 129, 130, 193, 132, 193, 194, 81, + 32, 1, 2, 129, 4, 129, 130, 193, 8, 129, 130, 193, 132, 193, 194, 97, + 16, 129, 130, 193, 132, 193, 194, 97, 136, 193, 194, 97, 196, 97, 98, 177, + }, { + 0, 0, 0, 2, 0, 4, 4, 2, 0, 8, 8, 2, 8, 4, 4, 2, + 0, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 18, + 0, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 34, + 32, 16, 16, 2, 16, 4, 4, 34, 16, 8, 8, 34, 8, 36, 36, 50, + 0, 64, 64, 2, 64, 4, 4, 2, 64, 8, 8, 2, 8, 4, 4, 66, + 64, 16, 16, 2, 16, 4, 4, 66, 16, 8, 8, 66, 8, 68, 68, 82, + 64, 32, 32, 2, 32, 4, 4, 66, 32, 8, 8, 66, 8, 68, 68, 98, + 32, 16, 16, 66, 16, 68, 68, 98, 16, 72, 72, 98, 72, 100, 100, 50, + 0, 128, 128, 2, 128, 4, 4, 2, 128, 8, 8, 2, 8, 4, 4, 130, + 128, 16, 16, 2, 16, 4, 4, 130, 16, 8, 8, 130, 8, 132, 132, 146, + 128, 32, 32, 2, 32, 4, 4, 130, 32, 8, 8, 130, 8, 132, 132, 162, + 32, 16, 16, 130, 16, 132, 132, 162, 16, 136, 136, 162, 136, 164, 164, 50, + 128, 64, 64, 2, 64, 4, 4, 130, 64, 8, 8, 130, 8, 132, 132, 194, + 64, 16, 16, 130, 16, 132, 132, 194, 16, 136, 136, 194, 136, 196, 196, 82, + 64, 32, 32, 130, 32, 132, 132, 194, 32, 136, 136, 194, 136, 196, 196, 98, + 32, 144, 144, 194, 144, 196, 196, 98, 144, 200, 200, 98, 200, 100, 100, 178, + }, { + 0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 10, 3, 12, 5, 6, 3, + 16, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 19, + 32, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 35, + 48, 17, 18, 3, 20, 5, 6, 35, 24, 9, 10, 35, 12, 37, 38, 51, + 64, 65, 66, 3, 68, 5, 6, 3, 72, 9, 10, 3, 12, 5, 6, 67, + 80, 17, 18, 3, 20, 5, 6, 67, 24, 9, 10, 67, 12, 69, 70, 83, + 96, 33, 34, 3, 36, 5, 6, 67, 40, 9, 10, 67, 12, 69, 70, 99, + 48, 17, 18, 67, 20, 69, 70, 99, 24, 73, 74, 99, 76, 101, 102, 51, + 128, 129, 130, 3, 132, 5, 6, 3, 136, 9, 10, 3, 12, 5, 6, 131, + 144, 17, 18, 3, 20, 5, 6, 131, 24, 9, 10, 131, 12, 133, 134, 147, + 160, 33, 34, 3, 36, 5, 6, 131, 40, 9, 10, 131, 12, 133, 134, 163, + 48, 17, 18, 131, 20, 133, 134, 163, 24, 137, 138, 163, 140, 165, 166, 51, + 192, 65, 66, 3, 68, 5, 6, 131, 72, 9, 10, 131, 12, 133, 134, 195, + 80, 17, 18, 131, 20, 133, 134, 195, 24, 137, 138, 195, 140, 197, 198, 83, + 96, 33, 34, 131, 36, 133, 134, 195, 40, 137, 138, 195, 140, 197, 198, 99, + 48, 145, 146, 195, 148, 197, 198, 99, 152, 201, 202, 99, 204, 101, 102, 179, + }, + { + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 8, 8, 4, + 0, 0, 0, 16, 0, 16, 16, 4, 0, 16, 16, 8, 16, 8, 8, 20, + 0, 0, 0, 32, 0, 32, 32, 4, 0, 32, 32, 8, 32, 8, 8, 36, + 0, 32, 32, 16, 32, 16, 16, 36, 32, 16, 16, 40, 16, 40, 40, 52, + 0, 0, 0, 64, 0, 64, 64, 4, 0, 64, 64, 8, 64, 8, 8, 68, + 0, 64, 64, 16, 64, 16, 16, 68, 64, 16, 16, 72, 16, 72, 72, 84, + 0, 64, 64, 32, 64, 32, 32, 68, 64, 32, 32, 72, 32, 72, 72, 100, + 64, 32, 32, 80, 32, 80, 80, 100, 32, 80, 80, 104, 80, 104, 104, 52, + 0, 0, 0, 128, 0, 128, 128, 4, 0, 128, 128, 8, 128, 8, 8, 132, + 0, 128, 128, 16, 128, 16, 16, 132, 128, 16, 16, 136, 16, 136, 136, 148, + 0, 128, 128, 32, 128, 32, 32, 132, 128, 32, 32, 136, 32, 136, 136, 164, + 128, 32, 32, 144, 32, 144, 144, 164, 32, 144, 144, 168, 144, 168, 168, 52, + 0, 128, 128, 64, 128, 64, 64, 132, 128, 64, 64, 136, 64, 136, 136, 196, + 128, 64, 64, 144, 64, 144, 144, 196, 64, 144, 144, 200, 144, 200, 200, 84, + 128, 64, 64, 160, 64, 160, 160, 196, 64, 160, 160, 200, 160, 200, 200, 100, + 64, 160, 160, 208, 160, 208, 208, 100, 160, 208, 208, 104, 208, 104, 104, 180, + }, { + 0, 1, 2, 1, 4, 1, 2, 5, 8, 1, 2, 9, 4, 9, 10, 5, + 16, 1, 2, 17, 4, 17, 18, 5, 8, 17, 18, 9, 20, 9, 10, 21, + 32, 1, 2, 33, 4, 33, 34, 5, 8, 33, 34, 9, 36, 9, 10, 37, + 16, 33, 34, 17, 36, 17, 18, 37, 40, 17, 18, 41, 20, 41, 42, 53, + 64, 1, 2, 65, 4, 65, 66, 5, 8, 65, 66, 9, 68, 9, 10, 69, + 16, 65, 66, 17, 68, 17, 18, 69, 72, 17, 18, 73, 20, 73, 74, 85, + 32, 65, 66, 33, 68, 33, 34, 69, 72, 33, 34, 73, 36, 73, 74, 101, + 80, 33, 34, 81, 36, 81, 82, 101, 40, 81, 82, 105, 84, 105, 106, 53, + 128, 1, 2, 129, 4, 129, 130, 5, 8, 129, 130, 9, 132, 9, 10, 133, + 16, 129, 130, 17, 132, 17, 18, 133, 136, 17, 18, 137, 20, 137, 138, 149, + 32, 129, 130, 33, 132, 33, 34, 133, 136, 33, 34, 137, 36, 137, 138, 165, + 144, 33, 34, 145, 36, 145, 146, 165, 40, 145, 146, 169, 148, 169, 170, 53, + 64, 129, 130, 65, 132, 65, 66, 133, 136, 65, 66, 137, 68, 137, 138, 197, + 144, 65, 66, 145, 68, 145, 146, 197, 72, 145, 146, 201, 148, 201, 202, 85, + 160, 65, 66, 161, 68, 161, 162, 197, 72, 161, 162, 201, 164, 201, 202, 101, + 80, 161, 162, 209, 164, 209, 210, 101, 168, 209, 210, 105, 212, 105, 106, 181, + }, { + 0, 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10, 8, 12, 12, 6, + 0, 16, 16, 18, 16, 20, 20, 6, 16, 24, 24, 10, 24, 12, 12, 22, + 0, 32, 32, 34, 32, 36, 36, 6, 32, 40, 40, 10, 40, 12, 12, 38, + 32, 48, 48, 18, 48, 20, 20, 38, 48, 24, 24, 42, 24, 44, 44, 54, + 0, 64, 64, 66, 64, 68, 68, 6, 64, 72, 72, 10, 72, 12, 12, 70, + 64, 80, 80, 18, 80, 20, 20, 70, 80, 24, 24, 74, 24, 76, 76, 86, + 64, 96, 96, 34, 96, 36, 36, 70, 96, 40, 40, 74, 40, 76, 76, 102, + 96, 48, 48, 82, 48, 84, 84, 102, 48, 88, 88, 106, 88, 108, 108, 54, + 0, 128, 128, 130, 128, 132, 132, 6, 128, 136, 136, 10, 136, 12, 12, 134, + 128, 144, 144, 18, 144, 20, 20, 134, 144, 24, 24, 138, 24, 140, 140, 150, + 128, 160, 160, 34, 160, 36, 36, 134, 160, 40, 40, 138, 40, 140, 140, 166, + 160, 48, 48, 146, 48, 148, 148, 166, 48, 152, 152, 170, 152, 172, 172, 54, + 128, 192, 192, 66, 192, 68, 68, 134, 192, 72, 72, 138, 72, 140, 140, 198, + 192, 80, 80, 146, 80, 148, 148, 198, 80, 152, 152, 202, 152, 204, 204, 86, + 192, 96, 96, 162, 96, 164, 164, 198, 96, 168, 168, 202, 168, 204, 204, 102, + 96, 176, 176, 210, 176, 212, 212, 102, 176, 216, 216, 106, 216, 108, 108, 182, + }, { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 7, + 16, 17, 18, 19, 20, 21, 22, 7, 24, 25, 26, 11, 28, 13, 14, 23, + 32, 33, 34, 35, 36, 37, 38, 7, 40, 41, 42, 11, 44, 13, 14, 39, + 48, 49, 50, 19, 52, 21, 22, 39, 56, 25, 26, 43, 28, 45, 46, 55, + 64, 65, 66, 67, 68, 69, 70, 7, 72, 73, 74, 11, 76, 13, 14, 71, + 80, 81, 82, 19, 84, 21, 22, 71, 88, 25, 26, 75, 28, 77, 78, 87, + 96, 97, 98, 35, 100, 37, 38, 71, 104, 41, 42, 75, 44, 77, 78, 103, + 112, 49, 50, 83, 52, 85, 86, 103, 56, 89, 90, 107, 92, 109, 110, 55, + 128, 129, 130, 131, 132, 133, 134, 7, 136, 137, 138, 11, 140, 13, 14, 135, + 144, 145, 146, 19, 148, 21, 22, 135, 152, 25, 26, 139, 28, 141, 142, 151, + 160, 161, 162, 35, 164, 37, 38, 135, 168, 41, 42, 139, 44, 141, 142, 167, + 176, 49, 50, 147, 52, 149, 150, 167, 56, 153, 154, 171, 156, 173, 174, 55, + 192, 193, 194, 67, 196, 69, 70, 135, 200, 73, 74, 139, 76, 141, 142, 199, + 208, 81, 82, 147, 84, 149, 150, 199, 88, 153, 154, 203, 156, 205, 206, 87, + 224, 97, 98, 163, 100, 165, 166, 199, 104, 169, 170, 203, 172, 205, 206, 103, + 112, 177, 178, 211, 180, 213, 214, 103, 184, 217, 218, 107, 220, 109, 110, 183, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, + 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 16, 0, 16, 16, 24, + 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 32, 0, 32, 32, 40, + 0, 0, 0, 32, 0, 32, 32, 48, 0, 32, 32, 48, 32, 48, 48, 56, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 72, + 0, 0, 0, 64, 0, 64, 64, 80, 0, 64, 64, 80, 64, 80, 80, 88, + 0, 0, 0, 64, 0, 64, 64, 96, 0, 64, 64, 96, 64, 96, 96, 104, + 0, 64, 64, 96, 64, 96, 96, 112, 64, 96, 96, 112, 96, 112, 112, 56, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 136, + 0, 0, 0, 128, 0, 128, 128, 144, 0, 128, 128, 144, 128, 144, 144, 152, + 0, 0, 0, 128, 0, 128, 128, 160, 0, 128, 128, 160, 128, 160, 160, 168, + 0, 128, 128, 160, 128, 160, 160, 176, 128, 160, 160, 176, 160, 176, 176, 56, + 0, 0, 0, 128, 0, 128, 128, 192, 0, 128, 128, 192, 128, 192, 192, 200, + 0, 128, 128, 192, 128, 192, 192, 208, 128, 192, 192, 208, 192, 208, 208, 88, + 0, 128, 128, 192, 128, 192, 192, 224, 128, 192, 192, 224, 192, 224, 224, 104, + 128, 192, 192, 224, 192, 224, 224, 112, 192, 224, 224, 112, 224, 112, 112, 184, + }, { + 0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 9, + 16, 1, 2, 1, 4, 1, 2, 17, 8, 1, 2, 17, 4, 17, 18, 25, + 32, 1, 2, 1, 4, 1, 2, 33, 8, 1, 2, 33, 4, 33, 34, 41, + 16, 1, 2, 33, 4, 33, 34, 49, 8, 33, 34, 49, 36, 49, 50, 57, + 64, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 73, + 16, 1, 2, 65, 4, 65, 66, 81, 8, 65, 66, 81, 68, 81, 82, 89, + 32, 1, 2, 65, 4, 65, 66, 97, 8, 65, 66, 97, 68, 97, 98, 105, + 16, 65, 66, 97, 68, 97, 98, 113, 72, 97, 98, 113, 100, 113, 114, 57, + 128, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 137, + 16, 1, 2, 129, 4, 129, 130, 145, 8, 129, 130, 145, 132, 145, 146, 153, + 32, 1, 2, 129, 4, 129, 130, 161, 8, 129, 130, 161, 132, 161, 162, 169, + 16, 129, 130, 161, 132, 161, 162, 177, 136, 161, 162, 177, 164, 177, 178, 57, + 64, 1, 2, 129, 4, 129, 130, 193, 8, 129, 130, 193, 132, 193, 194, 201, + 16, 129, 130, 193, 132, 193, 194, 209, 136, 193, 194, 209, 196, 209, 210, 89, + 32, 129, 130, 193, 132, 193, 194, 225, 136, 193, 194, 225, 196, 225, 226, 105, + 144, 193, 194, 225, 196, 225, 226, 113, 200, 225, 226, 113, 228, 113, 114, 185, + }, { + 0, 0, 0, 2, 0, 4, 4, 2, 0, 8, 8, 2, 8, 4, 4, 10, + 0, 16, 16, 2, 16, 4, 4, 18, 16, 8, 8, 18, 8, 20, 20, 26, + 0, 32, 32, 2, 32, 4, 4, 34, 32, 8, 8, 34, 8, 36, 36, 42, + 32, 16, 16, 34, 16, 36, 36, 50, 16, 40, 40, 50, 40, 52, 52, 58, + 0, 64, 64, 2, 64, 4, 4, 66, 64, 8, 8, 66, 8, 68, 68, 74, + 64, 16, 16, 66, 16, 68, 68, 82, 16, 72, 72, 82, 72, 84, 84, 90, + 64, 32, 32, 66, 32, 68, 68, 98, 32, 72, 72, 98, 72, 100, 100, 106, + 32, 80, 80, 98, 80, 100, 100, 114, 80, 104, 104, 114, 104, 116, 116, 58, + 0, 128, 128, 2, 128, 4, 4, 130, 128, 8, 8, 130, 8, 132, 132, 138, + 128, 16, 16, 130, 16, 132, 132, 146, 16, 136, 136, 146, 136, 148, 148, 154, + 128, 32, 32, 130, 32, 132, 132, 162, 32, 136, 136, 162, 136, 164, 164, 170, + 32, 144, 144, 162, 144, 164, 164, 178, 144, 168, 168, 178, 168, 180, 180, 58, + 128, 64, 64, 130, 64, 132, 132, 194, 64, 136, 136, 194, 136, 196, 196, 202, + 64, 144, 144, 194, 144, 196, 196, 210, 144, 200, 200, 210, 200, 212, 212, 90, + 64, 160, 160, 194, 160, 196, 196, 226, 160, 200, 200, 226, 200, 228, 228, 106, + 160, 208, 208, 226, 208, 228, 228, 114, 208, 232, 232, 114, 232, 116, 116, 186, + }, { + 0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 10, 3, 12, 5, 6, 11, + 16, 17, 18, 3, 20, 5, 6, 19, 24, 9, 10, 19, 12, 21, 22, 27, + 32, 33, 34, 3, 36, 5, 6, 35, 40, 9, 10, 35, 12, 37, 38, 43, + 48, 17, 18, 35, 20, 37, 38, 51, 24, 41, 42, 51, 44, 53, 54, 59, + 64, 65, 66, 3, 68, 5, 6, 67, 72, 9, 10, 67, 12, 69, 70, 75, + 80, 17, 18, 67, 20, 69, 70, 83, 24, 73, 74, 83, 76, 85, 86, 91, + 96, 33, 34, 67, 36, 69, 70, 99, 40, 73, 74, 99, 76, 101, 102, 107, + 48, 81, 82, 99, 84, 101, 102, 115, 88, 105, 106, 115, 108, 117, 118, 59, + 128, 129, 130, 3, 132, 5, 6, 131, 136, 9, 10, 131, 12, 133, 134, 139, + 144, 17, 18, 131, 20, 133, 134, 147, 24, 137, 138, 147, 140, 149, 150, 155, + 160, 33, 34, 131, 36, 133, 134, 163, 40, 137, 138, 163, 140, 165, 166, 171, + 48, 145, 146, 163, 148, 165, 166, 179, 152, 169, 170, 179, 172, 181, 182, 59, + 192, 65, 66, 131, 68, 133, 134, 195, 72, 137, 138, 195, 140, 197, 198, 203, + 80, 145, 146, 195, 148, 197, 198, 211, 152, 201, 202, 211, 204, 213, 214, 91, + 96, 161, 162, 195, 164, 197, 198, 227, 168, 201, 202, 227, 204, 229, 230, 107, + 176, 209, 210, 227, 212, 229, 230, 115, 216, 233, 234, 115, 236, 117, 118, 187, + }, + { + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 8, 8, 12, + 0, 0, 0, 16, 0, 16, 16, 20, 0, 16, 16, 24, 16, 24, 24, 28, + 0, 0, 0, 32, 0, 32, 32, 36, 0, 32, 32, 40, 32, 40, 40, 44, + 0, 32, 32, 48, 32, 48, 48, 52, 32, 48, 48, 56, 48, 56, 56, 60, + 0, 0, 0, 64, 0, 64, 64, 68, 0, 64, 64, 72, 64, 72, 72, 76, + 0, 64, 64, 80, 64, 80, 80, 84, 64, 80, 80, 88, 80, 88, 88, 92, + 0, 64, 64, 96, 64, 96, 96, 100, 64, 96, 96, 104, 96, 104, 104, 108, + 64, 96, 96, 112, 96, 112, 112, 116, 96, 112, 112, 120, 112, 120, 120, 60, + 0, 0, 0, 128, 0, 128, 128, 132, 0, 128, 128, 136, 128, 136, 136, 140, + 0, 128, 128, 144, 128, 144, 144, 148, 128, 144, 144, 152, 144, 152, 152, 156, + 0, 128, 128, 160, 128, 160, 160, 164, 128, 160, 160, 168, 160, 168, 168, 172, + 128, 160, 160, 176, 160, 176, 176, 180, 160, 176, 176, 184, 176, 184, 184, 60, + 0, 128, 128, 192, 128, 192, 192, 196, 128, 192, 192, 200, 192, 200, 200, 204, + 128, 192, 192, 208, 192, 208, 208, 212, 192, 208, 208, 216, 208, 216, 216, 92, + 128, 192, 192, 224, 192, 224, 224, 228, 192, 224, 224, 232, 224, 232, 232, 108, + 192, 224, 224, 240, 224, 240, 240, 116, 224, 240, 240, 120, 240, 120, 120, 188, + }, { + 0, 1, 2, 1, 4, 1, 2, 5, 8, 1, 2, 9, 4, 9, 10, 13, + 16, 1, 2, 17, 4, 17, 18, 21, 8, 17, 18, 25, 20, 25, 26, 29, + 32, 1, 2, 33, 4, 33, 34, 37, 8, 33, 34, 41, 36, 41, 42, 45, + 16, 33, 34, 49, 36, 49, 50, 53, 40, 49, 50, 57, 52, 57, 58, 61, + 64, 1, 2, 65, 4, 65, 66, 69, 8, 65, 66, 73, 68, 73, 74, 77, + 16, 65, 66, 81, 68, 81, 82, 85, 72, 81, 82, 89, 84, 89, 90, 93, + 32, 65, 66, 97, 68, 97, 98, 101, 72, 97, 98, 105, 100, 105, 106, 109, + 80, 97, 98, 113, 100, 113, 114, 117, 104, 113, 114, 121, 116, 121, 122, 61, + 128, 1, 2, 129, 4, 129, 130, 133, 8, 129, 130, 137, 132, 137, 138, 141, + 16, 129, 130, 145, 132, 145, 146, 149, 136, 145, 146, 153, 148, 153, 154, 157, + 32, 129, 130, 161, 132, 161, 162, 165, 136, 161, 162, 169, 164, 169, 170, 173, + 144, 161, 162, 177, 164, 177, 178, 181, 168, 177, 178, 185, 180, 185, 186, 61, + 64, 129, 130, 193, 132, 193, 194, 197, 136, 193, 194, 201, 196, 201, 202, 205, + 144, 193, 194, 209, 196, 209, 210, 213, 200, 209, 210, 217, 212, 217, 218, 93, + 160, 193, 194, 225, 196, 225, 226, 229, 200, 225, 226, 233, 228, 233, 234, 109, + 208, 225, 226, 241, 228, 241, 242, 117, 232, 241, 242, 121, 244, 121, 122, 189, + }, { + 0, 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10, 8, 12, 12, 14, + 0, 16, 16, 18, 16, 20, 20, 22, 16, 24, 24, 26, 24, 28, 28, 30, + 0, 32, 32, 34, 32, 36, 36, 38, 32, 40, 40, 42, 40, 44, 44, 46, + 32, 48, 48, 50, 48, 52, 52, 54, 48, 56, 56, 58, 56, 60, 60, 62, + 0, 64, 64, 66, 64, 68, 68, 70, 64, 72, 72, 74, 72, 76, 76, 78, + 64, 80, 80, 82, 80, 84, 84, 86, 80, 88, 88, 90, 88, 92, 92, 94, + 64, 96, 96, 98, 96, 100, 100, 102, 96, 104, 104, 106, 104, 108, 108, 110, + 96, 112, 112, 114, 112, 116, 116, 118, 112, 120, 120, 122, 120, 124, 124, 62, + 0, 128, 128, 130, 128, 132, 132, 134, 128, 136, 136, 138, 136, 140, 140, 142, + 128, 144, 144, 146, 144, 148, 148, 150, 144, 152, 152, 154, 152, 156, 156, 158, + 128, 160, 160, 162, 160, 164, 164, 166, 160, 168, 168, 170, 168, 172, 172, 174, + 160, 176, 176, 178, 176, 180, 180, 182, 176, 184, 184, 186, 184, 188, 188, 62, + 128, 192, 192, 194, 192, 196, 196, 198, 192, 200, 200, 202, 200, 204, 204, 206, + 192, 208, 208, 210, 208, 212, 212, 214, 208, 216, 216, 218, 216, 220, 220, 94, + 192, 224, 224, 226, 224, 228, 228, 230, 224, 232, 232, 234, 232, 236, 236, 110, + 224, 240, 240, 242, 240, 244, 244, 118, 240, 248, 248, 122, 248, 124, 124, 190, + }, { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 63, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, + 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, + 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 63, + 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, + 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 95, + 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 111, + 240, 241, 242, 243, 244, 245, 246, 119, 248, 249, 250, 123, 252, 125, 126, 191, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 192, + }, { + 0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 64, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 65, + 128, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 129, + 64, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 129, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 129, + 16, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 193, + }, { + 0, 0, 0, 2, 0, 4, 4, 2, 0, 8, 8, 2, 8, 4, 4, 2, + 0, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 2, + 0, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 2, + 32, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 2, + 0, 64, 64, 2, 64, 4, 4, 2, 64, 8, 8, 2, 8, 4, 4, 2, + 64, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 2, + 64, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 2, + 32, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 66, + 0, 128, 128, 2, 128, 4, 4, 2, 128, 8, 8, 2, 8, 4, 4, 2, + 128, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 2, + 128, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 2, + 32, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 130, + 128, 64, 64, 2, 64, 4, 4, 2, 64, 8, 8, 2, 8, 4, 4, 2, + 64, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 130, + 64, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 130, + 32, 16, 16, 2, 16, 4, 4, 130, 16, 8, 8, 130, 8, 132, 132, 194, + }, { + 0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 10, 3, 12, 5, 6, 3, + 16, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 3, + 32, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 3, + 48, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 3, + 64, 65, 66, 3, 68, 5, 6, 3, 72, 9, 10, 3, 12, 5, 6, 3, + 80, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 3, + 96, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 3, + 48, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 67, + 128, 129, 130, 3, 132, 5, 6, 3, 136, 9, 10, 3, 12, 5, 6, 3, + 144, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 3, + 160, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 3, + 48, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 131, + 192, 65, 66, 3, 68, 5, 6, 3, 72, 9, 10, 3, 12, 5, 6, 3, + 80, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 131, + 96, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 131, + 48, 17, 18, 3, 20, 5, 6, 131, 24, 9, 10, 131, 12, 133, 134, 195, + }, + { + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 8, 8, 4, + 0, 0, 0, 16, 0, 16, 16, 4, 0, 16, 16, 8, 16, 8, 8, 4, + 0, 0, 0, 32, 0, 32, 32, 4, 0, 32, 32, 8, 32, 8, 8, 4, + 0, 32, 32, 16, 32, 16, 16, 4, 32, 16, 16, 8, 16, 8, 8, 4, + 0, 0, 0, 64, 0, 64, 64, 4, 0, 64, 64, 8, 64, 8, 8, 4, + 0, 64, 64, 16, 64, 16, 16, 4, 64, 16, 16, 8, 16, 8, 8, 4, + 0, 64, 64, 32, 64, 32, 32, 4, 64, 32, 32, 8, 32, 8, 8, 4, + 64, 32, 32, 16, 32, 16, 16, 4, 32, 16, 16, 8, 16, 8, 8, 68, + 0, 0, 0, 128, 0, 128, 128, 4, 0, 128, 128, 8, 128, 8, 8, 4, + 0, 128, 128, 16, 128, 16, 16, 4, 128, 16, 16, 8, 16, 8, 8, 4, + 0, 128, 128, 32, 128, 32, 32, 4, 128, 32, 32, 8, 32, 8, 8, 4, + 128, 32, 32, 16, 32, 16, 16, 4, 32, 16, 16, 8, 16, 8, 8, 132, + 0, 128, 128, 64, 128, 64, 64, 4, 128, 64, 64, 8, 64, 8, 8, 4, + 128, 64, 64, 16, 64, 16, 16, 4, 64, 16, 16, 8, 16, 8, 8, 132, + 128, 64, 64, 32, 64, 32, 32, 4, 64, 32, 32, 8, 32, 8, 8, 132, + 64, 32, 32, 16, 32, 16, 16, 132, 32, 16, 16, 136, 16, 136, 136, 196, + }, { + 0, 1, 2, 1, 4, 1, 2, 5, 8, 1, 2, 9, 4, 9, 10, 5, + 16, 1, 2, 17, 4, 17, 18, 5, 8, 17, 18, 9, 20, 9, 10, 5, + 32, 1, 2, 33, 4, 33, 34, 5, 8, 33, 34, 9, 36, 9, 10, 5, + 16, 33, 34, 17, 36, 17, 18, 5, 40, 17, 18, 9, 20, 9, 10, 5, + 64, 1, 2, 65, 4, 65, 66, 5, 8, 65, 66, 9, 68, 9, 10, 5, + 16, 65, 66, 17, 68, 17, 18, 5, 72, 17, 18, 9, 20, 9, 10, 5, + 32, 65, 66, 33, 68, 33, 34, 5, 72, 33, 34, 9, 36, 9, 10, 5, + 80, 33, 34, 17, 36, 17, 18, 5, 40, 17, 18, 9, 20, 9, 10, 69, + 128, 1, 2, 129, 4, 129, 130, 5, 8, 129, 130, 9, 132, 9, 10, 5, + 16, 129, 130, 17, 132, 17, 18, 5, 136, 17, 18, 9, 20, 9, 10, 5, + 32, 129, 130, 33, 132, 33, 34, 5, 136, 33, 34, 9, 36, 9, 10, 5, + 144, 33, 34, 17, 36, 17, 18, 5, 40, 17, 18, 9, 20, 9, 10, 133, + 64, 129, 130, 65, 132, 65, 66, 5, 136, 65, 66, 9, 68, 9, 10, 5, + 144, 65, 66, 17, 68, 17, 18, 5, 72, 17, 18, 9, 20, 9, 10, 133, + 160, 65, 66, 33, 68, 33, 34, 5, 72, 33, 34, 9, 36, 9, 10, 133, + 80, 33, 34, 17, 36, 17, 18, 133, 40, 17, 18, 137, 20, 137, 138, 197, + }, { + 0, 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10, 8, 12, 12, 6, + 0, 16, 16, 18, 16, 20, 20, 6, 16, 24, 24, 10, 24, 12, 12, 6, + 0, 32, 32, 34, 32, 36, 36, 6, 32, 40, 40, 10, 40, 12, 12, 6, + 32, 48, 48, 18, 48, 20, 20, 6, 48, 24, 24, 10, 24, 12, 12, 6, + 0, 64, 64, 66, 64, 68, 68, 6, 64, 72, 72, 10, 72, 12, 12, 6, + 64, 80, 80, 18, 80, 20, 20, 6, 80, 24, 24, 10, 24, 12, 12, 6, + 64, 96, 96, 34, 96, 36, 36, 6, 96, 40, 40, 10, 40, 12, 12, 6, + 96, 48, 48, 18, 48, 20, 20, 6, 48, 24, 24, 10, 24, 12, 12, 70, + 0, 128, 128, 130, 128, 132, 132, 6, 128, 136, 136, 10, 136, 12, 12, 6, + 128, 144, 144, 18, 144, 20, 20, 6, 144, 24, 24, 10, 24, 12, 12, 6, + 128, 160, 160, 34, 160, 36, 36, 6, 160, 40, 40, 10, 40, 12, 12, 6, + 160, 48, 48, 18, 48, 20, 20, 6, 48, 24, 24, 10, 24, 12, 12, 134, + 128, 192, 192, 66, 192, 68, 68, 6, 192, 72, 72, 10, 72, 12, 12, 6, + 192, 80, 80, 18, 80, 20, 20, 6, 80, 24, 24, 10, 24, 12, 12, 134, + 192, 96, 96, 34, 96, 36, 36, 6, 96, 40, 40, 10, 40, 12, 12, 134, + 96, 48, 48, 18, 48, 20, 20, 134, 48, 24, 24, 138, 24, 140, 140, 198, + }, { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 7, + 16, 17, 18, 19, 20, 21, 22, 7, 24, 25, 26, 11, 28, 13, 14, 7, + 32, 33, 34, 35, 36, 37, 38, 7, 40, 41, 42, 11, 44, 13, 14, 7, + 48, 49, 50, 19, 52, 21, 22, 7, 56, 25, 26, 11, 28, 13, 14, 7, + 64, 65, 66, 67, 68, 69, 70, 7, 72, 73, 74, 11, 76, 13, 14, 7, + 80, 81, 82, 19, 84, 21, 22, 7, 88, 25, 26, 11, 28, 13, 14, 7, + 96, 97, 98, 35, 100, 37, 38, 7, 104, 41, 42, 11, 44, 13, 14, 7, + 112, 49, 50, 19, 52, 21, 22, 7, 56, 25, 26, 11, 28, 13, 14, 71, + 128, 129, 130, 131, 132, 133, 134, 7, 136, 137, 138, 11, 140, 13, 14, 7, + 144, 145, 146, 19, 148, 21, 22, 7, 152, 25, 26, 11, 28, 13, 14, 7, + 160, 161, 162, 35, 164, 37, 38, 7, 168, 41, 42, 11, 44, 13, 14, 7, + 176, 49, 50, 19, 52, 21, 22, 7, 56, 25, 26, 11, 28, 13, 14, 135, + 192, 193, 194, 67, 196, 69, 70, 7, 200, 73, 74, 11, 76, 13, 14, 7, + 208, 81, 82, 19, 84, 21, 22, 7, 88, 25, 26, 11, 28, 13, 14, 135, + 224, 97, 98, 35, 100, 37, 38, 7, 104, 41, 42, 11, 44, 13, 14, 135, + 112, 49, 50, 19, 52, 21, 22, 135, 56, 25, 26, 139, 28, 141, 142, 199, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, + 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 16, 0, 16, 16, 8, + 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 32, 0, 32, 32, 8, + 0, 0, 0, 32, 0, 32, 32, 16, 0, 32, 32, 16, 32, 16, 16, 8, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 8, + 0, 0, 0, 64, 0, 64, 64, 16, 0, 64, 64, 16, 64, 16, 16, 8, + 0, 0, 0, 64, 0, 64, 64, 32, 0, 64, 64, 32, 64, 32, 32, 8, + 0, 64, 64, 32, 64, 32, 32, 16, 64, 32, 32, 16, 32, 16, 16, 72, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 8, + 0, 0, 0, 128, 0, 128, 128, 16, 0, 128, 128, 16, 128, 16, 16, 8, + 0, 0, 0, 128, 0, 128, 128, 32, 0, 128, 128, 32, 128, 32, 32, 8, + 0, 128, 128, 32, 128, 32, 32, 16, 128, 32, 32, 16, 32, 16, 16, 136, + 0, 0, 0, 128, 0, 128, 128, 64, 0, 128, 128, 64, 128, 64, 64, 8, + 0, 128, 128, 64, 128, 64, 64, 16, 128, 64, 64, 16, 64, 16, 16, 136, + 0, 128, 128, 64, 128, 64, 64, 32, 128, 64, 64, 32, 64, 32, 32, 136, + 128, 64, 64, 32, 64, 32, 32, 144, 64, 32, 32, 144, 32, 144, 144, 200, + }, { + 0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 9, + 16, 1, 2, 1, 4, 1, 2, 17, 8, 1, 2, 17, 4, 17, 18, 9, + 32, 1, 2, 1, 4, 1, 2, 33, 8, 1, 2, 33, 4, 33, 34, 9, + 16, 1, 2, 33, 4, 33, 34, 17, 8, 33, 34, 17, 36, 17, 18, 9, + 64, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 9, + 16, 1, 2, 65, 4, 65, 66, 17, 8, 65, 66, 17, 68, 17, 18, 9, + 32, 1, 2, 65, 4, 65, 66, 33, 8, 65, 66, 33, 68, 33, 34, 9, + 16, 65, 66, 33, 68, 33, 34, 17, 72, 33, 34, 17, 36, 17, 18, 73, + 128, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 9, + 16, 1, 2, 129, 4, 129, 130, 17, 8, 129, 130, 17, 132, 17, 18, 9, + 32, 1, 2, 129, 4, 129, 130, 33, 8, 129, 130, 33, 132, 33, 34, 9, + 16, 129, 130, 33, 132, 33, 34, 17, 136, 33, 34, 17, 36, 17, 18, 137, + 64, 1, 2, 129, 4, 129, 130, 65, 8, 129, 130, 65, 132, 65, 66, 9, + 16, 129, 130, 65, 132, 65, 66, 17, 136, 65, 66, 17, 68, 17, 18, 137, + 32, 129, 130, 65, 132, 65, 66, 33, 136, 65, 66, 33, 68, 33, 34, 137, + 144, 65, 66, 33, 68, 33, 34, 145, 72, 33, 34, 145, 36, 145, 146, 201, + }, { + 0, 0, 0, 2, 0, 4, 4, 2, 0, 8, 8, 2, 8, 4, 4, 10, + 0, 16, 16, 2, 16, 4, 4, 18, 16, 8, 8, 18, 8, 20, 20, 10, + 0, 32, 32, 2, 32, 4, 4, 34, 32, 8, 8, 34, 8, 36, 36, 10, + 32, 16, 16, 34, 16, 36, 36, 18, 16, 40, 40, 18, 40, 20, 20, 10, + 0, 64, 64, 2, 64, 4, 4, 66, 64, 8, 8, 66, 8, 68, 68, 10, + 64, 16, 16, 66, 16, 68, 68, 18, 16, 72, 72, 18, 72, 20, 20, 10, + 64, 32, 32, 66, 32, 68, 68, 34, 32, 72, 72, 34, 72, 36, 36, 10, + 32, 80, 80, 34, 80, 36, 36, 18, 80, 40, 40, 18, 40, 20, 20, 74, + 0, 128, 128, 2, 128, 4, 4, 130, 128, 8, 8, 130, 8, 132, 132, 10, + 128, 16, 16, 130, 16, 132, 132, 18, 16, 136, 136, 18, 136, 20, 20, 10, + 128, 32, 32, 130, 32, 132, 132, 34, 32, 136, 136, 34, 136, 36, 36, 10, + 32, 144, 144, 34, 144, 36, 36, 18, 144, 40, 40, 18, 40, 20, 20, 138, + 128, 64, 64, 130, 64, 132, 132, 66, 64, 136, 136, 66, 136, 68, 68, 10, + 64, 144, 144, 66, 144, 68, 68, 18, 144, 72, 72, 18, 72, 20, 20, 138, + 64, 160, 160, 66, 160, 68, 68, 34, 160, 72, 72, 34, 72, 36, 36, 138, + 160, 80, 80, 34, 80, 36, 36, 146, 80, 40, 40, 146, 40, 148, 148, 202, + }, { + 0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 10, 3, 12, 5, 6, 11, + 16, 17, 18, 3, 20, 5, 6, 19, 24, 9, 10, 19, 12, 21, 22, 11, + 32, 33, 34, 3, 36, 5, 6, 35, 40, 9, 10, 35, 12, 37, 38, 11, + 48, 17, 18, 35, 20, 37, 38, 19, 24, 41, 42, 19, 44, 21, 22, 11, + 64, 65, 66, 3, 68, 5, 6, 67, 72, 9, 10, 67, 12, 69, 70, 11, + 80, 17, 18, 67, 20, 69, 70, 19, 24, 73, 74, 19, 76, 21, 22, 11, + 96, 33, 34, 67, 36, 69, 70, 35, 40, 73, 74, 35, 76, 37, 38, 11, + 48, 81, 82, 35, 84, 37, 38, 19, 88, 41, 42, 19, 44, 21, 22, 75, + 128, 129, 130, 3, 132, 5, 6, 131, 136, 9, 10, 131, 12, 133, 134, 11, + 144, 17, 18, 131, 20, 133, 134, 19, 24, 137, 138, 19, 140, 21, 22, 11, + 160, 33, 34, 131, 36, 133, 134, 35, 40, 137, 138, 35, 140, 37, 38, 11, + 48, 145, 146, 35, 148, 37, 38, 19, 152, 41, 42, 19, 44, 21, 22, 139, + 192, 65, 66, 131, 68, 133, 134, 67, 72, 137, 138, 67, 140, 69, 70, 11, + 80, 145, 146, 67, 148, 69, 70, 19, 152, 73, 74, 19, 76, 21, 22, 139, + 96, 161, 162, 67, 164, 69, 70, 35, 168, 73, 74, 35, 76, 37, 38, 139, + 176, 81, 82, 35, 84, 37, 38, 147, 88, 41, 42, 147, 44, 149, 150, 203, + }, + { + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 8, 8, 12, + 0, 0, 0, 16, 0, 16, 16, 20, 0, 16, 16, 24, 16, 24, 24, 12, + 0, 0, 0, 32, 0, 32, 32, 36, 0, 32, 32, 40, 32, 40, 40, 12, + 0, 32, 32, 48, 32, 48, 48, 20, 32, 48, 48, 24, 48, 24, 24, 12, + 0, 0, 0, 64, 0, 64, 64, 68, 0, 64, 64, 72, 64, 72, 72, 12, + 0, 64, 64, 80, 64, 80, 80, 20, 64, 80, 80, 24, 80, 24, 24, 12, + 0, 64, 64, 96, 64, 96, 96, 36, 64, 96, 96, 40, 96, 40, 40, 12, + 64, 96, 96, 48, 96, 48, 48, 20, 96, 48, 48, 24, 48, 24, 24, 76, + 0, 0, 0, 128, 0, 128, 128, 132, 0, 128, 128, 136, 128, 136, 136, 12, + 0, 128, 128, 144, 128, 144, 144, 20, 128, 144, 144, 24, 144, 24, 24, 12, + 0, 128, 128, 160, 128, 160, 160, 36, 128, 160, 160, 40, 160, 40, 40, 12, + 128, 160, 160, 48, 160, 48, 48, 20, 160, 48, 48, 24, 48, 24, 24, 140, + 0, 128, 128, 192, 128, 192, 192, 68, 128, 192, 192, 72, 192, 72, 72, 12, + 128, 192, 192, 80, 192, 80, 80, 20, 192, 80, 80, 24, 80, 24, 24, 140, + 128, 192, 192, 96, 192, 96, 96, 36, 192, 96, 96, 40, 96, 40, 40, 140, + 192, 96, 96, 48, 96, 48, 48, 148, 96, 48, 48, 152, 48, 152, 152, 204, + }, { + 0, 1, 2, 1, 4, 1, 2, 5, 8, 1, 2, 9, 4, 9, 10, 13, + 16, 1, 2, 17, 4, 17, 18, 21, 8, 17, 18, 25, 20, 25, 26, 13, + 32, 1, 2, 33, 4, 33, 34, 37, 8, 33, 34, 41, 36, 41, 42, 13, + 16, 33, 34, 49, 36, 49, 50, 21, 40, 49, 50, 25, 52, 25, 26, 13, + 64, 1, 2, 65, 4, 65, 66, 69, 8, 65, 66, 73, 68, 73, 74, 13, + 16, 65, 66, 81, 68, 81, 82, 21, 72, 81, 82, 25, 84, 25, 26, 13, + 32, 65, 66, 97, 68, 97, 98, 37, 72, 97, 98, 41, 100, 41, 42, 13, + 80, 97, 98, 49, 100, 49, 50, 21, 104, 49, 50, 25, 52, 25, 26, 77, + 128, 1, 2, 129, 4, 129, 130, 133, 8, 129, 130, 137, 132, 137, 138, 13, + 16, 129, 130, 145, 132, 145, 146, 21, 136, 145, 146, 25, 148, 25, 26, 13, + 32, 129, 130, 161, 132, 161, 162, 37, 136, 161, 162, 41, 164, 41, 42, 13, + 144, 161, 162, 49, 164, 49, 50, 21, 168, 49, 50, 25, 52, 25, 26, 141, + 64, 129, 130, 193, 132, 193, 194, 69, 136, 193, 194, 73, 196, 73, 74, 13, + 144, 193, 194, 81, 196, 81, 82, 21, 200, 81, 82, 25, 84, 25, 26, 141, + 160, 193, 194, 97, 196, 97, 98, 37, 200, 97, 98, 41, 100, 41, 42, 141, + 208, 97, 98, 49, 100, 49, 50, 149, 104, 49, 50, 153, 52, 153, 154, 205, + }, { + 0, 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10, 8, 12, 12, 14, + 0, 16, 16, 18, 16, 20, 20, 22, 16, 24, 24, 26, 24, 28, 28, 14, + 0, 32, 32, 34, 32, 36, 36, 38, 32, 40, 40, 42, 40, 44, 44, 14, + 32, 48, 48, 50, 48, 52, 52, 22, 48, 56, 56, 26, 56, 28, 28, 14, + 0, 64, 64, 66, 64, 68, 68, 70, 64, 72, 72, 74, 72, 76, 76, 14, + 64, 80, 80, 82, 80, 84, 84, 22, 80, 88, 88, 26, 88, 28, 28, 14, + 64, 96, 96, 98, 96, 100, 100, 38, 96, 104, 104, 42, 104, 44, 44, 14, + 96, 112, 112, 50, 112, 52, 52, 22, 112, 56, 56, 26, 56, 28, 28, 78, + 0, 128, 128, 130, 128, 132, 132, 134, 128, 136, 136, 138, 136, 140, 140, 14, + 128, 144, 144, 146, 144, 148, 148, 22, 144, 152, 152, 26, 152, 28, 28, 14, + 128, 160, 160, 162, 160, 164, 164, 38, 160, 168, 168, 42, 168, 44, 44, 14, + 160, 176, 176, 50, 176, 52, 52, 22, 176, 56, 56, 26, 56, 28, 28, 142, + 128, 192, 192, 194, 192, 196, 196, 70, 192, 200, 200, 74, 200, 76, 76, 14, + 192, 208, 208, 82, 208, 84, 84, 22, 208, 88, 88, 26, 88, 28, 28, 142, + 192, 224, 224, 98, 224, 100, 100, 38, 224, 104, 104, 42, 104, 44, 44, 142, + 224, 112, 112, 50, 112, 52, 52, 150, 112, 56, 56, 154, 56, 156, 156, 206, + }, { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 15, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 15, + 48, 49, 50, 51, 52, 53, 54, 23, 56, 57, 58, 27, 60, 29, 30, 15, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 15, + 80, 81, 82, 83, 84, 85, 86, 23, 88, 89, 90, 27, 92, 29, 30, 15, + 96, 97, 98, 99, 100, 101, 102, 39, 104, 105, 106, 43, 108, 45, 46, 15, + 112, 113, 114, 51, 116, 53, 54, 23, 120, 57, 58, 27, 60, 29, 30, 79, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 15, + 144, 145, 146, 147, 148, 149, 150, 23, 152, 153, 154, 27, 156, 29, 30, 15, + 160, 161, 162, 163, 164, 165, 166, 39, 168, 169, 170, 43, 172, 45, 46, 15, + 176, 177, 178, 51, 180, 53, 54, 23, 184, 57, 58, 27, 60, 29, 30, 143, + 192, 193, 194, 195, 196, 197, 198, 71, 200, 201, 202, 75, 204, 77, 78, 15, + 208, 209, 210, 83, 212, 85, 86, 23, 216, 89, 90, 27, 92, 29, 30, 143, + 224, 225, 226, 99, 228, 101, 102, 39, 232, 105, 106, 43, 108, 45, 46, 143, + 240, 113, 114, 51, 116, 53, 54, 151, 120, 57, 58, 155, 60, 157, 158, 207, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, + 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 32, 0, 32, 32, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 16, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 32, + 0, 0, 0, 64, 0, 64, 64, 32, 0, 64, 64, 32, 64, 32, 32, 80, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 16, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 32, + 0, 0, 0, 128, 0, 128, 128, 32, 0, 128, 128, 32, 128, 32, 32, 144, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 64, + 0, 0, 0, 128, 0, 128, 128, 64, 0, 128, 128, 64, 128, 64, 64, 144, + 0, 0, 0, 128, 0, 128, 128, 64, 0, 128, 128, 64, 128, 64, 64, 160, + 0, 128, 128, 64, 128, 64, 64, 160, 128, 64, 64, 160, 64, 160, 160, 208, + }, { + 0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 17, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 33, + 16, 1, 2, 1, 4, 1, 2, 33, 8, 1, 2, 33, 4, 33, 34, 17, + 64, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 65, + 16, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 17, + 32, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 33, + 16, 1, 2, 65, 4, 65, 66, 33, 8, 65, 66, 33, 68, 33, 34, 81, + 128, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 129, + 16, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 17, + 32, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 33, + 16, 1, 2, 129, 4, 129, 130, 33, 8, 129, 130, 33, 132, 33, 34, 145, + 64, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 65, + 16, 1, 2, 129, 4, 129, 130, 65, 8, 129, 130, 65, 132, 65, 66, 145, + 32, 1, 2, 129, 4, 129, 130, 65, 8, 129, 130, 65, 132, 65, 66, 161, + 16, 129, 130, 65, 132, 65, 66, 161, 136, 65, 66, 161, 68, 161, 162, 209, + }, { + 0, 0, 0, 2, 0, 4, 4, 2, 0, 8, 8, 2, 8, 4, 4, 2, + 0, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 18, + 0, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 34, + 32, 16, 16, 2, 16, 4, 4, 34, 16, 8, 8, 34, 8, 36, 36, 18, + 0, 64, 64, 2, 64, 4, 4, 2, 64, 8, 8, 2, 8, 4, 4, 66, + 64, 16, 16, 2, 16, 4, 4, 66, 16, 8, 8, 66, 8, 68, 68, 18, + 64, 32, 32, 2, 32, 4, 4, 66, 32, 8, 8, 66, 8, 68, 68, 34, + 32, 16, 16, 66, 16, 68, 68, 34, 16, 72, 72, 34, 72, 36, 36, 82, + 0, 128, 128, 2, 128, 4, 4, 2, 128, 8, 8, 2, 8, 4, 4, 130, + 128, 16, 16, 2, 16, 4, 4, 130, 16, 8, 8, 130, 8, 132, 132, 18, + 128, 32, 32, 2, 32, 4, 4, 130, 32, 8, 8, 130, 8, 132, 132, 34, + 32, 16, 16, 130, 16, 132, 132, 34, 16, 136, 136, 34, 136, 36, 36, 146, + 128, 64, 64, 2, 64, 4, 4, 130, 64, 8, 8, 130, 8, 132, 132, 66, + 64, 16, 16, 130, 16, 132, 132, 66, 16, 136, 136, 66, 136, 68, 68, 146, + 64, 32, 32, 130, 32, 132, 132, 66, 32, 136, 136, 66, 136, 68, 68, 162, + 32, 144, 144, 66, 144, 68, 68, 162, 144, 72, 72, 162, 72, 164, 164, 210, + }, { + 0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 10, 3, 12, 5, 6, 3, + 16, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 19, + 32, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 35, + 48, 17, 18, 3, 20, 5, 6, 35, 24, 9, 10, 35, 12, 37, 38, 19, + 64, 65, 66, 3, 68, 5, 6, 3, 72, 9, 10, 3, 12, 5, 6, 67, + 80, 17, 18, 3, 20, 5, 6, 67, 24, 9, 10, 67, 12, 69, 70, 19, + 96, 33, 34, 3, 36, 5, 6, 67, 40, 9, 10, 67, 12, 69, 70, 35, + 48, 17, 18, 67, 20, 69, 70, 35, 24, 73, 74, 35, 76, 37, 38, 83, + 128, 129, 130, 3, 132, 5, 6, 3, 136, 9, 10, 3, 12, 5, 6, 131, + 144, 17, 18, 3, 20, 5, 6, 131, 24, 9, 10, 131, 12, 133, 134, 19, + 160, 33, 34, 3, 36, 5, 6, 131, 40, 9, 10, 131, 12, 133, 134, 35, + 48, 17, 18, 131, 20, 133, 134, 35, 24, 137, 138, 35, 140, 37, 38, 147, + 192, 65, 66, 3, 68, 5, 6, 131, 72, 9, 10, 131, 12, 133, 134, 67, + 80, 17, 18, 131, 20, 133, 134, 67, 24, 137, 138, 67, 140, 69, 70, 147, + 96, 33, 34, 131, 36, 133, 134, 67, 40, 137, 138, 67, 140, 69, 70, 163, + 48, 145, 146, 67, 148, 69, 70, 163, 152, 73, 74, 163, 76, 165, 166, 211, + }, + { + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 8, 8, 4, + 0, 0, 0, 16, 0, 16, 16, 4, 0, 16, 16, 8, 16, 8, 8, 20, + 0, 0, 0, 32, 0, 32, 32, 4, 0, 32, 32, 8, 32, 8, 8, 36, + 0, 32, 32, 16, 32, 16, 16, 36, 32, 16, 16, 40, 16, 40, 40, 20, + 0, 0, 0, 64, 0, 64, 64, 4, 0, 64, 64, 8, 64, 8, 8, 68, + 0, 64, 64, 16, 64, 16, 16, 68, 64, 16, 16, 72, 16, 72, 72, 20, + 0, 64, 64, 32, 64, 32, 32, 68, 64, 32, 32, 72, 32, 72, 72, 36, + 64, 32, 32, 80, 32, 80, 80, 36, 32, 80, 80, 40, 80, 40, 40, 84, + 0, 0, 0, 128, 0, 128, 128, 4, 0, 128, 128, 8, 128, 8, 8, 132, + 0, 128, 128, 16, 128, 16, 16, 132, 128, 16, 16, 136, 16, 136, 136, 20, + 0, 128, 128, 32, 128, 32, 32, 132, 128, 32, 32, 136, 32, 136, 136, 36, + 128, 32, 32, 144, 32, 144, 144, 36, 32, 144, 144, 40, 144, 40, 40, 148, + 0, 128, 128, 64, 128, 64, 64, 132, 128, 64, 64, 136, 64, 136, 136, 68, + 128, 64, 64, 144, 64, 144, 144, 68, 64, 144, 144, 72, 144, 72, 72, 148, + 128, 64, 64, 160, 64, 160, 160, 68, 64, 160, 160, 72, 160, 72, 72, 164, + 64, 160, 160, 80, 160, 80, 80, 164, 160, 80, 80, 168, 80, 168, 168, 212, + }, { + 0, 1, 2, 1, 4, 1, 2, 5, 8, 1, 2, 9, 4, 9, 10, 5, + 16, 1, 2, 17, 4, 17, 18, 5, 8, 17, 18, 9, 20, 9, 10, 21, + 32, 1, 2, 33, 4, 33, 34, 5, 8, 33, 34, 9, 36, 9, 10, 37, + 16, 33, 34, 17, 36, 17, 18, 37, 40, 17, 18, 41, 20, 41, 42, 21, + 64, 1, 2, 65, 4, 65, 66, 5, 8, 65, 66, 9, 68, 9, 10, 69, + 16, 65, 66, 17, 68, 17, 18, 69, 72, 17, 18, 73, 20, 73, 74, 21, + 32, 65, 66, 33, 68, 33, 34, 69, 72, 33, 34, 73, 36, 73, 74, 37, + 80, 33, 34, 81, 36, 81, 82, 37, 40, 81, 82, 41, 84, 41, 42, 85, + 128, 1, 2, 129, 4, 129, 130, 5, 8, 129, 130, 9, 132, 9, 10, 133, + 16, 129, 130, 17, 132, 17, 18, 133, 136, 17, 18, 137, 20, 137, 138, 21, + 32, 129, 130, 33, 132, 33, 34, 133, 136, 33, 34, 137, 36, 137, 138, 37, + 144, 33, 34, 145, 36, 145, 146, 37, 40, 145, 146, 41, 148, 41, 42, 149, + 64, 129, 130, 65, 132, 65, 66, 133, 136, 65, 66, 137, 68, 137, 138, 69, + 144, 65, 66, 145, 68, 145, 146, 69, 72, 145, 146, 73, 148, 73, 74, 149, + 160, 65, 66, 161, 68, 161, 162, 69, 72, 161, 162, 73, 164, 73, 74, 165, + 80, 161, 162, 81, 164, 81, 82, 165, 168, 81, 82, 169, 84, 169, 170, 213, + }, { + 0, 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10, 8, 12, 12, 6, + 0, 16, 16, 18, 16, 20, 20, 6, 16, 24, 24, 10, 24, 12, 12, 22, + 0, 32, 32, 34, 32, 36, 36, 6, 32, 40, 40, 10, 40, 12, 12, 38, + 32, 48, 48, 18, 48, 20, 20, 38, 48, 24, 24, 42, 24, 44, 44, 22, + 0, 64, 64, 66, 64, 68, 68, 6, 64, 72, 72, 10, 72, 12, 12, 70, + 64, 80, 80, 18, 80, 20, 20, 70, 80, 24, 24, 74, 24, 76, 76, 22, + 64, 96, 96, 34, 96, 36, 36, 70, 96, 40, 40, 74, 40, 76, 76, 38, + 96, 48, 48, 82, 48, 84, 84, 38, 48, 88, 88, 42, 88, 44, 44, 86, + 0, 128, 128, 130, 128, 132, 132, 6, 128, 136, 136, 10, 136, 12, 12, 134, + 128, 144, 144, 18, 144, 20, 20, 134, 144, 24, 24, 138, 24, 140, 140, 22, + 128, 160, 160, 34, 160, 36, 36, 134, 160, 40, 40, 138, 40, 140, 140, 38, + 160, 48, 48, 146, 48, 148, 148, 38, 48, 152, 152, 42, 152, 44, 44, 150, + 128, 192, 192, 66, 192, 68, 68, 134, 192, 72, 72, 138, 72, 140, 140, 70, + 192, 80, 80, 146, 80, 148, 148, 70, 80, 152, 152, 74, 152, 76, 76, 150, + 192, 96, 96, 162, 96, 164, 164, 70, 96, 168, 168, 74, 168, 76, 76, 166, + 96, 176, 176, 82, 176, 84, 84, 166, 176, 88, 88, 170, 88, 172, 172, 214, + }, { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 7, + 16, 17, 18, 19, 20, 21, 22, 7, 24, 25, 26, 11, 28, 13, 14, 23, + 32, 33, 34, 35, 36, 37, 38, 7, 40, 41, 42, 11, 44, 13, 14, 39, + 48, 49, 50, 19, 52, 21, 22, 39, 56, 25, 26, 43, 28, 45, 46, 23, + 64, 65, 66, 67, 68, 69, 70, 7, 72, 73, 74, 11, 76, 13, 14, 71, + 80, 81, 82, 19, 84, 21, 22, 71, 88, 25, 26, 75, 28, 77, 78, 23, + 96, 97, 98, 35, 100, 37, 38, 71, 104, 41, 42, 75, 44, 77, 78, 39, + 112, 49, 50, 83, 52, 85, 86, 39, 56, 89, 90, 43, 92, 45, 46, 87, + 128, 129, 130, 131, 132, 133, 134, 7, 136, 137, 138, 11, 140, 13, 14, 135, + 144, 145, 146, 19, 148, 21, 22, 135, 152, 25, 26, 139, 28, 141, 142, 23, + 160, 161, 162, 35, 164, 37, 38, 135, 168, 41, 42, 139, 44, 141, 142, 39, + 176, 49, 50, 147, 52, 149, 150, 39, 56, 153, 154, 43, 156, 45, 46, 151, + 192, 193, 194, 67, 196, 69, 70, 135, 200, 73, 74, 139, 76, 141, 142, 71, + 208, 81, 82, 147, 84, 149, 150, 71, 88, 153, 154, 75, 156, 77, 78, 151, + 224, 97, 98, 163, 100, 165, 166, 71, 104, 169, 170, 75, 172, 77, 78, 167, + 112, 177, 178, 83, 180, 85, 86, 167, 184, 89, 90, 171, 92, 173, 174, 215, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, + 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 16, 0, 16, 16, 24, + 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 32, 0, 32, 32, 40, + 0, 0, 0, 32, 0, 32, 32, 48, 0, 32, 32, 48, 32, 48, 48, 24, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 72, + 0, 0, 0, 64, 0, 64, 64, 80, 0, 64, 64, 80, 64, 80, 80, 24, + 0, 0, 0, 64, 0, 64, 64, 96, 0, 64, 64, 96, 64, 96, 96, 40, + 0, 64, 64, 96, 64, 96, 96, 48, 64, 96, 96, 48, 96, 48, 48, 88, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 136, + 0, 0, 0, 128, 0, 128, 128, 144, 0, 128, 128, 144, 128, 144, 144, 24, + 0, 0, 0, 128, 0, 128, 128, 160, 0, 128, 128, 160, 128, 160, 160, 40, + 0, 128, 128, 160, 128, 160, 160, 48, 128, 160, 160, 48, 160, 48, 48, 152, + 0, 0, 0, 128, 0, 128, 128, 192, 0, 128, 128, 192, 128, 192, 192, 72, + 0, 128, 128, 192, 128, 192, 192, 80, 128, 192, 192, 80, 192, 80, 80, 152, + 0, 128, 128, 192, 128, 192, 192, 96, 128, 192, 192, 96, 192, 96, 96, 168, + 128, 192, 192, 96, 192, 96, 96, 176, 192, 96, 96, 176, 96, 176, 176, 216, + }, { + 0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 9, + 16, 1, 2, 1, 4, 1, 2, 17, 8, 1, 2, 17, 4, 17, 18, 25, + 32, 1, 2, 1, 4, 1, 2, 33, 8, 1, 2, 33, 4, 33, 34, 41, + 16, 1, 2, 33, 4, 33, 34, 49, 8, 33, 34, 49, 36, 49, 50, 25, + 64, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 73, + 16, 1, 2, 65, 4, 65, 66, 81, 8, 65, 66, 81, 68, 81, 82, 25, + 32, 1, 2, 65, 4, 65, 66, 97, 8, 65, 66, 97, 68, 97, 98, 41, + 16, 65, 66, 97, 68, 97, 98, 49, 72, 97, 98, 49, 100, 49, 50, 89, + 128, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 137, + 16, 1, 2, 129, 4, 129, 130, 145, 8, 129, 130, 145, 132, 145, 146, 25, + 32, 1, 2, 129, 4, 129, 130, 161, 8, 129, 130, 161, 132, 161, 162, 41, + 16, 129, 130, 161, 132, 161, 162, 49, 136, 161, 162, 49, 164, 49, 50, 153, + 64, 1, 2, 129, 4, 129, 130, 193, 8, 129, 130, 193, 132, 193, 194, 73, + 16, 129, 130, 193, 132, 193, 194, 81, 136, 193, 194, 81, 196, 81, 82, 153, + 32, 129, 130, 193, 132, 193, 194, 97, 136, 193, 194, 97, 196, 97, 98, 169, + 144, 193, 194, 97, 196, 97, 98, 177, 200, 97, 98, 177, 100, 177, 178, 217, + }, { + 0, 0, 0, 2, 0, 4, 4, 2, 0, 8, 8, 2, 8, 4, 4, 10, + 0, 16, 16, 2, 16, 4, 4, 18, 16, 8, 8, 18, 8, 20, 20, 26, + 0, 32, 32, 2, 32, 4, 4, 34, 32, 8, 8, 34, 8, 36, 36, 42, + 32, 16, 16, 34, 16, 36, 36, 50, 16, 40, 40, 50, 40, 52, 52, 26, + 0, 64, 64, 2, 64, 4, 4, 66, 64, 8, 8, 66, 8, 68, 68, 74, + 64, 16, 16, 66, 16, 68, 68, 82, 16, 72, 72, 82, 72, 84, 84, 26, + 64, 32, 32, 66, 32, 68, 68, 98, 32, 72, 72, 98, 72, 100, 100, 42, + 32, 80, 80, 98, 80, 100, 100, 50, 80, 104, 104, 50, 104, 52, 52, 90, + 0, 128, 128, 2, 128, 4, 4, 130, 128, 8, 8, 130, 8, 132, 132, 138, + 128, 16, 16, 130, 16, 132, 132, 146, 16, 136, 136, 146, 136, 148, 148, 26, + 128, 32, 32, 130, 32, 132, 132, 162, 32, 136, 136, 162, 136, 164, 164, 42, + 32, 144, 144, 162, 144, 164, 164, 50, 144, 168, 168, 50, 168, 52, 52, 154, + 128, 64, 64, 130, 64, 132, 132, 194, 64, 136, 136, 194, 136, 196, 196, 74, + 64, 144, 144, 194, 144, 196, 196, 82, 144, 200, 200, 82, 200, 84, 84, 154, + 64, 160, 160, 194, 160, 196, 196, 98, 160, 200, 200, 98, 200, 100, 100, 170, + 160, 208, 208, 98, 208, 100, 100, 178, 208, 104, 104, 178, 104, 180, 180, 218, + }, { + 0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 10, 3, 12, 5, 6, 11, + 16, 17, 18, 3, 20, 5, 6, 19, 24, 9, 10, 19, 12, 21, 22, 27, + 32, 33, 34, 3, 36, 5, 6, 35, 40, 9, 10, 35, 12, 37, 38, 43, + 48, 17, 18, 35, 20, 37, 38, 51, 24, 41, 42, 51, 44, 53, 54, 27, + 64, 65, 66, 3, 68, 5, 6, 67, 72, 9, 10, 67, 12, 69, 70, 75, + 80, 17, 18, 67, 20, 69, 70, 83, 24, 73, 74, 83, 76, 85, 86, 27, + 96, 33, 34, 67, 36, 69, 70, 99, 40, 73, 74, 99, 76, 101, 102, 43, + 48, 81, 82, 99, 84, 101, 102, 51, 88, 105, 106, 51, 108, 53, 54, 91, + 128, 129, 130, 3, 132, 5, 6, 131, 136, 9, 10, 131, 12, 133, 134, 139, + 144, 17, 18, 131, 20, 133, 134, 147, 24, 137, 138, 147, 140, 149, 150, 27, + 160, 33, 34, 131, 36, 133, 134, 163, 40, 137, 138, 163, 140, 165, 166, 43, + 48, 145, 146, 163, 148, 165, 166, 51, 152, 169, 170, 51, 172, 53, 54, 155, + 192, 65, 66, 131, 68, 133, 134, 195, 72, 137, 138, 195, 140, 197, 198, 75, + 80, 145, 146, 195, 148, 197, 198, 83, 152, 201, 202, 83, 204, 85, 86, 155, + 96, 161, 162, 195, 164, 197, 198, 99, 168, 201, 202, 99, 204, 101, 102, 171, + 176, 209, 210, 99, 212, 101, 102, 179, 216, 105, 106, 179, 108, 181, 182, 219, + }, + { + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 8, 8, 12, + 0, 0, 0, 16, 0, 16, 16, 20, 0, 16, 16, 24, 16, 24, 24, 28, + 0, 0, 0, 32, 0, 32, 32, 36, 0, 32, 32, 40, 32, 40, 40, 44, + 0, 32, 32, 48, 32, 48, 48, 52, 32, 48, 48, 56, 48, 56, 56, 28, + 0, 0, 0, 64, 0, 64, 64, 68, 0, 64, 64, 72, 64, 72, 72, 76, + 0, 64, 64, 80, 64, 80, 80, 84, 64, 80, 80, 88, 80, 88, 88, 28, + 0, 64, 64, 96, 64, 96, 96, 100, 64, 96, 96, 104, 96, 104, 104, 44, + 64, 96, 96, 112, 96, 112, 112, 52, 96, 112, 112, 56, 112, 56, 56, 92, + 0, 0, 0, 128, 0, 128, 128, 132, 0, 128, 128, 136, 128, 136, 136, 140, + 0, 128, 128, 144, 128, 144, 144, 148, 128, 144, 144, 152, 144, 152, 152, 28, + 0, 128, 128, 160, 128, 160, 160, 164, 128, 160, 160, 168, 160, 168, 168, 44, + 128, 160, 160, 176, 160, 176, 176, 52, 160, 176, 176, 56, 176, 56, 56, 156, + 0, 128, 128, 192, 128, 192, 192, 196, 128, 192, 192, 200, 192, 200, 200, 76, + 128, 192, 192, 208, 192, 208, 208, 84, 192, 208, 208, 88, 208, 88, 88, 156, + 128, 192, 192, 224, 192, 224, 224, 100, 192, 224, 224, 104, 224, 104, 104, 172, + 192, 224, 224, 112, 224, 112, 112, 180, 224, 112, 112, 184, 112, 184, 184, 220, + }, { + 0, 1, 2, 1, 4, 1, 2, 5, 8, 1, 2, 9, 4, 9, 10, 13, + 16, 1, 2, 17, 4, 17, 18, 21, 8, 17, 18, 25, 20, 25, 26, 29, + 32, 1, 2, 33, 4, 33, 34, 37, 8, 33, 34, 41, 36, 41, 42, 45, + 16, 33, 34, 49, 36, 49, 50, 53, 40, 49, 50, 57, 52, 57, 58, 29, + 64, 1, 2, 65, 4, 65, 66, 69, 8, 65, 66, 73, 68, 73, 74, 77, + 16, 65, 66, 81, 68, 81, 82, 85, 72, 81, 82, 89, 84, 89, 90, 29, + 32, 65, 66, 97, 68, 97, 98, 101, 72, 97, 98, 105, 100, 105, 106, 45, + 80, 97, 98, 113, 100, 113, 114, 53, 104, 113, 114, 57, 116, 57, 58, 93, + 128, 1, 2, 129, 4, 129, 130, 133, 8, 129, 130, 137, 132, 137, 138, 141, + 16, 129, 130, 145, 132, 145, 146, 149, 136, 145, 146, 153, 148, 153, 154, 29, + 32, 129, 130, 161, 132, 161, 162, 165, 136, 161, 162, 169, 164, 169, 170, 45, + 144, 161, 162, 177, 164, 177, 178, 53, 168, 177, 178, 57, 180, 57, 58, 157, + 64, 129, 130, 193, 132, 193, 194, 197, 136, 193, 194, 201, 196, 201, 202, 77, + 144, 193, 194, 209, 196, 209, 210, 85, 200, 209, 210, 89, 212, 89, 90, 157, + 160, 193, 194, 225, 196, 225, 226, 101, 200, 225, 226, 105, 228, 105, 106, 173, + 208, 225, 226, 113, 228, 113, 114, 181, 232, 113, 114, 185, 116, 185, 186, 221, + }, { + 0, 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10, 8, 12, 12, 14, + 0, 16, 16, 18, 16, 20, 20, 22, 16, 24, 24, 26, 24, 28, 28, 30, + 0, 32, 32, 34, 32, 36, 36, 38, 32, 40, 40, 42, 40, 44, 44, 46, + 32, 48, 48, 50, 48, 52, 52, 54, 48, 56, 56, 58, 56, 60, 60, 30, + 0, 64, 64, 66, 64, 68, 68, 70, 64, 72, 72, 74, 72, 76, 76, 78, + 64, 80, 80, 82, 80, 84, 84, 86, 80, 88, 88, 90, 88, 92, 92, 30, + 64, 96, 96, 98, 96, 100, 100, 102, 96, 104, 104, 106, 104, 108, 108, 46, + 96, 112, 112, 114, 112, 116, 116, 54, 112, 120, 120, 58, 120, 60, 60, 94, + 0, 128, 128, 130, 128, 132, 132, 134, 128, 136, 136, 138, 136, 140, 140, 142, + 128, 144, 144, 146, 144, 148, 148, 150, 144, 152, 152, 154, 152, 156, 156, 30, + 128, 160, 160, 162, 160, 164, 164, 166, 160, 168, 168, 170, 168, 172, 172, 46, + 160, 176, 176, 178, 176, 180, 180, 54, 176, 184, 184, 58, 184, 60, 60, 158, + 128, 192, 192, 194, 192, 196, 196, 198, 192, 200, 200, 202, 200, 204, 204, 78, + 192, 208, 208, 210, 208, 212, 212, 86, 208, 216, 216, 90, 216, 92, 92, 158, + 192, 224, 224, 226, 224, 228, 228, 102, 224, 232, 232, 106, 232, 108, 108, 174, + 224, 240, 240, 114, 240, 116, 116, 182, 240, 120, 120, 186, 120, 188, 188, 222, + }, { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 31, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 31, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 47, + 112, 113, 114, 115, 116, 117, 118, 55, 120, 121, 122, 59, 124, 61, 62, 95, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, + 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 31, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 47, + 176, 177, 178, 179, 180, 181, 182, 55, 184, 185, 186, 59, 188, 61, 62, 159, + 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 79, + 208, 209, 210, 211, 212, 213, 214, 87, 216, 217, 218, 91, 220, 93, 94, 159, + 224, 225, 226, 227, 228, 229, 230, 103, 232, 233, 234, 107, 236, 109, 110, 175, + 240, 241, 242, 115, 244, 117, 118, 183, 248, 121, 122, 187, 124, 189, 190, 223, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 96, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 160, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 192, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 192, + 0, 0, 0, 128, 0, 128, 128, 192, 0, 128, 128, 192, 128, 192, 192, 224, + }, { + 0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 33, + 64, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 65, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 65, + 16, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 97, + 128, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 129, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 129, + 16, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 161, + 64, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 129, + 16, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 193, + 32, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 193, + 16, 1, 2, 129, 4, 129, 130, 193, 8, 129, 130, 193, 132, 193, 194, 225, + }, { + 0, 0, 0, 2, 0, 4, 4, 2, 0, 8, 8, 2, 8, 4, 4, 2, + 0, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 2, + 0, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 2, + 32, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 34, + 0, 64, 64, 2, 64, 4, 4, 2, 64, 8, 8, 2, 8, 4, 4, 2, + 64, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 66, + 64, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 66, + 32, 16, 16, 2, 16, 4, 4, 66, 16, 8, 8, 66, 8, 68, 68, 98, + 0, 128, 128, 2, 128, 4, 4, 2, 128, 8, 8, 2, 8, 4, 4, 2, + 128, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 130, + 128, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 130, + 32, 16, 16, 2, 16, 4, 4, 130, 16, 8, 8, 130, 8, 132, 132, 162, + 128, 64, 64, 2, 64, 4, 4, 2, 64, 8, 8, 2, 8, 4, 4, 130, + 64, 16, 16, 2, 16, 4, 4, 130, 16, 8, 8, 130, 8, 132, 132, 194, + 64, 32, 32, 2, 32, 4, 4, 130, 32, 8, 8, 130, 8, 132, 132, 194, + 32, 16, 16, 130, 16, 132, 132, 194, 16, 136, 136, 194, 136, 196, 196, 226, + }, { + 0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 10, 3, 12, 5, 6, 3, + 16, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 3, + 32, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 3, + 48, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 35, + 64, 65, 66, 3, 68, 5, 6, 3, 72, 9, 10, 3, 12, 5, 6, 3, + 80, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 67, + 96, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 67, + 48, 17, 18, 3, 20, 5, 6, 67, 24, 9, 10, 67, 12, 69, 70, 99, + 128, 129, 130, 3, 132, 5, 6, 3, 136, 9, 10, 3, 12, 5, 6, 3, + 144, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 131, + 160, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 131, + 48, 17, 18, 3, 20, 5, 6, 131, 24, 9, 10, 131, 12, 133, 134, 163, + 192, 65, 66, 3, 68, 5, 6, 3, 72, 9, 10, 3, 12, 5, 6, 131, + 80, 17, 18, 3, 20, 5, 6, 131, 24, 9, 10, 131, 12, 133, 134, 195, + 96, 33, 34, 3, 36, 5, 6, 131, 40, 9, 10, 131, 12, 133, 134, 195, + 48, 17, 18, 131, 20, 133, 134, 195, 24, 137, 138, 195, 140, 197, 198, 227, + }, + { + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 8, 8, 4, + 0, 0, 0, 16, 0, 16, 16, 4, 0, 16, 16, 8, 16, 8, 8, 4, + 0, 0, 0, 32, 0, 32, 32, 4, 0, 32, 32, 8, 32, 8, 8, 4, + 0, 32, 32, 16, 32, 16, 16, 4, 32, 16, 16, 8, 16, 8, 8, 36, + 0, 0, 0, 64, 0, 64, 64, 4, 0, 64, 64, 8, 64, 8, 8, 4, + 0, 64, 64, 16, 64, 16, 16, 4, 64, 16, 16, 8, 16, 8, 8, 68, + 0, 64, 64, 32, 64, 32, 32, 4, 64, 32, 32, 8, 32, 8, 8, 68, + 64, 32, 32, 16, 32, 16, 16, 68, 32, 16, 16, 72, 16, 72, 72, 100, + 0, 0, 0, 128, 0, 128, 128, 4, 0, 128, 128, 8, 128, 8, 8, 4, + 0, 128, 128, 16, 128, 16, 16, 4, 128, 16, 16, 8, 16, 8, 8, 132, + 0, 128, 128, 32, 128, 32, 32, 4, 128, 32, 32, 8, 32, 8, 8, 132, + 128, 32, 32, 16, 32, 16, 16, 132, 32, 16, 16, 136, 16, 136, 136, 164, + 0, 128, 128, 64, 128, 64, 64, 4, 128, 64, 64, 8, 64, 8, 8, 132, + 128, 64, 64, 16, 64, 16, 16, 132, 64, 16, 16, 136, 16, 136, 136, 196, + 128, 64, 64, 32, 64, 32, 32, 132, 64, 32, 32, 136, 32, 136, 136, 196, + 64, 32, 32, 144, 32, 144, 144, 196, 32, 144, 144, 200, 144, 200, 200, 228, + }, { + 0, 1, 2, 1, 4, 1, 2, 5, 8, 1, 2, 9, 4, 9, 10, 5, + 16, 1, 2, 17, 4, 17, 18, 5, 8, 17, 18, 9, 20, 9, 10, 5, + 32, 1, 2, 33, 4, 33, 34, 5, 8, 33, 34, 9, 36, 9, 10, 5, + 16, 33, 34, 17, 36, 17, 18, 5, 40, 17, 18, 9, 20, 9, 10, 37, + 64, 1, 2, 65, 4, 65, 66, 5, 8, 65, 66, 9, 68, 9, 10, 5, + 16, 65, 66, 17, 68, 17, 18, 5, 72, 17, 18, 9, 20, 9, 10, 69, + 32, 65, 66, 33, 68, 33, 34, 5, 72, 33, 34, 9, 36, 9, 10, 69, + 80, 33, 34, 17, 36, 17, 18, 69, 40, 17, 18, 73, 20, 73, 74, 101, + 128, 1, 2, 129, 4, 129, 130, 5, 8, 129, 130, 9, 132, 9, 10, 5, + 16, 129, 130, 17, 132, 17, 18, 5, 136, 17, 18, 9, 20, 9, 10, 133, + 32, 129, 130, 33, 132, 33, 34, 5, 136, 33, 34, 9, 36, 9, 10, 133, + 144, 33, 34, 17, 36, 17, 18, 133, 40, 17, 18, 137, 20, 137, 138, 165, + 64, 129, 130, 65, 132, 65, 66, 5, 136, 65, 66, 9, 68, 9, 10, 133, + 144, 65, 66, 17, 68, 17, 18, 133, 72, 17, 18, 137, 20, 137, 138, 197, + 160, 65, 66, 33, 68, 33, 34, 133, 72, 33, 34, 137, 36, 137, 138, 197, + 80, 33, 34, 145, 36, 145, 146, 197, 40, 145, 146, 201, 148, 201, 202, 229, + }, { + 0, 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10, 8, 12, 12, 6, + 0, 16, 16, 18, 16, 20, 20, 6, 16, 24, 24, 10, 24, 12, 12, 6, + 0, 32, 32, 34, 32, 36, 36, 6, 32, 40, 40, 10, 40, 12, 12, 6, + 32, 48, 48, 18, 48, 20, 20, 6, 48, 24, 24, 10, 24, 12, 12, 38, + 0, 64, 64, 66, 64, 68, 68, 6, 64, 72, 72, 10, 72, 12, 12, 6, + 64, 80, 80, 18, 80, 20, 20, 6, 80, 24, 24, 10, 24, 12, 12, 70, + 64, 96, 96, 34, 96, 36, 36, 6, 96, 40, 40, 10, 40, 12, 12, 70, + 96, 48, 48, 18, 48, 20, 20, 70, 48, 24, 24, 74, 24, 76, 76, 102, + 0, 128, 128, 130, 128, 132, 132, 6, 128, 136, 136, 10, 136, 12, 12, 6, + 128, 144, 144, 18, 144, 20, 20, 6, 144, 24, 24, 10, 24, 12, 12, 134, + 128, 160, 160, 34, 160, 36, 36, 6, 160, 40, 40, 10, 40, 12, 12, 134, + 160, 48, 48, 18, 48, 20, 20, 134, 48, 24, 24, 138, 24, 140, 140, 166, + 128, 192, 192, 66, 192, 68, 68, 6, 192, 72, 72, 10, 72, 12, 12, 134, + 192, 80, 80, 18, 80, 20, 20, 134, 80, 24, 24, 138, 24, 140, 140, 198, + 192, 96, 96, 34, 96, 36, 36, 134, 96, 40, 40, 138, 40, 140, 140, 198, + 96, 48, 48, 146, 48, 148, 148, 198, 48, 152, 152, 202, 152, 204, 204, 230, + }, { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 7, + 16, 17, 18, 19, 20, 21, 22, 7, 24, 25, 26, 11, 28, 13, 14, 7, + 32, 33, 34, 35, 36, 37, 38, 7, 40, 41, 42, 11, 44, 13, 14, 7, + 48, 49, 50, 19, 52, 21, 22, 7, 56, 25, 26, 11, 28, 13, 14, 39, + 64, 65, 66, 67, 68, 69, 70, 7, 72, 73, 74, 11, 76, 13, 14, 7, + 80, 81, 82, 19, 84, 21, 22, 7, 88, 25, 26, 11, 28, 13, 14, 71, + 96, 97, 98, 35, 100, 37, 38, 7, 104, 41, 42, 11, 44, 13, 14, 71, + 112, 49, 50, 19, 52, 21, 22, 71, 56, 25, 26, 75, 28, 77, 78, 103, + 128, 129, 130, 131, 132, 133, 134, 7, 136, 137, 138, 11, 140, 13, 14, 7, + 144, 145, 146, 19, 148, 21, 22, 7, 152, 25, 26, 11, 28, 13, 14, 135, + 160, 161, 162, 35, 164, 37, 38, 7, 168, 41, 42, 11, 44, 13, 14, 135, + 176, 49, 50, 19, 52, 21, 22, 135, 56, 25, 26, 139, 28, 141, 142, 167, + 192, 193, 194, 67, 196, 69, 70, 7, 200, 73, 74, 11, 76, 13, 14, 135, + 208, 81, 82, 19, 84, 21, 22, 135, 88, 25, 26, 139, 28, 141, 142, 199, + 224, 97, 98, 35, 100, 37, 38, 135, 104, 41, 42, 139, 44, 141, 142, 199, + 112, 49, 50, 147, 52, 149, 150, 199, 56, 153, 154, 203, 156, 205, 206, 231, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, + 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 16, 0, 16, 16, 8, + 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 32, 0, 32, 32, 8, + 0, 0, 0, 32, 0, 32, 32, 16, 0, 32, 32, 16, 32, 16, 16, 40, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 8, + 0, 0, 0, 64, 0, 64, 64, 16, 0, 64, 64, 16, 64, 16, 16, 72, + 0, 0, 0, 64, 0, 64, 64, 32, 0, 64, 64, 32, 64, 32, 32, 72, + 0, 64, 64, 32, 64, 32, 32, 80, 64, 32, 32, 80, 32, 80, 80, 104, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 8, + 0, 0, 0, 128, 0, 128, 128, 16, 0, 128, 128, 16, 128, 16, 16, 136, + 0, 0, 0, 128, 0, 128, 128, 32, 0, 128, 128, 32, 128, 32, 32, 136, + 0, 128, 128, 32, 128, 32, 32, 144, 128, 32, 32, 144, 32, 144, 144, 168, + 0, 0, 0, 128, 0, 128, 128, 64, 0, 128, 128, 64, 128, 64, 64, 136, + 0, 128, 128, 64, 128, 64, 64, 144, 128, 64, 64, 144, 64, 144, 144, 200, + 0, 128, 128, 64, 128, 64, 64, 160, 128, 64, 64, 160, 64, 160, 160, 200, + 128, 64, 64, 160, 64, 160, 160, 208, 64, 160, 160, 208, 160, 208, 208, 232, + }, { + 0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 9, + 16, 1, 2, 1, 4, 1, 2, 17, 8, 1, 2, 17, 4, 17, 18, 9, + 32, 1, 2, 1, 4, 1, 2, 33, 8, 1, 2, 33, 4, 33, 34, 9, + 16, 1, 2, 33, 4, 33, 34, 17, 8, 33, 34, 17, 36, 17, 18, 41, + 64, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 9, + 16, 1, 2, 65, 4, 65, 66, 17, 8, 65, 66, 17, 68, 17, 18, 73, + 32, 1, 2, 65, 4, 65, 66, 33, 8, 65, 66, 33, 68, 33, 34, 73, + 16, 65, 66, 33, 68, 33, 34, 81, 72, 33, 34, 81, 36, 81, 82, 105, + 128, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 9, + 16, 1, 2, 129, 4, 129, 130, 17, 8, 129, 130, 17, 132, 17, 18, 137, + 32, 1, 2, 129, 4, 129, 130, 33, 8, 129, 130, 33, 132, 33, 34, 137, + 16, 129, 130, 33, 132, 33, 34, 145, 136, 33, 34, 145, 36, 145, 146, 169, + 64, 1, 2, 129, 4, 129, 130, 65, 8, 129, 130, 65, 132, 65, 66, 137, + 16, 129, 130, 65, 132, 65, 66, 145, 136, 65, 66, 145, 68, 145, 146, 201, + 32, 129, 130, 65, 132, 65, 66, 161, 136, 65, 66, 161, 68, 161, 162, 201, + 144, 65, 66, 161, 68, 161, 162, 209, 72, 161, 162, 209, 164, 209, 210, 233, + }, { + 0, 0, 0, 2, 0, 4, 4, 2, 0, 8, 8, 2, 8, 4, 4, 10, + 0, 16, 16, 2, 16, 4, 4, 18, 16, 8, 8, 18, 8, 20, 20, 10, + 0, 32, 32, 2, 32, 4, 4, 34, 32, 8, 8, 34, 8, 36, 36, 10, + 32, 16, 16, 34, 16, 36, 36, 18, 16, 40, 40, 18, 40, 20, 20, 42, + 0, 64, 64, 2, 64, 4, 4, 66, 64, 8, 8, 66, 8, 68, 68, 10, + 64, 16, 16, 66, 16, 68, 68, 18, 16, 72, 72, 18, 72, 20, 20, 74, + 64, 32, 32, 66, 32, 68, 68, 34, 32, 72, 72, 34, 72, 36, 36, 74, + 32, 80, 80, 34, 80, 36, 36, 82, 80, 40, 40, 82, 40, 84, 84, 106, + 0, 128, 128, 2, 128, 4, 4, 130, 128, 8, 8, 130, 8, 132, 132, 10, + 128, 16, 16, 130, 16, 132, 132, 18, 16, 136, 136, 18, 136, 20, 20, 138, + 128, 32, 32, 130, 32, 132, 132, 34, 32, 136, 136, 34, 136, 36, 36, 138, + 32, 144, 144, 34, 144, 36, 36, 146, 144, 40, 40, 146, 40, 148, 148, 170, + 128, 64, 64, 130, 64, 132, 132, 66, 64, 136, 136, 66, 136, 68, 68, 138, + 64, 144, 144, 66, 144, 68, 68, 146, 144, 72, 72, 146, 72, 148, 148, 202, + 64, 160, 160, 66, 160, 68, 68, 162, 160, 72, 72, 162, 72, 164, 164, 202, + 160, 80, 80, 162, 80, 164, 164, 210, 80, 168, 168, 210, 168, 212, 212, 234, + }, { + 0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 10, 3, 12, 5, 6, 11, + 16, 17, 18, 3, 20, 5, 6, 19, 24, 9, 10, 19, 12, 21, 22, 11, + 32, 33, 34, 3, 36, 5, 6, 35, 40, 9, 10, 35, 12, 37, 38, 11, + 48, 17, 18, 35, 20, 37, 38, 19, 24, 41, 42, 19, 44, 21, 22, 43, + 64, 65, 66, 3, 68, 5, 6, 67, 72, 9, 10, 67, 12, 69, 70, 11, + 80, 17, 18, 67, 20, 69, 70, 19, 24, 73, 74, 19, 76, 21, 22, 75, + 96, 33, 34, 67, 36, 69, 70, 35, 40, 73, 74, 35, 76, 37, 38, 75, + 48, 81, 82, 35, 84, 37, 38, 83, 88, 41, 42, 83, 44, 85, 86, 107, + 128, 129, 130, 3, 132, 5, 6, 131, 136, 9, 10, 131, 12, 133, 134, 11, + 144, 17, 18, 131, 20, 133, 134, 19, 24, 137, 138, 19, 140, 21, 22, 139, + 160, 33, 34, 131, 36, 133, 134, 35, 40, 137, 138, 35, 140, 37, 38, 139, + 48, 145, 146, 35, 148, 37, 38, 147, 152, 41, 42, 147, 44, 149, 150, 171, + 192, 65, 66, 131, 68, 133, 134, 67, 72, 137, 138, 67, 140, 69, 70, 139, + 80, 145, 146, 67, 148, 69, 70, 147, 152, 73, 74, 147, 76, 149, 150, 203, + 96, 161, 162, 67, 164, 69, 70, 163, 168, 73, 74, 163, 76, 165, 166, 203, + 176, 81, 82, 163, 84, 165, 166, 211, 88, 169, 170, 211, 172, 213, 214, 235, + }, + { + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 8, 8, 12, + 0, 0, 0, 16, 0, 16, 16, 20, 0, 16, 16, 24, 16, 24, 24, 12, + 0, 0, 0, 32, 0, 32, 32, 36, 0, 32, 32, 40, 32, 40, 40, 12, + 0, 32, 32, 48, 32, 48, 48, 20, 32, 48, 48, 24, 48, 24, 24, 44, + 0, 0, 0, 64, 0, 64, 64, 68, 0, 64, 64, 72, 64, 72, 72, 12, + 0, 64, 64, 80, 64, 80, 80, 20, 64, 80, 80, 24, 80, 24, 24, 76, + 0, 64, 64, 96, 64, 96, 96, 36, 64, 96, 96, 40, 96, 40, 40, 76, + 64, 96, 96, 48, 96, 48, 48, 84, 96, 48, 48, 88, 48, 88, 88, 108, + 0, 0, 0, 128, 0, 128, 128, 132, 0, 128, 128, 136, 128, 136, 136, 12, + 0, 128, 128, 144, 128, 144, 144, 20, 128, 144, 144, 24, 144, 24, 24, 140, + 0, 128, 128, 160, 128, 160, 160, 36, 128, 160, 160, 40, 160, 40, 40, 140, + 128, 160, 160, 48, 160, 48, 48, 148, 160, 48, 48, 152, 48, 152, 152, 172, + 0, 128, 128, 192, 128, 192, 192, 68, 128, 192, 192, 72, 192, 72, 72, 140, + 128, 192, 192, 80, 192, 80, 80, 148, 192, 80, 80, 152, 80, 152, 152, 204, + 128, 192, 192, 96, 192, 96, 96, 164, 192, 96, 96, 168, 96, 168, 168, 204, + 192, 96, 96, 176, 96, 176, 176, 212, 96, 176, 176, 216, 176, 216, 216, 236, + }, { + 0, 1, 2, 1, 4, 1, 2, 5, 8, 1, 2, 9, 4, 9, 10, 13, + 16, 1, 2, 17, 4, 17, 18, 21, 8, 17, 18, 25, 20, 25, 26, 13, + 32, 1, 2, 33, 4, 33, 34, 37, 8, 33, 34, 41, 36, 41, 42, 13, + 16, 33, 34, 49, 36, 49, 50, 21, 40, 49, 50, 25, 52, 25, 26, 45, + 64, 1, 2, 65, 4, 65, 66, 69, 8, 65, 66, 73, 68, 73, 74, 13, + 16, 65, 66, 81, 68, 81, 82, 21, 72, 81, 82, 25, 84, 25, 26, 77, + 32, 65, 66, 97, 68, 97, 98, 37, 72, 97, 98, 41, 100, 41, 42, 77, + 80, 97, 98, 49, 100, 49, 50, 85, 104, 49, 50, 89, 52, 89, 90, 109, + 128, 1, 2, 129, 4, 129, 130, 133, 8, 129, 130, 137, 132, 137, 138, 13, + 16, 129, 130, 145, 132, 145, 146, 21, 136, 145, 146, 25, 148, 25, 26, 141, + 32, 129, 130, 161, 132, 161, 162, 37, 136, 161, 162, 41, 164, 41, 42, 141, + 144, 161, 162, 49, 164, 49, 50, 149, 168, 49, 50, 153, 52, 153, 154, 173, + 64, 129, 130, 193, 132, 193, 194, 69, 136, 193, 194, 73, 196, 73, 74, 141, + 144, 193, 194, 81, 196, 81, 82, 149, 200, 81, 82, 153, 84, 153, 154, 205, + 160, 193, 194, 97, 196, 97, 98, 165, 200, 97, 98, 169, 100, 169, 170, 205, + 208, 97, 98, 177, 100, 177, 178, 213, 104, 177, 178, 217, 180, 217, 218, 237, + }, { + 0, 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10, 8, 12, 12, 14, + 0, 16, 16, 18, 16, 20, 20, 22, 16, 24, 24, 26, 24, 28, 28, 14, + 0, 32, 32, 34, 32, 36, 36, 38, 32, 40, 40, 42, 40, 44, 44, 14, + 32, 48, 48, 50, 48, 52, 52, 22, 48, 56, 56, 26, 56, 28, 28, 46, + 0, 64, 64, 66, 64, 68, 68, 70, 64, 72, 72, 74, 72, 76, 76, 14, + 64, 80, 80, 82, 80, 84, 84, 22, 80, 88, 88, 26, 88, 28, 28, 78, + 64, 96, 96, 98, 96, 100, 100, 38, 96, 104, 104, 42, 104, 44, 44, 78, + 96, 112, 112, 50, 112, 52, 52, 86, 112, 56, 56, 90, 56, 92, 92, 110, + 0, 128, 128, 130, 128, 132, 132, 134, 128, 136, 136, 138, 136, 140, 140, 14, + 128, 144, 144, 146, 144, 148, 148, 22, 144, 152, 152, 26, 152, 28, 28, 142, + 128, 160, 160, 162, 160, 164, 164, 38, 160, 168, 168, 42, 168, 44, 44, 142, + 160, 176, 176, 50, 176, 52, 52, 150, 176, 56, 56, 154, 56, 156, 156, 174, + 128, 192, 192, 194, 192, 196, 196, 70, 192, 200, 200, 74, 200, 76, 76, 142, + 192, 208, 208, 82, 208, 84, 84, 150, 208, 88, 88, 154, 88, 156, 156, 206, + 192, 224, 224, 98, 224, 100, 100, 166, 224, 104, 104, 170, 104, 172, 172, 206, + 224, 112, 112, 178, 112, 180, 180, 214, 112, 184, 184, 218, 184, 220, 220, 238, + }, { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 15, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 15, + 48, 49, 50, 51, 52, 53, 54, 23, 56, 57, 58, 27, 60, 29, 30, 47, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 15, + 80, 81, 82, 83, 84, 85, 86, 23, 88, 89, 90, 27, 92, 29, 30, 79, + 96, 97, 98, 99, 100, 101, 102, 39, 104, 105, 106, 43, 108, 45, 46, 79, + 112, 113, 114, 51, 116, 53, 54, 87, 120, 57, 58, 91, 60, 93, 94, 111, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 15, + 144, 145, 146, 147, 148, 149, 150, 23, 152, 153, 154, 27, 156, 29, 30, 143, + 160, 161, 162, 163, 164, 165, 166, 39, 168, 169, 170, 43, 172, 45, 46, 143, + 176, 177, 178, 51, 180, 53, 54, 151, 184, 57, 58, 155, 60, 157, 158, 175, + 192, 193, 194, 195, 196, 197, 198, 71, 200, 201, 202, 75, 204, 77, 78, 143, + 208, 209, 210, 83, 212, 85, 86, 151, 216, 89, 90, 155, 92, 157, 158, 207, + 224, 225, 226, 99, 228, 101, 102, 167, 232, 105, 106, 171, 108, 173, 174, 207, + 240, 113, 114, 179, 116, 181, 182, 215, 120, 185, 186, 219, 188, 221, 222, 239, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, + 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 32, 0, 32, 32, 48, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 80, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 96, + 0, 0, 0, 64, 0, 64, 64, 96, 0, 64, 64, 96, 64, 96, 96, 112, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 144, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 160, + 0, 0, 0, 128, 0, 128, 128, 160, 0, 128, 128, 160, 128, 160, 160, 176, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 192, + 0, 0, 0, 128, 0, 128, 128, 192, 0, 128, 128, 192, 128, 192, 192, 208, + 0, 0, 0, 128, 0, 128, 128, 192, 0, 128, 128, 192, 128, 192, 192, 224, + 0, 128, 128, 192, 128, 192, 192, 224, 128, 192, 192, 224, 192, 224, 224, 240, + }, { + 0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, + 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 17, + 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 33, + 16, 1, 2, 1, 4, 1, 2, 33, 8, 1, 2, 33, 4, 33, 34, 49, + 64, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 65, + 16, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 81, + 32, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 97, + 16, 1, 2, 65, 4, 65, 66, 97, 8, 65, 66, 97, 68, 97, 98, 113, + 128, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 129, + 16, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 145, + 32, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 161, + 16, 1, 2, 129, 4, 129, 130, 161, 8, 129, 130, 161, 132, 161, 162, 177, + 64, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 193, + 16, 1, 2, 129, 4, 129, 130, 193, 8, 129, 130, 193, 132, 193, 194, 209, + 32, 1, 2, 129, 4, 129, 130, 193, 8, 129, 130, 193, 132, 193, 194, 225, + 16, 129, 130, 193, 132, 193, 194, 225, 136, 193, 194, 225, 196, 225, 226, 241, + }, { + 0, 0, 0, 2, 0, 4, 4, 2, 0, 8, 8, 2, 8, 4, 4, 2, + 0, 16, 16, 2, 16, 4, 4, 2, 16, 8, 8, 2, 8, 4, 4, 18, + 0, 32, 32, 2, 32, 4, 4, 2, 32, 8, 8, 2, 8, 4, 4, 34, + 32, 16, 16, 2, 16, 4, 4, 34, 16, 8, 8, 34, 8, 36, 36, 50, + 0, 64, 64, 2, 64, 4, 4, 2, 64, 8, 8, 2, 8, 4, 4, 66, + 64, 16, 16, 2, 16, 4, 4, 66, 16, 8, 8, 66, 8, 68, 68, 82, + 64, 32, 32, 2, 32, 4, 4, 66, 32, 8, 8, 66, 8, 68, 68, 98, + 32, 16, 16, 66, 16, 68, 68, 98, 16, 72, 72, 98, 72, 100, 100, 114, + 0, 128, 128, 2, 128, 4, 4, 2, 128, 8, 8, 2, 8, 4, 4, 130, + 128, 16, 16, 2, 16, 4, 4, 130, 16, 8, 8, 130, 8, 132, 132, 146, + 128, 32, 32, 2, 32, 4, 4, 130, 32, 8, 8, 130, 8, 132, 132, 162, + 32, 16, 16, 130, 16, 132, 132, 162, 16, 136, 136, 162, 136, 164, 164, 178, + 128, 64, 64, 2, 64, 4, 4, 130, 64, 8, 8, 130, 8, 132, 132, 194, + 64, 16, 16, 130, 16, 132, 132, 194, 16, 136, 136, 194, 136, 196, 196, 210, + 64, 32, 32, 130, 32, 132, 132, 194, 32, 136, 136, 194, 136, 196, 196, 226, + 32, 144, 144, 194, 144, 196, 196, 226, 144, 200, 200, 226, 200, 228, 228, 242, + }, { + 0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 10, 3, 12, 5, 6, 3, + 16, 17, 18, 3, 20, 5, 6, 3, 24, 9, 10, 3, 12, 5, 6, 19, + 32, 33, 34, 3, 36, 5, 6, 3, 40, 9, 10, 3, 12, 5, 6, 35, + 48, 17, 18, 3, 20, 5, 6, 35, 24, 9, 10, 35, 12, 37, 38, 51, + 64, 65, 66, 3, 68, 5, 6, 3, 72, 9, 10, 3, 12, 5, 6, 67, + 80, 17, 18, 3, 20, 5, 6, 67, 24, 9, 10, 67, 12, 69, 70, 83, + 96, 33, 34, 3, 36, 5, 6, 67, 40, 9, 10, 67, 12, 69, 70, 99, + 48, 17, 18, 67, 20, 69, 70, 99, 24, 73, 74, 99, 76, 101, 102, 115, + 128, 129, 130, 3, 132, 5, 6, 3, 136, 9, 10, 3, 12, 5, 6, 131, + 144, 17, 18, 3, 20, 5, 6, 131, 24, 9, 10, 131, 12, 133, 134, 147, + 160, 33, 34, 3, 36, 5, 6, 131, 40, 9, 10, 131, 12, 133, 134, 163, + 48, 17, 18, 131, 20, 133, 134, 163, 24, 137, 138, 163, 140, 165, 166, 179, + 192, 65, 66, 3, 68, 5, 6, 131, 72, 9, 10, 131, 12, 133, 134, 195, + 80, 17, 18, 131, 20, 133, 134, 195, 24, 137, 138, 195, 140, 197, 198, 211, + 96, 33, 34, 131, 36, 133, 134, 195, 40, 137, 138, 195, 140, 197, 198, 227, + 48, 145, 146, 195, 148, 197, 198, 227, 152, 201, 202, 227, 204, 229, 230, 243, + }, + { + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 8, 8, 4, + 0, 0, 0, 16, 0, 16, 16, 4, 0, 16, 16, 8, 16, 8, 8, 20, + 0, 0, 0, 32, 0, 32, 32, 4, 0, 32, 32, 8, 32, 8, 8, 36, + 0, 32, 32, 16, 32, 16, 16, 36, 32, 16, 16, 40, 16, 40, 40, 52, + 0, 0, 0, 64, 0, 64, 64, 4, 0, 64, 64, 8, 64, 8, 8, 68, + 0, 64, 64, 16, 64, 16, 16, 68, 64, 16, 16, 72, 16, 72, 72, 84, + 0, 64, 64, 32, 64, 32, 32, 68, 64, 32, 32, 72, 32, 72, 72, 100, + 64, 32, 32, 80, 32, 80, 80, 100, 32, 80, 80, 104, 80, 104, 104, 116, + 0, 0, 0, 128, 0, 128, 128, 4, 0, 128, 128, 8, 128, 8, 8, 132, + 0, 128, 128, 16, 128, 16, 16, 132, 128, 16, 16, 136, 16, 136, 136, 148, + 0, 128, 128, 32, 128, 32, 32, 132, 128, 32, 32, 136, 32, 136, 136, 164, + 128, 32, 32, 144, 32, 144, 144, 164, 32, 144, 144, 168, 144, 168, 168, 180, + 0, 128, 128, 64, 128, 64, 64, 132, 128, 64, 64, 136, 64, 136, 136, 196, + 128, 64, 64, 144, 64, 144, 144, 196, 64, 144, 144, 200, 144, 200, 200, 212, + 128, 64, 64, 160, 64, 160, 160, 196, 64, 160, 160, 200, 160, 200, 200, 228, + 64, 160, 160, 208, 160, 208, 208, 228, 160, 208, 208, 232, 208, 232, 232, 244, + }, { + 0, 1, 2, 1, 4, 1, 2, 5, 8, 1, 2, 9, 4, 9, 10, 5, + 16, 1, 2, 17, 4, 17, 18, 5, 8, 17, 18, 9, 20, 9, 10, 21, + 32, 1, 2, 33, 4, 33, 34, 5, 8, 33, 34, 9, 36, 9, 10, 37, + 16, 33, 34, 17, 36, 17, 18, 37, 40, 17, 18, 41, 20, 41, 42, 53, + 64, 1, 2, 65, 4, 65, 66, 5, 8, 65, 66, 9, 68, 9, 10, 69, + 16, 65, 66, 17, 68, 17, 18, 69, 72, 17, 18, 73, 20, 73, 74, 85, + 32, 65, 66, 33, 68, 33, 34, 69, 72, 33, 34, 73, 36, 73, 74, 101, + 80, 33, 34, 81, 36, 81, 82, 101, 40, 81, 82, 105, 84, 105, 106, 117, + 128, 1, 2, 129, 4, 129, 130, 5, 8, 129, 130, 9, 132, 9, 10, 133, + 16, 129, 130, 17, 132, 17, 18, 133, 136, 17, 18, 137, 20, 137, 138, 149, + 32, 129, 130, 33, 132, 33, 34, 133, 136, 33, 34, 137, 36, 137, 138, 165, + 144, 33, 34, 145, 36, 145, 146, 165, 40, 145, 146, 169, 148, 169, 170, 181, + 64, 129, 130, 65, 132, 65, 66, 133, 136, 65, 66, 137, 68, 137, 138, 197, + 144, 65, 66, 145, 68, 145, 146, 197, 72, 145, 146, 201, 148, 201, 202, 213, + 160, 65, 66, 161, 68, 161, 162, 197, 72, 161, 162, 201, 164, 201, 202, 229, + 80, 161, 162, 209, 164, 209, 210, 229, 168, 209, 210, 233, 212, 233, 234, 245, + }, { + 0, 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10, 8, 12, 12, 6, + 0, 16, 16, 18, 16, 20, 20, 6, 16, 24, 24, 10, 24, 12, 12, 22, + 0, 32, 32, 34, 32, 36, 36, 6, 32, 40, 40, 10, 40, 12, 12, 38, + 32, 48, 48, 18, 48, 20, 20, 38, 48, 24, 24, 42, 24, 44, 44, 54, + 0, 64, 64, 66, 64, 68, 68, 6, 64, 72, 72, 10, 72, 12, 12, 70, + 64, 80, 80, 18, 80, 20, 20, 70, 80, 24, 24, 74, 24, 76, 76, 86, + 64, 96, 96, 34, 96, 36, 36, 70, 96, 40, 40, 74, 40, 76, 76, 102, + 96, 48, 48, 82, 48, 84, 84, 102, 48, 88, 88, 106, 88, 108, 108, 118, + 0, 128, 128, 130, 128, 132, 132, 6, 128, 136, 136, 10, 136, 12, 12, 134, + 128, 144, 144, 18, 144, 20, 20, 134, 144, 24, 24, 138, 24, 140, 140, 150, + 128, 160, 160, 34, 160, 36, 36, 134, 160, 40, 40, 138, 40, 140, 140, 166, + 160, 48, 48, 146, 48, 148, 148, 166, 48, 152, 152, 170, 152, 172, 172, 182, + 128, 192, 192, 66, 192, 68, 68, 134, 192, 72, 72, 138, 72, 140, 140, 198, + 192, 80, 80, 146, 80, 148, 148, 198, 80, 152, 152, 202, 152, 204, 204, 214, + 192, 96, 96, 162, 96, 164, 164, 198, 96, 168, 168, 202, 168, 204, 204, 230, + 96, 176, 176, 210, 176, 212, 212, 230, 176, 216, 216, 234, 216, 236, 236, 246, + }, { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 7, + 16, 17, 18, 19, 20, 21, 22, 7, 24, 25, 26, 11, 28, 13, 14, 23, + 32, 33, 34, 35, 36, 37, 38, 7, 40, 41, 42, 11, 44, 13, 14, 39, + 48, 49, 50, 19, 52, 21, 22, 39, 56, 25, 26, 43, 28, 45, 46, 55, + 64, 65, 66, 67, 68, 69, 70, 7, 72, 73, 74, 11, 76, 13, 14, 71, + 80, 81, 82, 19, 84, 21, 22, 71, 88, 25, 26, 75, 28, 77, 78, 87, + 96, 97, 98, 35, 100, 37, 38, 71, 104, 41, 42, 75, 44, 77, 78, 103, + 112, 49, 50, 83, 52, 85, 86, 103, 56, 89, 90, 107, 92, 109, 110, 119, + 128, 129, 130, 131, 132, 133, 134, 7, 136, 137, 138, 11, 140, 13, 14, 135, + 144, 145, 146, 19, 148, 21, 22, 135, 152, 25, 26, 139, 28, 141, 142, 151, + 160, 161, 162, 35, 164, 37, 38, 135, 168, 41, 42, 139, 44, 141, 142, 167, + 176, 49, 50, 147, 52, 149, 150, 167, 56, 153, 154, 171, 156, 173, 174, 183, + 192, 193, 194, 67, 196, 69, 70, 135, 200, 73, 74, 139, 76, 141, 142, 199, + 208, 81, 82, 147, 84, 149, 150, 199, 88, 153, 154, 203, 156, 205, 206, 215, + 224, 97, 98, 163, 100, 165, 166, 199, 104, 169, 170, 203, 172, 205, 206, 231, + 112, 177, 178, 211, 180, 213, 214, 231, 184, 217, 218, 235, 220, 237, 238, 247, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, + 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 16, 0, 16, 16, 24, + 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 32, 0, 32, 32, 40, + 0, 0, 0, 32, 0, 32, 32, 48, 0, 32, 32, 48, 32, 48, 48, 56, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 64, 0, 64, 64, 72, + 0, 0, 0, 64, 0, 64, 64, 80, 0, 64, 64, 80, 64, 80, 80, 88, + 0, 0, 0, 64, 0, 64, 64, 96, 0, 64, 64, 96, 64, 96, 96, 104, + 0, 64, 64, 96, 64, 96, 96, 112, 64, 96, 96, 112, 96, 112, 112, 120, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 136, + 0, 0, 0, 128, 0, 128, 128, 144, 0, 128, 128, 144, 128, 144, 144, 152, + 0, 0, 0, 128, 0, 128, 128, 160, 0, 128, 128, 160, 128, 160, 160, 168, + 0, 128, 128, 160, 128, 160, 160, 176, 128, 160, 160, 176, 160, 176, 176, 184, + 0, 0, 0, 128, 0, 128, 128, 192, 0, 128, 128, 192, 128, 192, 192, 200, + 0, 128, 128, 192, 128, 192, 192, 208, 128, 192, 192, 208, 192, 208, 208, 216, + 0, 128, 128, 192, 128, 192, 192, 224, 128, 192, 192, 224, 192, 224, 224, 232, + 128, 192, 192, 224, 192, 224, 224, 240, 192, 224, 224, 240, 224, 240, 240, 248, + }, { + 0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 9, + 16, 1, 2, 1, 4, 1, 2, 17, 8, 1, 2, 17, 4, 17, 18, 25, + 32, 1, 2, 1, 4, 1, 2, 33, 8, 1, 2, 33, 4, 33, 34, 41, + 16, 1, 2, 33, 4, 33, 34, 49, 8, 33, 34, 49, 36, 49, 50, 57, + 64, 1, 2, 1, 4, 1, 2, 65, 8, 1, 2, 65, 4, 65, 66, 73, + 16, 1, 2, 65, 4, 65, 66, 81, 8, 65, 66, 81, 68, 81, 82, 89, + 32, 1, 2, 65, 4, 65, 66, 97, 8, 65, 66, 97, 68, 97, 98, 105, + 16, 65, 66, 97, 68, 97, 98, 113, 72, 97, 98, 113, 100, 113, 114, 121, + 128, 1, 2, 1, 4, 1, 2, 129, 8, 1, 2, 129, 4, 129, 130, 137, + 16, 1, 2, 129, 4, 129, 130, 145, 8, 129, 130, 145, 132, 145, 146, 153, + 32, 1, 2, 129, 4, 129, 130, 161, 8, 129, 130, 161, 132, 161, 162, 169, + 16, 129, 130, 161, 132, 161, 162, 177, 136, 161, 162, 177, 164, 177, 178, 185, + 64, 1, 2, 129, 4, 129, 130, 193, 8, 129, 130, 193, 132, 193, 194, 201, + 16, 129, 130, 193, 132, 193, 194, 209, 136, 193, 194, 209, 196, 209, 210, 217, + 32, 129, 130, 193, 132, 193, 194, 225, 136, 193, 194, 225, 196, 225, 226, 233, + 144, 193, 194, 225, 196, 225, 226, 241, 200, 225, 226, 241, 228, 241, 242, 249, + }, { + 0, 0, 0, 2, 0, 4, 4, 2, 0, 8, 8, 2, 8, 4, 4, 10, + 0, 16, 16, 2, 16, 4, 4, 18, 16, 8, 8, 18, 8, 20, 20, 26, + 0, 32, 32, 2, 32, 4, 4, 34, 32, 8, 8, 34, 8, 36, 36, 42, + 32, 16, 16, 34, 16, 36, 36, 50, 16, 40, 40, 50, 40, 52, 52, 58, + 0, 64, 64, 2, 64, 4, 4, 66, 64, 8, 8, 66, 8, 68, 68, 74, + 64, 16, 16, 66, 16, 68, 68, 82, 16, 72, 72, 82, 72, 84, 84, 90, + 64, 32, 32, 66, 32, 68, 68, 98, 32, 72, 72, 98, 72, 100, 100, 106, + 32, 80, 80, 98, 80, 100, 100, 114, 80, 104, 104, 114, 104, 116, 116, 122, + 0, 128, 128, 2, 128, 4, 4, 130, 128, 8, 8, 130, 8, 132, 132, 138, + 128, 16, 16, 130, 16, 132, 132, 146, 16, 136, 136, 146, 136, 148, 148, 154, + 128, 32, 32, 130, 32, 132, 132, 162, 32, 136, 136, 162, 136, 164, 164, 170, + 32, 144, 144, 162, 144, 164, 164, 178, 144, 168, 168, 178, 168, 180, 180, 186, + 128, 64, 64, 130, 64, 132, 132, 194, 64, 136, 136, 194, 136, 196, 196, 202, + 64, 144, 144, 194, 144, 196, 196, 210, 144, 200, 200, 210, 200, 212, 212, 218, + 64, 160, 160, 194, 160, 196, 196, 226, 160, 200, 200, 226, 200, 228, 228, 234, + 160, 208, 208, 226, 208, 228, 228, 242, 208, 232, 232, 242, 232, 244, 244, 250, + }, { + 0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 10, 3, 12, 5, 6, 11, + 16, 17, 18, 3, 20, 5, 6, 19, 24, 9, 10, 19, 12, 21, 22, 27, + 32, 33, 34, 3, 36, 5, 6, 35, 40, 9, 10, 35, 12, 37, 38, 43, + 48, 17, 18, 35, 20, 37, 38, 51, 24, 41, 42, 51, 44, 53, 54, 59, + 64, 65, 66, 3, 68, 5, 6, 67, 72, 9, 10, 67, 12, 69, 70, 75, + 80, 17, 18, 67, 20, 69, 70, 83, 24, 73, 74, 83, 76, 85, 86, 91, + 96, 33, 34, 67, 36, 69, 70, 99, 40, 73, 74, 99, 76, 101, 102, 107, + 48, 81, 82, 99, 84, 101, 102, 115, 88, 105, 106, 115, 108, 117, 118, 123, + 128, 129, 130, 3, 132, 5, 6, 131, 136, 9, 10, 131, 12, 133, 134, 139, + 144, 17, 18, 131, 20, 133, 134, 147, 24, 137, 138, 147, 140, 149, 150, 155, + 160, 33, 34, 131, 36, 133, 134, 163, 40, 137, 138, 163, 140, 165, 166, 171, + 48, 145, 146, 163, 148, 165, 166, 179, 152, 169, 170, 179, 172, 181, 182, 187, + 192, 65, 66, 131, 68, 133, 134, 195, 72, 137, 138, 195, 140, 197, 198, 203, + 80, 145, 146, 195, 148, 197, 198, 211, 152, 201, 202, 211, 204, 213, 214, 219, + 96, 161, 162, 195, 164, 197, 198, 227, 168, 201, 202, 227, 204, 229, 230, 235, + 176, 209, 210, 227, 212, 229, 230, 243, 216, 233, 234, 243, 236, 245, 246, 251, + }, + { + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 8, 8, 12, + 0, 0, 0, 16, 0, 16, 16, 20, 0, 16, 16, 24, 16, 24, 24, 28, + 0, 0, 0, 32, 0, 32, 32, 36, 0, 32, 32, 40, 32, 40, 40, 44, + 0, 32, 32, 48, 32, 48, 48, 52, 32, 48, 48, 56, 48, 56, 56, 60, + 0, 0, 0, 64, 0, 64, 64, 68, 0, 64, 64, 72, 64, 72, 72, 76, + 0, 64, 64, 80, 64, 80, 80, 84, 64, 80, 80, 88, 80, 88, 88, 92, + 0, 64, 64, 96, 64, 96, 96, 100, 64, 96, 96, 104, 96, 104, 104, 108, + 64, 96, 96, 112, 96, 112, 112, 116, 96, 112, 112, 120, 112, 120, 120, 124, + 0, 0, 0, 128, 0, 128, 128, 132, 0, 128, 128, 136, 128, 136, 136, 140, + 0, 128, 128, 144, 128, 144, 144, 148, 128, 144, 144, 152, 144, 152, 152, 156, + 0, 128, 128, 160, 128, 160, 160, 164, 128, 160, 160, 168, 160, 168, 168, 172, + 128, 160, 160, 176, 160, 176, 176, 180, 160, 176, 176, 184, 176, 184, 184, 188, + 0, 128, 128, 192, 128, 192, 192, 196, 128, 192, 192, 200, 192, 200, 200, 204, + 128, 192, 192, 208, 192, 208, 208, 212, 192, 208, 208, 216, 208, 216, 216, 220, + 128, 192, 192, 224, 192, 224, 224, 228, 192, 224, 224, 232, 224, 232, 232, 236, + 192, 224, 224, 240, 224, 240, 240, 244, 224, 240, 240, 248, 240, 248, 248, 252, + }, { + 0, 1, 2, 1, 4, 1, 2, 5, 8, 1, 2, 9, 4, 9, 10, 13, + 16, 1, 2, 17, 4, 17, 18, 21, 8, 17, 18, 25, 20, 25, 26, 29, + 32, 1, 2, 33, 4, 33, 34, 37, 8, 33, 34, 41, 36, 41, 42, 45, + 16, 33, 34, 49, 36, 49, 50, 53, 40, 49, 50, 57, 52, 57, 58, 61, + 64, 1, 2, 65, 4, 65, 66, 69, 8, 65, 66, 73, 68, 73, 74, 77, + 16, 65, 66, 81, 68, 81, 82, 85, 72, 81, 82, 89, 84, 89, 90, 93, + 32, 65, 66, 97, 68, 97, 98, 101, 72, 97, 98, 105, 100, 105, 106, 109, + 80, 97, 98, 113, 100, 113, 114, 117, 104, 113, 114, 121, 116, 121, 122, 125, + 128, 1, 2, 129, 4, 129, 130, 133, 8, 129, 130, 137, 132, 137, 138, 141, + 16, 129, 130, 145, 132, 145, 146, 149, 136, 145, 146, 153, 148, 153, 154, 157, + 32, 129, 130, 161, 132, 161, 162, 165, 136, 161, 162, 169, 164, 169, 170, 173, + 144, 161, 162, 177, 164, 177, 178, 181, 168, 177, 178, 185, 180, 185, 186, 189, + 64, 129, 130, 193, 132, 193, 194, 197, 136, 193, 194, 201, 196, 201, 202, 205, + 144, 193, 194, 209, 196, 209, 210, 213, 200, 209, 210, 217, 212, 217, 218, 221, + 160, 193, 194, 225, 196, 225, 226, 229, 200, 225, 226, 233, 228, 233, 234, 237, + 208, 225, 226, 241, 228, 241, 242, 245, 232, 241, 242, 249, 244, 249, 250, 253, + }, { + 0, 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10, 8, 12, 12, 14, + 0, 16, 16, 18, 16, 20, 20, 22, 16, 24, 24, 26, 24, 28, 28, 30, + 0, 32, 32, 34, 32, 36, 36, 38, 32, 40, 40, 42, 40, 44, 44, 46, + 32, 48, 48, 50, 48, 52, 52, 54, 48, 56, 56, 58, 56, 60, 60, 62, + 0, 64, 64, 66, 64, 68, 68, 70, 64, 72, 72, 74, 72, 76, 76, 78, + 64, 80, 80, 82, 80, 84, 84, 86, 80, 88, 88, 90, 88, 92, 92, 94, + 64, 96, 96, 98, 96, 100, 100, 102, 96, 104, 104, 106, 104, 108, 108, 110, + 96, 112, 112, 114, 112, 116, 116, 118, 112, 120, 120, 122, 120, 124, 124, 126, + 0, 128, 128, 130, 128, 132, 132, 134, 128, 136, 136, 138, 136, 140, 140, 142, + 128, 144, 144, 146, 144, 148, 148, 150, 144, 152, 152, 154, 152, 156, 156, 158, + 128, 160, 160, 162, 160, 164, 164, 166, 160, 168, 168, 170, 168, 172, 172, 174, + 160, 176, 176, 178, 176, 180, 180, 182, 176, 184, 184, 186, 184, 188, 188, 190, + 128, 192, 192, 194, 192, 196, 196, 198, 192, 200, 200, 202, 200, 204, 204, 206, + 192, 208, 208, 210, 208, 212, 212, 214, 208, 216, 216, 218, 216, 220, 220, 222, + 192, 224, 224, 226, 224, 228, 228, 230, 224, 232, 232, 234, 232, 236, 236, 238, + 224, 240, 240, 242, 240, 244, 244, 246, 240, 248, 248, 250, 248, 252, 252, 254, + }, { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, + 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, + 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, + 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, + 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + }, +} + +// popLUT contains pre-computed population counts +var popLUT = [256]uint8{ + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, +} diff --git a/vendor/github.com/bits-and-blooms/bitset/popcnt.go b/vendor/github.com/bits-and-blooms/bitset/popcnt.go index 76577a83828..93492390bf7 100644 --- a/vendor/github.com/bits-and-blooms/bitset/popcnt.go +++ b/vendor/github.com/bits-and-blooms/bitset/popcnt.go @@ -1,53 +1,59 @@ package bitset -// bit population count, take from -// https://code.google.com/p/go/issues/detail?id=4988#c11 -// credit: https://code.google.com/u/arnehormann/ -func popcount(x uint64) (n uint64) { - x -= (x >> 1) & 0x5555555555555555 - x = (x>>2)&0x3333333333333333 + x&0x3333333333333333 - x += x >> 4 - x &= 0x0f0f0f0f0f0f0f0f - x *= 0x0101010101010101 - return x >> 56 -} +import "math/bits" -func popcntSliceGo(s []uint64) uint64 { - cnt := uint64(0) +func popcntSlice(s []uint64) uint64 { + var cnt int for _, x := range s { - cnt += popcount(x) + cnt += bits.OnesCount64(x) } - return cnt + return uint64(cnt) } -func popcntMaskSliceGo(s, m []uint64) uint64 { - cnt := uint64(0) +func popcntMaskSlice(s, m []uint64) uint64 { + var cnt int + // this explicit check eliminates a bounds check in the loop + if len(m) < len(s) { + panic("mask slice is too short") + } for i := range s { - cnt += popcount(s[i] &^ m[i]) + cnt += bits.OnesCount64(s[i] &^ m[i]) } - return cnt + return uint64(cnt) } -func popcntAndSliceGo(s, m []uint64) uint64 { - cnt := uint64(0) +func popcntAndSlice(s, m []uint64) uint64 { + var cnt int + // this explicit check eliminates a bounds check in the loop + if len(m) < len(s) { + panic("mask slice is too short") + } for i := range s { - cnt += popcount(s[i] & m[i]) + cnt += bits.OnesCount64(s[i] & m[i]) } - return cnt + return uint64(cnt) } -func popcntOrSliceGo(s, m []uint64) uint64 { - cnt := uint64(0) +func popcntOrSlice(s, m []uint64) uint64 { + var cnt int + // this explicit check eliminates a bounds check in the loop + if len(m) < len(s) { + panic("mask slice is too short") + } for i := range s { - cnt += popcount(s[i] | m[i]) + cnt += bits.OnesCount64(s[i] | m[i]) } - return cnt + return uint64(cnt) } -func popcntXorSliceGo(s, m []uint64) uint64 { - cnt := uint64(0) +func popcntXorSlice(s, m []uint64) uint64 { + var cnt int + // this explicit check eliminates a bounds check in the loop + if len(m) < len(s) { + panic("mask slice is too short") + } for i := range s { - cnt += popcount(s[i] ^ m[i]) + cnt += bits.OnesCount64(s[i] ^ m[i]) } - return cnt + return uint64(cnt) } diff --git a/vendor/github.com/bits-and-blooms/bitset/popcnt_19.go b/vendor/github.com/bits-and-blooms/bitset/popcnt_19.go deleted file mode 100644 index 7855c04b5b2..00000000000 --- a/vendor/github.com/bits-and-blooms/bitset/popcnt_19.go +++ /dev/null @@ -1,62 +0,0 @@ -//go:build go1.9 -// +build go1.9 - -package bitset - -import "math/bits" - -func popcntSlice(s []uint64) uint64 { - var cnt int - for _, x := range s { - cnt += bits.OnesCount64(x) - } - return uint64(cnt) -} - -func popcntMaskSlice(s, m []uint64) uint64 { - var cnt int - // this explicit check eliminates a bounds check in the loop - if len(m) < len(s) { - panic("mask slice is too short") - } - for i := range s { - cnt += bits.OnesCount64(s[i] &^ m[i]) - } - return uint64(cnt) -} - -func popcntAndSlice(s, m []uint64) uint64 { - var cnt int - // this explicit check eliminates a bounds check in the loop - if len(m) < len(s) { - panic("mask slice is too short") - } - for i := range s { - cnt += bits.OnesCount64(s[i] & m[i]) - } - return uint64(cnt) -} - -func popcntOrSlice(s, m []uint64) uint64 { - var cnt int - // this explicit check eliminates a bounds check in the loop - if len(m) < len(s) { - panic("mask slice is too short") - } - for i := range s { - cnt += bits.OnesCount64(s[i] | m[i]) - } - return uint64(cnt) -} - -func popcntXorSlice(s, m []uint64) uint64 { - var cnt int - // this explicit check eliminates a bounds check in the loop - if len(m) < len(s) { - panic("mask slice is too short") - } - for i := range s { - cnt += bits.OnesCount64(s[i] ^ m[i]) - } - return uint64(cnt) -} diff --git a/vendor/github.com/bits-and-blooms/bitset/popcnt_amd64.go b/vendor/github.com/bits-and-blooms/bitset/popcnt_amd64.go deleted file mode 100644 index 116e044407c..00000000000 --- a/vendor/github.com/bits-and-blooms/bitset/popcnt_amd64.go +++ /dev/null @@ -1,68 +0,0 @@ -//go:build !go1.9 && amd64 && !appengine -// +build !go1.9,amd64,!appengine - -package bitset - -// *** the following functions are defined in popcnt_amd64.s - -//go:noescape - -func hasAsm() bool - -// useAsm is a flag used to select the GO or ASM implementation of the popcnt function -var useAsm = hasAsm() - -//go:noescape - -func popcntSliceAsm(s []uint64) uint64 - -//go:noescape - -func popcntMaskSliceAsm(s, m []uint64) uint64 - -//go:noescape - -func popcntAndSliceAsm(s, m []uint64) uint64 - -//go:noescape - -func popcntOrSliceAsm(s, m []uint64) uint64 - -//go:noescape - -func popcntXorSliceAsm(s, m []uint64) uint64 - -func popcntSlice(s []uint64) uint64 { - if useAsm { - return popcntSliceAsm(s) - } - return popcntSliceGo(s) -} - -func popcntMaskSlice(s, m []uint64) uint64 { - if useAsm { - return popcntMaskSliceAsm(s, m) - } - return popcntMaskSliceGo(s, m) -} - -func popcntAndSlice(s, m []uint64) uint64 { - if useAsm { - return popcntAndSliceAsm(s, m) - } - return popcntAndSliceGo(s, m) -} - -func popcntOrSlice(s, m []uint64) uint64 { - if useAsm { - return popcntOrSliceAsm(s, m) - } - return popcntOrSliceGo(s, m) -} - -func popcntXorSlice(s, m []uint64) uint64 { - if useAsm { - return popcntXorSliceAsm(s, m) - } - return popcntXorSliceGo(s, m) -} diff --git a/vendor/github.com/bits-and-blooms/bitset/popcnt_amd64.s b/vendor/github.com/bits-and-blooms/bitset/popcnt_amd64.s deleted file mode 100644 index 666c0dcc17f..00000000000 --- a/vendor/github.com/bits-and-blooms/bitset/popcnt_amd64.s +++ /dev/null @@ -1,104 +0,0 @@ -// +build !go1.9 -// +build amd64,!appengine - -TEXT ·hasAsm(SB),4,$0-1 -MOVQ $1, AX -CPUID -SHRQ $23, CX -ANDQ $1, CX -MOVB CX, ret+0(FP) -RET - -#define POPCNTQ_DX_DX BYTE $0xf3; BYTE $0x48; BYTE $0x0f; BYTE $0xb8; BYTE $0xd2 - -TEXT ·popcntSliceAsm(SB),4,$0-32 -XORQ AX, AX -MOVQ s+0(FP), SI -MOVQ s_len+8(FP), CX -TESTQ CX, CX -JZ popcntSliceEnd -popcntSliceLoop: -BYTE $0xf3; BYTE $0x48; BYTE $0x0f; BYTE $0xb8; BYTE $0x16 // POPCNTQ (SI), DX -ADDQ DX, AX -ADDQ $8, SI -LOOP popcntSliceLoop -popcntSliceEnd: -MOVQ AX, ret+24(FP) -RET - -TEXT ·popcntMaskSliceAsm(SB),4,$0-56 -XORQ AX, AX -MOVQ s+0(FP), SI -MOVQ s_len+8(FP), CX -TESTQ CX, CX -JZ popcntMaskSliceEnd -MOVQ m+24(FP), DI -popcntMaskSliceLoop: -MOVQ (DI), DX -NOTQ DX -ANDQ (SI), DX -POPCNTQ_DX_DX -ADDQ DX, AX -ADDQ $8, SI -ADDQ $8, DI -LOOP popcntMaskSliceLoop -popcntMaskSliceEnd: -MOVQ AX, ret+48(FP) -RET - -TEXT ·popcntAndSliceAsm(SB),4,$0-56 -XORQ AX, AX -MOVQ s+0(FP), SI -MOVQ s_len+8(FP), CX -TESTQ CX, CX -JZ popcntAndSliceEnd -MOVQ m+24(FP), DI -popcntAndSliceLoop: -MOVQ (DI), DX -ANDQ (SI), DX -POPCNTQ_DX_DX -ADDQ DX, AX -ADDQ $8, SI -ADDQ $8, DI -LOOP popcntAndSliceLoop -popcntAndSliceEnd: -MOVQ AX, ret+48(FP) -RET - -TEXT ·popcntOrSliceAsm(SB),4,$0-56 -XORQ AX, AX -MOVQ s+0(FP), SI -MOVQ s_len+8(FP), CX -TESTQ CX, CX -JZ popcntOrSliceEnd -MOVQ m+24(FP), DI -popcntOrSliceLoop: -MOVQ (DI), DX -ORQ (SI), DX -POPCNTQ_DX_DX -ADDQ DX, AX -ADDQ $8, SI -ADDQ $8, DI -LOOP popcntOrSliceLoop -popcntOrSliceEnd: -MOVQ AX, ret+48(FP) -RET - -TEXT ·popcntXorSliceAsm(SB),4,$0-56 -XORQ AX, AX -MOVQ s+0(FP), SI -MOVQ s_len+8(FP), CX -TESTQ CX, CX -JZ popcntXorSliceEnd -MOVQ m+24(FP), DI -popcntXorSliceLoop: -MOVQ (DI), DX -XORQ (SI), DX -POPCNTQ_DX_DX -ADDQ DX, AX -ADDQ $8, SI -ADDQ $8, DI -LOOP popcntXorSliceLoop -popcntXorSliceEnd: -MOVQ AX, ret+48(FP) -RET diff --git a/vendor/github.com/bits-and-blooms/bitset/popcnt_generic.go b/vendor/github.com/bits-and-blooms/bitset/popcnt_generic.go deleted file mode 100644 index 9e0ad464e09..00000000000 --- a/vendor/github.com/bits-and-blooms/bitset/popcnt_generic.go +++ /dev/null @@ -1,25 +0,0 @@ -//go:build !go1.9 && (!amd64 || appengine) -// +build !go1.9 -// +build !amd64 appengine - -package bitset - -func popcntSlice(s []uint64) uint64 { - return popcntSliceGo(s) -} - -func popcntMaskSlice(s, m []uint64) uint64 { - return popcntMaskSliceGo(s, m) -} - -func popcntAndSlice(s, m []uint64) uint64 { - return popcntAndSliceGo(s, m) -} - -func popcntOrSlice(s, m []uint64) uint64 { - return popcntOrSliceGo(s, m) -} - -func popcntXorSlice(s, m []uint64) uint64 { - return popcntXorSliceGo(s, m) -} diff --git a/vendor/github.com/bits-and-blooms/bitset/select.go b/vendor/github.com/bits-and-blooms/bitset/select.go index f15e74a2c9e..a43c6bd6a2e 100644 --- a/vendor/github.com/bits-and-blooms/bitset/select.go +++ b/vendor/github.com/bits-and-blooms/bitset/select.go @@ -1,10 +1,12 @@ package bitset +import "math/bits" + func select64(w uint64, j uint) uint { seen := 0 // Divide 64bit part := w & 0xFFFFFFFF - n := uint(popcount(part)) + n := uint(bits.OnesCount64(part)) if n <= j { part = w >> 32 seen += 32 @@ -15,7 +17,7 @@ func select64(w uint64, j uint) uint { // Divide 32bit part = ww & 0xFFFF - n = uint(popcount(part)) + n = uint(bits.OnesCount64(part)) if n <= j { part = ww >> 16 seen += 16 @@ -25,7 +27,7 @@ func select64(w uint64, j uint) uint { // Divide 16bit part = ww & 0xFF - n = uint(popcount(part)) + n = uint(bits.OnesCount64(part)) if n <= j { part = ww >> 8 seen += 8 diff --git a/vendor/github.com/bits-and-blooms/bitset/trailing_zeros_18.go b/vendor/github.com/bits-and-blooms/bitset/trailing_zeros_18.go deleted file mode 100644 index 12336e76af3..00000000000 --- a/vendor/github.com/bits-and-blooms/bitset/trailing_zeros_18.go +++ /dev/null @@ -1,15 +0,0 @@ -//go:build !go1.9 -// +build !go1.9 - -package bitset - -var deBruijn = [...]byte{ - 0, 1, 56, 2, 57, 49, 28, 3, 61, 58, 42, 50, 38, 29, 17, 4, - 62, 47, 59, 36, 45, 43, 51, 22, 53, 39, 33, 30, 24, 18, 12, 5, - 63, 55, 48, 27, 60, 41, 37, 16, 46, 35, 44, 21, 52, 32, 23, 11, - 54, 26, 40, 15, 34, 20, 31, 10, 25, 14, 19, 9, 13, 8, 7, 6, -} - -func trailingZeroes64(v uint64) uint { - return uint(deBruijn[((v&-v)*0x03f79d71b4ca8b09)>>58]) -} diff --git a/vendor/github.com/bits-and-blooms/bitset/trailing_zeros_19.go b/vendor/github.com/bits-and-blooms/bitset/trailing_zeros_19.go deleted file mode 100644 index cfb0a840910..00000000000 --- a/vendor/github.com/bits-and-blooms/bitset/trailing_zeros_19.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build go1.9 -// +build go1.9 - -package bitset - -import "math/bits" - -func trailingZeroes64(v uint64) uint { - return uint(bits.TrailingZeros64(v)) -} diff --git a/vendor/github.com/consensys/bavard/.gitignore b/vendor/github.com/consensys/bavard/.gitignore deleted file mode 100644 index 4a3d4858e0f..00000000000 --- a/vendor/github.com/consensys/bavard/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ - -.idea/* \ No newline at end of file diff --git a/vendor/github.com/consensys/bavard/LICENSE b/vendor/github.com/consensys/bavard/LICENSE deleted file mode 100644 index f49a4e16e68..00000000000 --- a/vendor/github.com/consensys/bavard/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file diff --git a/vendor/github.com/consensys/bavard/README.md b/vendor/github.com/consensys/bavard/README.md deleted file mode 100644 index a4ceab6130f..00000000000 --- a/vendor/github.com/consensys/bavard/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# bavard - -Internal package with some code-generation helper (txt/template and asm). - -Used by: - -* [gnark](https://github.com/consensys/gnark) -* [gurvy](https://github.com/consensys/gurvy) -* [goff](https://github.com/consensys/goff) \ No newline at end of file diff --git a/vendor/github.com/consensys/bavard/bavard.go b/vendor/github.com/consensys/bavard/bavard.go deleted file mode 100644 index c9164dcf426..00000000000 --- a/vendor/github.com/consensys/bavard/bavard.go +++ /dev/null @@ -1,345 +0,0 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package bavard contains helper functions to generate consistent code from text/template templates. -// it is used by github.com/consensys/gnark && github.com/consensys/gnark-crypto -package bavard - -import ( - "bytes" - "errors" - "fmt" - "io" - "os" - "os/exec" - "path" - "path/filepath" - "strings" - "sync" - "text/template" - - "rsc.io/tmplfunc" -) - -// Bavard root object to configure the code generation from text/template -type Bavard struct { - verbose bool - fmt bool - imports bool - docFile bool - packageName string - license string - generated string - buildTag string - funcs template.FuncMap -} - -// BatchGenerator enables more efficient and clean multiple file generation -type BatchGenerator struct { - defaultOpts []func(*Bavard) error -} - -// NewBatchGenerator returns a new BatchGenerator -func NewBatchGenerator(copyrightHolder string, copyrightYear int, generatedBy string) *BatchGenerator { - return &BatchGenerator{ - defaultOpts: []func(*Bavard) error{ - Apache2(copyrightHolder, copyrightYear), - GeneratedBy(generatedBy), - Format(false), - Import(false), - Verbose(true), - }, - } -} - -// Entry to be used in batch generation of files -type Entry struct { - File string - Templates []string - BuildTag string -} - -// GenerateFromString will concatenate templates and create output file from executing the resulting text/template -// see other package functions to add options (package name, licensing, build tags, ...) -func GenerateFromString(output string, templates []string, data interface{}, options ...func(*Bavard) error) error { - var b Bavard - - var buf bytes.Buffer - - if err := b.config(&buf, output, options...); err != nil { - return err - } - - fnHelpers := helpers() - for k, v := range b.funcs { - fnHelpers[k] = v - } - - tmpl := template.New("").Funcs(fnHelpers) - - if err := tmplfunc.Parse(tmpl, aggregate(templates)); err != nil { - return err - } - - // execute template - if err := tmpl.Execute(&buf, data); err != nil { - return err - } - - return b.create(output, &buf) -} - -// GenerateFromFiles will concatenate templates and create output file from executing the resulting text/template -// see other package functions to add options (package name, licensing, build tags, ...) -func GenerateFromFiles(output string, templateF []string, data interface{}, options ...func(*Bavard) error) error { - var b Bavard - var buf bytes.Buffer - - b.config(&buf, output, options...) - - // parse templates - fnHelpers := helpers() - for k, v := range b.funcs { - fnHelpers[k] = v - } - - if len(templateF) == 0 { - return errors.New("missing templates") - } - tName := path.Base(templateF[0]) - - tmpl := template.New(tName).Funcs(fnHelpers) - - if err := tmplfunc.ParseFiles(tmpl, templateF...); err != nil { - return err - } - - // execute template - if err := tmpl.Execute(&buf, data); err != nil { - return err - } - return b.create(output, &buf) -} - -func (b *Bavard) config(buf *bytes.Buffer, output string, options ...func(*Bavard) error) error { - // default settings - b.imports = false - b.fmt = false - b.verbose = true - b.generated = "bavard" - b.docFile = strings.HasSuffix(output, "doc.go") - - // handle options - for _, option := range options { - if err := option(b); err != nil { - return err - } - } - - if b.buildTag != "" { - if _, err := buf.WriteString("// +build " + b.buildTag + "\n"); err != nil { - return err - } - } - - if b.license != "" { - if _, err := buf.WriteString(b.license + "\n"); err != nil { - return err - } - } - if _, err := buf.WriteString(fmt.Sprintf("// Code generated by %s DO NOT EDIT\n\n", b.generated)); err != nil { - return err - } - - if !b.docFile && b.packageName != "" { - if _, err := buf.WriteString("package " + b.packageName + "\n\n"); err != nil { - return err - } - } - return nil -} - -func (b *Bavard) create(output string, buf *bytes.Buffer) error { - // create output dir if not exist - _ = os.MkdirAll(filepath.Dir(output), os.ModePerm) - - // create output file - file, err := os.Create(output) - if err != nil { - return err - } - if b.verbose { - fmt.Printf("generating %-70s\n", filepath.Clean(output)) - } - if _, err := io.Copy(file, buf); err != nil { - file.Close() - return err - } - - file.Close() - - // format generated code - if b.fmt { - cmd := exec.Command("gofmt", "-s", "-w", output) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - if err := cmd.Run(); err != nil { - return err - } - } - - // run goimports on generated code - if b.imports { - cmd := exec.Command("goimports", "-w", output) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - if err := cmd.Run(); err != nil { - return err - } - } - - return nil -} - -func aggregate(values []string) string { - var sb strings.Builder - for _, v := range values { - sb.WriteString(v) - } - return sb.String() -} - -// Apache2Header returns a Apache2 header string -func Apache2Header(copyrightHolder string, year int) string { - apache2 := ` - // Copyright %d %s - // - // Licensed under the Apache License, Version 2.0 (the "License"); - // you may not use this file except in compliance with the License. - // You may obtain a copy of the License at - // - // http://www.apache.org/licenses/LICENSE-2.0 - // - // Unless required by applicable law or agreed to in writing, software - // distributed under the License is distributed on an "AS IS" BASIS, - // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - // See the License for the specific language governing permissions and - // limitations under the License. - ` - return fmt.Sprintf(apache2, year, copyrightHolder) -} - -// Apache2 returns a bavard option to be used in Generate writing an apache2 licence header in the generated file -func Apache2(copyrightHolder string, year int) func(*Bavard) error { - return func(b *Bavard) error { - b.license = Apache2Header(copyrightHolder, year) - return nil - } -} - -// GeneratedBy returns a bavard option to be used in Generate writing a standard -// "Code generated by 'label' DO NOT EDIT" -func GeneratedBy(label string) func(*Bavard) error { - return func(b *Bavard) error { - b.generated = label - return nil - } -} - -// BuildTag returns a bavard option to be used in Generate adding build tags string on top of the generated file -func BuildTag(buildTag string) func(*Bavard) error { - return func(b *Bavard) error { - b.buildTag = buildTag - return nil - } -} - -// Package returns a bavard option adding package name and optional package documentation in the generated file -func Package(name string) func(*Bavard) error { - return func(b *Bavard) error { - b.packageName = name - return nil - } -} - -// Verbose returns a bavard option to be used in Generate. If set to true, will print to stdout during code generation -func Verbose(v bool) func(*Bavard) error { - return func(b *Bavard) error { - b.verbose = v - return nil - } -} - -// Format returns a bavard option to be used in Generate. If set to true, will run gofmt on generated file. -// Or simple tab alignment on .s files -func Format(v bool) func(*Bavard) error { - return func(b *Bavard) error { - b.fmt = v - return nil - } -} - -// Import returns a bavard option to be used in Generate. If set to true, will run goimports -func Import(v bool) func(*Bavard) error { - return func(b *Bavard) error { - b.imports = v - return nil - } -} - -// Funcs returns a bavard option to be used in Generate. See text/template FuncMap for more info -func Funcs(funcs template.FuncMap) func(*Bavard) error { - return func(b *Bavard) error { - b.funcs = funcs - return nil - } -} - -// Generate an entry with generator default config -func (b *BatchGenerator) Generate(data interface{}, packageName string, baseTmplDir string, entries ...Entry) error { - return b.GenerateWithOptions(data, packageName, baseTmplDir, make([]func(*Bavard)error,0), entries...) -} - -// GenerateWithOptions allows adding extra configuration (helper functions etc.) to a batch generation -func (b *BatchGenerator) GenerateWithOptions(data interface{}, packageName string, baseTmplDir string, extraOptions []func(*Bavard) error, entries ...Entry) error { - var firstError error - var lock sync.RWMutex - var wg sync.WaitGroup - for i := 0; i < len(entries); i++ { - wg.Add(1) - go func(entry Entry) { - defer wg.Done() - opts := make([]func(*Bavard) error, len(b.defaultOpts) + len(extraOptions)) - copy(opts, b.defaultOpts) - copy(opts[len(b.defaultOpts):], extraOptions) - if entry.BuildTag != "" { - opts = append(opts, BuildTag(entry.BuildTag)) - } - opts = append(opts, Package(packageName)) - for j := 0; j < len(entry.Templates); j++ { - entry.Templates[j] = filepath.Join(baseTmplDir, entry.Templates[j]) - } - if err := GenerateFromFiles(entry.File, entry.Templates, data, opts...); err != nil { - lock.Lock() - if firstError == nil { - firstError = err - } - lock.Unlock() - } - }(entries[i]) - } - wg.Wait() - - return firstError -} \ No newline at end of file diff --git a/vendor/github.com/consensys/bavard/helpers.go b/vendor/github.com/consensys/bavard/helpers.go deleted file mode 100644 index 2e2f91f4fc1..00000000000 --- a/vendor/github.com/consensys/bavard/helpers.go +++ /dev/null @@ -1,525 +0,0 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package bavard - -import ( - "bytes" - "errors" - "fmt" - "math/big" - "math/bits" - "reflect" - "strconv" - "strings" - "sync" - "text/template" -) - -// Template helpers (txt/template) -func helpers() template.FuncMap { - // functions used in template - return template.FuncMap{ - "add": add, - "bits": getBits, - "bytes": intBytes, //TODO: Do this directly - "capitalize": strings.Title, - "dict": dict, - "div": div, - "divides": divides, - "first": first, - "gt": gt, - "interval": interval, - "iterate": iterate, - "select": _select, - "last": last, - "list": makeSlice, - "log": fmt.Println, - "lt": lt, - "mod": mod, - "mul": mul, - "mul2": mul2, - "noFirst": noFirst, - "noLast": noLast, - "notNil": notNil, - "pretty": pretty, - "printList": printList, - "reverse": reverse, - "sub": sub, - "supScr": toSuperscript, - "toInt64": toInt64, - "toLower": strings.ToLower, - "toTitle": strings.Title, - "toUpper": strings.ToUpper, - "words64": bigIntToUint64SliceAsString, - } -} - -func _select(condition bool, ifNot, ifSo interface{}) interface{} { - if condition { - return ifSo - } - return ifNot -} - -func pretty(a interface{}) interface{} { - if res, err := printList(a); err == nil { - return res - } - - if s, ok := a.(big.Int); ok { - return s.String() - } - - return a -} - -func cmp(a, b interface{}, expectedCmp int) (bool, error) { - aI, err := toBigInt(a) - if err != nil { - return false, err - } - var bI big.Int - bI, err = toBigInt(b) - if err != nil { - return false, err - } - return aI.Cmp(&bI) == expectedCmp, nil -} - -func lt(a, b interface{}) (bool, error) { - return cmp(a, b, -1) -} - -func gt(a, b interface{}) (bool, error) { - return cmp(a, b, +1) -} - -func getBitsBig(a big.Int) ([]bool, error) { - l := a.BitLen() - res := make([]bool, l) - for i := 0; i < l; i ++ { - res[i] = a.Bit(i) == 1 - } - return res, nil -} - -func getBits(a interface{}) ([]bool, error) { - - if aBI, ok := a.(big.Int); ok { - return getBitsBig(aBI) - } - - var res []bool - aI, err := toInt64(a) - - if err != nil { - return res, err - } - - for aI != 0 { - res = append(res, aI%2 != 0) - aI /= 2 - } - - return res, nil -} - -func toBigInt(a interface{}) (big.Int, error) { - switch i := a.(type) { - case big.Int: - return i, nil - case *big.Int: - return *i, nil - /*case string: - var res big.Int - res.SetString(i, 0) - return res, nil*/ - default: - n, err := toInt64(i) - return *big.NewInt(n), err - } -} - -func toInt64(a interface{}) (int64, error) { - switch i := a.(type) { - case uint8: - return int64(i), nil - case int8: - return int64(i), nil - case uint16: - return int64(i), nil - case int16: - return int64(i), nil - case uint32: - return int64(i), nil - case int32: - return int64(i), nil - case uint64: - if i>>63 != 0 { - return -1, fmt.Errorf("uint64 value won't fit in int64") - } - return int64(i), nil - case int64: - return i, nil - case int: - return int64(i), nil - case big.Int: - if !i.IsInt64() { - return -1, fmt.Errorf("big.Int value won't fit in int64") - } - return i.Int64(), nil - case *big.Int: - if !i.IsInt64() { - return -1, fmt.Errorf("big.Int value won't fit in int64") - } - return i.Int64(), nil - default: - return 0, fmt.Errorf("cannot convert to int64 from type %T", i) - } -} - -func mod(a, b interface{}) (int64, error) { - - var err error - A, err := toInt64(a) - - if err != nil { - return 0, err - } - - B, err := toInt64(b) - - if err != nil { - return 0, err - } - return A % B, nil -} - -func intBytes(i big.Int) []byte { - return i.Bytes() -} - -func interval(begin, end interface{}) ([]int64, error) { - beginInt, err := toInt64(begin) - if err != nil { - return nil, err - } - endInt, err := toInt64(end) - if err != nil { - return nil, err - } - - l := endInt - beginInt - r := make([]int64, l) - for i := int64(0); i < l; i++ { - r[i] = i + beginInt - } - return r, nil -} - -// Adopted from https://stackoverflow.com/a/50487104/5116581 -func notNil(input interface{}) bool { - isNil := input == nil || (reflect.ValueOf(input).Kind() == reflect.Ptr && reflect.ValueOf(input).IsNil()) - return !isNil -} - -func AssertSlice(input interface{}) (reflect.Value, error) { - s := reflect.ValueOf(input) - if s.Kind() != reflect.Slice { - return s, fmt.Errorf("value %s is not a slice", fmt.Sprint(s)) - } - return s, nil -} - -func first(input interface{}) (interface{}, error) { - s, err := AssertSlice(input) - if err != nil { - return nil, err - } - if s.Len() == 0 { - return nil, fmt.Errorf("empty slice") - } - return s.Index(0).Interface(), nil -} - -func last(input interface{}) (interface{}, error) { - s, err := AssertSlice(input) - if err != nil { - return nil, err - } - if s.Len() == 0 { - return nil, fmt.Errorf("empty slice") - } - return s.Index(s.Len() - 1).Interface(), nil -} - -var StringBuilderPool = sync.Pool{New: func() interface{} { return &strings.Builder{} }} - -func WriteBigIntAsUint64Slice(builder *strings.Builder, input *big.Int) { - words := input.Bits() - - if len(words) == 0 { - builder.WriteString("0") - return - } - - for i := 0; i < len(words); i++ { - w := uint64(words[i]) - - if bits.UintSize == 32 && i < len(words)-1 { - i++ - w = (w << 32) | uint64(words[i]) - } - - builder.WriteString(strconv.FormatUint(w, 10)) - - if i < len(words)-1 { - builder.WriteString(", ") - } - } -} - -func bigIntToUint64SliceAsString(in interface{}) (string, error) { - - var input *big.Int - - switch i := in.(type) { - case big.Int: - input = &i - case *big.Int: - input = i - default: - return "", fmt.Errorf("unsupported type %T", in) - } - - builder := StringBuilderPool.Get().(*strings.Builder) - builder.Reset() - defer StringBuilderPool.Put(builder) - - WriteBigIntAsUint64Slice(builder, input) - - return builder.String(), nil -} - -func printList(input interface{}) (string, error) { - - s, err := AssertSlice(input) - - if err != nil || s.Len() == 0 { - return "", err - } - - builder := StringBuilderPool.Get().(*strings.Builder) - builder.Reset() - defer StringBuilderPool.Put(builder) - - builder.WriteString(fmt.Sprint(pretty(s.Index(0).Interface()))) - - for i := 1; i < s.Len(); i++ { - builder.WriteString(", ") - builder.WriteString(fmt.Sprint(pretty(s.Index(i).Interface()))) - } - - return builder.String(), nil -} - -func iterate(start, end interface{}) (r []int64, err error) { - - startI, err := toInt64(start) - if err != nil { - return nil, err - } - var endI int64 - endI, err = toInt64(end) - - if err != nil { - return nil, err - } - - for i := startI; i < endI; i++ { - r = append(r, i) - } - return -} - -func reverse(input interface{}) interface{} { - - s, err := AssertSlice(input) - if err != nil { - return err - } - l := s.Len() - toReturn := reflect.MakeSlice(s.Type(), l, l) - - l-- - for i := 0; i <= l; i++ { - toReturn.Index(l - i).Set(s.Index(i)) - } - return toReturn.Interface() -} - -func noFirst(input interface{}) interface{} { - s, err := AssertSlice(input) - if s.Len() == 0 { - return input - } - if err != nil { - return err - } - l := s.Len() - 1 - toReturn := reflect.MakeSlice(s.Type(), l, l) - for i := 0; i < l; i++ { - toReturn.Index(i).Set(s.Index(i + 1)) - } - return toReturn.Interface() -} - -func noLast(input interface{}) interface{} { - s, err := AssertSlice(input) - if s.Len() == 0 { - return input - } - if err != nil { - return err - } - l := s.Len() - 1 - toReturn := reflect.MakeSlice(s.Type(), l, l) - for i := 0; i < l; i++ { - toReturn.Index(i).Set(s.Index(i)) - } - return toReturn.Interface() -} - -func add(a, b interface{}) (int64, error) { - aI, err := toInt64(a) - if err != nil { - return 0, err - } - var bI int64 - if bI, err = toInt64(b); err != nil { - return 0, err - } - return aI + bI, nil -} -func mul(a, b interface{}) (int64, error) { - aI, err := toInt64(a) - if err != nil { - return 0, err - } - var bI int64 - if bI, err = toInt64(b); err != nil { - return 0, err - } - return aI * bI, nil -} -func sub(a, b interface{}) (int64, error) { - aI, err := toInt64(a) - if err != nil { - return 0, err - } - var bI int64 - if bI, err = toInt64(b); err != nil { - return 0, err - } - return aI - bI, nil -} -func mul2(a interface{}) (int64, error) { - aI, err := toInt64(a) - if err != nil { - return 0, err - } - - return aI * 2, nil -} -func div(a, b interface{}) (int64, error) { - aI, err := toInt64(a) - if err != nil { - return 0, err - } - var bI int64 - if bI, err = toInt64(b); err != nil { - return 0, err - } - return aI / bI, nil -} - -func makeSlice(values ...interface{}) []interface{} { - return values -} - -func dict(values ...interface{}) (map[string]interface{}, error) { - if len(values)%2 != 0 { - return nil, errors.New("invalid dict call") - } - dict := make(map[string]interface{}, len(values)/2) - for i := 0; i < len(values); i += 2 { - key, ok := values[i].(string) - if !ok { - return nil, errors.New("dict keys must be strings") - } - dict[key] = values[i+1] - } - return dict, nil -} - -// return true if c1 divides c2, that is, c2 % c1 == 0 -func divides(c1, c2 interface{}) (bool, error) { - - //try to convert to int64 - c1Int, err := toInt64(c1) - if err != nil { - return false, err - } - var c2Int int64 - c2Int, err = toInt64(c2) - if err != nil { - return false, err - } - - return c2Int%c1Int == 0, nil -} - -// Imitating supsub -var superscripts = map[rune]rune{ - '0': '⁰', - '1': '¹', - '2': '²', - '3': '³', - '4': '⁴', - '5': '⁵', - '6': '⁶', - '7': '⁷', - '8': '⁸', - '9': '⁹', -} - -// toSuperscript writes a number as a "power" -//TODO: Use https://github.com/lynn9388/supsub ? -//Copying supsub -func toSuperscript(a interface{}) (string, error) { - i, err := toInt64(a) - - if err != nil { - return "", err - } - - s := strconv.FormatInt(i, 10) - var buf bytes.Buffer - for _, r := range s { - sup := superscripts[r] - buf.WriteRune(sup) - } - return buf.String(), nil -} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/bls12-377.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/bls12-377.go index 43fbe1f6c7a..4b3ea6fbc0f 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/bls12-377.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/bls12-377.go @@ -62,7 +62,7 @@ var g1Infinity G1Jac var g2Infinity G2Jac // optimal Ate loop counter -var loopCounter [64]int8 +var LoopCounter [64]int8 // Parameters useful for the GLV scalar multiplication. The third roots define the // endomorphisms ϕ₁ and ϕ₂ for and . lambda is such that lies above @@ -134,7 +134,7 @@ func init() { endo.v.A0.SetString("216465761340224619389371505802605247630151569547285782856803747159100223055385581585702401816380679166954762214499") // binary decomposition of x₀ little endian - loopCounter = [64]int8{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1} + LoopCounter = [64]int8{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1} // x₀ xGen.SetString("9586122913090633729", 10) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/arith.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/arith.go index 6f281563b3d..5c9905de801 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/arith.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/arith.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -58,16 +47,3 @@ func madd3(a, b, c, d, e uint64) (hi uint64, lo uint64) { hi, _ = bits.Add64(hi, e, carry) return } -func max(a int, b int) int { - if a > b { - return a - } - return b -} - -func min(a int, b int) int { - if a < b { - return a - } - return b -} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/asm.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/asm.go deleted file mode 100644 index 0481989ec6a..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/asm.go +++ /dev/null @@ -1,27 +0,0 @@ -//go:build !noadx -// +build !noadx - -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by consensys/gnark-crypto DO NOT EDIT - -package fp - -import "golang.org/x/sys/cpu" - -var ( - supportAdx = cpu.X86.HasADX && cpu.X86.HasBMI2 - _ = supportAdx -) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/asm_noadx.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/asm_noadx.go deleted file mode 100644 index 92f8cc0f424..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/asm_noadx.go +++ /dev/null @@ -1,28 +0,0 @@ -//go:build noadx -// +build noadx - -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by consensys/gnark-crypto DO NOT EDIT - -package fp - -// note: this is needed for test purposes, as dynamically changing supportAdx doesn't flag -// certain errors (like fatal error: missing stackmap) -// this ensures we test all asm path. -var ( - supportAdx = false - _ = supportAdx -) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/doc.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/doc.go index c4d87f7b017..94fc02f30ee 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/doc.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/doc.go @@ -1,22 +1,13 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT // Package fp contains field arithmetic operations for modulus = 0x1ae3a4...000001. // -// The API is similar to math/big (big.Int), but the operations are significantly faster (up to 20x for the modular multiplication on amd64, see also https://hackmd.io/@gnark/modular_multiplication) +// The API is similar to math/big (big.Int), but the operations are significantly faster (up to 20x). +// +// Additionally fp.Vector offers an API to manipulate []Element. // // The modulus is hardcoded in all the operations. // @@ -49,5 +40,7 @@ // // # Warning // -// This code has not been audited and is provided as-is. In particular, there is no security guarantees such as constant time implementation or side-channel attack resistance. +// There is no security guarantees such as constant time implementation or side-channel attack resistance. +// This code is provided as-is. Partially audited, see https://github.com/Consensys/gnark/tree/master/audits +// for more details. package fp diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element.go index 81a730fbd4c..998fca7f70a 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -54,12 +43,12 @@ const ( // Field modulus q const ( - q0 uint64 = 9586122913090633729 - q1 uint64 = 1660523435060625408 - q2 uint64 = 2230234197602682880 - q3 uint64 = 1883307231910630287 - q4 uint64 = 14284016967150029115 - q5 uint64 = 121098312706494698 + q0 = 9586122913090633729 + q1 = 1660523435060625408 + q2 = 2230234197602682880 + q3 = 1883307231910630287 + q4 = 14284016967150029115 + q5 = 121098312706494698 ) var qElement = Element{ @@ -83,7 +72,7 @@ func Modulus() *big.Int { // q + r'.r = 1, i.e., qInvNeg = - q⁻¹ mod r // used for Montgomery reduction -const qInvNeg uint64 = 9586122913090633727 +const qInvNeg = 9586122913090633727 func init() { _modulus.SetString("1ae3a4617c510eac63b05c06ca1493b1a22d9f300f5138f1ef3622fba094800170b5d44300000008508c00000000001", 16) @@ -374,6 +363,16 @@ func (z *Element) SetRandom() (*Element, error) { } } +// MustSetRandom sets z to a uniform random value in [0, q). +// +// It panics if reading from crypto/rand.Reader errors. +func (z *Element) MustSetRandom() *Element { + if _, err := z.SetRandom(); err != nil { + panic(err) + } + return z +} + // smallerThanModulus returns true if z < q // This is not constant time func (z *Element) smallerThanModulus() bool { @@ -521,32 +520,8 @@ func (z *Element) Select(c int, x0 *Element, x1 *Element) *Element { // and is used for testing purposes. func _mulGeneric(z, x, y *Element) { - // Implements CIOS multiplication -- section 2.3.2 of Tolga Acar's thesis - // https://www.microsoft.com/en-us/research/wp-content/uploads/1998/06/97Acar.pdf - // - // The algorithm: - // - // for i=0 to N-1 - // C := 0 - // for j=0 to N-1 - // (C,t[j]) := t[j] + x[j]*y[i] + C - // (t[N+1],t[N]) := t[N] + C - // - // C := 0 - // m := t[0]*q'[0] mod D - // (C,_) := t[0] + m*q[0] - // for j=1 to N-1 - // (C,t[j-1]) := t[j] + m*q[j] + C - // - // (C,t[N-1]) := t[N] + C - // t[N] := t[N+1] + C - // - // → N is the number of machine words needed to store the modulus q - // → D is the word size. For example, on a 64-bit architecture D is 2 64 - // → x[i], y[i], q[i] is the ith word of the numbers x,y,q - // → q'[0] is the lowest word of the number -q⁻¹ mod r. This quantity is pre-computed, as it does not depend on the inputs. - // → t is a temporary array of size N+2 - // → C, S are machine words. A pair (C,S) refers to (hi-bits, lo-bits) of a two-word number + // Algorithm 2 of "Faster Montgomery Multiplication and Multi-Scalar-Multiplication for SNARKS" + // by Y. El Housni and G. Botrel https://doi.org/10.46586/tches.v2023.i3.504-521 var t [7]uint64 var D uint64 @@ -1122,7 +1097,7 @@ func (z *Element) SetBigInt(v *big.Int) *Element { // v == 0 return z } else if c != 1 && v.Cmp(&zero) != -1 { - // 0 < v < q + // 0 <= v < q return z.setBigInt(v) } @@ -1249,6 +1224,8 @@ type ByteOrder interface { String() string } +var errInvalidEncoding = errors.New("invalid fp.Element encoding") + // BigEndian is the big-endian implementation of ByteOrder and AppendByteOrder. var BigEndian bigEndian @@ -1266,7 +1243,7 @@ func (bigEndian) Element(b *[Bytes]byte) (Element, error) { z[5] = binary.BigEndian.Uint64((*b)[0:8]) if !z.smallerThanModulus() { - return Element{}, errors.New("invalid fp.Element encoding") + return Element{}, errInvalidEncoding } z.toMont() @@ -1300,7 +1277,7 @@ func (littleEndian) Element(b *[Bytes]byte) (Element, error) { z[5] = binary.LittleEndian.Uint64((*b)[40:48]) if !z.smallerThanModulus() { - return Element{}, errors.New("invalid fp.Element encoding") + return Element{}, errInvalidEncoding } z.toMont() diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_amd64.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_amd64.go new file mode 100644 index 00000000000..ff2159178d8 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_amd64.go @@ -0,0 +1,62 @@ +//go:build !purego + +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fp + +import ( + _ "github.com/consensys/gnark-crypto/field/asm/element_6w" + "github.com/consensys/gnark-crypto/utils/cpu" +) + +var supportAdx = cpu.SupportADX + +//go:noescape +func MulBy3(x *Element) + +//go:noescape +func MulBy5(x *Element) + +//go:noescape +func MulBy13(x *Element) + +//go:noescape +func mul(res, x, y *Element) + +//go:noescape +func fromMont(res *Element) + +//go:noescape +func reduce(res *Element) + +// Butterfly sets +// +// a = a + b (mod q) +// b = a - b (mod q) +// +//go:noescape +func Butterfly(a, b *Element) + +// Mul z = x * y (mod q) +// +// x and y must be less than q +func (z *Element) Mul(x, y *Element) *Element { + + // Algorithm 2 of "Faster Montgomery Multiplication and Multi-Scalar-Multiplication for SNARKS" + // by Y. El Housni and G. Botrel https://doi.org/10.46586/tches.v2023.i3.504-521 + + mul(z, x, y) + return z +} + +// Square z = x * x (mod q) +// +// x must be less than q +func (z *Element) Square(x *Element) *Element { + // see Mul for doc. + mul(z, x, x) + return z +} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_amd64.s b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_amd64.s new file mode 100644 index 00000000000..822bdf56a50 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_amd64.s @@ -0,0 +1,10 @@ +//go:build !purego + +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +// We include the hash to force the Go compiler to recompile: 18408829383245254329 +#include "../../../field/asm/element_6w/element_6w_amd64.s" + diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_arm64.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_arm64.go new file mode 100644 index 00000000000..a4510da8ebc --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_arm64.go @@ -0,0 +1,72 @@ +//go:build !purego + +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fp + +import ( + _ "github.com/consensys/gnark-crypto/field/asm/element_6w" +) + +// Butterfly sets +// +// a = a + b (mod q) +// b = a - b (mod q) +// +//go:noescape +func Butterfly(a, b *Element) + +//go:noescape +func mul(res, x, y *Element) + +// Mul z = x * y (mod q) +// +// x and y must be less than q +func (z *Element) Mul(x, y *Element) *Element { + mul(z, x, y) + return z +} + +// Square z = x * x (mod q) +// +// x must be less than q +func (z *Element) Square(x *Element) *Element { + // see Mul for doc. + mul(z, x, x) + return z +} + +// MulBy3 x *= 3 (mod q) +func MulBy3(x *Element) { + _x := *x + x.Double(x).Add(x, &_x) +} + +// MulBy5 x *= 5 (mod q) +func MulBy5(x *Element) { + _x := *x + x.Double(x).Double(x).Add(x, &_x) +} + +// MulBy13 x *= 13 (mod q) +func MulBy13(x *Element) { + var y = Element{ + 1176283927673829444, + 14130787773971430395, + 11354866436980285261, + 15740727779991009548, + 14951814113394531041, + 33013799364667434, + } + x.Mul(x, &y) +} + +func fromMont(z *Element) { + _fromMontGeneric(z) +} + +//go:noescape +func reduce(res *Element) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_arm64.s b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_arm64.s new file mode 100644 index 00000000000..2defbe4c21a --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_arm64.s @@ -0,0 +1,10 @@ +//go:build !purego + +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +// We include the hash to force the Go compiler to recompile: 15397482240260640864 +#include "../../../field/asm/element_6w/element_6w_arm64.s" + diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_exp.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_exp.go index e3d936dfc19..34f76d1aa7d 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_exp.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_exp.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_mul_amd64.s b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_mul_amd64.s deleted file mode 100644 index 3e7650e5aab..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_mul_amd64.s +++ /dev/null @@ -1,857 +0,0 @@ -// +build !purego - -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "textflag.h" -#include "funcdata.h" - -// modulus q -DATA q<>+0(SB)/8, $0x8508c00000000001 -DATA q<>+8(SB)/8, $0x170b5d4430000000 -DATA q<>+16(SB)/8, $0x1ef3622fba094800 -DATA q<>+24(SB)/8, $0x1a22d9f300f5138f -DATA q<>+32(SB)/8, $0xc63b05c06ca1493b -DATA q<>+40(SB)/8, $0x01ae3a4617c510ea -GLOBL q<>(SB), (RODATA+NOPTR), $48 - -// qInv0 q'[0] -DATA qInv0<>(SB)/8, $0x8508bfffffffffff -GLOBL qInv0<>(SB), (RODATA+NOPTR), $8 - -#define REDUCE(ra0, ra1, ra2, ra3, ra4, ra5, rb0, rb1, rb2, rb3, rb4, rb5) \ - MOVQ ra0, rb0; \ - SUBQ q<>(SB), ra0; \ - MOVQ ra1, rb1; \ - SBBQ q<>+8(SB), ra1; \ - MOVQ ra2, rb2; \ - SBBQ q<>+16(SB), ra2; \ - MOVQ ra3, rb3; \ - SBBQ q<>+24(SB), ra3; \ - MOVQ ra4, rb4; \ - SBBQ q<>+32(SB), ra4; \ - MOVQ ra5, rb5; \ - SBBQ q<>+40(SB), ra5; \ - CMOVQCS rb0, ra0; \ - CMOVQCS rb1, ra1; \ - CMOVQCS rb2, ra2; \ - CMOVQCS rb3, ra3; \ - CMOVQCS rb4, ra4; \ - CMOVQCS rb5, ra5; \ - -// mul(res, x, y *Element) -TEXT ·mul(SB), $24-24 - - // the algorithm is described in the Element.Mul declaration (.go) - // however, to benefit from the ADCX and ADOX carry chains - // we split the inner loops in 2: - // for i=0 to N-1 - // for j=0 to N-1 - // (A,t[j]) := t[j] + x[j]*y[i] + A - // m := t[0]*q'[0] mod W - // C,_ := t[0] + m*q[0] - // for j=1 to N-1 - // (C,t[j-1]) := t[j] + m*q[j] + C - // t[N-1] = C + A - - NO_LOCAL_POINTERS - CMPB ·supportAdx(SB), $1 - JNE l1 - MOVQ x+8(FP), R8 - - // x[0] -> R10 - // x[1] -> R11 - // x[2] -> R12 - MOVQ 0(R8), R10 - MOVQ 8(R8), R11 - MOVQ 16(R8), R12 - MOVQ y+16(FP), R13 - - // A -> BP - // t[0] -> R14 - // t[1] -> R15 - // t[2] -> CX - // t[3] -> BX - // t[4] -> SI - // t[5] -> DI - // clear the flags - XORQ AX, AX - MOVQ 0(R13), DX - - // (A,t[0]) := x[0]*y[0] + A - MULXQ R10, R14, R15 - - // (A,t[1]) := x[1]*y[0] + A - MULXQ R11, AX, CX - ADOXQ AX, R15 - - // (A,t[2]) := x[2]*y[0] + A - MULXQ R12, AX, BX - ADOXQ AX, CX - - // (A,t[3]) := x[3]*y[0] + A - MULXQ 24(R8), AX, SI - ADOXQ AX, BX - - // (A,t[4]) := x[4]*y[0] + A - MULXQ 32(R8), AX, DI - ADOXQ AX, SI - - // (A,t[5]) := x[5]*y[0] + A - MULXQ 40(R8), AX, BP - ADOXQ AX, DI - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADOXQ AX, BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, R9 - ADCXQ R14, AX - MOVQ R9, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R15, R14 - MULXQ q<>+8(SB), AX, R15 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R15 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R15 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ SI, BX - MULXQ q<>+32(SB), AX, SI - ADOXQ AX, BX - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ DI, SI - MULXQ q<>+40(SB), AX, DI - ADOXQ AX, SI - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, DI - ADOXQ BP, DI - - // clear the flags - XORQ AX, AX - MOVQ 8(R13), DX - - // (A,t[0]) := t[0] + x[0]*y[1] + A - MULXQ R10, AX, BP - ADOXQ AX, R14 - - // (A,t[1]) := t[1] + x[1]*y[1] + A - ADCXQ BP, R15 - MULXQ R11, AX, BP - ADOXQ AX, R15 - - // (A,t[2]) := t[2] + x[2]*y[1] + A - ADCXQ BP, CX - MULXQ R12, AX, BP - ADOXQ AX, CX - - // (A,t[3]) := t[3] + x[3]*y[1] + A - ADCXQ BP, BX - MULXQ 24(R8), AX, BP - ADOXQ AX, BX - - // (A,t[4]) := t[4] + x[4]*y[1] + A - ADCXQ BP, SI - MULXQ 32(R8), AX, BP - ADOXQ AX, SI - - // (A,t[5]) := t[5] + x[5]*y[1] + A - ADCXQ BP, DI - MULXQ 40(R8), AX, BP - ADOXQ AX, DI - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, R9 - ADCXQ R14, AX - MOVQ R9, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R15, R14 - MULXQ q<>+8(SB), AX, R15 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R15 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R15 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ SI, BX - MULXQ q<>+32(SB), AX, SI - ADOXQ AX, BX - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ DI, SI - MULXQ q<>+40(SB), AX, DI - ADOXQ AX, SI - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, DI - ADOXQ BP, DI - - // clear the flags - XORQ AX, AX - MOVQ 16(R13), DX - - // (A,t[0]) := t[0] + x[0]*y[2] + A - MULXQ R10, AX, BP - ADOXQ AX, R14 - - // (A,t[1]) := t[1] + x[1]*y[2] + A - ADCXQ BP, R15 - MULXQ R11, AX, BP - ADOXQ AX, R15 - - // (A,t[2]) := t[2] + x[2]*y[2] + A - ADCXQ BP, CX - MULXQ R12, AX, BP - ADOXQ AX, CX - - // (A,t[3]) := t[3] + x[3]*y[2] + A - ADCXQ BP, BX - MULXQ 24(R8), AX, BP - ADOXQ AX, BX - - // (A,t[4]) := t[4] + x[4]*y[2] + A - ADCXQ BP, SI - MULXQ 32(R8), AX, BP - ADOXQ AX, SI - - // (A,t[5]) := t[5] + x[5]*y[2] + A - ADCXQ BP, DI - MULXQ 40(R8), AX, BP - ADOXQ AX, DI - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, R9 - ADCXQ R14, AX - MOVQ R9, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R15, R14 - MULXQ q<>+8(SB), AX, R15 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R15 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R15 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ SI, BX - MULXQ q<>+32(SB), AX, SI - ADOXQ AX, BX - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ DI, SI - MULXQ q<>+40(SB), AX, DI - ADOXQ AX, SI - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, DI - ADOXQ BP, DI - - // clear the flags - XORQ AX, AX - MOVQ 24(R13), DX - - // (A,t[0]) := t[0] + x[0]*y[3] + A - MULXQ R10, AX, BP - ADOXQ AX, R14 - - // (A,t[1]) := t[1] + x[1]*y[3] + A - ADCXQ BP, R15 - MULXQ R11, AX, BP - ADOXQ AX, R15 - - // (A,t[2]) := t[2] + x[2]*y[3] + A - ADCXQ BP, CX - MULXQ R12, AX, BP - ADOXQ AX, CX - - // (A,t[3]) := t[3] + x[3]*y[3] + A - ADCXQ BP, BX - MULXQ 24(R8), AX, BP - ADOXQ AX, BX - - // (A,t[4]) := t[4] + x[4]*y[3] + A - ADCXQ BP, SI - MULXQ 32(R8), AX, BP - ADOXQ AX, SI - - // (A,t[5]) := t[5] + x[5]*y[3] + A - ADCXQ BP, DI - MULXQ 40(R8), AX, BP - ADOXQ AX, DI - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, R9 - ADCXQ R14, AX - MOVQ R9, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R15, R14 - MULXQ q<>+8(SB), AX, R15 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R15 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R15 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ SI, BX - MULXQ q<>+32(SB), AX, SI - ADOXQ AX, BX - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ DI, SI - MULXQ q<>+40(SB), AX, DI - ADOXQ AX, SI - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, DI - ADOXQ BP, DI - - // clear the flags - XORQ AX, AX - MOVQ 32(R13), DX - - // (A,t[0]) := t[0] + x[0]*y[4] + A - MULXQ R10, AX, BP - ADOXQ AX, R14 - - // (A,t[1]) := t[1] + x[1]*y[4] + A - ADCXQ BP, R15 - MULXQ R11, AX, BP - ADOXQ AX, R15 - - // (A,t[2]) := t[2] + x[2]*y[4] + A - ADCXQ BP, CX - MULXQ R12, AX, BP - ADOXQ AX, CX - - // (A,t[3]) := t[3] + x[3]*y[4] + A - ADCXQ BP, BX - MULXQ 24(R8), AX, BP - ADOXQ AX, BX - - // (A,t[4]) := t[4] + x[4]*y[4] + A - ADCXQ BP, SI - MULXQ 32(R8), AX, BP - ADOXQ AX, SI - - // (A,t[5]) := t[5] + x[5]*y[4] + A - ADCXQ BP, DI - MULXQ 40(R8), AX, BP - ADOXQ AX, DI - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, R9 - ADCXQ R14, AX - MOVQ R9, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R15, R14 - MULXQ q<>+8(SB), AX, R15 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R15 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R15 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ SI, BX - MULXQ q<>+32(SB), AX, SI - ADOXQ AX, BX - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ DI, SI - MULXQ q<>+40(SB), AX, DI - ADOXQ AX, SI - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, DI - ADOXQ BP, DI - - // clear the flags - XORQ AX, AX - MOVQ 40(R13), DX - - // (A,t[0]) := t[0] + x[0]*y[5] + A - MULXQ R10, AX, BP - ADOXQ AX, R14 - - // (A,t[1]) := t[1] + x[1]*y[5] + A - ADCXQ BP, R15 - MULXQ R11, AX, BP - ADOXQ AX, R15 - - // (A,t[2]) := t[2] + x[2]*y[5] + A - ADCXQ BP, CX - MULXQ R12, AX, BP - ADOXQ AX, CX - - // (A,t[3]) := t[3] + x[3]*y[5] + A - ADCXQ BP, BX - MULXQ 24(R8), AX, BP - ADOXQ AX, BX - - // (A,t[4]) := t[4] + x[4]*y[5] + A - ADCXQ BP, SI - MULXQ 32(R8), AX, BP - ADOXQ AX, SI - - // (A,t[5]) := t[5] + x[5]*y[5] + A - ADCXQ BP, DI - MULXQ 40(R8), AX, BP - ADOXQ AX, DI - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, R9 - ADCXQ R14, AX - MOVQ R9, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R15, R14 - MULXQ q<>+8(SB), AX, R15 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R15 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R15 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ SI, BX - MULXQ q<>+32(SB), AX, SI - ADOXQ AX, BX - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ DI, SI - MULXQ q<>+40(SB), AX, DI - ADOXQ AX, SI - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, DI - ADOXQ BP, DI - - // reduce element(R14,R15,CX,BX,SI,DI) using temp registers (R9,R8,R13,R10,R11,R12) - REDUCE(R14,R15,CX,BX,SI,DI,R9,R8,R13,R10,R11,R12) - - MOVQ res+0(FP), AX - MOVQ R14, 0(AX) - MOVQ R15, 8(AX) - MOVQ CX, 16(AX) - MOVQ BX, 24(AX) - MOVQ SI, 32(AX) - MOVQ DI, 40(AX) - RET - -l1: - MOVQ res+0(FP), AX - MOVQ AX, (SP) - MOVQ x+8(FP), AX - MOVQ AX, 8(SP) - MOVQ y+16(FP), AX - MOVQ AX, 16(SP) - CALL ·_mulGeneric(SB) - RET - -TEXT ·fromMont(SB), $8-8 - NO_LOCAL_POINTERS - - // the algorithm is described here - // https://hackmd.io/@gnark/modular_multiplication - // when y = 1 we have: - // for i=0 to N-1 - // t[i] = x[i] - // for i=0 to N-1 - // m := t[0]*q'[0] mod W - // C,_ := t[0] + m*q[0] - // for j=1 to N-1 - // (C,t[j-1]) := t[j] + m*q[j] + C - // t[N-1] = C - CMPB ·supportAdx(SB), $1 - JNE l2 - MOVQ res+0(FP), DX - MOVQ 0(DX), R14 - MOVQ 8(DX), R15 - MOVQ 16(DX), CX - MOVQ 24(DX), BX - MOVQ 32(DX), SI - MOVQ 40(DX), DI - XORQ DX, DX - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R14, AX - MOVQ BP, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R15, R14 - MULXQ q<>+8(SB), AX, R15 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R15 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R15 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ SI, BX - MULXQ q<>+32(SB), AX, SI - ADOXQ AX, BX - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ DI, SI - MULXQ q<>+40(SB), AX, DI - ADOXQ AX, SI - MOVQ $0, AX - ADCXQ AX, DI - ADOXQ AX, DI - XORQ DX, DX - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R14, AX - MOVQ BP, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R15, R14 - MULXQ q<>+8(SB), AX, R15 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R15 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R15 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ SI, BX - MULXQ q<>+32(SB), AX, SI - ADOXQ AX, BX - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ DI, SI - MULXQ q<>+40(SB), AX, DI - ADOXQ AX, SI - MOVQ $0, AX - ADCXQ AX, DI - ADOXQ AX, DI - XORQ DX, DX - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R14, AX - MOVQ BP, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R15, R14 - MULXQ q<>+8(SB), AX, R15 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R15 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R15 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ SI, BX - MULXQ q<>+32(SB), AX, SI - ADOXQ AX, BX - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ DI, SI - MULXQ q<>+40(SB), AX, DI - ADOXQ AX, SI - MOVQ $0, AX - ADCXQ AX, DI - ADOXQ AX, DI - XORQ DX, DX - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R14, AX - MOVQ BP, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R15, R14 - MULXQ q<>+8(SB), AX, R15 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R15 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R15 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ SI, BX - MULXQ q<>+32(SB), AX, SI - ADOXQ AX, BX - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ DI, SI - MULXQ q<>+40(SB), AX, DI - ADOXQ AX, SI - MOVQ $0, AX - ADCXQ AX, DI - ADOXQ AX, DI - XORQ DX, DX - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R14, AX - MOVQ BP, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R15, R14 - MULXQ q<>+8(SB), AX, R15 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R15 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R15 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ SI, BX - MULXQ q<>+32(SB), AX, SI - ADOXQ AX, BX - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ DI, SI - MULXQ q<>+40(SB), AX, DI - ADOXQ AX, SI - MOVQ $0, AX - ADCXQ AX, DI - ADOXQ AX, DI - XORQ DX, DX - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R14, AX - MOVQ BP, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R15, R14 - MULXQ q<>+8(SB), AX, R15 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R15 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R15 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ SI, BX - MULXQ q<>+32(SB), AX, SI - ADOXQ AX, BX - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ DI, SI - MULXQ q<>+40(SB), AX, DI - ADOXQ AX, SI - MOVQ $0, AX - ADCXQ AX, DI - ADOXQ AX, DI - - // reduce element(R14,R15,CX,BX,SI,DI) using temp registers (R8,R9,R10,R11,R12,R13) - REDUCE(R14,R15,CX,BX,SI,DI,R8,R9,R10,R11,R12,R13) - - MOVQ res+0(FP), AX - MOVQ R14, 0(AX) - MOVQ R15, 8(AX) - MOVQ CX, 16(AX) - MOVQ BX, 24(AX) - MOVQ SI, 32(AX) - MOVQ DI, 40(AX) - RET - -l2: - MOVQ res+0(FP), AX - MOVQ AX, (SP) - CALL ·_fromMontGeneric(SB) - RET diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_ops_amd64.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_ops_amd64.go deleted file mode 100644 index 83bba45aedf..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_ops_amd64.go +++ /dev/null @@ -1,107 +0,0 @@ -//go:build !purego -// +build !purego - -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by consensys/gnark-crypto DO NOT EDIT - -package fp - -//go:noescape -func MulBy3(x *Element) - -//go:noescape -func MulBy5(x *Element) - -//go:noescape -func MulBy13(x *Element) - -//go:noescape -func mul(res, x, y *Element) - -//go:noescape -func fromMont(res *Element) - -//go:noescape -func reduce(res *Element) - -// Butterfly sets -// -// a = a + b (mod q) -// b = a - b (mod q) -// -//go:noescape -func Butterfly(a, b *Element) - -// Mul z = x * y (mod q) -// -// x and y must be less than q -func (z *Element) Mul(x, y *Element) *Element { - - // Implements CIOS multiplication -- section 2.3.2 of Tolga Acar's thesis - // https://www.microsoft.com/en-us/research/wp-content/uploads/1998/06/97Acar.pdf - // - // The algorithm: - // - // for i=0 to N-1 - // C := 0 - // for j=0 to N-1 - // (C,t[j]) := t[j] + x[j]*y[i] + C - // (t[N+1],t[N]) := t[N] + C - // - // C := 0 - // m := t[0]*q'[0] mod D - // (C,_) := t[0] + m*q[0] - // for j=1 to N-1 - // (C,t[j-1]) := t[j] + m*q[j] + C - // - // (C,t[N-1]) := t[N] + C - // t[N] := t[N+1] + C - // - // → N is the number of machine words needed to store the modulus q - // → D is the word size. For example, on a 64-bit architecture D is 2 64 - // → x[i], y[i], q[i] is the ith word of the numbers x,y,q - // → q'[0] is the lowest word of the number -q⁻¹ mod r. This quantity is pre-computed, as it does not depend on the inputs. - // → t is a temporary array of size N+2 - // → C, S are machine words. A pair (C,S) refers to (hi-bits, lo-bits) of a two-word number - // - // As described here https://hackmd.io/@gnark/modular_multiplication we can get rid of one carry chain and simplify: - // (also described in https://eprint.iacr.org/2022/1400.pdf annex) - // - // for i=0 to N-1 - // (A,t[0]) := t[0] + x[0]*y[i] - // m := t[0]*q'[0] mod W - // C,_ := t[0] + m*q[0] - // for j=1 to N-1 - // (A,t[j]) := t[j] + x[j]*y[i] + A - // (C,t[j-1]) := t[j] + m*q[j] + C - // - // t[N-1] = C + A - // - // This optimization saves 5N + 2 additions in the algorithm, and can be used whenever the highest bit - // of the modulus is zero (and not all of the remaining bits are set). - - mul(z, x, y) - return z -} - -// Square z = x * x (mod q) -// -// x must be less than q -func (z *Element) Square(x *Element) *Element { - // see Mul for doc. - mul(z, x, x) - return z -} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_ops_amd64.s b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_ops_amd64.s deleted file mode 100644 index 7242622a4a4..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_ops_amd64.s +++ /dev/null @@ -1,306 +0,0 @@ -// +build !purego - -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "textflag.h" -#include "funcdata.h" - -// modulus q -DATA q<>+0(SB)/8, $0x8508c00000000001 -DATA q<>+8(SB)/8, $0x170b5d4430000000 -DATA q<>+16(SB)/8, $0x1ef3622fba094800 -DATA q<>+24(SB)/8, $0x1a22d9f300f5138f -DATA q<>+32(SB)/8, $0xc63b05c06ca1493b -DATA q<>+40(SB)/8, $0x01ae3a4617c510ea -GLOBL q<>(SB), (RODATA+NOPTR), $48 - -// qInv0 q'[0] -DATA qInv0<>(SB)/8, $0x8508bfffffffffff -GLOBL qInv0<>(SB), (RODATA+NOPTR), $8 - -#define REDUCE(ra0, ra1, ra2, ra3, ra4, ra5, rb0, rb1, rb2, rb3, rb4, rb5) \ - MOVQ ra0, rb0; \ - SUBQ q<>(SB), ra0; \ - MOVQ ra1, rb1; \ - SBBQ q<>+8(SB), ra1; \ - MOVQ ra2, rb2; \ - SBBQ q<>+16(SB), ra2; \ - MOVQ ra3, rb3; \ - SBBQ q<>+24(SB), ra3; \ - MOVQ ra4, rb4; \ - SBBQ q<>+32(SB), ra4; \ - MOVQ ra5, rb5; \ - SBBQ q<>+40(SB), ra5; \ - CMOVQCS rb0, ra0; \ - CMOVQCS rb1, ra1; \ - CMOVQCS rb2, ra2; \ - CMOVQCS rb3, ra3; \ - CMOVQCS rb4, ra4; \ - CMOVQCS rb5, ra5; \ - -TEXT ·reduce(SB), NOSPLIT, $0-8 - MOVQ res+0(FP), AX - MOVQ 0(AX), DX - MOVQ 8(AX), CX - MOVQ 16(AX), BX - MOVQ 24(AX), SI - MOVQ 32(AX), DI - MOVQ 40(AX), R8 - - // reduce element(DX,CX,BX,SI,DI,R8) using temp registers (R9,R10,R11,R12,R13,R14) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10,R11,R12,R13,R14) - - MOVQ DX, 0(AX) - MOVQ CX, 8(AX) - MOVQ BX, 16(AX) - MOVQ SI, 24(AX) - MOVQ DI, 32(AX) - MOVQ R8, 40(AX) - RET - -// MulBy3(x *Element) -TEXT ·MulBy3(SB), NOSPLIT, $0-8 - MOVQ x+0(FP), AX - MOVQ 0(AX), DX - MOVQ 8(AX), CX - MOVQ 16(AX), BX - MOVQ 24(AX), SI - MOVQ 32(AX), DI - MOVQ 40(AX), R8 - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - ADCQ DI, DI - ADCQ R8, R8 - - // reduce element(DX,CX,BX,SI,DI,R8) using temp registers (R9,R10,R11,R12,R13,R14) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10,R11,R12,R13,R14) - - ADDQ 0(AX), DX - ADCQ 8(AX), CX - ADCQ 16(AX), BX - ADCQ 24(AX), SI - ADCQ 32(AX), DI - ADCQ 40(AX), R8 - - // reduce element(DX,CX,BX,SI,DI,R8) using temp registers (R15,R9,R10,R11,R12,R13) - REDUCE(DX,CX,BX,SI,DI,R8,R15,R9,R10,R11,R12,R13) - - MOVQ DX, 0(AX) - MOVQ CX, 8(AX) - MOVQ BX, 16(AX) - MOVQ SI, 24(AX) - MOVQ DI, 32(AX) - MOVQ R8, 40(AX) - RET - -// MulBy5(x *Element) -TEXT ·MulBy5(SB), NOSPLIT, $0-8 - MOVQ x+0(FP), AX - MOVQ 0(AX), DX - MOVQ 8(AX), CX - MOVQ 16(AX), BX - MOVQ 24(AX), SI - MOVQ 32(AX), DI - MOVQ 40(AX), R8 - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - ADCQ DI, DI - ADCQ R8, R8 - - // reduce element(DX,CX,BX,SI,DI,R8) using temp registers (R9,R10,R11,R12,R13,R14) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10,R11,R12,R13,R14) - - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - ADCQ DI, DI - ADCQ R8, R8 - - // reduce element(DX,CX,BX,SI,DI,R8) using temp registers (R15,R9,R10,R11,R12,R13) - REDUCE(DX,CX,BX,SI,DI,R8,R15,R9,R10,R11,R12,R13) - - ADDQ 0(AX), DX - ADCQ 8(AX), CX - ADCQ 16(AX), BX - ADCQ 24(AX), SI - ADCQ 32(AX), DI - ADCQ 40(AX), R8 - - // reduce element(DX,CX,BX,SI,DI,R8) using temp registers (R14,R15,R9,R10,R11,R12) - REDUCE(DX,CX,BX,SI,DI,R8,R14,R15,R9,R10,R11,R12) - - MOVQ DX, 0(AX) - MOVQ CX, 8(AX) - MOVQ BX, 16(AX) - MOVQ SI, 24(AX) - MOVQ DI, 32(AX) - MOVQ R8, 40(AX) - RET - -// MulBy13(x *Element) -TEXT ·MulBy13(SB), $40-8 - MOVQ x+0(FP), AX - MOVQ 0(AX), DX - MOVQ 8(AX), CX - MOVQ 16(AX), BX - MOVQ 24(AX), SI - MOVQ 32(AX), DI - MOVQ 40(AX), R8 - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - ADCQ DI, DI - ADCQ R8, R8 - - // reduce element(DX,CX,BX,SI,DI,R8) using temp registers (R9,R10,R11,R12,R13,R14) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10,R11,R12,R13,R14) - - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - ADCQ DI, DI - ADCQ R8, R8 - - // reduce element(DX,CX,BX,SI,DI,R8) using temp registers (R15,s0-8(SP),s1-16(SP),s2-24(SP),s3-32(SP),s4-40(SP)) - REDUCE(DX,CX,BX,SI,DI,R8,R15,s0-8(SP),s1-16(SP),s2-24(SP),s3-32(SP),s4-40(SP)) - - MOVQ DX, R15 - MOVQ CX, s0-8(SP) - MOVQ BX, s1-16(SP) - MOVQ SI, s2-24(SP) - MOVQ DI, s3-32(SP) - MOVQ R8, s4-40(SP) - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - ADCQ DI, DI - ADCQ R8, R8 - - // reduce element(DX,CX,BX,SI,DI,R8) using temp registers (R9,R10,R11,R12,R13,R14) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10,R11,R12,R13,R14) - - ADDQ R15, DX - ADCQ s0-8(SP), CX - ADCQ s1-16(SP), BX - ADCQ s2-24(SP), SI - ADCQ s3-32(SP), DI - ADCQ s4-40(SP), R8 - - // reduce element(DX,CX,BX,SI,DI,R8) using temp registers (R9,R10,R11,R12,R13,R14) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10,R11,R12,R13,R14) - - ADDQ 0(AX), DX - ADCQ 8(AX), CX - ADCQ 16(AX), BX - ADCQ 24(AX), SI - ADCQ 32(AX), DI - ADCQ 40(AX), R8 - - // reduce element(DX,CX,BX,SI,DI,R8) using temp registers (R9,R10,R11,R12,R13,R14) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10,R11,R12,R13,R14) - - MOVQ DX, 0(AX) - MOVQ CX, 8(AX) - MOVQ BX, 16(AX) - MOVQ SI, 24(AX) - MOVQ DI, 32(AX) - MOVQ R8, 40(AX) - RET - -// Butterfly(a, b *Element) sets a = a + b; b = a - b -TEXT ·Butterfly(SB), $48-16 - MOVQ a+0(FP), AX - MOVQ 0(AX), CX - MOVQ 8(AX), BX - MOVQ 16(AX), SI - MOVQ 24(AX), DI - MOVQ 32(AX), R8 - MOVQ 40(AX), R9 - MOVQ CX, R10 - MOVQ BX, R11 - MOVQ SI, R12 - MOVQ DI, R13 - MOVQ R8, R14 - MOVQ R9, R15 - XORQ AX, AX - MOVQ b+8(FP), DX - ADDQ 0(DX), CX - ADCQ 8(DX), BX - ADCQ 16(DX), SI - ADCQ 24(DX), DI - ADCQ 32(DX), R8 - ADCQ 40(DX), R9 - SUBQ 0(DX), R10 - SBBQ 8(DX), R11 - SBBQ 16(DX), R12 - SBBQ 24(DX), R13 - SBBQ 32(DX), R14 - SBBQ 40(DX), R15 - MOVQ CX, s0-8(SP) - MOVQ BX, s1-16(SP) - MOVQ SI, s2-24(SP) - MOVQ DI, s3-32(SP) - MOVQ R8, s4-40(SP) - MOVQ R9, s5-48(SP) - MOVQ $0x8508c00000000001, CX - MOVQ $0x170b5d4430000000, BX - MOVQ $0x1ef3622fba094800, SI - MOVQ $0x1a22d9f300f5138f, DI - MOVQ $0xc63b05c06ca1493b, R8 - MOVQ $0x01ae3a4617c510ea, R9 - CMOVQCC AX, CX - CMOVQCC AX, BX - CMOVQCC AX, SI - CMOVQCC AX, DI - CMOVQCC AX, R8 - CMOVQCC AX, R9 - ADDQ CX, R10 - ADCQ BX, R11 - ADCQ SI, R12 - ADCQ DI, R13 - ADCQ R8, R14 - ADCQ R9, R15 - MOVQ s0-8(SP), CX - MOVQ s1-16(SP), BX - MOVQ s2-24(SP), SI - MOVQ s3-32(SP), DI - MOVQ s4-40(SP), R8 - MOVQ s5-48(SP), R9 - MOVQ R10, 0(DX) - MOVQ R11, 8(DX) - MOVQ R12, 16(DX) - MOVQ R13, 24(DX) - MOVQ R14, 32(DX) - MOVQ R15, 40(DX) - - // reduce element(CX,BX,SI,DI,R8,R9) using temp registers (R10,R11,R12,R13,R14,R15) - REDUCE(CX,BX,SI,DI,R8,R9,R10,R11,R12,R13,R14,R15) - - MOVQ a+0(FP), AX - MOVQ CX, 0(AX) - MOVQ BX, 8(AX) - MOVQ SI, 16(AX) - MOVQ DI, 24(AX) - MOVQ R8, 32(AX) - MOVQ R9, 40(AX) - RET diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_ops_purego.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_purego.go similarity index 88% rename from vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_ops_purego.go rename to vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_purego.go index a4c3796b96b..8a2e93e999f 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_ops_purego.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_purego.go @@ -1,19 +1,7 @@ -//go:build !amd64 || purego -// +build !amd64 purego +//go:build purego || (!amd64 && !arm64) -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -46,14 +34,6 @@ func MulBy13(x *Element) { x.Mul(x, &y) } -// Butterfly sets -// -// a = a + b (mod q) -// b = a - b (mod q) -func Butterfly(a, b *Element) { - _butterflyGeneric(a, b) -} - func fromMont(z *Element) { _fromMontGeneric(z) } @@ -67,48 +47,8 @@ func reduce(z *Element) { // x and y must be less than q func (z *Element) Mul(x, y *Element) *Element { - // Implements CIOS multiplication -- section 2.3.2 of Tolga Acar's thesis - // https://www.microsoft.com/en-us/research/wp-content/uploads/1998/06/97Acar.pdf - // - // The algorithm: - // - // for i=0 to N-1 - // C := 0 - // for j=0 to N-1 - // (C,t[j]) := t[j] + x[j]*y[i] + C - // (t[N+1],t[N]) := t[N] + C - // - // C := 0 - // m := t[0]*q'[0] mod D - // (C,_) := t[0] + m*q[0] - // for j=1 to N-1 - // (C,t[j-1]) := t[j] + m*q[j] + C - // - // (C,t[N-1]) := t[N] + C - // t[N] := t[N+1] + C - // - // → N is the number of machine words needed to store the modulus q - // → D is the word size. For example, on a 64-bit architecture D is 2 64 - // → x[i], y[i], q[i] is the ith word of the numbers x,y,q - // → q'[0] is the lowest word of the number -q⁻¹ mod r. This quantity is pre-computed, as it does not depend on the inputs. - // → t is a temporary array of size N+2 - // → C, S are machine words. A pair (C,S) refers to (hi-bits, lo-bits) of a two-word number - // - // As described here https://hackmd.io/@gnark/modular_multiplication we can get rid of one carry chain and simplify: - // (also described in https://eprint.iacr.org/2022/1400.pdf annex) - // - // for i=0 to N-1 - // (A,t[0]) := t[0] + x[0]*y[i] - // m := t[0]*q'[0] mod W - // C,_ := t[0] + m*q[0] - // for j=1 to N-1 - // (A,t[j]) := t[j] + x[j]*y[i] + A - // (C,t[j-1]) := t[j] + m*q[j] + C - // - // t[N-1] = C + A - // - // This optimization saves 5N + 2 additions in the algorithm, and can be used whenever the highest bit - // of the modulus is zero (and not all of the remaining bits are set). + // Algorithm 2 of "Faster Montgomery Multiplication and Multi-Scalar-Multiplication for SNARKS" + // by Y. El Housni and G. Botrel https://doi.org/10.46586/tches.v2023.i3.504-521 var t0, t1, t2, t3, t4, t5 uint64 var u0, u1, u2, u3, u4, u5 uint64 @@ -743,3 +683,11 @@ func (z *Element) Square(x *Element) *Element { } return z } + +// Butterfly sets +// +// a = a + b (mod q) +// b = a - b (mod q) +func Butterfly(a, b *Element) { + _butterflyGeneric(a, b) +} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_utils.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_utils.go index 6da4e95fd7a..b65d7303695 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_utils.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/element_utils.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. package fp diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/vector.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/vector.go index 3fe11371029..798d212144d 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/vector.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/vector.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -19,9 +8,12 @@ package fp import ( "bytes" "encoding/binary" + "errors" "fmt" "io" + "math/bits" "runtime" + "slices" "strings" "sync" "sync/atomic" @@ -78,40 +70,84 @@ func (vector *Vector) WriteTo(w io.Writer) (int64, error) { return n, nil } -// AsyncReadFrom reads a vector of big endian encoded Element. -// Length of the vector must be encoded as a uint32 on the first 4 bytes. -// It consumes the needed bytes from the reader and returns the number of bytes read and an error if any. -// It also returns a channel that will be closed when the validation is done. -// The validation consist of checking that the elements are smaller than the modulus, and -// converting them to montgomery form. -func (vector *Vector) AsyncReadFrom(r io.Reader) (int64, error, chan error) { +// AsyncReadFrom implements an asynchronous version of [Vector.ReadFrom]. It +// reads the reader r in full and then performs the validation and conversion to +// Montgomery form separately in a goroutine. Any error encountered during +// reading is returned directly, while errors encountered during +// validation/conversion are sent on the returned channel. Thus the caller must +// wait on the channel to ensure the vector is ready to use. The method +// additionally returns the number of bytes read from r. +// +// The errors during reading can be: +// - an error while reading from r; +// - not enough bytes in r to read the full vector indicated by header. +// +// The reader can contain more bytes than needed to decode the vector, in which +// case the extra bytes are ignored. In that case the reader is not seeked nor +// read further. +// +// The method allocates sufficiently large slice to store the vector. If the +// current slice fits the vector, it is reused, otherwise the slice is grown to +// fit the vector. +// +// The serialized encoding is as follows: +// - first 4 bytes: length of the vector as a big-endian uint32 +// - for each element of the vector, [Bytes] bytes representing the element in +// big-endian encoding. +func (vector *Vector) AsyncReadFrom(r io.Reader) (int64, error, chan error) { // nolint ST1008 chErr := make(chan error, 1) var buf [Bytes]byte if read, err := io.ReadFull(r, buf[:4]); err != nil { close(chErr) return int64(read), err, chErr } - sliceLen := binary.BigEndian.Uint32(buf[:4]) - - n := int64(4) - (*vector) = make(Vector, sliceLen) - if sliceLen == 0 { + headerSliceLen := uint64(binary.BigEndian.Uint32(buf[:4])) + + // to avoid allocating too large slice when the header is tampered, we limit + // the maximum allocation. We set the target to 4GB. This incurs a performance + // hit when reading very large slices, but protects against OOM. + targetSize := uint64(1 << 32) // 4GB + if bits.UintSize == 32 { + // reduce target size to 1GB on 32 bits architectures + targetSize = uint64(1 << 30) // 1GB + } + maxAllocateSliceLength := targetSize / uint64(Bytes) + + totalRead := int64(4) + *vector = (*vector)[:0] + if headerSliceLen == 0 { + // if the vector was nil previously even by reslicing we have a nil vector. + // but we want to have an empty slice to indicate that the vector has zero length. + if *vector == nil { + *vector = []Element{} + } + // we return already here to avoid launching a goroutine doing nothing below close(chErr) - return n, nil, chErr + return totalRead, nil, chErr } - bSlice := unsafe.Slice((*byte)(unsafe.Pointer(&(*vector)[0])), sliceLen*Bytes) - read, err := io.ReadFull(r, bSlice) - n += int64(read) - if err != nil { - close(chErr) - return n, err, chErr + for i := uint64(0); i < headerSliceLen; i += maxAllocateSliceLength { + if len(*vector) <= int(i) { + (*vector) = append(*vector, make([]Element, int(min(headerSliceLen-i, maxAllocateSliceLength)))...) + } + bSlice := unsafe.Slice((*byte)(unsafe.Pointer(&(*vector)[i])), int(min(headerSliceLen-i, maxAllocateSliceLength))*Bytes) + read, err := io.ReadFull(r, bSlice) + totalRead += int64(read) + if errors.Is(err, io.ErrUnexpectedEOF) { + close(chErr) + return totalRead, fmt.Errorf("less data than expected: read %d elements, expected %d", i+uint64(read)/Bytes, headerSliceLen), chErr + } + if err != nil { + close(chErr) + return totalRead, err, chErr + } } + bSlice := unsafe.Slice((*byte)(unsafe.Pointer(&(*vector)[0])), int(headerSliceLen)*Bytes) go func() { var cptErrors uint64 // process the elements in parallel - execute(int(sliceLen), func(start, end int) { + execute(int(headerSliceLen), func(start, end int) { var z Element for i := start; i < end; i++ { @@ -140,35 +176,72 @@ func (vector *Vector) AsyncReadFrom(r io.Reader) (int64, error, chan error) { } close(chErr) }() - return n, nil, chErr + return totalRead, nil, chErr } -// ReadFrom implements io.ReaderFrom and reads a vector of big endian encoded Element. -// Length of the vector must be encoded as a uint32 on the first 4 bytes. +// ReadFrom reads the vector from the reader r. It returns the number of bytes +// read and an error, if any. The errors can be: +// - an error while reading from r; +// - not enough bytes in r to read the full vector indicated by header; +// - when decoding the bytes into elements. +// +// The reader can contain more bytes than needed to decode the vector, in which case +// the extra bytes are ignored. In that case the reader is not seeked nor read further. +// +// The method allocates sufficiently large slice to store the vector. If the current slice fits +// the vector, it is reused, otherwise the slice is grown to fit the vector. +// +// The serialized encoding is as follows: +// - first 4 bytes: length of the vector as a big-endian uint32 +// - for each element of the vector, [Bytes] bytes representing the element in big-endian encoding. +// +// The method implements [io.ReaderFrom] interface. func (vector *Vector) ReadFrom(r io.Reader) (int64, error) { - var buf [Bytes]byte if read, err := io.ReadFull(r, buf[:4]); err != nil { return int64(read), err } - sliceLen := binary.BigEndian.Uint32(buf[:4]) - - n := int64(4) - (*vector) = make(Vector, sliceLen) + headerSliceLen := uint64(binary.BigEndian.Uint32(buf[:4])) + + // to avoid allocating too large slice when the header is tampered, we limit + // the maximum allocation. We set the target to 4GB. This incurs a performance + // hit when reading very large slices, but protects against OOM. + targetSize := uint64(1 << 32) // 4GB + if bits.UintSize == 32 { + // reduce target size to 1GB on 32 bits architectures + targetSize = uint64(1 << 30) // 1GB + } + maxAllocateSliceLength := targetSize / uint64(Bytes) + + totalRead := int64(4) // include already the header length + *vector = (*vector)[:0] + // if the vector was nil previously even by reslicing we have a nil vector. But we want + // to have an empty slice to indicate that the vector has zero length. When headerSliceLen == 0 + // we handle this edge case after reading the header as the loop body below is skipped. + if headerSliceLen == 0 && *vector == nil { + *vector = []Element{} + } - for i := 0; i < int(sliceLen); i++ { + for i := uint64(0); i < headerSliceLen; i++ { read, err := io.ReadFull(r, buf[:]) - n += int64(read) + totalRead += int64(read) + if errors.Is(err, io.ErrUnexpectedEOF) { + return totalRead, fmt.Errorf("less data than expected: read %d elements, expected %d", i, headerSliceLen) + } if err != nil { - return n, err + return totalRead, fmt.Errorf("error reading element %d: %w", i, err) } - (*vector)[i], err = BigEndian.Element(&buf) + if uint64(cap(*vector)) <= i { + (*vector) = slices.Grow(*vector, int(min(headerSliceLen-i, maxAllocateSliceLength))) + } + el, err := BigEndian.Element(&buf) if err != nil { - return n, err + return totalRead, fmt.Errorf("error decoding element %d: %w", i, err) } + *vector = append(*vector, el) } - return n, nil + return totalRead, nil } // String implements fmt.Stringer interface @@ -201,6 +274,88 @@ func (vector Vector) Swap(i, j int) { vector[i], vector[j] = vector[j], vector[i] } +// SetRandom sets the elements in vector to independent uniform random values in [0, q). +// +// This might error only if reading from crypto/rand.Reader errors, +// in which case the values in vector are undefined. +func (vector Vector) SetRandom() error { + for i := range vector { + if _, err := vector[i].SetRandom(); err != nil { + return err + } + } + return nil +} + +// MustSetRandom sets the elements in vector to independent uniform random values in [0, q). +// +// It panics if reading from crypto/rand.Reader errors. +func (vector Vector) MustSetRandom() { + for i := range vector { + if _, err := vector[i].SetRandom(); err != nil { + panic(err) + } + } +} + +// Equal returns true if vector and other have the same length and same elements. +func (vector Vector) Equal(other Vector) bool { + return slices.Equal(vector, other) +} + +func addVecGeneric(res, a, b Vector) { + if len(a) != len(b) || len(a) != len(res) { + panic("vector.Add: vectors don't have the same length") + } + for i := 0; i < len(a); i++ { + res[i].Add(&a[i], &b[i]) + } +} + +func subVecGeneric(res, a, b Vector) { + if len(a) != len(b) || len(a) != len(res) { + panic("vector.Sub: vectors don't have the same length") + } + for i := 0; i < len(a); i++ { + res[i].Sub(&a[i], &b[i]) + } +} + +func scalarMulVecGeneric(res, a Vector, b *Element) { + if len(a) != len(res) { + panic("vector.ScalarMul: vectors don't have the same length") + } + for i := 0; i < len(a); i++ { + res[i].Mul(&a[i], b) + } +} + +func sumVecGeneric(res *Element, a Vector) { + for i := 0; i < len(a); i++ { + res.Add(res, &a[i]) + } +} + +func innerProductVecGeneric(res *Element, a, b Vector) { + if len(a) != len(b) { + panic("vector.InnerProduct: vectors don't have the same length") + } + var tmp Element + for i := 0; i < len(a); i++ { + tmp.Mul(&a[i], &b[i]) + res.Add(res, &tmp) + } +} + +func mulVecGeneric(res, a, b Vector) { + if len(a) != len(b) || len(a) != len(res) { + panic("vector.Mul: vectors don't have the same length") + } + for i := 0; i < len(a); i++ { + res[i].Mul(&a[i], &b[i]) + } +} + // TODO @gbotrel make a public package out of that. // execute executes the work function in parallel. // this is copy paste from internal/parallel/parallel.go diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/vector_purego.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/vector_purego.go new file mode 100644 index 00000000000..85670501dfe --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fp/vector_purego.go @@ -0,0 +1,43 @@ +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fp + +// Add adds two vectors element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) Add(a, b Vector) { + addVecGeneric(*vector, a, b) +} + +// Sub subtracts two vectors element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) Sub(a, b Vector) { + subVecGeneric(*vector, a, b) +} + +// ScalarMul multiplies a vector by a scalar element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) ScalarMul(a Vector, b *Element) { + scalarMulVecGeneric(*vector, a, b) +} + +// Sum computes the sum of all elements in the vector. +func (vector *Vector) Sum() (res Element) { + sumVecGeneric(&res, *vector) + return +} + +// InnerProduct computes the inner product of two vectors. +// It panics if the vectors don't have the same length. +func (vector *Vector) InnerProduct(other Vector) (res Element) { + innerProductVecGeneric(&res, *vector, other) + return +} + +// Mul multiplies two vectors element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) Mul(a, b Vector) { + mulVecGeneric(*vector, a, b) +} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/arith.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/arith.go index 7cfd55da199..8dbae56e320 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/arith.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/arith.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -58,16 +47,3 @@ func madd3(a, b, c, d, e uint64) (hi uint64, lo uint64) { hi, _ = bits.Add64(hi, e, carry) return } -func max(a int, b int) int { - if a > b { - return a - } - return b -} - -func min(a int, b int) int { - if a < b { - return a - } - return b -} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/asm.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/asm.go deleted file mode 100644 index da061913ba7..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/asm.go +++ /dev/null @@ -1,27 +0,0 @@ -//go:build !noadx -// +build !noadx - -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by consensys/gnark-crypto DO NOT EDIT - -package fr - -import "golang.org/x/sys/cpu" - -var ( - supportAdx = cpu.X86.HasADX && cpu.X86.HasBMI2 - _ = supportAdx -) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/asm_noadx.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/asm_noadx.go deleted file mode 100644 index 7f52ffa197b..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/asm_noadx.go +++ /dev/null @@ -1,28 +0,0 @@ -//go:build noadx -// +build noadx - -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by consensys/gnark-crypto DO NOT EDIT - -package fr - -// note: this is needed for test purposes, as dynamically changing supportAdx doesn't flag -// certain errors (like fatal error: missing stackmap) -// this ensures we test all asm path. -var ( - supportAdx = false - _ = supportAdx -) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/doc.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/doc.go index 08f1a0ba2ec..50e4ef63502 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/doc.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/doc.go @@ -1,22 +1,13 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT // Package fr contains field arithmetic operations for modulus = 0x12ab65...000001. // -// The API is similar to math/big (big.Int), but the operations are significantly faster (up to 20x for the modular multiplication on amd64, see also https://hackmd.io/@gnark/modular_multiplication) +// The API is similar to math/big (big.Int), but the operations are significantly faster (up to 20x). +// +// Additionally fr.Vector offers an API to manipulate []Element using AVX512 instructions if available. // // The modulus is hardcoded in all the operations. // @@ -49,5 +40,7 @@ // // # Warning // -// This code has not been audited and is provided as-is. In particular, there is no security guarantees such as constant time implementation or side-channel attack resistance. +// There is no security guarantees such as constant time implementation or side-channel attack resistance. +// This code is provided as-is. Partially audited, see https://github.com/Consensys/gnark/tree/master/audits +// for more details. package fr diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element.go index 07be74489e8..067821922c1 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -54,10 +43,10 @@ const ( // Field modulus q const ( - q0 uint64 = 725501752471715841 - q1 uint64 = 6461107452199829505 - q2 uint64 = 6968279316240510977 - q3 uint64 = 1345280370688173398 + q0 = 725501752471715841 + q1 = 6461107452199829505 + q2 = 6968279316240510977 + q3 = 1345280370688173398 ) var qElement = Element{ @@ -79,7 +68,10 @@ func Modulus() *big.Int { // q + r'.r = 1, i.e., qInvNeg = - q⁻¹ mod r // used for Montgomery reduction -const qInvNeg uint64 = 725501752471715839 +const qInvNeg = 725501752471715839 + +// mu = 2^288 / q needed for partial Barrett reduction +const mu uint64 = 58893420465 func init() { _modulus.SetString("12ab655e9a2ca55660b44d1e5c37b00159aa76fed00000010a11800000000001", 16) @@ -350,6 +342,16 @@ func (z *Element) SetRandom() (*Element, error) { } } +// MustSetRandom sets z to a uniform random value in [0, q). +// +// It panics if reading from crypto/rand.Reader errors. +func (z *Element) MustSetRandom() *Element { + if _, err := z.SetRandom(); err != nil { + panic(err) + } + return z +} + // smallerThanModulus returns true if z < q // This is not constant time func (z *Element) smallerThanModulus() bool { @@ -477,32 +479,8 @@ func (z *Element) Select(c int, x0 *Element, x1 *Element) *Element { // and is used for testing purposes. func _mulGeneric(z, x, y *Element) { - // Implements CIOS multiplication -- section 2.3.2 of Tolga Acar's thesis - // https://www.microsoft.com/en-us/research/wp-content/uploads/1998/06/97Acar.pdf - // - // The algorithm: - // - // for i=0 to N-1 - // C := 0 - // for j=0 to N-1 - // (C,t[j]) := t[j] + x[j]*y[i] + C - // (t[N+1],t[N]) := t[N] + C - // - // C := 0 - // m := t[0]*q'[0] mod D - // (C,_) := t[0] + m*q[0] - // for j=1 to N-1 - // (C,t[j-1]) := t[j] + m*q[j] + C - // - // (C,t[N-1]) := t[N] + C - // t[N] := t[N+1] + C - // - // → N is the number of machine words needed to store the modulus q - // → D is the word size. For example, on a 64-bit architecture D is 2 64 - // → x[i], y[i], q[i] is the ith word of the numbers x,y,q - // → q'[0] is the lowest word of the number -q⁻¹ mod r. This quantity is pre-computed, as it does not depend on the inputs. - // → t is a temporary array of size N+2 - // → C, S are machine words. A pair (C,S) refers to (hi-bits, lo-bits) of a two-word number + // Algorithm 2 of "Faster Montgomery Multiplication and Multi-Scalar-Multiplication for SNARKS" + // by Y. El Housni and G. Botrel https://doi.org/10.46586/tches.v2023.i3.504-521 var t [5]uint64 var D uint64 @@ -960,7 +938,7 @@ func (z *Element) SetBigInt(v *big.Int) *Element { // v == 0 return z } else if c != 1 && v.Cmp(&zero) != -1 { - // 0 < v < q + // 0 <= v < q return z.setBigInt(v) } @@ -1087,6 +1065,8 @@ type ByteOrder interface { String() string } +var errInvalidEncoding = errors.New("invalid fr.Element encoding") + // BigEndian is the big-endian implementation of ByteOrder and AppendByteOrder. var BigEndian bigEndian @@ -1102,7 +1082,7 @@ func (bigEndian) Element(b *[Bytes]byte) (Element, error) { z[3] = binary.BigEndian.Uint64((*b)[0:8]) if !z.smallerThanModulus() { - return Element{}, errors.New("invalid fr.Element encoding") + return Element{}, errInvalidEncoding } z.toMont() @@ -1132,7 +1112,7 @@ func (littleEndian) Element(b *[Bytes]byte) (Element, error) { z[3] = binary.LittleEndian.Uint64((*b)[24:32]) if !z.smallerThanModulus() { - return Element{}, errors.New("invalid fr.Element encoding") + return Element{}, errInvalidEncoding } z.toMont() diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element_amd64.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element_amd64.go new file mode 100644 index 00000000000..c282ebc9fc8 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element_amd64.go @@ -0,0 +1,62 @@ +//go:build !purego + +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fr + +import ( + _ "github.com/consensys/gnark-crypto/field/asm/element_4w" + "github.com/consensys/gnark-crypto/utils/cpu" +) + +var supportAdx = cpu.SupportADX + +//go:noescape +func MulBy3(x *Element) + +//go:noescape +func MulBy5(x *Element) + +//go:noescape +func MulBy13(x *Element) + +//go:noescape +func mul(res, x, y *Element) + +//go:noescape +func fromMont(res *Element) + +//go:noescape +func reduce(res *Element) + +// Butterfly sets +// +// a = a + b (mod q) +// b = a - b (mod q) +// +//go:noescape +func Butterfly(a, b *Element) + +// Mul z = x * y (mod q) +// +// x and y must be less than q +func (z *Element) Mul(x, y *Element) *Element { + + // Algorithm 2 of "Faster Montgomery Multiplication and Multi-Scalar-Multiplication for SNARKS" + // by Y. El Housni and G. Botrel https://doi.org/10.46586/tches.v2023.i3.504-521 + + mul(z, x, y) + return z +} + +// Square z = x * x (mod q) +// +// x must be less than q +func (z *Element) Square(x *Element) *Element { + // see Mul for doc. + mul(z, x, x) + return z +} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element_amd64.s b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element_amd64.s new file mode 100644 index 00000000000..b45615aa361 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element_amd64.s @@ -0,0 +1,10 @@ +//go:build !purego + +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +// We include the hash to force the Go compiler to recompile: 14652627197992229521 +#include "../../../field/asm/element_4w/element_4w_amd64.s" + diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element_arm64.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element_arm64.go new file mode 100644 index 00000000000..fc800231719 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element_arm64.go @@ -0,0 +1,70 @@ +//go:build !purego + +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fr + +import ( + _ "github.com/consensys/gnark-crypto/field/asm/element_4w" +) + +// Butterfly sets +// +// a = a + b (mod q) +// b = a - b (mod q) +// +//go:noescape +func Butterfly(a, b *Element) + +//go:noescape +func mul(res, x, y *Element) + +// Mul z = x * y (mod q) +// +// x and y must be less than q +func (z *Element) Mul(x, y *Element) *Element { + mul(z, x, y) + return z +} + +// Square z = x * x (mod q) +// +// x must be less than q +func (z *Element) Square(x *Element) *Element { + // see Mul for doc. + mul(z, x, x) + return z +} + +// MulBy3 x *= 3 (mod q) +func MulBy3(x *Element) { + _x := *x + x.Double(x).Add(x, &_x) +} + +// MulBy5 x *= 5 (mod q) +func MulBy5(x *Element) { + _x := *x + x.Double(x).Double(x).Add(x, &_x) +} + +// MulBy13 x *= 13 (mod q) +func MulBy13(x *Element) { + var y = Element{ + 18434640649710993230, + 12067750152132099910, + 14024878721438555919, + 347766975729306096, + } + x.Mul(x, &y) +} + +func fromMont(z *Element) { + _fromMontGeneric(z) +} + +//go:noescape +func reduce(res *Element) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element_arm64.s b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element_arm64.s new file mode 100644 index 00000000000..c8df07e3454 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element_arm64.s @@ -0,0 +1,10 @@ +//go:build !purego + +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +// We include the hash to force the Go compiler to recompile: 1501560133179981797 +#include "../../../field/asm/element_4w/element_4w_arm64.s" + diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element_exp.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element_exp.go index 654ea55faa3..9a426616301 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element_exp.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element_exp.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element_mul_amd64.s b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element_mul_amd64.s deleted file mode 100644 index dc601e91e38..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element_mul_amd64.s +++ /dev/null @@ -1,487 +0,0 @@ -// +build !purego - -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "textflag.h" -#include "funcdata.h" - -// modulus q -DATA q<>+0(SB)/8, $0x0a11800000000001 -DATA q<>+8(SB)/8, $0x59aa76fed0000001 -DATA q<>+16(SB)/8, $0x60b44d1e5c37b001 -DATA q<>+24(SB)/8, $0x12ab655e9a2ca556 -GLOBL q<>(SB), (RODATA+NOPTR), $32 - -// qInv0 q'[0] -DATA qInv0<>(SB)/8, $0x0a117fffffffffff -GLOBL qInv0<>(SB), (RODATA+NOPTR), $8 - -#define REDUCE(ra0, ra1, ra2, ra3, rb0, rb1, rb2, rb3) \ - MOVQ ra0, rb0; \ - SUBQ q<>(SB), ra0; \ - MOVQ ra1, rb1; \ - SBBQ q<>+8(SB), ra1; \ - MOVQ ra2, rb2; \ - SBBQ q<>+16(SB), ra2; \ - MOVQ ra3, rb3; \ - SBBQ q<>+24(SB), ra3; \ - CMOVQCS rb0, ra0; \ - CMOVQCS rb1, ra1; \ - CMOVQCS rb2, ra2; \ - CMOVQCS rb3, ra3; \ - -// mul(res, x, y *Element) -TEXT ·mul(SB), $24-24 - - // the algorithm is described in the Element.Mul declaration (.go) - // however, to benefit from the ADCX and ADOX carry chains - // we split the inner loops in 2: - // for i=0 to N-1 - // for j=0 to N-1 - // (A,t[j]) := t[j] + x[j]*y[i] + A - // m := t[0]*q'[0] mod W - // C,_ := t[0] + m*q[0] - // for j=1 to N-1 - // (C,t[j-1]) := t[j] + m*q[j] + C - // t[N-1] = C + A - - NO_LOCAL_POINTERS - CMPB ·supportAdx(SB), $1 - JNE l1 - MOVQ x+8(FP), SI - - // x[0] -> DI - // x[1] -> R8 - // x[2] -> R9 - // x[3] -> R10 - MOVQ 0(SI), DI - MOVQ 8(SI), R8 - MOVQ 16(SI), R9 - MOVQ 24(SI), R10 - MOVQ y+16(FP), R11 - - // A -> BP - // t[0] -> R14 - // t[1] -> R13 - // t[2] -> CX - // t[3] -> BX - // clear the flags - XORQ AX, AX - MOVQ 0(R11), DX - - // (A,t[0]) := x[0]*y[0] + A - MULXQ DI, R14, R13 - - // (A,t[1]) := x[1]*y[0] + A - MULXQ R8, AX, CX - ADOXQ AX, R13 - - // (A,t[2]) := x[2]*y[0] + A - MULXQ R9, AX, BX - ADOXQ AX, CX - - // (A,t[3]) := x[3]*y[0] + A - MULXQ R10, AX, BP - ADOXQ AX, BX - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADOXQ AX, BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, R12 - ADCXQ R14, AX - MOVQ R12, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R13, R14 - MULXQ q<>+8(SB), AX, R13 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R13 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R13 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // t[3] = C + A - MOVQ $0, AX - ADCXQ AX, BX - ADOXQ BP, BX - - // clear the flags - XORQ AX, AX - MOVQ 8(R11), DX - - // (A,t[0]) := t[0] + x[0]*y[1] + A - MULXQ DI, AX, BP - ADOXQ AX, R14 - - // (A,t[1]) := t[1] + x[1]*y[1] + A - ADCXQ BP, R13 - MULXQ R8, AX, BP - ADOXQ AX, R13 - - // (A,t[2]) := t[2] + x[2]*y[1] + A - ADCXQ BP, CX - MULXQ R9, AX, BP - ADOXQ AX, CX - - // (A,t[3]) := t[3] + x[3]*y[1] + A - ADCXQ BP, BX - MULXQ R10, AX, BP - ADOXQ AX, BX - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, R12 - ADCXQ R14, AX - MOVQ R12, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R13, R14 - MULXQ q<>+8(SB), AX, R13 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R13 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R13 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // t[3] = C + A - MOVQ $0, AX - ADCXQ AX, BX - ADOXQ BP, BX - - // clear the flags - XORQ AX, AX - MOVQ 16(R11), DX - - // (A,t[0]) := t[0] + x[0]*y[2] + A - MULXQ DI, AX, BP - ADOXQ AX, R14 - - // (A,t[1]) := t[1] + x[1]*y[2] + A - ADCXQ BP, R13 - MULXQ R8, AX, BP - ADOXQ AX, R13 - - // (A,t[2]) := t[2] + x[2]*y[2] + A - ADCXQ BP, CX - MULXQ R9, AX, BP - ADOXQ AX, CX - - // (A,t[3]) := t[3] + x[3]*y[2] + A - ADCXQ BP, BX - MULXQ R10, AX, BP - ADOXQ AX, BX - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, R12 - ADCXQ R14, AX - MOVQ R12, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R13, R14 - MULXQ q<>+8(SB), AX, R13 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R13 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R13 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // t[3] = C + A - MOVQ $0, AX - ADCXQ AX, BX - ADOXQ BP, BX - - // clear the flags - XORQ AX, AX - MOVQ 24(R11), DX - - // (A,t[0]) := t[0] + x[0]*y[3] + A - MULXQ DI, AX, BP - ADOXQ AX, R14 - - // (A,t[1]) := t[1] + x[1]*y[3] + A - ADCXQ BP, R13 - MULXQ R8, AX, BP - ADOXQ AX, R13 - - // (A,t[2]) := t[2] + x[2]*y[3] + A - ADCXQ BP, CX - MULXQ R9, AX, BP - ADOXQ AX, CX - - // (A,t[3]) := t[3] + x[3]*y[3] + A - ADCXQ BP, BX - MULXQ R10, AX, BP - ADOXQ AX, BX - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, R12 - ADCXQ R14, AX - MOVQ R12, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R13, R14 - MULXQ q<>+8(SB), AX, R13 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R13 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R13 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // t[3] = C + A - MOVQ $0, AX - ADCXQ AX, BX - ADOXQ BP, BX - - // reduce element(R14,R13,CX,BX) using temp registers (SI,R12,R11,DI) - REDUCE(R14,R13,CX,BX,SI,R12,R11,DI) - - MOVQ res+0(FP), AX - MOVQ R14, 0(AX) - MOVQ R13, 8(AX) - MOVQ CX, 16(AX) - MOVQ BX, 24(AX) - RET - -l1: - MOVQ res+0(FP), AX - MOVQ AX, (SP) - MOVQ x+8(FP), AX - MOVQ AX, 8(SP) - MOVQ y+16(FP), AX - MOVQ AX, 16(SP) - CALL ·_mulGeneric(SB) - RET - -TEXT ·fromMont(SB), $8-8 - NO_LOCAL_POINTERS - - // the algorithm is described here - // https://hackmd.io/@gnark/modular_multiplication - // when y = 1 we have: - // for i=0 to N-1 - // t[i] = x[i] - // for i=0 to N-1 - // m := t[0]*q'[0] mod W - // C,_ := t[0] + m*q[0] - // for j=1 to N-1 - // (C,t[j-1]) := t[j] + m*q[j] + C - // t[N-1] = C - CMPB ·supportAdx(SB), $1 - JNE l2 - MOVQ res+0(FP), DX - MOVQ 0(DX), R14 - MOVQ 8(DX), R13 - MOVQ 16(DX), CX - MOVQ 24(DX), BX - XORQ DX, DX - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R14, AX - MOVQ BP, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R13, R14 - MULXQ q<>+8(SB), AX, R13 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R13 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R13 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - MOVQ $0, AX - ADCXQ AX, BX - ADOXQ AX, BX - XORQ DX, DX - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R14, AX - MOVQ BP, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R13, R14 - MULXQ q<>+8(SB), AX, R13 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R13 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R13 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - MOVQ $0, AX - ADCXQ AX, BX - ADOXQ AX, BX - XORQ DX, DX - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R14, AX - MOVQ BP, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R13, R14 - MULXQ q<>+8(SB), AX, R13 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R13 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R13 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - MOVQ $0, AX - ADCXQ AX, BX - ADOXQ AX, BX - XORQ DX, DX - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R14, AX - MOVQ BP, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R13, R14 - MULXQ q<>+8(SB), AX, R13 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R13 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R13 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - MOVQ $0, AX - ADCXQ AX, BX - ADOXQ AX, BX - - // reduce element(R14,R13,CX,BX) using temp registers (SI,DI,R8,R9) - REDUCE(R14,R13,CX,BX,SI,DI,R8,R9) - - MOVQ res+0(FP), AX - MOVQ R14, 0(AX) - MOVQ R13, 8(AX) - MOVQ CX, 16(AX) - MOVQ BX, 24(AX) - RET - -l2: - MOVQ res+0(FP), AX - MOVQ AX, (SP) - CALL ·_fromMontGeneric(SB) - RET diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element_ops_amd64.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element_ops_amd64.go deleted file mode 100644 index e40a9caed55..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element_ops_amd64.go +++ /dev/null @@ -1,107 +0,0 @@ -//go:build !purego -// +build !purego - -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by consensys/gnark-crypto DO NOT EDIT - -package fr - -//go:noescape -func MulBy3(x *Element) - -//go:noescape -func MulBy5(x *Element) - -//go:noescape -func MulBy13(x *Element) - -//go:noescape -func mul(res, x, y *Element) - -//go:noescape -func fromMont(res *Element) - -//go:noescape -func reduce(res *Element) - -// Butterfly sets -// -// a = a + b (mod q) -// b = a - b (mod q) -// -//go:noescape -func Butterfly(a, b *Element) - -// Mul z = x * y (mod q) -// -// x and y must be less than q -func (z *Element) Mul(x, y *Element) *Element { - - // Implements CIOS multiplication -- section 2.3.2 of Tolga Acar's thesis - // https://www.microsoft.com/en-us/research/wp-content/uploads/1998/06/97Acar.pdf - // - // The algorithm: - // - // for i=0 to N-1 - // C := 0 - // for j=0 to N-1 - // (C,t[j]) := t[j] + x[j]*y[i] + C - // (t[N+1],t[N]) := t[N] + C - // - // C := 0 - // m := t[0]*q'[0] mod D - // (C,_) := t[0] + m*q[0] - // for j=1 to N-1 - // (C,t[j-1]) := t[j] + m*q[j] + C - // - // (C,t[N-1]) := t[N] + C - // t[N] := t[N+1] + C - // - // → N is the number of machine words needed to store the modulus q - // → D is the word size. For example, on a 64-bit architecture D is 2 64 - // → x[i], y[i], q[i] is the ith word of the numbers x,y,q - // → q'[0] is the lowest word of the number -q⁻¹ mod r. This quantity is pre-computed, as it does not depend on the inputs. - // → t is a temporary array of size N+2 - // → C, S are machine words. A pair (C,S) refers to (hi-bits, lo-bits) of a two-word number - // - // As described here https://hackmd.io/@gnark/modular_multiplication we can get rid of one carry chain and simplify: - // (also described in https://eprint.iacr.org/2022/1400.pdf annex) - // - // for i=0 to N-1 - // (A,t[0]) := t[0] + x[0]*y[i] - // m := t[0]*q'[0] mod W - // C,_ := t[0] + m*q[0] - // for j=1 to N-1 - // (A,t[j]) := t[j] + x[j]*y[i] + A - // (C,t[j-1]) := t[j] + m*q[j] + C - // - // t[N-1] = C + A - // - // This optimization saves 5N + 2 additions in the algorithm, and can be used whenever the highest bit - // of the modulus is zero (and not all of the remaining bits are set). - - mul(z, x, y) - return z -} - -// Square z = x * x (mod q) -// -// x must be less than q -func (z *Element) Square(x *Element) *Element { - // see Mul for doc. - mul(z, x, x) - return z -} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element_ops_amd64.s b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element_ops_amd64.s deleted file mode 100644 index afe75ff25e2..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element_ops_amd64.s +++ /dev/null @@ -1,230 +0,0 @@ -// +build !purego - -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "textflag.h" -#include "funcdata.h" - -// modulus q -DATA q<>+0(SB)/8, $0x0a11800000000001 -DATA q<>+8(SB)/8, $0x59aa76fed0000001 -DATA q<>+16(SB)/8, $0x60b44d1e5c37b001 -DATA q<>+24(SB)/8, $0x12ab655e9a2ca556 -GLOBL q<>(SB), (RODATA+NOPTR), $32 - -// qInv0 q'[0] -DATA qInv0<>(SB)/8, $0x0a117fffffffffff -GLOBL qInv0<>(SB), (RODATA+NOPTR), $8 - -#define REDUCE(ra0, ra1, ra2, ra3, rb0, rb1, rb2, rb3) \ - MOVQ ra0, rb0; \ - SUBQ q<>(SB), ra0; \ - MOVQ ra1, rb1; \ - SBBQ q<>+8(SB), ra1; \ - MOVQ ra2, rb2; \ - SBBQ q<>+16(SB), ra2; \ - MOVQ ra3, rb3; \ - SBBQ q<>+24(SB), ra3; \ - CMOVQCS rb0, ra0; \ - CMOVQCS rb1, ra1; \ - CMOVQCS rb2, ra2; \ - CMOVQCS rb3, ra3; \ - -TEXT ·reduce(SB), NOSPLIT, $0-8 - MOVQ res+0(FP), AX - MOVQ 0(AX), DX - MOVQ 8(AX), CX - MOVQ 16(AX), BX - MOVQ 24(AX), SI - - // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) - - MOVQ DX, 0(AX) - MOVQ CX, 8(AX) - MOVQ BX, 16(AX) - MOVQ SI, 24(AX) - RET - -// MulBy3(x *Element) -TEXT ·MulBy3(SB), NOSPLIT, $0-8 - MOVQ x+0(FP), AX - MOVQ 0(AX), DX - MOVQ 8(AX), CX - MOVQ 16(AX), BX - MOVQ 24(AX), SI - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - - // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) - - ADDQ 0(AX), DX - ADCQ 8(AX), CX - ADCQ 16(AX), BX - ADCQ 24(AX), SI - - // reduce element(DX,CX,BX,SI) using temp registers (R11,R12,R13,R14) - REDUCE(DX,CX,BX,SI,R11,R12,R13,R14) - - MOVQ DX, 0(AX) - MOVQ CX, 8(AX) - MOVQ BX, 16(AX) - MOVQ SI, 24(AX) - RET - -// MulBy5(x *Element) -TEXT ·MulBy5(SB), NOSPLIT, $0-8 - MOVQ x+0(FP), AX - MOVQ 0(AX), DX - MOVQ 8(AX), CX - MOVQ 16(AX), BX - MOVQ 24(AX), SI - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - - // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) - - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - - // reduce element(DX,CX,BX,SI) using temp registers (R11,R12,R13,R14) - REDUCE(DX,CX,BX,SI,R11,R12,R13,R14) - - ADDQ 0(AX), DX - ADCQ 8(AX), CX - ADCQ 16(AX), BX - ADCQ 24(AX), SI - - // reduce element(DX,CX,BX,SI) using temp registers (R15,DI,R8,R9) - REDUCE(DX,CX,BX,SI,R15,DI,R8,R9) - - MOVQ DX, 0(AX) - MOVQ CX, 8(AX) - MOVQ BX, 16(AX) - MOVQ SI, 24(AX) - RET - -// MulBy13(x *Element) -TEXT ·MulBy13(SB), NOSPLIT, $0-8 - MOVQ x+0(FP), AX - MOVQ 0(AX), DX - MOVQ 8(AX), CX - MOVQ 16(AX), BX - MOVQ 24(AX), SI - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - - // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) - - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - - // reduce element(DX,CX,BX,SI) using temp registers (R11,R12,R13,R14) - REDUCE(DX,CX,BX,SI,R11,R12,R13,R14) - - MOVQ DX, R11 - MOVQ CX, R12 - MOVQ BX, R13 - MOVQ SI, R14 - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - - // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) - - ADDQ R11, DX - ADCQ R12, CX - ADCQ R13, BX - ADCQ R14, SI - - // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) - - ADDQ 0(AX), DX - ADCQ 8(AX), CX - ADCQ 16(AX), BX - ADCQ 24(AX), SI - - // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) - - MOVQ DX, 0(AX) - MOVQ CX, 8(AX) - MOVQ BX, 16(AX) - MOVQ SI, 24(AX) - RET - -// Butterfly(a, b *Element) sets a = a + b; b = a - b -TEXT ·Butterfly(SB), NOSPLIT, $0-16 - MOVQ a+0(FP), AX - MOVQ 0(AX), CX - MOVQ 8(AX), BX - MOVQ 16(AX), SI - MOVQ 24(AX), DI - MOVQ CX, R8 - MOVQ BX, R9 - MOVQ SI, R10 - MOVQ DI, R11 - XORQ AX, AX - MOVQ b+8(FP), DX - ADDQ 0(DX), CX - ADCQ 8(DX), BX - ADCQ 16(DX), SI - ADCQ 24(DX), DI - SUBQ 0(DX), R8 - SBBQ 8(DX), R9 - SBBQ 16(DX), R10 - SBBQ 24(DX), R11 - MOVQ $0x0a11800000000001, R12 - MOVQ $0x59aa76fed0000001, R13 - MOVQ $0x60b44d1e5c37b001, R14 - MOVQ $0x12ab655e9a2ca556, R15 - CMOVQCC AX, R12 - CMOVQCC AX, R13 - CMOVQCC AX, R14 - CMOVQCC AX, R15 - ADDQ R12, R8 - ADCQ R13, R9 - ADCQ R14, R10 - ADCQ R15, R11 - MOVQ R8, 0(DX) - MOVQ R9, 8(DX) - MOVQ R10, 16(DX) - MOVQ R11, 24(DX) - - // reduce element(CX,BX,SI,DI) using temp registers (R8,R9,R10,R11) - REDUCE(CX,BX,SI,DI,R8,R9,R10,R11) - - MOVQ a+0(FP), AX - MOVQ CX, 0(AX) - MOVQ BX, 8(AX) - MOVQ SI, 16(AX) - MOVQ DI, 24(AX) - RET diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element_ops_purego.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element_purego.go similarity index 80% rename from vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element_ops_purego.go rename to vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element_purego.go index fe434ed6161..537648f3d19 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element_ops_purego.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/element_purego.go @@ -1,19 +1,7 @@ -//go:build !amd64 || purego -// +build !amd64 purego +//go:build purego || (!amd64 && !arm64) -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -44,14 +32,6 @@ func MulBy13(x *Element) { x.Mul(x, &y) } -// Butterfly sets -// -// a = a + b (mod q) -// b = a - b (mod q) -func Butterfly(a, b *Element) { - _butterflyGeneric(a, b) -} - func fromMont(z *Element) { _fromMontGeneric(z) } @@ -65,48 +45,8 @@ func reduce(z *Element) { // x and y must be less than q func (z *Element) Mul(x, y *Element) *Element { - // Implements CIOS multiplication -- section 2.3.2 of Tolga Acar's thesis - // https://www.microsoft.com/en-us/research/wp-content/uploads/1998/06/97Acar.pdf - // - // The algorithm: - // - // for i=0 to N-1 - // C := 0 - // for j=0 to N-1 - // (C,t[j]) := t[j] + x[j]*y[i] + C - // (t[N+1],t[N]) := t[N] + C - // - // C := 0 - // m := t[0]*q'[0] mod D - // (C,_) := t[0] + m*q[0] - // for j=1 to N-1 - // (C,t[j-1]) := t[j] + m*q[j] + C - // - // (C,t[N-1]) := t[N] + C - // t[N] := t[N+1] + C - // - // → N is the number of machine words needed to store the modulus q - // → D is the word size. For example, on a 64-bit architecture D is 2 64 - // → x[i], y[i], q[i] is the ith word of the numbers x,y,q - // → q'[0] is the lowest word of the number -q⁻¹ mod r. This quantity is pre-computed, as it does not depend on the inputs. - // → t is a temporary array of size N+2 - // → C, S are machine words. A pair (C,S) refers to (hi-bits, lo-bits) of a two-word number - // - // As described here https://hackmd.io/@gnark/modular_multiplication we can get rid of one carry chain and simplify: - // (also described in https://eprint.iacr.org/2022/1400.pdf annex) - // - // for i=0 to N-1 - // (A,t[0]) := t[0] + x[0]*y[i] - // m := t[0]*q'[0] mod W - // C,_ := t[0] + m*q[0] - // for j=1 to N-1 - // (A,t[j]) := t[j] + x[j]*y[i] + A - // (C,t[j-1]) := t[j] + m*q[j] + C - // - // t[N-1] = C + A - // - // This optimization saves 5N + 2 additions in the algorithm, and can be used whenever the highest bit - // of the modulus is zero (and not all of the remaining bits are set). + // Algorithm 2 of "Faster Montgomery Multiplication and Multi-Scalar-Multiplication for SNARKS" + // by Y. El Housni and G. Botrel https://doi.org/10.46586/tches.v2023.i3.504-521 var t0, t1, t2, t3 uint64 var u0, u1, u2, u3 uint64 @@ -441,3 +381,11 @@ func (z *Element) Square(x *Element) *Element { } return z } + +// Butterfly sets +// +// a = a + b (mod q) +// b = a - b (mod q) +func Butterfly(a, b *Element) { + _butterflyGeneric(a, b) +} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/generator.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/generator.go new file mode 100644 index 00000000000..7ca9c27bb92 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/generator.go @@ -0,0 +1,36 @@ +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fr + +import ( + "fmt" + "math/big" + "math/bits" + + "github.com/consensys/gnark-crypto/ecc" +) + +// Generator returns a generator for Z/2^(log(m))Z +// or an error if m is too big (required root of unity doesn't exist) +func Generator(m uint64) (Element, error) { + x := ecc.NextPowerOfTwo(m) + + var rootOfUnity Element + + rootOfUnity.SetString("8065159656716812877374967518403273466521432693661810619979959746626482506078") + const maxOrderRoot uint64 = 47 + + // find generator for Z/2^(log(m))Z + logx := uint64(bits.TrailingZeros64(x)) + if logx > maxOrderRoot { + return Element{}, fmt.Errorf("m (%d) is too big: the required root of unity does not exist", m) + } + + expo := uint64(1 << (maxOrderRoot - logx)) + var generator Element + generator.Exp(rootOfUnity, big.NewInt(int64(expo))) // order x + return generator, nil +} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/vector.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/vector.go index 00ad8a8986b..eee2062de72 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/vector.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/vector.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -19,9 +8,12 @@ package fr import ( "bytes" "encoding/binary" + "errors" "fmt" "io" + "math/bits" "runtime" + "slices" "strings" "sync" "sync/atomic" @@ -78,40 +70,84 @@ func (vector *Vector) WriteTo(w io.Writer) (int64, error) { return n, nil } -// AsyncReadFrom reads a vector of big endian encoded Element. -// Length of the vector must be encoded as a uint32 on the first 4 bytes. -// It consumes the needed bytes from the reader and returns the number of bytes read and an error if any. -// It also returns a channel that will be closed when the validation is done. -// The validation consist of checking that the elements are smaller than the modulus, and -// converting them to montgomery form. -func (vector *Vector) AsyncReadFrom(r io.Reader) (int64, error, chan error) { +// AsyncReadFrom implements an asynchronous version of [Vector.ReadFrom]. It +// reads the reader r in full and then performs the validation and conversion to +// Montgomery form separately in a goroutine. Any error encountered during +// reading is returned directly, while errors encountered during +// validation/conversion are sent on the returned channel. Thus the caller must +// wait on the channel to ensure the vector is ready to use. The method +// additionally returns the number of bytes read from r. +// +// The errors during reading can be: +// - an error while reading from r; +// - not enough bytes in r to read the full vector indicated by header. +// +// The reader can contain more bytes than needed to decode the vector, in which +// case the extra bytes are ignored. In that case the reader is not seeked nor +// read further. +// +// The method allocates sufficiently large slice to store the vector. If the +// current slice fits the vector, it is reused, otherwise the slice is grown to +// fit the vector. +// +// The serialized encoding is as follows: +// - first 4 bytes: length of the vector as a big-endian uint32 +// - for each element of the vector, [Bytes] bytes representing the element in +// big-endian encoding. +func (vector *Vector) AsyncReadFrom(r io.Reader) (int64, error, chan error) { // nolint ST1008 chErr := make(chan error, 1) var buf [Bytes]byte if read, err := io.ReadFull(r, buf[:4]); err != nil { close(chErr) return int64(read), err, chErr } - sliceLen := binary.BigEndian.Uint32(buf[:4]) - - n := int64(4) - (*vector) = make(Vector, sliceLen) - if sliceLen == 0 { + headerSliceLen := uint64(binary.BigEndian.Uint32(buf[:4])) + + // to avoid allocating too large slice when the header is tampered, we limit + // the maximum allocation. We set the target to 4GB. This incurs a performance + // hit when reading very large slices, but protects against OOM. + targetSize := uint64(1 << 32) // 4GB + if bits.UintSize == 32 { + // reduce target size to 1GB on 32 bits architectures + targetSize = uint64(1 << 30) // 1GB + } + maxAllocateSliceLength := targetSize / uint64(Bytes) + + totalRead := int64(4) + *vector = (*vector)[:0] + if headerSliceLen == 0 { + // if the vector was nil previously even by reslicing we have a nil vector. + // but we want to have an empty slice to indicate that the vector has zero length. + if *vector == nil { + *vector = []Element{} + } + // we return already here to avoid launching a goroutine doing nothing below close(chErr) - return n, nil, chErr + return totalRead, nil, chErr } - bSlice := unsafe.Slice((*byte)(unsafe.Pointer(&(*vector)[0])), sliceLen*Bytes) - read, err := io.ReadFull(r, bSlice) - n += int64(read) - if err != nil { - close(chErr) - return n, err, chErr + for i := uint64(0); i < headerSliceLen; i += maxAllocateSliceLength { + if len(*vector) <= int(i) { + (*vector) = append(*vector, make([]Element, int(min(headerSliceLen-i, maxAllocateSliceLength)))...) + } + bSlice := unsafe.Slice((*byte)(unsafe.Pointer(&(*vector)[i])), int(min(headerSliceLen-i, maxAllocateSliceLength))*Bytes) + read, err := io.ReadFull(r, bSlice) + totalRead += int64(read) + if errors.Is(err, io.ErrUnexpectedEOF) { + close(chErr) + return totalRead, fmt.Errorf("less data than expected: read %d elements, expected %d", i+uint64(read)/Bytes, headerSliceLen), chErr + } + if err != nil { + close(chErr) + return totalRead, err, chErr + } } + bSlice := unsafe.Slice((*byte)(unsafe.Pointer(&(*vector)[0])), int(headerSliceLen)*Bytes) go func() { var cptErrors uint64 // process the elements in parallel - execute(int(sliceLen), func(start, end int) { + execute(int(headerSliceLen), func(start, end int) { var z Element for i := start; i < end; i++ { @@ -138,35 +174,72 @@ func (vector *Vector) AsyncReadFrom(r io.Reader) (int64, error, chan error) { } close(chErr) }() - return n, nil, chErr + return totalRead, nil, chErr } -// ReadFrom implements io.ReaderFrom and reads a vector of big endian encoded Element. -// Length of the vector must be encoded as a uint32 on the first 4 bytes. +// ReadFrom reads the vector from the reader r. It returns the number of bytes +// read and an error, if any. The errors can be: +// - an error while reading from r; +// - not enough bytes in r to read the full vector indicated by header; +// - when decoding the bytes into elements. +// +// The reader can contain more bytes than needed to decode the vector, in which case +// the extra bytes are ignored. In that case the reader is not seeked nor read further. +// +// The method allocates sufficiently large slice to store the vector. If the current slice fits +// the vector, it is reused, otherwise the slice is grown to fit the vector. +// +// The serialized encoding is as follows: +// - first 4 bytes: length of the vector as a big-endian uint32 +// - for each element of the vector, [Bytes] bytes representing the element in big-endian encoding. +// +// The method implements [io.ReaderFrom] interface. func (vector *Vector) ReadFrom(r io.Reader) (int64, error) { - var buf [Bytes]byte if read, err := io.ReadFull(r, buf[:4]); err != nil { return int64(read), err } - sliceLen := binary.BigEndian.Uint32(buf[:4]) - - n := int64(4) - (*vector) = make(Vector, sliceLen) + headerSliceLen := uint64(binary.BigEndian.Uint32(buf[:4])) + + // to avoid allocating too large slice when the header is tampered, we limit + // the maximum allocation. We set the target to 4GB. This incurs a performance + // hit when reading very large slices, but protects against OOM. + targetSize := uint64(1 << 32) // 4GB + if bits.UintSize == 32 { + // reduce target size to 1GB on 32 bits architectures + targetSize = uint64(1 << 30) // 1GB + } + maxAllocateSliceLength := targetSize / uint64(Bytes) + + totalRead := int64(4) // include already the header length + *vector = (*vector)[:0] + // if the vector was nil previously even by reslicing we have a nil vector. But we want + // to have an empty slice to indicate that the vector has zero length. When headerSliceLen == 0 + // we handle this edge case after reading the header as the loop body below is skipped. + if headerSliceLen == 0 && *vector == nil { + *vector = []Element{} + } - for i := 0; i < int(sliceLen); i++ { + for i := uint64(0); i < headerSliceLen; i++ { read, err := io.ReadFull(r, buf[:]) - n += int64(read) + totalRead += int64(read) + if errors.Is(err, io.ErrUnexpectedEOF) { + return totalRead, fmt.Errorf("less data than expected: read %d elements, expected %d", i, headerSliceLen) + } if err != nil { - return n, err + return totalRead, fmt.Errorf("error reading element %d: %w", i, err) } - (*vector)[i], err = BigEndian.Element(&buf) + if uint64(cap(*vector)) <= i { + (*vector) = slices.Grow(*vector, int(min(headerSliceLen-i, maxAllocateSliceLength))) + } + el, err := BigEndian.Element(&buf) if err != nil { - return n, err + return totalRead, fmt.Errorf("error decoding element %d: %w", i, err) } + *vector = append(*vector, el) } - return n, nil + return totalRead, nil } // String implements fmt.Stringer interface @@ -199,6 +272,88 @@ func (vector Vector) Swap(i, j int) { vector[i], vector[j] = vector[j], vector[i] } +// SetRandom sets the elements in vector to independent uniform random values in [0, q). +// +// This might error only if reading from crypto/rand.Reader errors, +// in which case the values in vector are undefined. +func (vector Vector) SetRandom() error { + for i := range vector { + if _, err := vector[i].SetRandom(); err != nil { + return err + } + } + return nil +} + +// MustSetRandom sets the elements in vector to independent uniform random values in [0, q). +// +// It panics if reading from crypto/rand.Reader errors. +func (vector Vector) MustSetRandom() { + for i := range vector { + if _, err := vector[i].SetRandom(); err != nil { + panic(err) + } + } +} + +// Equal returns true if vector and other have the same length and same elements. +func (vector Vector) Equal(other Vector) bool { + return slices.Equal(vector, other) +} + +func addVecGeneric(res, a, b Vector) { + if len(a) != len(b) || len(a) != len(res) { + panic("vector.Add: vectors don't have the same length") + } + for i := 0; i < len(a); i++ { + res[i].Add(&a[i], &b[i]) + } +} + +func subVecGeneric(res, a, b Vector) { + if len(a) != len(b) || len(a) != len(res) { + panic("vector.Sub: vectors don't have the same length") + } + for i := 0; i < len(a); i++ { + res[i].Sub(&a[i], &b[i]) + } +} + +func scalarMulVecGeneric(res, a Vector, b *Element) { + if len(a) != len(res) { + panic("vector.ScalarMul: vectors don't have the same length") + } + for i := 0; i < len(a); i++ { + res[i].Mul(&a[i], b) + } +} + +func sumVecGeneric(res *Element, a Vector) { + for i := 0; i < len(a); i++ { + res.Add(res, &a[i]) + } +} + +func innerProductVecGeneric(res *Element, a, b Vector) { + if len(a) != len(b) { + panic("vector.InnerProduct: vectors don't have the same length") + } + var tmp Element + for i := 0; i < len(a); i++ { + tmp.Mul(&a[i], &b[i]) + res.Add(res, &tmp) + } +} + +func mulVecGeneric(res, a, b Vector) { + if len(a) != len(b) || len(a) != len(res) { + panic("vector.Mul: vectors don't have the same length") + } + for i := 0; i < len(a); i++ { + res[i].Mul(&a[i], &b[i]) + } +} + // TODO @gbotrel make a public package out of that. // execute executes the work function in parallel. // this is copy paste from internal/parallel/parallel.go diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/vector_amd64.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/vector_amd64.go new file mode 100644 index 00000000000..8b6df0b4026 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/vector_amd64.go @@ -0,0 +1,154 @@ +//go:build !purego + +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fr + +import ( + _ "github.com/consensys/gnark-crypto/field/asm/element_4w" + "github.com/consensys/gnark-crypto/utils/cpu" +) + +// Add adds two vectors element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) Add(a, b Vector) { + if len(a) != len(b) || len(a) != len(*vector) { + panic("vector.Add: vectors don't have the same length") + } + n := uint64(len(a)) + addVec(&(*vector)[0], &a[0], &b[0], n) +} + +//go:noescape +func addVec(res, a, b *Element, n uint64) + +// Sub subtracts two vectors element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) Sub(a, b Vector) { + if len(a) != len(b) || len(a) != len(*vector) { + panic("vector.Sub: vectors don't have the same length") + } + subVec(&(*vector)[0], &a[0], &b[0], uint64(len(a))) +} + +//go:noescape +func subVec(res, a, b *Element, n uint64) + +// ScalarMul multiplies a vector by a scalar element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) ScalarMul(a Vector, b *Element) { + if len(a) != len(*vector) { + panic("vector.ScalarMul: vectors don't have the same length") + } + const maxN = (1 << 32) - 1 + if !cpu.SupportAVX512 || uint64(len(a)) >= maxN { + // call scalarMulVecGeneric + scalarMulVecGeneric(*vector, a, b) + return + } + n := uint64(len(a)) + if n == 0 { + return + } + // the code for scalarMul is identical to mulVec; and it expects at least + // 2 elements in the vector to fill the Z registers + var bb [2]Element + bb[0] = *b + bb[1] = *b + const blockSize = 16 + scalarMulVec(&(*vector)[0], &a[0], &bb[0], n/blockSize, qInvNeg) + if n%blockSize != 0 { + // call scalarMulVecGeneric on the rest + start := n - n%blockSize + scalarMulVecGeneric((*vector)[start:], a[start:], b) + } +} + +//go:noescape +func scalarMulVec(res, a, b *Element, n uint64, qInvNeg uint64) + +// Sum computes the sum of all elements in the vector. +func (vector *Vector) Sum() (res Element) { + n := uint64(len(*vector)) + if n == 0 { + return + } + const minN = 16 * 7 // AVX512 slower than generic for small n + const maxN = (1 << 32) - 1 + if !cpu.SupportAVX512 || n <= minN || n >= maxN { + // call sumVecGeneric + sumVecGeneric(&res, *vector) + return + } + sumVec(&res, &(*vector)[0], uint64(len(*vector))) + return +} + +//go:noescape +func sumVec(res *Element, a *Element, n uint64) + +// InnerProduct computes the inner product of two vectors. +// It panics if the vectors don't have the same length. +func (vector *Vector) InnerProduct(other Vector) (res Element) { + n := uint64(len(*vector)) + if n == 0 { + return + } + if n != uint64(len(other)) { + panic("vector.InnerProduct: vectors don't have the same length") + } + const maxN = (1 << 32) - 1 + if !cpu.SupportAVX512 || n >= maxN { + // call innerProductVecGeneric + // note; we could split the vector into smaller chunks and call innerProductVec + innerProductVecGeneric(&res, *vector, other) + return + } + innerProdVec(&res[0], &(*vector)[0], &other[0], uint64(len(*vector))) + + return +} + +//go:noescape +func innerProdVec(res *uint64, a, b *Element, n uint64) + +// Mul multiplies two vectors element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) Mul(a, b Vector) { + if len(a) != len(b) || len(a) != len(*vector) { + panic("vector.Mul: vectors don't have the same length") + } + n := uint64(len(a)) + if n == 0 { + return + } + const maxN = (1 << 32) - 1 + if !cpu.SupportAVX512 || n >= maxN { + // call mulVecGeneric + mulVecGeneric(*vector, a, b) + return + } + + const blockSize = 16 + mulVec(&(*vector)[0], &a[0], &b[0], n/blockSize, qInvNeg) + if n%blockSize != 0 { + // call mulVecGeneric on the rest + start := n - n%blockSize + mulVecGeneric((*vector)[start:], a[start:], b[start:]) + } + +} + +// Patterns use for transposing the vectors in mulVec +var ( + pattern1 = [8]uint64{0, 8, 1, 9, 2, 10, 3, 11} + pattern2 = [8]uint64{12, 4, 13, 5, 14, 6, 15, 7} + pattern3 = [8]uint64{0, 1, 8, 9, 2, 3, 10, 11} + pattern4 = [8]uint64{12, 13, 4, 5, 14, 15, 6, 7} +) + +//go:noescape +func mulVec(res, a, b *Element, n uint64, qInvNeg uint64) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/vector_purego.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/vector_purego.go new file mode 100644 index 00000000000..6608e394c79 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/fr/vector_purego.go @@ -0,0 +1,45 @@ +//go:build purego || !amd64 + +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fr + +// Add adds two vectors element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) Add(a, b Vector) { + addVecGeneric(*vector, a, b) +} + +// Sub subtracts two vectors element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) Sub(a, b Vector) { + subVecGeneric(*vector, a, b) +} + +// ScalarMul multiplies a vector by a scalar element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) ScalarMul(a Vector, b *Element) { + scalarMulVecGeneric(*vector, a, b) +} + +// Sum computes the sum of all elements in the vector. +func (vector *Vector) Sum() (res Element) { + sumVecGeneric(&res, *vector) + return +} + +// InnerProduct computes the inner product of two vectors. +// It panics if the vectors don't have the same length. +func (vector *Vector) InnerProduct(other Vector) (res Element) { + innerProductVecGeneric(&res, *vector, other) + return +} + +// Mul multiplies two vectors element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) Mul(a, b Vector) { + mulVecGeneric(*vector, a, b) +} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/g1.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/g1.go index e1bc1809f45..b727642fee2 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/g1.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/g1.go @@ -1,16 +1,5 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -25,38 +14,40 @@ import ( "runtime" ) -// G1Affine point in affine coordinates +// G1Affine is a point in affine coordinates (x,y) type G1Affine struct { X, Y fp.Element } -// G1Jac is a point with fp.Element coordinates +// G1Jac is a point in Jacobian coordinates (x=X/Z², y=Y/Z³) type G1Jac struct { X, Y, Z fp.Element } -// g1JacExtended parameterized Jacobian coordinates (x=X/ZZ, y=Y/ZZZ, ZZ³=ZZZ²) +// g1JacExtended is a point in extended Jacobian coordinates (x=X/ZZ, y=Y/ZZZ, ZZ³=ZZZ²) type g1JacExtended struct { X, Y, ZZ, ZZZ fp.Element } // ------------------------------------------------------------------------------------------------- -// Affine +// Affine coordinates -// Set sets p to the provided point +// Set sets p to a in affine coordinates. func (p *G1Affine) Set(a *G1Affine) *G1Affine { p.X, p.Y = a.X, a.Y return p } -// setInfinity sets p to O -func (p *G1Affine) setInfinity() *G1Affine { +// SetInfinity sets p to the infinity point, which is encoded as (0,0). +// N.B.: (0,0) is never on the curve for j=0 curves (Y²=X³+B). +func (p *G1Affine) SetInfinity() *G1Affine { p.X.SetZero() p.Y.SetZero() return p } -// ScalarMultiplication computes and returns p = a ⋅ s +// ScalarMultiplication computes and returns p = [s]a +// where p and a are affine points. func (p *G1Affine) ScalarMultiplication(a *G1Affine, s *big.Int) *G1Affine { var _p G1Jac _p.FromAffine(a) @@ -65,15 +56,8 @@ func (p *G1Affine) ScalarMultiplication(a *G1Affine, s *big.Int) *G1Affine { return p } -// ScalarMultiplicationAffine computes and returns p = a ⋅ s -// Takes an affine point and returns a Jacobian point (useful for KZG) -func (p *G1Jac) ScalarMultiplicationAffine(a *G1Affine, s *big.Int) *G1Jac { - p.FromAffine(a) - p.mulGLV(p, s) - return p -} - -// ScalarMultiplicationBase computes and returns p = g ⋅ s where g is the prime subgroup generator +// ScalarMultiplicationBase computes and returns p = [s]g +// where g is the affine point generating the prime subgroup. func (p *G1Affine) ScalarMultiplicationBase(s *big.Int) *G1Affine { var _p G1Jac _p.mulGLV(&g1Gen, s) @@ -81,51 +65,88 @@ func (p *G1Affine) ScalarMultiplicationBase(s *big.Int) *G1Affine { return p } -// Add adds two point in affine coordinates. -// This should rarely be used as it is very inefficient compared to Jacobian +// Add adds two points in affine coordinates. +// It uses the Jacobian addition with a.Z=b.Z=1 and converts the result to affine coordinates. +// +// https://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-mmadd-2007-bl func (p *G1Affine) Add(a, b *G1Affine) *G1Affine { - var p1, p2 G1Jac - p1.FromAffine(a) - p2.FromAffine(b) - p1.AddAssign(&p2) - p.FromJacobian(&p1) - return p + var q G1Jac + // a is infinity, return b + if a.IsInfinity() { + p.Set(b) + return p + } + // b is infinity, return a + if b.IsInfinity() { + p.Set(a) + return p + } + if a.X.Equal(&b.X) { + // if b == a, we double instead + if a.Y.Equal(&b.Y) { + q.DoubleMixed(a) + return p.FromJacobian(&q) + } else { + // if b == -a, we return 0 + return p.SetInfinity() + } + } + var H, HH, I, J, r, V fp.Element + H.Sub(&b.X, &a.X) + HH.Square(&H) + I.Double(&HH).Double(&I) + J.Mul(&H, &I) + r.Sub(&b.Y, &a.Y) + r.Double(&r) + V.Mul(&a.X, &I) + q.X.Square(&r). + Sub(&q.X, &J). + Sub(&q.X, &V). + Sub(&q.X, &V) + q.Y.Sub(&V, &q.X). + Mul(&q.Y, &r) + J.Mul(&a.Y, &J).Double(&J) + q.Y.Sub(&q.Y, &J) + q.Z.Double(&H) + + return p.FromJacobian(&q) } // Double doubles a point in affine coordinates. -// This should rarely be used as it is very inefficient compared to Jacobian +// It converts the point to Jacobian coordinates, doubles it using Jacobian +// addition with a.Z=1, and converts it back to affine coordinates. +// +// http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-mdbl-2007-bl func (p *G1Affine) Double(a *G1Affine) *G1Affine { - var p1 G1Jac - p1.FromAffine(a) - p1.Double(&p1) - p.FromJacobian(&p1) + var q G1Jac + q.FromAffine(a) + q.DoubleMixed(a) + p.FromJacobian(&q) return p } -// Sub subs two point in affine coordinates. -// This should rarely be used as it is very inefficient compared to Jacobian +// Sub subtracts two points in affine coordinates. +// It uses a similar approach to Add, but negates the second point before adding. func (p *G1Affine) Sub(a, b *G1Affine) *G1Affine { - var p1, p2 G1Jac - p1.FromAffine(a) - p2.FromAffine(b) - p1.SubAssign(&p2) - p.FromJacobian(&p1) + var bneg G1Affine + bneg.Neg(b) + p.Add(a, &bneg) return p } -// Equal tests if two points (in Affine coordinates) are equal +// Equal tests if two points in affine coordinates are equal. func (p *G1Affine) Equal(a *G1Affine) bool { return p.X.Equal(&a.X) && p.Y.Equal(&a.Y) } -// Neg computes -G +// Neg sets p to the affine negative point -a = (a.X, -a.Y). func (p *G1Affine) Neg(a *G1Affine) *G1Affine { p.X = a.X p.Y.Neg(&a.Y) return p } -// FromJacobian rescales a point in Jacobian coord in z=1 plane +// FromJacobian converts a point p1 from Jacobian to affine coordinates. func (p *G1Affine) FromJacobian(p1 *G1Jac) *G1Affine { var a, b fp.Element @@ -144,7 +165,7 @@ func (p *G1Affine) FromJacobian(p1 *G1Jac) *G1Affine { return p } -// String returns the string representation of the point or "O" if it is infinity +// String returns the string representation E(x,y) of the affine point p or "O" if it is infinity. func (p *G1Affine) String() string { if p.IsInfinity() { return "O" @@ -152,21 +173,25 @@ func (p *G1Affine) String() string { return "E([" + p.X.String() + "," + p.Y.String() + "])" } -// IsInfinity checks if the point is infinity -// in affine, it's encoded as (0,0) -// (0,0) is never on the curve for j=0 curves +// IsInfinity checks if the affine point p is infinity, which is encoded as (0,0). +// N.B.: (0,0) is never on the curve for j=0 curves (Y²=X³+B). func (p *G1Affine) IsInfinity() bool { return p.X.IsZero() && p.Y.IsZero() } -// IsOnCurve returns true if p in on the curve +// IsOnCurve returns true if the affine point p in on the curve. func (p *G1Affine) IsOnCurve() bool { - var point G1Jac - point.FromAffine(p) - return point.IsOnCurve() // call this function to handle infinity point + if p.IsInfinity() { + return true + } + var left, right fp.Element + left.Square(&p.Y) + right.Square(&p.X).Mul(&right, &p.X) + right.Add(&right, &bCurveCoeff) + return left.Equal(&right) } -// IsInSubGroup returns true if p is in the correct subgroup, false otherwise +// IsInSubGroup returns true if the affine point p is in the correct subgroup, false otherwise. func (p *G1Affine) IsInSubGroup() bool { var _p G1Jac _p.FromAffine(p) @@ -174,84 +199,76 @@ func (p *G1Affine) IsInSubGroup() bool { } // ------------------------------------------------------------------------------------------------- -// Jacobian +// Jacobian coordinates -// Set sets p to the provided point -func (p *G1Jac) Set(a *G1Jac) *G1Jac { - p.X, p.Y, p.Z = a.X, a.Y, a.Z +// Set sets p to a in Jacobian coordinates. +func (p *G1Jac) Set(q *G1Jac) *G1Jac { + p.X, p.Y, p.Z = q.X, q.Y, q.Z return p } -// Equal tests if two points (in Jacobian coordinates) are equal -func (p *G1Jac) Equal(a *G1Jac) bool { +// Equal tests if two points in Jacobian coordinates are equal. +func (p *G1Jac) Equal(q *G1Jac) bool { // If one point is infinity, the other must also be infinity. if p.Z.IsZero() { - return a.Z.IsZero() + return q.Z.IsZero() } // If the other point is infinity, return false since we can't // the following checks would be incorrect. - if a.Z.IsZero() { + if q.Z.IsZero() { return false } var pZSquare, aZSquare fp.Element pZSquare.Square(&p.Z) - aZSquare.Square(&a.Z) + aZSquare.Square(&q.Z) var lhs, rhs fp.Element lhs.Mul(&p.X, &aZSquare) - rhs.Mul(&a.X, &pZSquare) + rhs.Mul(&q.X, &pZSquare) if !lhs.Equal(&rhs) { return false } - lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &a.Z) - rhs.Mul(&a.Y, &pZSquare).Mul(&rhs, &p.Z) + lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &q.Z) + rhs.Mul(&q.Y, &pZSquare).Mul(&rhs, &p.Z) return lhs.Equal(&rhs) } -// Neg computes -G -func (p *G1Jac) Neg(a *G1Jac) *G1Jac { - *p = *a - p.Y.Neg(&a.Y) +// Neg sets p to the Jacobian negative point -q = (q.X, -q.Y, q.Z). +func (p *G1Jac) Neg(q *G1Jac) *G1Jac { + *p = *q + p.Y.Neg(&q.Y) return p } -// SubAssign subtracts two points on the curve -func (p *G1Jac) SubAssign(a *G1Jac) *G1Jac { - var tmp G1Jac - tmp.Set(a) - tmp.Y.Neg(&tmp.Y) - p.AddAssign(&tmp) - return p -} - -// AddAssign point addition in montgomery form +// AddAssign sets p to p+a in Jacobian coordinates. +// // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl -func (p *G1Jac) AddAssign(a *G1Jac) *G1Jac { +func (p *G1Jac) AddAssign(q *G1Jac) *G1Jac { - // p is infinity, return a + // p is infinity, return q if p.Z.IsZero() { - p.Set(a) + p.Set(q) return p } - // a is infinity, return p - if a.Z.IsZero() { + // q is infinity, return p + if q.Z.IsZero() { return p } var Z1Z1, Z2Z2, U1, U2, S1, S2, H, I, J, r, V fp.Element - Z1Z1.Square(&a.Z) + Z1Z1.Square(&q.Z) Z2Z2.Square(&p.Z) - U1.Mul(&a.X, &Z2Z2) + U1.Mul(&q.X, &Z2Z2) U2.Mul(&p.X, &Z1Z1) - S1.Mul(&a.Y, &p.Z). + S1.Mul(&q.Y, &p.Z). Mul(&S1, &Z2Z2) - S2.Mul(&p.Y, &a.Z). + S2.Mul(&p.Y, &q.Z). Mul(&S2, &Z1Z1) - // if p == a, we double instead + // if p == q, we double instead if U1.Equal(&U2) && S1.Equal(&S2) { return p.DoubleAssign() } @@ -270,7 +287,7 @@ func (p *G1Jac) AddAssign(a *G1Jac) *G1Jac { Mul(&p.Y, &r) S1.Mul(&S1, &J).Double(&S1) p.Y.Sub(&p.Y, &S1) - p.Z.Add(&p.Z, &a.Z) + p.Z.Add(&p.Z, &q.Z) p.Z.Square(&p.Z). Sub(&p.Z, &Z1Z1). Sub(&p.Z, &Z2Z2). @@ -279,7 +296,48 @@ func (p *G1Jac) AddAssign(a *G1Jac) *G1Jac { return p } -// AddMixed point addition +// SubAssign sets p to p-a in Jacobian coordinates. +// It uses a similar approach to AddAssign, but negates the point a before adding. +func (p *G1Jac) SubAssign(q *G1Jac) *G1Jac { + var tmp G1Jac + tmp.Set(q) + tmp.Y.Neg(&tmp.Y) + p.AddAssign(&tmp) + return p +} + +// Double sets p to [2]q in Jacobian coordinates. +// +// https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl +func (p *G1Jac) DoubleMixed(a *G1Affine) *G1Jac { + var XX, YY, YYYY, S, M, T fp.Element + XX.Square(&a.X) + YY.Square(&a.Y) + YYYY.Square(&YY) + S.Add(&a.X, &YY). + Square(&S). + Sub(&S, &XX). + Sub(&S, &YYYY). + Double(&S) + M.Double(&XX). + Add(&M, &XX) // -> + A, but A=0 here + T.Square(&M). + Sub(&T, &S). + Sub(&T, &S) + p.X.Set(&T) + p.Y.Sub(&S, &T). + Mul(&p.Y, &M) + YYYY.Double(&YYYY). + Double(&YYYY). + Double(&YYYY) + p.Y.Sub(&p.Y, &YYYY) + p.Z.Double(&a.Y) + + return p +} + +// AddMixed sets p to p+a in Jacobian coordinates, where a.Z = 1. +// // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-madd-2007-bl func (p *G1Jac) AddMixed(a *G1Affine) *G1Jac { @@ -303,7 +361,7 @@ func (p *G1Jac) AddMixed(a *G1Affine) *G1Jac { // if p == a, we double instead if U2.Equal(&p.X) && S2.Equal(&p.Y) { - return p.DoubleAssign() + return p.DoubleMixed(a) } H.Sub(&U2, &p.X) @@ -328,7 +386,8 @@ func (p *G1Jac) AddMixed(a *G1Affine) *G1Jac { return p } -// Double doubles a point in Jacobian coordinates +// Double sets p to [2]q in Jacobian coordinates. +// // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl func (p *G1Jac) Double(q *G1Jac) *G1Jac { p.Set(q) @@ -336,7 +395,8 @@ func (p *G1Jac) Double(q *G1Jac) *G1Jac { return p } -// DoubleAssign doubles a point in Jacobian coordinates +// DoubleAssign doubles p in Jacobian coordinates. +// // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl func (p *G1Jac) DoubleAssign() *G1Jac { @@ -368,43 +428,50 @@ func (p *G1Jac) DoubleAssign() *G1Jac { return p } -// ScalarMultiplication computes and returns p = a ⋅ s +// ScalarMultiplication computes and returns p = [s]a +// where p and a are Jacobian points. +// using the GLV technique. // see https://www.iacr.org/archive/crypto2001/21390189.pdf -func (p *G1Jac) ScalarMultiplication(a *G1Jac, s *big.Int) *G1Jac { - return p.mulGLV(a, s) +func (p *G1Jac) ScalarMultiplication(q *G1Jac, s *big.Int) *G1Jac { + return p.mulGLV(q, s) +} + +// ScalarMultiplicationBase computes and returns p = [s]g +// where g is the prime subgroup generator. +func (p *G1Jac) ScalarMultiplicationBase(s *big.Int) *G1Jac { + return p.mulGLV(&g1Gen, s) + } -// String returns canonical representation of the point in affine coordinates +// String converts p to affine coordinates and returns its string representation E(x,y) or "O" if it is infinity. func (p *G1Jac) String() string { _p := G1Affine{} _p.FromJacobian(p) return _p.String() } -// FromAffine sets p = Q, p in Jacobian, Q in affine -func (p *G1Jac) FromAffine(Q *G1Affine) *G1Jac { - if Q.IsInfinity() { +// FromAffine converts a point a from affine to Jacobian coordinates. +func (p *G1Jac) FromAffine(a *G1Affine) *G1Jac { + if a.IsInfinity() { p.Z.SetZero() p.X.SetOne() p.Y.SetOne() return p } p.Z.SetOne() - p.X.Set(&Q.X) - p.Y.Set(&Q.Y) + p.X.Set(&a.X) + p.Y.Set(&a.Y) return p } -// IsOnCurve returns true if p in on the curve +// IsOnCurve returns true if the Jacobian point p in on the curve. func (p *G1Jac) IsOnCurve() bool { - var left, right, tmp fp.Element + var left, right, tmp, ZZ fp.Element left.Square(&p.Y) right.Square(&p.X).Mul(&right, &p.X) - tmp.Square(&p.Z). - Square(&tmp). - Mul(&tmp, &p.Z). - Mul(&tmp, &p.Z). - Mul(&tmp, &bCurveCoeff) + ZZ.Square(&p.Z) + tmp.Square(&ZZ).Mul(&tmp, &ZZ) + // Mul tmp by bCurveCoeff=1 (nothing to do) right.Add(&right, &tmp) return left.Equal(&right) } @@ -416,25 +483,28 @@ func (p *G1Jac) IsOnCurve() bool { // 1, x². So we check that p+x²ϕ(p) // is the infinity. func (p *G1Jac) IsInSubGroup() bool { - + if !p.IsOnCurve() { + return false + } var res G1Jac res.phi(p). - ScalarMultiplication(&res, &xGen). - ScalarMultiplication(&res, &xGen). - AddAssign(p) + mulBySeed(&res). + mulBySeed(&res). + Neg(&res) - return res.IsOnCurve() && res.Z.IsZero() + return res.Equal(p) } -// mulWindowed computes a 2-bits windowed scalar multiplication -func (p *G1Jac) mulWindowed(a *G1Jac, s *big.Int) *G1Jac { +// mulWindowed computes the 2-bits windowed double-and-add scalar +// multiplication p=[s]q in Jacobian coordinates. +func (p *G1Jac) mulWindowed(q *G1Jac, s *big.Int) *G1Jac { var res G1Jac var ops [3]G1Jac - ops[0].Set(a) + ops[0].Set(q) if s.Sign() == -1 { ops[0].Neg(&ops[0]) } @@ -461,17 +531,50 @@ func (p *G1Jac) mulWindowed(a *G1Jac, s *big.Int) *G1Jac { } -// ϕ assigns p to ϕ(a) where ϕ: (x,y) → (w x,y), and returns p -// where w is a third root of unity in 𝔽p -func (p *G1Jac) phi(a *G1Jac) *G1Jac { - p.Set(a) +// mulBySeed multiplies the point q by the seed xGen in Jacobian coordinates +// using an optimized addition chain. +func (p *G1Jac) mulBySeed(q *G1Jac) *G1Jac { + // Generated by github.com/mmcloughlin/addchain v0.4.0. + // Operations: 61 doublings 7 additions + + // Allocate Temporaries. + var res, t0, t1 G1Jac + res.Double(q) + res.AddAssign(q) + res.Double(&res) + res.AddAssign(q) + t0.Double(&res) + for i := 1; i < 2; i++ { + t0.Double(&t0) + } + res.AddAssign(&t0) + t1.Double(&res) + t1.AddAssign(&res) + t0.AddAssign(&t1) + for i := 0; i < 10; i++ { + t0.Double(&t0) + } + res.AddAssign(&t0) + for i := 0; i < 46; i++ { + res.Double(&res) + } + res.AddAssign(q) + p.Set(&res) + return p +} + +// phi sets p to ϕ(a) where ϕ: (x,y) → (w x,y), +// where w is a third root of unity. +func (p *G1Jac) phi(q *G1Jac) *G1Jac { + p.Set(q) p.X.Mul(&p.X, &thirdRootOneG1) return p } // mulGLV computes the scalar multiplication using a windowed-GLV method +// // see https://www.iacr.org/archive/crypto2001/21390189.pdf -func (p *G1Jac) mulGLV(a *G1Jac, s *big.Int) *G1Jac { +func (p *G1Jac) mulGLV(q *G1Jac, s *big.Int) *G1Jac { var table [15]G1Jac var res G1Jac @@ -479,11 +582,11 @@ func (p *G1Jac) mulGLV(a *G1Jac, s *big.Int) *G1Jac { res.Set(&g1Infinity) - // table[b3b2b1b0-1] = b3b2 ⋅ ϕ(a) + b1b0*a - table[0].Set(a) - table[3].phi(a) + // table[b3b2b1b0-1] = b3b2 ⋅ ϕ(q) + b1b0*q + table[0].Set(q) + table[3].phi(q) - // split the scalar, modifies ±a, ϕ(a) accordingly + // split the scalar, modifies ±q, ϕ(q) accordingly k := ecc.SplitScalar(s, &glvBasis) if k[0].Sign() == -1 { @@ -496,7 +599,7 @@ func (p *G1Jac) mulGLV(a *G1Jac, s *big.Int) *G1Jac { } // precompute table (2 bits sliding window) - // table[b3b2b1b0-1] = b3b2 ⋅ ϕ(a) + b1b0 ⋅ a if b3b2b1b0 != 0 + // table[b3b2b1b0-1] = b3b2 ⋅ ϕ(q) + b1b0 ⋅ q if b3b2b1b0 != 0 table[1].Double(&table[0]) table[2].Set(&table[1]).AddAssign(&table[0]) table[4].Set(&table[3]).AddAssign(&table[0]) @@ -552,23 +655,23 @@ func (p *G1Affine) ClearCofactor(a *G1Affine) *G1Affine { } // ClearCofactor maps a point in E(Fp) to E(Fp)[r] -func (p *G1Jac) ClearCofactor(a *G1Jac) *G1Jac { +func (p *G1Jac) ClearCofactor(q *G1Jac) *G1Jac { // cf https://eprint.iacr.org/2019/403.pdf, 5 var res G1Jac - res.ScalarMultiplication(a, &xGen).Neg(&res).AddAssign(a) + res.mulBySeed(q).Neg(&res).AddAssign(q) p.Set(&res) return p } -// JointScalarMultiplicationBase computes [s1]g+[s2]a using Straus-Shamir technique -// where g is the prime subgroup generator -func (p *G1Jac) JointScalarMultiplicationBase(a *G1Affine, s1, s2 *big.Int) *G1Jac { +// JointScalarMultiplication computes [s1]a1+[s2]a2 using Strauss-Shamir technique +// where a1 and a2 are affine points. +func (p *G1Jac) JointScalarMultiplication(a1, a2 *G1Affine, s1, s2 *big.Int) *G1Jac { var res, p1, p2 G1Jac res.Set(&g1Infinity) - p1.Set(&g1Gen) - p2.FromAffine(a) + p1.FromAffine(a1) + p2.FromAffine(a2) var table [15]G1Jac @@ -632,17 +735,24 @@ func (p *G1Jac) JointScalarMultiplicationBase(a *G1Affine, s1, s2 *big.Int) *G1J } +// JointScalarMultiplicationBase computes [s1]g+[s2]a using Straus-Shamir technique +// where g is the prime subgroup generator. +func (p *G1Jac) JointScalarMultiplicationBase(a *G1Affine, s1, s2 *big.Int) *G1Jac { + return p.JointScalarMultiplication(&g1GenAff, a, s1, s2) + +} + // ------------------------------------------------------------------------------------------------- -// Jacobian extended +// extended Jacobian coordinates -// Set sets p to the provided point -func (p *g1JacExtended) Set(a *g1JacExtended) *g1JacExtended { - p.X, p.Y, p.ZZ, p.ZZZ = a.X, a.Y, a.ZZ, a.ZZZ +// Set sets p to a in extended Jacobian coordinates. +func (p *g1JacExtended) Set(q *g1JacExtended) *g1JacExtended { + p.X, p.Y, p.ZZ, p.ZZZ = q.X, q.Y, q.ZZ, q.ZZZ return p } -// setInfinity sets p to O -func (p *g1JacExtended) setInfinity() *g1JacExtended { +// SetInfinity sets p to the infinity point (1,1,0,0). +func (p *g1JacExtended) SetInfinity() *g1JacExtended { p.X.SetOne() p.Y.SetOne() p.ZZ = fp.Element{} @@ -650,43 +760,45 @@ func (p *g1JacExtended) setInfinity() *g1JacExtended { return p } -func (p *g1JacExtended) IsZero() bool { +// IsInfinity checks if the p is infinity, i.e. p.ZZ=0. +func (p *g1JacExtended) IsInfinity() bool { return p.ZZ.IsZero() } -// fromJacExtended sets Q in affine coordinates -func (p *G1Affine) fromJacExtended(Q *g1JacExtended) *G1Affine { - if Q.ZZ.IsZero() { +// fromJacExtended converts an extended Jacobian point to an affine point. +func (p *G1Affine) fromJacExtended(q *g1JacExtended) *G1Affine { + if q.ZZ.IsZero() { p.X = fp.Element{} p.Y = fp.Element{} return p } - p.X.Inverse(&Q.ZZ).Mul(&p.X, &Q.X) - p.Y.Inverse(&Q.ZZZ).Mul(&p.Y, &Q.Y) + p.X.Inverse(&q.ZZ).Mul(&p.X, &q.X) + p.Y.Inverse(&q.ZZZ).Mul(&p.Y, &q.Y) return p } -// fromJacExtended sets Q in Jacobian coordinates -func (p *G1Jac) fromJacExtended(Q *g1JacExtended) *G1Jac { - if Q.ZZ.IsZero() { +// fromJacExtended converts an extended Jacobian point to a Jacobian point. +func (p *G1Jac) fromJacExtended(q *g1JacExtended) *G1Jac { + if q.ZZ.IsZero() { p.Set(&g1Infinity) return p } - p.X.Mul(&Q.ZZ, &Q.X).Mul(&p.X, &Q.ZZ) - p.Y.Mul(&Q.ZZZ, &Q.Y).Mul(&p.Y, &Q.ZZZ) - p.Z.Set(&Q.ZZZ) + p.X.Mul(&q.ZZ, &q.X).Mul(&p.X, &q.ZZ) + p.Y.Mul(&q.ZZZ, &q.Y).Mul(&p.Y, &q.ZZZ) + p.Z.Set(&q.ZZZ) return p } -// unsafeFromJacExtended sets p in Jacobian coordinates, but don't check for infinity -func (p *G1Jac) unsafeFromJacExtended(Q *g1JacExtended) *G1Jac { - p.X.Square(&Q.ZZ).Mul(&p.X, &Q.X) - p.Y.Square(&Q.ZZZ).Mul(&p.Y, &Q.Y) - p.Z = Q.ZZZ +// unsafeFromJacExtended converts an extended Jacobian point, distinct from Infinity, to a Jacobian point. +func (p *G1Jac) unsafeFromJacExtended(q *g1JacExtended) *G1Jac { + p.X.Square(&q.ZZ).Mul(&p.X, &q.X) + p.Y.Square(&q.ZZZ).Mul(&p.Y, &q.Y) + p.Z = q.ZZZ return p } -// add point in Jacobian extended coordinates +// add sets p to p+q in extended Jacobian coordinates. +// // https://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-add-2008-s func (p *g1JacExtended) add(q *g1JacExtended) *g1JacExtended { //if q is infinity return p @@ -742,10 +854,11 @@ func (p *g1JacExtended) add(q *g1JacExtended) *g1JacExtended { return p } -// double point in Jacobian extended coordinates +// double sets p to [2]q in Jacobian extended coordinates. +// // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#doubling-dbl-2008-s-1 -// since we consider any point on Z=0 as the point at infinity -// this doubling formula works for infinity points as well +// N.B.: since we consider any point on Z=0 as the point at infinity +// this doubling formula works for infinity points as well. func (p *g1JacExtended) double(q *g1JacExtended) *g1JacExtended { var U, V, W, S, XX, M fp.Element @@ -755,7 +868,7 @@ func (p *g1JacExtended) double(q *g1JacExtended) *g1JacExtended { S.Mul(&q.X, &V) XX.Square(&q.X) M.Double(&XX). - Add(&M, &XX) // -> + a, but a=0 here + Add(&M, &XX) // -> + A, but A=0 here U.Mul(&W, &q.Y) p.X.Square(&M). @@ -770,9 +883,10 @@ func (p *g1JacExtended) double(q *g1JacExtended) *g1JacExtended { return p } -// subMixed same as addMixed, but will negate a.Y +// addMixed sets p to p+q in extended Jacobian coordinates, where a.ZZ=1. +// // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-madd-2008-s -func (p *g1JacExtended) subMixed(a *G1Affine) *g1JacExtended { +func (p *g1JacExtended) addMixed(a *G1Affine) *g1JacExtended { //if a is infinity return p if a.IsInfinity() { @@ -781,7 +895,7 @@ func (p *g1JacExtended) subMixed(a *G1Affine) *g1JacExtended { // p is infinity, return a if p.ZZ.IsZero() { p.X = a.X - p.Y.Neg(&a.Y) + p.Y = a.Y p.ZZ.SetOne() p.ZZZ.SetOne() return p @@ -794,12 +908,11 @@ func (p *g1JacExtended) subMixed(a *G1Affine) *g1JacExtended { P.Sub(&P, &p.X) R.Mul(&a.Y, &p.ZZZ) - R.Neg(&R) R.Sub(&R, &p.Y) if P.IsZero() { if R.IsZero() { - return p.doubleNegMixed(a) + return p.doubleMixed(a) } p.ZZ = fp.Element{} @@ -826,9 +939,10 @@ func (p *g1JacExtended) subMixed(a *G1Affine) *g1JacExtended { } -// addMixed +// subMixed works the same as addMixed, but negates a.Y. +// // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-madd-2008-s -func (p *g1JacExtended) addMixed(a *G1Affine) *g1JacExtended { +func (p *g1JacExtended) subMixed(a *G1Affine) *g1JacExtended { //if a is infinity return p if a.IsInfinity() { @@ -837,7 +951,7 @@ func (p *g1JacExtended) addMixed(a *G1Affine) *g1JacExtended { // p is infinity, return a if p.ZZ.IsZero() { p.X = a.X - p.Y = a.Y + p.Y.Neg(&a.Y) p.ZZ.SetOne() p.ZZZ.SetOne() return p @@ -850,11 +964,12 @@ func (p *g1JacExtended) addMixed(a *G1Affine) *g1JacExtended { P.Sub(&P, &p.X) R.Mul(&a.Y, &p.ZZZ) + R.Neg(&R) R.Sub(&R, &p.Y) if P.IsZero() { if R.IsZero() { - return p.doubleMixed(a) + return p.doubleNegMixed(a) } p.ZZ = fp.Element{} @@ -881,21 +996,21 @@ func (p *g1JacExtended) addMixed(a *G1Affine) *g1JacExtended { } -// doubleNegMixed same as double, but will negate q.Y -func (p *g1JacExtended) doubleNegMixed(q *G1Affine) *g1JacExtended { +// doubleNegMixed works the same as double, but negates q.Y. +func (p *g1JacExtended) doubleNegMixed(a *G1Affine) *g1JacExtended { var U, V, W, S, XX, M, S2, L fp.Element - U.Double(&q.Y) + U.Double(&a.Y) U.Neg(&U) V.Square(&U) W.Mul(&U, &V) - S.Mul(&q.X, &V) - XX.Square(&q.X) + S.Mul(&a.X, &V) + XX.Square(&a.X) M.Double(&XX). - Add(&M, &XX) // -> + a, but a=0 here + Add(&M, &XX) // -> + A, but A=0 here S2.Double(&S) - L.Mul(&W, &q.Y) + L.Mul(&W, &a.Y) p.X.Square(&M). Sub(&p.X, &S2) @@ -908,21 +1023,22 @@ func (p *g1JacExtended) doubleNegMixed(q *G1Affine) *g1JacExtended { return p } -// doubleMixed point in Jacobian extended coordinates +// doubleMixed sets p to [2]a in Jacobian extended coordinates, where a.ZZ=1. +// // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#doubling-dbl-2008-s-1 -func (p *g1JacExtended) doubleMixed(q *G1Affine) *g1JacExtended { +func (p *g1JacExtended) doubleMixed(a *G1Affine) *g1JacExtended { var U, V, W, S, XX, M, S2, L fp.Element - U.Double(&q.Y) + U.Double(&a.Y) V.Square(&U) W.Mul(&U, &V) - S.Mul(&q.X, &V) - XX.Square(&q.X) + S.Mul(&a.X, &V) + XX.Square(&a.X) M.Double(&XX). - Add(&M, &XX) // -> + a, but a=0 here + Add(&M, &XX) // -> + A, but A=0 here S2.Double(&S) - L.Mul(&W, &q.Y) + L.Mul(&W, &a.Y) p.X.Square(&M). Sub(&p.X, &S2) @@ -936,7 +1052,7 @@ func (p *g1JacExtended) doubleMixed(q *G1Affine) *g1JacExtended { } // BatchJacobianToAffineG1 converts points in Jacobian coordinates to Affine coordinates -// performing a single field inversion (Montgomery batch inversion trick). +// performing a single field inversion using the Montgomery batch inversion trick. func BatchJacobianToAffineG1(points []G1Jac) []G1Affine { result := make([]G1Affine, len(points)) zeroes := make([]bool, len(points)) @@ -986,7 +1102,7 @@ func BatchJacobianToAffineG1(points []G1Jac) []G1Affine { // BatchScalarMultiplicationG1 multiplies the same base by all scalars // and return resulting points in affine coordinates -// uses a simple windowed-NAF like exponentiation algorithm +// uses a simple windowed-NAF-like multiplication algorithm. func BatchScalarMultiplicationG1(base *G1Affine, scalars []fr.Element) []G1Affine { // approximate cost in group ops is // cost = 2^{c-1} + n(scalar.nbBits+nbChunks) @@ -1068,18 +1184,29 @@ func BatchScalarMultiplicationG1(base *G1Affine, scalars []fr.Element) []G1Affin return toReturnAff } -// batch add affine coordinates -// using batch inversion -// special cases (doubling, infinity) must be filtered out before this call +// batchAddG1Affine adds affine points using the Montgomery batch inversion trick. +// Special cases (doubling, infinity) must be filtered out before this call. func batchAddG1Affine[TP pG1Affine, TPP ppG1Affine, TC cG1Affine](R *TPP, P *TP, batchSize int) { var lambda, lambdain TC - // add part + // from https://docs.zkproof.org/pages/standards/accepted-workshop3/proposal-turbo_plonk.pdf + // affine point addition formula + // R(X1, Y1) + P(X2, Y2) = Q(X3, Y3) + // λ = (Y2 - Y1) / (X2 - X1) + // X3 = λ² - (X1 + X2) + // Y3 = λ * (X1 - X3) - Y1 + + // first we compute the 1 / (X2 - X1) for all points using Montgomery batch inversion trick + + // X2 - X1 for j := 0; j < batchSize; j++ { lambdain[j].Sub(&(*P)[j].X, &(*R)[j].X) } - // invert denominator using montgomery batch invert technique + // montgomery batch inversion; + // lambda[0] = 1 / (P[0].X - R[0].X) + // lambda[1] = 1 / (P[1].X - R[1].X) + // ... { var accumulator fp.Element lambda[0].SetOne() @@ -1099,22 +1226,24 @@ func batchAddG1Affine[TP pG1Affine, TPP ppG1Affine, TC cG1Affine](R *TPP, P *TP, lambda[0].Set(&accumulator) } - var d fp.Element - var rr G1Affine + var t fp.Element + var Q G1Affine - // add part for j := 0; j < batchSize; j++ { - // computa lambda - d.Sub(&(*P)[j].Y, &(*R)[j].Y) - lambda[j].Mul(&lambda[j], &d) - - // compute X, Y - rr.X.Square(&lambda[j]) - rr.X.Sub(&rr.X, &(*R)[j].X) - rr.X.Sub(&rr.X, &(*P)[j].X) - d.Sub(&(*R)[j].X, &rr.X) - rr.Y.Mul(&lambda[j], &d) - rr.Y.Sub(&rr.Y, &(*R)[j].Y) - (*R)[j].Set(&rr) + // λ = (Y2 - Y1) / (X2 - X1) + t.Sub(&(*P)[j].Y, &(*R)[j].Y) + lambda[j].Mul(&lambda[j], &t) + + // X3 = λ² - (X1 + X2) + Q.X.Square(&lambda[j]) + Q.X.Sub(&Q.X, &(*R)[j].X) + Q.X.Sub(&Q.X, &(*P)[j].X) + + // Y3 = λ * (X1 - X3) - Y1 + t.Sub(&(*R)[j].X, &Q.X) + Q.Y.Mul(&lambda[j], &t) + Q.Y.Sub(&Q.Y, &(*R)[j].Y) + + (*R)[j].Set(&Q) } } diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/g2.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/g2.go index c256d8210e8..263a8f85214 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/g2.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/g2.go @@ -1,22 +1,12 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT package bls12377 import ( + "crypto/rand" "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark-crypto/ecc/bls12-377/fr" "github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower" @@ -25,17 +15,17 @@ import ( "runtime" ) -// G2Affine point in affine coordinates +// G2Affine is a point in affine coordinates (x,y) type G2Affine struct { X, Y fptower.E2 } -// G2Jac is a point with fptower.E2 coordinates +// G2Jac is a point in Jacobian coordinates (x=X/Z², y=Y/Z³) type G2Jac struct { X, Y, Z fptower.E2 } -// g2JacExtended parameterized Jacobian coordinates (x=X/ZZ, y=Y/ZZZ, ZZ³=ZZZ²) +// g2JacExtended is a point in extended Jacobian coordinates (x=X/ZZ, y=Y/ZZZ, ZZ³=ZZZ²) type g2JacExtended struct { X, Y, ZZ, ZZZ fptower.E2 } @@ -46,22 +36,24 @@ type g2Proj struct { } // ------------------------------------------------------------------------------------------------- -// Affine +// Affine coordinates -// Set sets p to the provided point +// Set sets p to a in affine coordinates. func (p *G2Affine) Set(a *G2Affine) *G2Affine { p.X, p.Y = a.X, a.Y return p } -// setInfinity sets p to O -func (p *G2Affine) setInfinity() *G2Affine { +// SetInfinity sets p to the infinity point, which is encoded as (0,0). +// N.B.: (0,0) is never on the curve for j=0 curves (Y²=X³+B). +func (p *G2Affine) SetInfinity() *G2Affine { p.X.SetZero() p.Y.SetZero() return p } -// ScalarMultiplication computes and returns p = a ⋅ s +// ScalarMultiplication computes and returns p = [s]a +// where p and a are affine points. func (p *G2Affine) ScalarMultiplication(a *G2Affine, s *big.Int) *G2Affine { var _p G2Jac _p.FromAffine(a) @@ -70,51 +62,97 @@ func (p *G2Affine) ScalarMultiplication(a *G2Affine, s *big.Int) *G2Affine { return p } -// Add adds two point in affine coordinates. -// This should rarely be used as it is very inefficient compared to Jacobian -func (p *G2Affine) Add(a, b *G2Affine) *G2Affine { - var p1, p2 G2Jac - p1.FromAffine(a) - p2.FromAffine(b) - p1.AddAssign(&p2) - p.FromJacobian(&p1) +// ScalarMultiplicationBase computes and returns p = [s]g +// where g is the affine point generating the prime subgroup. +func (p *G2Affine) ScalarMultiplicationBase(s *big.Int) *G2Affine { + var _p G2Jac + _p.mulGLV(&g2Gen, s) + p.FromJacobian(&_p) return p } +// Add adds two points in affine coordinates. +// It uses the Jacobian addition with a.Z=b.Z=1 and converts the result to affine coordinates. +// +// https://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-mmadd-2007-bl +func (p *G2Affine) Add(a, b *G2Affine) *G2Affine { + var q G2Jac + // a is infinity, return b + if a.IsInfinity() { + p.Set(b) + return p + } + // b is infinity, return a + if b.IsInfinity() { + p.Set(a) + return p + } + if a.X.Equal(&b.X) { + // if b == a, we double instead + if a.Y.Equal(&b.Y) { + q.DoubleMixed(a) + return p.FromJacobian(&q) + } else { + // if b == -a, we return 0 + return p.SetInfinity() + } + } + var H, HH, I, J, r, V fptower.E2 + H.Sub(&b.X, &a.X) + HH.Square(&H) + I.Double(&HH).Double(&I) + J.Mul(&H, &I) + r.Sub(&b.Y, &a.Y) + r.Double(&r) + V.Mul(&a.X, &I) + q.X.Square(&r). + Sub(&q.X, &J). + Sub(&q.X, &V). + Sub(&q.X, &V) + q.Y.Sub(&V, &q.X). + Mul(&q.Y, &r) + J.Mul(&a.Y, &J).Double(&J) + q.Y.Sub(&q.Y, &J) + q.Z.Double(&H) + + return p.FromJacobian(&q) +} + // Double doubles a point in affine coordinates. -// This should rarely be used as it is very inefficient compared to Jacobian +// It converts the point to Jacobian coordinates, doubles it using Jacobian +// addition with a.Z=1, and converts it back to affine coordinates. +// +// http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-mdbl-2007-bl func (p *G2Affine) Double(a *G2Affine) *G2Affine { - var p1 G2Jac - p1.FromAffine(a) - p1.Double(&p1) - p.FromJacobian(&p1) + var q G2Jac + q.FromAffine(a) + q.DoubleMixed(a) + p.FromJacobian(&q) return p } -// Sub subs two point in affine coordinates. -// This should rarely be used as it is very inefficient compared to Jacobian +// Sub subtracts two points in affine coordinates. +// It uses a similar approach to Add, but negates the second point before adding. func (p *G2Affine) Sub(a, b *G2Affine) *G2Affine { - var p1, p2 G2Jac - p1.FromAffine(a) - p2.FromAffine(b) - p1.SubAssign(&p2) - p.FromJacobian(&p1) + var bneg G2Affine + bneg.Neg(b) + p.Add(a, &bneg) return p } -// Equal tests if two points (in Affine coordinates) are equal +// Equal tests if two points in affine coordinates are equal. func (p *G2Affine) Equal(a *G2Affine) bool { return p.X.Equal(&a.X) && p.Y.Equal(&a.Y) } -// Neg computes -G +// Neg sets p to the affine negative point -a = (a.X, -a.Y). func (p *G2Affine) Neg(a *G2Affine) *G2Affine { p.X = a.X p.Y.Neg(&a.Y) return p } -// FromJacobian rescales a point in Jacobian coord in z=1 plane +// FromJacobian converts a point p1 from Jacobian to affine coordinates. func (p *G2Affine) FromJacobian(p1 *G2Jac) *G2Affine { var a, b fptower.E2 @@ -133,7 +171,7 @@ func (p *G2Affine) FromJacobian(p1 *G2Jac) *G2Affine { return p } -// String returns the string representation of the point or "O" if it is infinity +// String returns the string representation E(x,y) of the affine point p or "O" if it is infinity. func (p *G2Affine) String() string { if p.IsInfinity() { return "O" @@ -141,21 +179,25 @@ func (p *G2Affine) String() string { return "E([" + p.X.String() + "," + p.Y.String() + "])" } -// IsInfinity checks if the point is infinity -// in affine, it's encoded as (0,0) -// (0,0) is never on the curve for j=0 curves +// IsInfinity checks if the affine point p is infinity, which is encoded as (0,0). +// N.B.: (0,0) is never on the curve for j=0 curves (Y²=X³+B). func (p *G2Affine) IsInfinity() bool { return p.X.IsZero() && p.Y.IsZero() } -// IsOnCurve returns true if p in on the curve +// IsOnCurve returns true if the affine point p in on the curve. func (p *G2Affine) IsOnCurve() bool { - var point G2Jac - point.FromAffine(p) - return point.IsOnCurve() // call this function to handle infinity point + if p.IsInfinity() { + return true + } + var left, right fptower.E2 + left.Square(&p.Y) + right.Square(&p.X).Mul(&right, &p.X) + right.Add(&right, &bTwistCurveCoeff) + return left.Equal(&right) } -// IsInSubGroup returns true if p is in the correct subgroup, false otherwise +// IsInSubGroup returns true if the affine point p is in the correct subgroup, false otherwise. func (p *G2Affine) IsInSubGroup() bool { var _p G2Jac _p.FromAffine(p) @@ -163,84 +205,76 @@ func (p *G2Affine) IsInSubGroup() bool { } // ------------------------------------------------------------------------------------------------- -// Jacobian +// Jacobian coordinates -// Set sets p to the provided point -func (p *G2Jac) Set(a *G2Jac) *G2Jac { - p.X, p.Y, p.Z = a.X, a.Y, a.Z +// Set sets p to a in Jacobian coordinates. +func (p *G2Jac) Set(q *G2Jac) *G2Jac { + p.X, p.Y, p.Z = q.X, q.Y, q.Z return p } -// Equal tests if two points (in Jacobian coordinates) are equal -func (p *G2Jac) Equal(a *G2Jac) bool { +// Equal tests if two points in Jacobian coordinates are equal. +func (p *G2Jac) Equal(q *G2Jac) bool { // If one point is infinity, the other must also be infinity. if p.Z.IsZero() { - return a.Z.IsZero() + return q.Z.IsZero() } // If the other point is infinity, return false since we can't // the following checks would be incorrect. - if a.Z.IsZero() { + if q.Z.IsZero() { return false } var pZSquare, aZSquare fptower.E2 pZSquare.Square(&p.Z) - aZSquare.Square(&a.Z) + aZSquare.Square(&q.Z) var lhs, rhs fptower.E2 lhs.Mul(&p.X, &aZSquare) - rhs.Mul(&a.X, &pZSquare) + rhs.Mul(&q.X, &pZSquare) if !lhs.Equal(&rhs) { return false } - lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &a.Z) - rhs.Mul(&a.Y, &pZSquare).Mul(&rhs, &p.Z) + lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &q.Z) + rhs.Mul(&q.Y, &pZSquare).Mul(&rhs, &p.Z) return lhs.Equal(&rhs) } -// Neg computes -G -func (p *G2Jac) Neg(a *G2Jac) *G2Jac { - *p = *a - p.Y.Neg(&a.Y) +// Neg sets p to the Jacobian negative point -q = (q.X, -q.Y, q.Z). +func (p *G2Jac) Neg(q *G2Jac) *G2Jac { + *p = *q + p.Y.Neg(&q.Y) return p } -// SubAssign subtracts two points on the curve -func (p *G2Jac) SubAssign(a *G2Jac) *G2Jac { - var tmp G2Jac - tmp.Set(a) - tmp.Y.Neg(&tmp.Y) - p.AddAssign(&tmp) - return p -} - -// AddAssign point addition in montgomery form +// AddAssign sets p to p+a in Jacobian coordinates. +// // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl -func (p *G2Jac) AddAssign(a *G2Jac) *G2Jac { +func (p *G2Jac) AddAssign(q *G2Jac) *G2Jac { - // p is infinity, return a + // p is infinity, return q if p.Z.IsZero() { - p.Set(a) + p.Set(q) return p } - // a is infinity, return p - if a.Z.IsZero() { + // q is infinity, return p + if q.Z.IsZero() { return p } var Z1Z1, Z2Z2, U1, U2, S1, S2, H, I, J, r, V fptower.E2 - Z1Z1.Square(&a.Z) + Z1Z1.Square(&q.Z) Z2Z2.Square(&p.Z) - U1.Mul(&a.X, &Z2Z2) + U1.Mul(&q.X, &Z2Z2) U2.Mul(&p.X, &Z1Z1) - S1.Mul(&a.Y, &p.Z). + S1.Mul(&q.Y, &p.Z). Mul(&S1, &Z2Z2) - S2.Mul(&p.Y, &a.Z). + S2.Mul(&p.Y, &q.Z). Mul(&S2, &Z1Z1) - // if p == a, we double instead + // if p == q, we double instead if U1.Equal(&U2) && S1.Equal(&S2) { return p.DoubleAssign() } @@ -259,7 +293,7 @@ func (p *G2Jac) AddAssign(a *G2Jac) *G2Jac { Mul(&p.Y, &r) S1.Mul(&S1, &J).Double(&S1) p.Y.Sub(&p.Y, &S1) - p.Z.Add(&p.Z, &a.Z) + p.Z.Add(&p.Z, &q.Z) p.Z.Square(&p.Z). Sub(&p.Z, &Z1Z1). Sub(&p.Z, &Z2Z2). @@ -268,7 +302,48 @@ func (p *G2Jac) AddAssign(a *G2Jac) *G2Jac { return p } -// AddMixed point addition +// SubAssign sets p to p-a in Jacobian coordinates. +// It uses a similar approach to AddAssign, but negates the point a before adding. +func (p *G2Jac) SubAssign(q *G2Jac) *G2Jac { + var tmp G2Jac + tmp.Set(q) + tmp.Y.Neg(&tmp.Y) + p.AddAssign(&tmp) + return p +} + +// Double sets p to [2]q in Jacobian coordinates. +// +// https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl +func (p *G2Jac) DoubleMixed(a *G2Affine) *G2Jac { + var XX, YY, YYYY, S, M, T fptower.E2 + XX.Square(&a.X) + YY.Square(&a.Y) + YYYY.Square(&YY) + S.Add(&a.X, &YY). + Square(&S). + Sub(&S, &XX). + Sub(&S, &YYYY). + Double(&S) + M.Double(&XX). + Add(&M, &XX) // -> + A, but A=0 here + T.Square(&M). + Sub(&T, &S). + Sub(&T, &S) + p.X.Set(&T) + p.Y.Sub(&S, &T). + Mul(&p.Y, &M) + YYYY.Double(&YYYY). + Double(&YYYY). + Double(&YYYY) + p.Y.Sub(&p.Y, &YYYY) + p.Z.Double(&a.Y) + + return p +} + +// AddMixed sets p to p+a in Jacobian coordinates, where a.Z = 1. +// // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-madd-2007-bl func (p *G2Jac) AddMixed(a *G2Affine) *G2Jac { @@ -292,7 +367,7 @@ func (p *G2Jac) AddMixed(a *G2Affine) *G2Jac { // if p == a, we double instead if U2.Equal(&p.X) && S2.Equal(&p.Y) { - return p.DoubleAssign() + return p.DoubleMixed(a) } H.Sub(&U2, &p.X) @@ -317,7 +392,8 @@ func (p *G2Jac) AddMixed(a *G2Affine) *G2Jac { return p } -// Double doubles a point in Jacobian coordinates +// Double sets p to [2]q in Jacobian coordinates. +// // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl func (p *G2Jac) Double(q *G2Jac) *G2Jac { p.Set(q) @@ -325,7 +401,8 @@ func (p *G2Jac) Double(q *G2Jac) *G2Jac { return p } -// DoubleAssign doubles a point in Jacobian coordinates +// DoubleAssign doubles p in Jacobian coordinates. +// // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl func (p *G2Jac) DoubleAssign() *G2Jac { @@ -357,43 +434,50 @@ func (p *G2Jac) DoubleAssign() *G2Jac { return p } -// ScalarMultiplication computes and returns p = a ⋅ s +// ScalarMultiplication computes and returns p = [s]a +// where p and a are Jacobian points. +// using the GLV technique. // see https://www.iacr.org/archive/crypto2001/21390189.pdf -func (p *G2Jac) ScalarMultiplication(a *G2Jac, s *big.Int) *G2Jac { - return p.mulGLV(a, s) +func (p *G2Jac) ScalarMultiplication(q *G2Jac, s *big.Int) *G2Jac { + return p.mulGLV(q, s) } -// String returns canonical representation of the point in affine coordinates +// ScalarMultiplicationBase computes and returns p = [s]g +// where g is the prime subgroup generator. +func (p *G2Jac) ScalarMultiplicationBase(s *big.Int) *G2Jac { + return p.mulGLV(&g2Gen, s) + +} + +// String converts p to affine coordinates and returns its string representation E(x,y) or "O" if it is infinity. func (p *G2Jac) String() string { _p := G2Affine{} _p.FromJacobian(p) return _p.String() } -// FromAffine sets p = Q, p in Jacobian, Q in affine -func (p *G2Jac) FromAffine(Q *G2Affine) *G2Jac { - if Q.IsInfinity() { +// FromAffine converts a point a from affine to Jacobian coordinates. +func (p *G2Jac) FromAffine(a *G2Affine) *G2Jac { + if a.IsInfinity() { p.Z.SetZero() p.X.SetOne() p.Y.SetOne() return p } p.Z.SetOne() - p.X.Set(&Q.X) - p.Y.Set(&Q.Y) + p.X.Set(&a.X) + p.Y.Set(&a.Y) return p } -// IsOnCurve returns true if p in on the curve +// IsOnCurve returns true if the Jacobian point p in on the curve. func (p *G2Jac) IsOnCurve() bool { - var left, right, tmp fptower.E2 + var left, right, tmp, ZZ fptower.E2 left.Square(&p.Y) right.Square(&p.X).Mul(&right, &p.X) - tmp.Square(&p.Z). - Square(&tmp). - Mul(&tmp, &p.Z). - Mul(&tmp, &p.Z). - Mul(&tmp, &bTwistCurveCoeff) + ZZ.Square(&p.Z) + tmp.Square(&ZZ).Mul(&tmp, &ZZ) + tmp.MulBybTwistCurveCoeff(&tmp) right.Add(&right, &tmp) return left.Equal(&right) } @@ -402,21 +486,24 @@ func (p *G2Jac) IsOnCurve() bool { // and https://eprint.iacr.org/2022/352.pdf, sec. 4.2 // ψ(p) = [x₀]P func (p *G2Jac) IsInSubGroup() bool { - var res, tmp G2Jac - tmp.psi(p) - res.ScalarMultiplication(p, &xGen). - SubAssign(&tmp) + if !p.IsOnCurve() { + return false + } + var res, img G2Jac + img.psi(p) + res.mulBySeed(p) - return res.IsOnCurve() && res.Z.IsZero() + return res.Equal(&img) } -// mulWindowed computes a 2-bits windowed scalar multiplication -func (p *G2Jac) mulWindowed(a *G2Jac, s *big.Int) *G2Jac { +// mulWindowed computes the 2-bits windowed double-and-add scalar +// multiplication p=[s]q in Jacobian coordinates. +func (p *G2Jac) mulWindowed(q *G2Jac, s *big.Int) *G2Jac { var res G2Jac var ops [3]G2Jac - ops[0].Set(a) + ops[0].Set(q) if s.Sign() == -1 { ops[0].Neg(&ops[0]) } @@ -443,26 +530,59 @@ func (p *G2Jac) mulWindowed(a *G2Jac, s *big.Int) *G2Jac { } -// ψ(p) = u o π o u⁻¹ where u:E'→E iso from the twist to E -func (p *G2Jac) psi(a *G2Jac) *G2Jac { - p.Set(a) +// mulBySeed multiplies the point q by the seed xGen in Jacobian coordinates +// using an optimized addition chain. +func (p *G2Jac) mulBySeed(q *G2Jac) *G2Jac { + // Generated by github.com/mmcloughlin/addchain v0.4.0. + // Operations: 61 doublings 7 additions + + // Allocate Temporaries. + var res, t0, t1 G2Jac + res.Double(q) + res.AddAssign(q) + res.Double(&res) + res.AddAssign(q) + t0.Double(&res) + for i := 1; i < 2; i++ { + t0.Double(&t0) + } + res.AddAssign(&t0) + t1.Double(&res) + t1.AddAssign(&res) + t0.AddAssign(&t1) + for i := 0; i < 10; i++ { + t0.Double(&t0) + } + res.AddAssign(&t0) + for i := 0; i < 46; i++ { + res.Double(&res) + } + res.AddAssign(q) + p.Set(&res) + return p +} + +// psi sets p to ψ(q) = u o π o u⁻¹ where u:E'→E is the isomorphism from the twist to the curve E and π is the Frobenius map. +func (p *G2Jac) psi(q *G2Jac) *G2Jac { + p.Set(q) p.X.Conjugate(&p.X).Mul(&p.X, &endo.u) p.Y.Conjugate(&p.Y).Mul(&p.Y, &endo.v) p.Z.Conjugate(&p.Z) return p } -// ϕ assigns p to ϕ(a) where ϕ: (x,y) → (w x,y), and returns p -// where w is a third root of unity in 𝔽p -func (p *G2Jac) phi(a *G2Jac) *G2Jac { - p.Set(a) +// phi sets p to ϕ(a) where ϕ: (x,y) → (w x,y), +// where w is a third root of unity. +func (p *G2Jac) phi(q *G2Jac) *G2Jac { + p.Set(q) p.X.MulByElement(&p.X, &thirdRootOneG2) return p } // mulGLV computes the scalar multiplication using a windowed-GLV method +// // see https://www.iacr.org/archive/crypto2001/21390189.pdf -func (p *G2Jac) mulGLV(a *G2Jac, s *big.Int) *G2Jac { +func (p *G2Jac) mulGLV(q *G2Jac, s *big.Int) *G2Jac { var table [15]G2Jac var res G2Jac @@ -470,11 +590,11 @@ func (p *G2Jac) mulGLV(a *G2Jac, s *big.Int) *G2Jac { res.Set(&g2Infinity) - // table[b3b2b1b0-1] = b3b2 ⋅ ϕ(a) + b1b0*a - table[0].Set(a) - table[3].phi(a) + // table[b3b2b1b0-1] = b3b2 ⋅ ϕ(q) + b1b0*q + table[0].Set(q) + table[3].phi(q) - // split the scalar, modifies ±a, ϕ(a) accordingly + // split the scalar, modifies ±q, ϕ(q) accordingly k := ecc.SplitScalar(s, &glvBasis) if k[0].Sign() == -1 { @@ -487,7 +607,7 @@ func (p *G2Jac) mulGLV(a *G2Jac, s *big.Int) *G2Jac { } // precompute table (2 bits sliding window) - // table[b3b2b1b0-1] = b3b2 ⋅ ϕ(a) + b1b0 ⋅ a if b3b2b1b0 != 0 + // table[b3b2b1b0-1] = b3b2 ⋅ ϕ(q) + b1b0 ⋅ q if b3b2b1b0 != 0 table[1].Double(&table[0]) table[2].Set(&table[1]).AddAssign(&table[0]) table[4].Set(&table[3]).AddAssign(&table[0]) @@ -543,23 +663,23 @@ func (p *G2Affine) ClearCofactor(a *G2Affine) *G2Affine { } // ClearCofactor maps a point in curve to r-torsion -func (p *G2Jac) ClearCofactor(a *G2Jac) *G2Jac { +func (p *G2Jac) ClearCofactor(q *G2Jac) *G2Jac { // https://eprint.iacr.org/2017/419.pdf, 4.1 var xg, xxg, res, t G2Jac - xg.ScalarMultiplication(a, &xGen) - xxg.ScalarMultiplication(&xg, &xGen) + xg.mulBySeed(q) + xxg.mulBySeed(&xg) res.Set(&xxg). SubAssign(&xg). - SubAssign(a) + SubAssign(q) t.Set(&xg). - SubAssign(a). + SubAssign(q). psi(&t) res.AddAssign(&t) - t.Double(a) + t.Double(q) t.X.MulByElement(&t.X, &thirdRootOneG1) res.SubAssign(&t) @@ -571,16 +691,16 @@ func (p *G2Jac) ClearCofactor(a *G2Jac) *G2Jac { } // ------------------------------------------------------------------------------------------------- -// Jacobian extended +// extended Jacobian coordinates -// Set sets p to the provided point -func (p *g2JacExtended) Set(a *g2JacExtended) *g2JacExtended { - p.X, p.Y, p.ZZ, p.ZZZ = a.X, a.Y, a.ZZ, a.ZZZ +// Set sets p to a in extended Jacobian coordinates. +func (p *g2JacExtended) Set(q *g2JacExtended) *g2JacExtended { + p.X, p.Y, p.ZZ, p.ZZZ = q.X, q.Y, q.ZZ, q.ZZZ return p } -// setInfinity sets p to O -func (p *g2JacExtended) setInfinity() *g2JacExtended { +// SetInfinity sets p to the infinity point (1,1,0,0). +func (p *g2JacExtended) SetInfinity() *g2JacExtended { p.X.SetOne() p.Y.SetOne() p.ZZ = fptower.E2{} @@ -588,43 +708,45 @@ func (p *g2JacExtended) setInfinity() *g2JacExtended { return p } -func (p *g2JacExtended) IsZero() bool { +// IsInfinity checks if the p is infinity, i.e. p.ZZ=0. +func (p *g2JacExtended) IsInfinity() bool { return p.ZZ.IsZero() } -// fromJacExtended sets Q in affine coordinates -func (p *G2Affine) fromJacExtended(Q *g2JacExtended) *G2Affine { - if Q.ZZ.IsZero() { +// fromJacExtended converts an extended Jacobian point to an affine point. +func (p *G2Affine) fromJacExtended(q *g2JacExtended) *G2Affine { + if q.ZZ.IsZero() { p.X = fptower.E2{} p.Y = fptower.E2{} return p } - p.X.Inverse(&Q.ZZ).Mul(&p.X, &Q.X) - p.Y.Inverse(&Q.ZZZ).Mul(&p.Y, &Q.Y) + p.X.Inverse(&q.ZZ).Mul(&p.X, &q.X) + p.Y.Inverse(&q.ZZZ).Mul(&p.Y, &q.Y) return p } -// fromJacExtended sets Q in Jacobian coordinates -func (p *G2Jac) fromJacExtended(Q *g2JacExtended) *G2Jac { - if Q.ZZ.IsZero() { +// fromJacExtended converts an extended Jacobian point to a Jacobian point. +func (p *G2Jac) fromJacExtended(q *g2JacExtended) *G2Jac { + if q.ZZ.IsZero() { p.Set(&g2Infinity) return p } - p.X.Mul(&Q.ZZ, &Q.X).Mul(&p.X, &Q.ZZ) - p.Y.Mul(&Q.ZZZ, &Q.Y).Mul(&p.Y, &Q.ZZZ) - p.Z.Set(&Q.ZZZ) + p.X.Mul(&q.ZZ, &q.X).Mul(&p.X, &q.ZZ) + p.Y.Mul(&q.ZZZ, &q.Y).Mul(&p.Y, &q.ZZZ) + p.Z.Set(&q.ZZZ) return p } -// unsafeFromJacExtended sets p in Jacobian coordinates, but don't check for infinity -func (p *G2Jac) unsafeFromJacExtended(Q *g2JacExtended) *G2Jac { - p.X.Square(&Q.ZZ).Mul(&p.X, &Q.X) - p.Y.Square(&Q.ZZZ).Mul(&p.Y, &Q.Y) - p.Z = Q.ZZZ +// unsafeFromJacExtended converts an extended Jacobian point, distinct from Infinity, to a Jacobian point. +func (p *G2Jac) unsafeFromJacExtended(q *g2JacExtended) *G2Jac { + p.X.Square(&q.ZZ).Mul(&p.X, &q.X) + p.Y.Square(&q.ZZZ).Mul(&p.Y, &q.Y) + p.Z = q.ZZZ return p } -// add point in Jacobian extended coordinates +// add sets p to p+q in extended Jacobian coordinates. +// // https://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-add-2008-s func (p *g2JacExtended) add(q *g2JacExtended) *g2JacExtended { //if q is infinity return p @@ -680,10 +802,11 @@ func (p *g2JacExtended) add(q *g2JacExtended) *g2JacExtended { return p } -// double point in Jacobian extended coordinates +// double sets p to [2]q in Jacobian extended coordinates. +// // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#doubling-dbl-2008-s-1 -// since we consider any point on Z=0 as the point at infinity -// this doubling formula works for infinity points as well +// N.B.: since we consider any point on Z=0 as the point at infinity +// this doubling formula works for infinity points as well. func (p *g2JacExtended) double(q *g2JacExtended) *g2JacExtended { var U, V, W, S, XX, M fptower.E2 @@ -693,7 +816,7 @@ func (p *g2JacExtended) double(q *g2JacExtended) *g2JacExtended { S.Mul(&q.X, &V) XX.Square(&q.X) M.Double(&XX). - Add(&M, &XX) // -> + a, but a=0 here + Add(&M, &XX) // -> + A, but A=0 here U.Mul(&W, &q.Y) p.X.Square(&M). @@ -708,9 +831,10 @@ func (p *g2JacExtended) double(q *g2JacExtended) *g2JacExtended { return p } -// subMixed same as addMixed, but will negate a.Y +// addMixed sets p to p+q in extended Jacobian coordinates, where a.ZZ=1. +// // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-madd-2008-s -func (p *g2JacExtended) subMixed(a *G2Affine) *g2JacExtended { +func (p *g2JacExtended) addMixed(a *G2Affine) *g2JacExtended { //if a is infinity return p if a.IsInfinity() { @@ -719,7 +843,7 @@ func (p *g2JacExtended) subMixed(a *G2Affine) *g2JacExtended { // p is infinity, return a if p.ZZ.IsZero() { p.X = a.X - p.Y.Neg(&a.Y) + p.Y = a.Y p.ZZ.SetOne() p.ZZZ.SetOne() return p @@ -732,12 +856,11 @@ func (p *g2JacExtended) subMixed(a *G2Affine) *g2JacExtended { P.Sub(&P, &p.X) R.Mul(&a.Y, &p.ZZZ) - R.Neg(&R) R.Sub(&R, &p.Y) if P.IsZero() { if R.IsZero() { - return p.doubleNegMixed(a) + return p.doubleMixed(a) } p.ZZ = fptower.E2{} @@ -764,9 +887,10 @@ func (p *g2JacExtended) subMixed(a *G2Affine) *g2JacExtended { } -// addMixed +// subMixed works the same as addMixed, but negates a.Y. +// // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-madd-2008-s -func (p *g2JacExtended) addMixed(a *G2Affine) *g2JacExtended { +func (p *g2JacExtended) subMixed(a *G2Affine) *g2JacExtended { //if a is infinity return p if a.IsInfinity() { @@ -775,7 +899,7 @@ func (p *g2JacExtended) addMixed(a *G2Affine) *g2JacExtended { // p is infinity, return a if p.ZZ.IsZero() { p.X = a.X - p.Y = a.Y + p.Y.Neg(&a.Y) p.ZZ.SetOne() p.ZZZ.SetOne() return p @@ -788,11 +912,12 @@ func (p *g2JacExtended) addMixed(a *G2Affine) *g2JacExtended { P.Sub(&P, &p.X) R.Mul(&a.Y, &p.ZZZ) + R.Neg(&R) R.Sub(&R, &p.Y) if P.IsZero() { if R.IsZero() { - return p.doubleMixed(a) + return p.doubleNegMixed(a) } p.ZZ = fptower.E2{} @@ -819,21 +944,21 @@ func (p *g2JacExtended) addMixed(a *G2Affine) *g2JacExtended { } -// doubleNegMixed same as double, but will negate q.Y -func (p *g2JacExtended) doubleNegMixed(q *G2Affine) *g2JacExtended { +// doubleNegMixed works the same as double, but negates q.Y. +func (p *g2JacExtended) doubleNegMixed(a *G2Affine) *g2JacExtended { var U, V, W, S, XX, M, S2, L fptower.E2 - U.Double(&q.Y) + U.Double(&a.Y) U.Neg(&U) V.Square(&U) W.Mul(&U, &V) - S.Mul(&q.X, &V) - XX.Square(&q.X) + S.Mul(&a.X, &V) + XX.Square(&a.X) M.Double(&XX). - Add(&M, &XX) // -> + a, but a=0 here + Add(&M, &XX) // -> + A, but A=0 here S2.Double(&S) - L.Mul(&W, &q.Y) + L.Mul(&W, &a.Y) p.X.Square(&M). Sub(&p.X, &S2) @@ -846,21 +971,22 @@ func (p *g2JacExtended) doubleNegMixed(q *G2Affine) *g2JacExtended { return p } -// doubleMixed point in Jacobian extended coordinates +// doubleMixed sets p to [2]a in Jacobian extended coordinates, where a.ZZ=1. +// // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#doubling-dbl-2008-s-1 -func (p *g2JacExtended) doubleMixed(q *G2Affine) *g2JacExtended { +func (p *g2JacExtended) doubleMixed(a *G2Affine) *g2JacExtended { var U, V, W, S, XX, M, S2, L fptower.E2 - U.Double(&q.Y) + U.Double(&a.Y) V.Square(&U) W.Mul(&U, &V) - S.Mul(&q.X, &V) - XX.Square(&q.X) + S.Mul(&a.X, &V) + XX.Square(&a.X) M.Double(&XX). - Add(&M, &XX) // -> + a, but a=0 here + Add(&M, &XX) // -> + A, but A=0 here S2.Double(&S) - L.Mul(&W, &q.Y) + L.Mul(&W, &a.Y) p.X.Square(&M). Sub(&p.X, &S2) @@ -874,38 +1000,38 @@ func (p *g2JacExtended) doubleMixed(q *G2Affine) *g2JacExtended { } // ------------------------------------------------------------------------------------------------- -// Homogenous projective +// Homogenous projective coordinates -// Set sets p to the provided point -func (p *g2Proj) Set(a *g2Proj) *g2Proj { - p.x, p.y, p.z = a.x, a.y, a.z +// Set sets p to a in projective coordinates. +func (p *g2Proj) Set(q *g2Proj) *g2Proj { + p.x, p.y, p.z = q.x, q.y, q.z return p } -// Neg computes -G -func (p *g2Proj) Neg(a *g2Proj) *g2Proj { - *p = *a - p.y.Neg(&a.y) +// Neg sets p to the projective negative point -q = (q.X, -q.Y). +func (p *g2Proj) Neg(q *g2Proj) *g2Proj { + *p = *q + p.y.Neg(&q.y) return p } -// FromAffine sets p = Q, p in homogenous projective, Q in affine -func (p *g2Proj) FromAffine(Q *G2Affine) *g2Proj { - if Q.X.IsZero() && Q.Y.IsZero() { +// FromAffine converts q in affine to p in projective coordinates. +func (p *g2Proj) FromAffine(a *G2Affine) *g2Proj { + if a.X.IsZero() && a.Y.IsZero() { p.z.SetZero() p.x.SetOne() p.y.SetOne() return p } p.z.SetOne() - p.x.Set(&Q.X) - p.y.Set(&Q.Y) + p.x.Set(&a.X) + p.y.Set(&a.Y) return p } // BatchScalarMultiplicationG2 multiplies the same base by all scalars // and return resulting points in affine coordinates -// uses a simple windowed-NAF like exponentiation algorithm +// uses a simple windowed-NAF-like multiplication algorithm. func BatchScalarMultiplicationG2(base *G2Affine, scalars []fr.Element) []G2Affine { // approximate cost in group ops is // cost = 2^{c-1} + n(scalar.nbBits+nbChunks) @@ -984,18 +1110,29 @@ func BatchScalarMultiplicationG2(base *G2Affine, scalars []fr.Element) []G2Affin return toReturn } -// batch add affine coordinates -// using batch inversion -// special cases (doubling, infinity) must be filtered out before this call +// batchAddG2Affine adds affine points using the Montgomery batch inversion trick. +// Special cases (doubling, infinity) must be filtered out before this call. func batchAddG2Affine[TP pG2Affine, TPP ppG2Affine, TC cG2Affine](R *TPP, P *TP, batchSize int) { var lambda, lambdain TC - // add part + // from https://docs.zkproof.org/pages/standards/accepted-workshop3/proposal-turbo_plonk.pdf + // affine point addition formula + // R(X1, Y1) + P(X2, Y2) = Q(X3, Y3) + // λ = (Y2 - Y1) / (X2 - X1) + // X3 = λ² - (X1 + X2) + // Y3 = λ * (X1 - X3) - Y1 + + // first we compute the 1 / (X2 - X1) for all points using Montgomery batch inversion trick + + // X2 - X1 for j := 0; j < batchSize; j++ { lambdain[j].Sub(&(*P)[j].X, &(*R)[j].X) } - // invert denominator using montgomery batch invert technique + // montgomery batch inversion; + // lambda[0] = 1 / (P[0].X - R[0].X) + // lambda[1] = 1 / (P[1].X - R[1].X) + // ... { var accumulator fptower.E2 lambda[0].SetOne() @@ -1015,22 +1152,41 @@ func batchAddG2Affine[TP pG2Affine, TPP ppG2Affine, TC cG2Affine](R *TPP, P *TP, lambda[0].Set(&accumulator) } - var d fptower.E2 - var rr G2Affine + var t fptower.E2 + var Q G2Affine - // add part for j := 0; j < batchSize; j++ { - // computa lambda - d.Sub(&(*P)[j].Y, &(*R)[j].Y) - lambda[j].Mul(&lambda[j], &d) - - // compute X, Y - rr.X.Square(&lambda[j]) - rr.X.Sub(&rr.X, &(*R)[j].X) - rr.X.Sub(&rr.X, &(*P)[j].X) - d.Sub(&(*R)[j].X, &rr.X) - rr.Y.Mul(&lambda[j], &d) - rr.Y.Sub(&rr.Y, &(*R)[j].Y) - (*R)[j].Set(&rr) + // λ = (Y2 - Y1) / (X2 - X1) + t.Sub(&(*P)[j].Y, &(*R)[j].Y) + lambda[j].Mul(&lambda[j], &t) + + // X3 = λ² - (X1 + X2) + Q.X.Square(&lambda[j]) + Q.X.Sub(&Q.X, &(*R)[j].X) + Q.X.Sub(&Q.X, &(*P)[j].X) + + // Y3 = λ * (X1 - X3) - Y1 + t.Sub(&(*R)[j].X, &Q.X) + Q.Y.Mul(&lambda[j], &t) + Q.Y.Sub(&Q.Y, &(*R)[j].Y) + + (*R)[j].Set(&Q) } } + +// RandomOnG2 produces a random point in G2 +// using standard map-to-curve methods, which means the relative discrete log +// of the generated point with respect to the canonical generator is not known. +func RandomOnG2() (G2Affine, error) { + if gBytes, err := randomFrSizedBytes(); err != nil { + return G2Affine{}, err + } else { + return HashToG2(gBytes, []byte("random on g2")) + } +} + +func randomFrSizedBytes() ([]byte, error) { + res := make([]byte, fr.Bytes) + _, err := rand.Read(res) + return res, err +} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/hash_to_curve/g1.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/hash_to_curve/g1.go new file mode 100644 index 00000000000..2b9ae3ecfab --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/hash_to_curve/g1.go @@ -0,0 +1,219 @@ +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package hash_to_curve + +import ( + "math/big" + + "github.com/consensys/gnark-crypto/ecc/bls12-377/fp" +) + +// Note: This only works for simple extensions + +var ( + g1sswuCurveACoeff = fp.Element{17252667382019449424, 8408110001211059699, 18415587021986261264, 10797086888535946954, 9462758283094809199, 54995354010328751} + g1sswuCurveBCoeff = fp.Element{11130294635325289193, 6502679372128844082, 15863297759487624914, 16270683149854112145, 3560014356538878812, 27923742146399959} +) + +var g1sswuCurveZ = fp.Element{9871116327010172167, 9167007004823125620, 18338974479346628539, 5649234265355377548, 13442091487463296847, 77904398905292312} + +// G1SSWUCurveCoefficients returns the coefficients of the SSWU curve. +func G1SSWUIsogenyCurveCoefficients() (A fp.Element, B fp.Element) { + return g1sswuCurveACoeff, g1sswuCurveBCoeff +} + +// G1SSWUIsogenyZ returns the recommended Z value of the SSWU curve. +// +// See https://www.rfc-editor.org/rfc/rfc9380.html#weierstrass +func G1SSWUIsogenyZ() fp.Element { + return g1sswuCurveZ +} + +var ( + g1IsogenyXNumeratorMap = []fp.Element{ + {9381318728011785451, 8795417190580748876, 15171640721257608922, 11815547924113428908, 15499908520243100994, 75408755324413256}, + {12414498063752772717, 9915153185132073893, 5598625970987438951, 3342254783599619135, 3349592178919125510, 9993871847068096}, + {4662210776746950618, 10687085762534440940, 7484820859645808636, 2221301482234255553, 10609677459585442106, 9950135580589350}, + } + g1IsogenyXDenominatorMap = []fp.Element{ + {12764504107591987636, 2767124593109192342, 3947759810240204190, 13369019134398476541, 13398368715676502040, 39975487388272384}, + } + g1IsogenyYNumeratorMap = []fp.Element{ + {13844135623281082635, 637899392157745290, 5176720401210677272, 4780940929980393029, 13803251044890140836, 51447363642369244}, + {512010462697120695, 609509684909242946, 13763343875136563934, 2839514380057330869, 15407015190976871917, 114223893455203604}, + {14191436515319700132, 6479619458373647736, 9513056055282499867, 15178407828209519654, 12166396751953702822, 75539964123849493}, + {2331105388373475309, 5343542881267220470, 12965782466677680126, 1110650741117127776, 5304838729792721053, 4975067790294675}, + } + g1IsogenyYDenominatorMap = []fp.Element{ + {8694832399336342723, 13482963304561246841, 6984108042366343277, 8355250559073919616, 16937021447778317421, 44890599540624877}, + {1100361703846424922, 5005767817281133373, 917019320419705433, 14251746270386956490, 5522097789867984932, 4443041874334878}, + {1400024175356859676, 8301373779327577028, 11843279430720612570, 3213569255776326391, 3301617999610402890, 119926462164817154}, + } +) + +// G1IsogenyMap returns the isogeny map for the curve. +// The isogeny map is a list of polynomial coefficients for the x and y coordinate computation. +// The order of the coefficients is as follows: +// - x numerator, x denominator, y numerator, y denominator. +func G1IsogenyMap() [4][]fp.Element { + return [4][]fp.Element{ + g1IsogenyXNumeratorMap, + g1IsogenyXDenominatorMap, + g1IsogenyYNumeratorMap, + g1IsogenyYDenominatorMap, + } +} + +func g1IsogenyXNumerator(dst *fp.Element, x *fp.Element) { + g1EvalPolynomial(dst, false, g1IsogenyXNumeratorMap, x) +} + +func g1IsogenyXDenominator(dst *fp.Element, x *fp.Element) { + g1EvalPolynomial(dst, true, g1IsogenyXDenominatorMap, x) +} + +func g1IsogenyYNumerator(dst *fp.Element, x *fp.Element, y *fp.Element) { + var _dst fp.Element + g1EvalPolynomial(&_dst, false, g1IsogenyYNumeratorMap, x) + dst.Mul(&_dst, y) +} + +func g1IsogenyYDenominator(dst *fp.Element, x *fp.Element) { + g1EvalPolynomial(dst, true, g1IsogenyYDenominatorMap, x) +} + +// G1 computes the isogeny map of the curve element, given by its coordinates pX and pY. +// It mutates the coordinates pX and pY to the new coordinates of the isogeny map. +func G1Isogeny(pX, pY *fp.Element) { + + den := make([]fp.Element, 2) + + g1IsogenyYDenominator(&den[1], pX) + g1IsogenyXDenominator(&den[0], pX) + + g1IsogenyYNumerator(pY, pX, pY) + g1IsogenyXNumerator(pX, pX) + + den = fp.BatchInvert(den) + + pX.Mul(pX, &den[0]) + pY.Mul(pY, &den[1]) +} + +// G1SqrtRatio computes the square root of u/v and returns 0 iff u/v was indeed a quadratic residue. +// If not, we get sqrt(Z * u / v). Recall that Z is non-residue. +// If v = 0, u/v is meaningless and the output is unspecified, without raising an error. +// The main idea is that since the computation of the square root involves taking large powers of u/v, the inversion of v can be avoided +func G1SqrtRatio(z *fp.Element, u *fp.Element, v *fp.Element) uint64 { + + // https://www.rfc-editor.org/rfc/rfc9380.html#name-sqrt_ratio-for-any-field + + tv1 := fp.Element{7563926049028936178, 2688164645460651601, 12112688591437172399, 3177973240564633687, 14764383749841851163, 52487407124055189} //tv1 = c6 + + var tv2, tv3, tv4, tv5 fp.Element + var exp big.Int + // c4 = 70368744177663 = 2⁴⁶ - 1 + // q is odd so c1 is at least 1. + exp.SetBytes([]byte{63, 255, 255, 255, 255, 255}) + + tv2.Exp(*v, &exp) // 2. tv2 = vᶜ⁴ + tv3.Square(&tv2) // 3. tv3 = tv2² + tv3.Mul(&tv3, v) // 4. tv3 = tv3 * v + tv5.Mul(u, &tv3) // 5. tv5 = u * tv3 + + // c3 = 1837921289030710838195067919506396475074392872918698035817074744121558668640693829665401097909504529 + exp.SetBytes([]byte{3, 92, 116, 140, 47, 138, 33, 213, 140, 118, 11, 128, 217, 66, 146, 118, 52, 69, 179, 230, 1, 234, 39, 30, 61, 230, 196, 95, 116, 18, 144, 0, 46, 22, 186, 136, 96, 0, 0, 1, 10, 17}) + + tv5.Exp(tv5, &exp) // 6. tv5 = tv5ᶜ³ + tv5.Mul(&tv5, &tv2) // 7. tv5 = tv5 * tv2 + tv2.Mul(&tv5, v) // 8. tv2 = tv5 * v + tv3.Mul(&tv5, u) // 9. tv3 = tv5 * u + tv4.Mul(&tv3, &tv2) // 10. tv4 = tv3 * tv2 + + // c5 = 35184372088832 + exp.SetBytes([]byte{32, 0, 0, 0, 0, 0}) + tv5.Exp(tv4, &exp) // 11. tv5 = tv4ᶜ⁵ + isQNr := g1NotOne(&tv5) // 12. isQR = tv5 == 1 + c7 := fp.Element{13262060633605929793, 16269117706405780335, 1787999441809606207, 11078968899094441280, 17534011895423012165, 96686002316065324} + tv2.Mul(&tv3, &c7) // 13. tv2 = tv3 * c7 + tv5.Mul(&tv4, &tv1) // 14. tv5 = tv4 * tv1 + tv3.Select(int(isQNr), &tv3, &tv2) // 15. tv3 = CMOV(tv2, tv3, isQR) + tv4.Select(int(isQNr), &tv4, &tv5) // 16. tv4 = CMOV(tv5, tv4, isQR) + exp.Lsh(big.NewInt(1), 46-2) // 18, 19: tv5 = 2ⁱ⁻² for i = c1 + + for i := 46; i >= 2; i-- { // 17. for i in (c1, c1 - 1, ..., 2): + + tv5.Exp(tv4, &exp) // 20. tv5 = tv4ᵗᵛ⁵ + nE1 := g1NotOne(&tv5) // 21. e1 = tv5 == 1 + tv2.Mul(&tv3, &tv1) // 22. tv2 = tv3 * tv1 + tv1.Mul(&tv1, &tv1) // 23. tv1 = tv1 * tv1 Why not write square? + tv5.Mul(&tv4, &tv1) // 24. tv5 = tv4 * tv1 + tv3.Select(int(nE1), &tv3, &tv2) // 25. tv3 = CMOV(tv2, tv3, e1) + tv4.Select(int(nE1), &tv4, &tv5) // 26. tv4 = CMOV(tv5, tv4, e1) + + if i > 2 { + exp.Rsh(&exp, 1) // 18, 19. tv5 = 2ⁱ⁻² + } + } + + *z = tv3 + return isQNr +} + +func g1NotOne(x *fp.Element) uint64 { + + var one fp.Element + return one.SetOne().NotEqual(x) + +} + +// G1MulByZ multiplies x by [5] and stores the result in z +func G1MulByZ(z *fp.Element, x *fp.Element) { + + res := *x + + res.Double(&res) + res.Double(&res) + res.Add(&res, x) + + *z = res +} + +func g1EvalPolynomial(z *fp.Element, monic bool, coefficients []fp.Element, x *fp.Element) { + dst := coefficients[len(coefficients)-1] + + if monic { + dst.Add(&dst, x) + } + + for i := len(coefficients) - 2; i >= 0; i-- { + dst.Mul(&dst, x) + dst.Add(&dst, &coefficients[i]) + } + + z.Set(&dst) +} + +// G1Sgn0 is an algebraic substitute for the notion of sign in ordered fields. +// Namely, every non-zero quadratic residue in a finite field of characteristic =/= 2 has exactly two square roots, one of each sign. +// +// See: https://www.rfc-editor.org/rfc/rfc9380.html#name-the-sgn0-function +// +// The sign of an element is not obviously related to that of its Montgomery form +func G1Sgn0(z *fp.Element) uint64 { + + nonMont := z.Bits() + + // m == 1 + return nonMont[0] % 2 + +} + +func G1NotZero(x *fp.Element) uint64 { + + return x[0] | x[1] | x[2] | x[3] | x[4] | x[5] + +} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/hash_to_curve/g2.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/hash_to_curve/g2.go new file mode 100644 index 00000000000..23c1dd5fb1b --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/hash_to_curve/g2.go @@ -0,0 +1,690 @@ +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package hash_to_curve + +import ( + "math/big" + + "github.com/consensys/gnark-crypto/ecc/bls12-377/fp" + "github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower" +) + +// Note: This only works for simple extensions + +var ( + g2sswuCurveACoeff = fptower.E2{ + A0: fp.Element{4274545572028848265, 14157081418478689358, 13123833976752631407, 4466041663276938746, 9062541850312583986, 90030181981586611}, + A1: fp.Element{4627353644986202063, 14941155654691983603, 14266958733709189881, 10264689865410103271, 10052798319587953375, 111844286035220969}, + } + g2sswuCurveBCoeff = fptower.E2{ + A0: fp.Element{10237434857876739089, 8476639787604822147, 6641637803208190023, 1721529389316620686, 8656544759275761743, 38999476160258021}, + A1: fp.Element{2360755569119276357, 10390833517265838837, 12467133771585386911, 8219721226907645480, 3130947551623757939, 83517800164149569}, + } +) + +var g2sswuCurveZ = fptower.E2{ + A0: fp.Element{10560307807486212317, 9936456306313395274, 2092561269709285211, 8738829082964617622, 5243865315912343348, 114311569748804731}, + A1: fp.Element{202099033278250856, 5854854902718660529, 11492539364873682930, 8885205928937022213, 5545221690922665192, 39800542322357402}, +} + +// G2SSWUCurveCoefficients returns the coefficients of the SSWU curve. +func G2SSWUIsogenyCurveCoefficients() (A fptower.E2, B fptower.E2) { + return g2sswuCurveACoeff, g2sswuCurveBCoeff +} + +// G2SSWUIsogenyZ returns the recommended Z value of the SSWU curve. +// +// See https://www.rfc-editor.org/rfc/rfc9380.html#weierstrass +func G2SSWUIsogenyZ() fptower.E2 { + return g2sswuCurveZ +} + +var ( + g2IsogenyXNumeratorMap = []fptower.E2{ + { + A0: fp.Element{3551783286045471771, 15672698349814166255, 7201714524012399751, 9685135133462022557, 11459791422433132438, 34279211894444158}, + A1: fp.Element{6733784119909728882, 8027365598504339614, 9826395261252013434, 17766961605401961078, 16718790361550578585, 8827310132881948}, + }, + { + A0: fp.Element{10039326048219096853, 8025585753053690704, 15692757884719051200, 14081267914923412694, 12483400733579637594, 41501995942887693}, + A1: fp.Element{3285050121746765179, 16424976010740556635, 13525960835401060630, 8230390587856081588, 332312595686915068, 58693565636984574}, + }, + { + A0: fp.Element{17569899329826403508, 9637548884483664645, 11559603533194429416, 509473447889017775, 16843450937194425803, 11820413515158522}, + A1: fp.Element{18082143759519379917, 7350976797508953919, 8718515184478260262, 11424641547646470649, 12610734036362352161, 109931236078585740}, + }, + { + A0: fp.Element{14344095877598929896, 14770204065590636976, 13870643972022067464, 14327299415926938990, 2100218127689809229, 111985606372347998}, + A1: fp.Element{18166912950538149334, 7903342274102247275, 11235613814926762637, 6048582781848067329, 9865957781737849443, 72257053590751229}, + }, + { + A0: fp.Element{9289693438943775070, 611273684478921638, 3161020385710416475, 2286858861996231773, 14631078872284738786, 101751379483637100}, + A1: fp.Element{218371821390517888, 3239557307852648611, 7956123978234311251, 4433191957359481551, 7602230667186897987, 36183482319693410}, + }, + { + A0: fp.Element{7524026848147356443, 15899508093607509001, 9269755160329214834, 12526651159477248728, 3756002781809695765, 101164747683440023}, + A1: fp.Element{6220885675233469595, 1070578225745722143, 9028649589122227273, 241265531361573072, 17722097355684345537, 59426317598728635}, + }, + { + A0: fp.Element{1147337684740884862, 11995598217907408439, 6334092051568104396, 4490620767408292574, 16484486820571077628, 32056264099725884}, + A1: fp.Element{1626504798254052117, 15843967556282260399, 3222912561813979091, 1092398256542226755, 15613117580878270463, 35759440311789519}, + }, + { + A0: fp.Element{9456818710433496904, 8738575976265225627, 17481785322204872502, 10252666647792359788, 13007033241788380867, 54062177864773120}, + A1: fp.Element{7857657292788377886, 18159261954362575139, 6957043223229770024, 101887390030524213, 7411469664095682342, 17462521019270966}, + }, + { + A0: fp.Element{5935437080311313022, 4869272223104979307, 14892623520420170949, 6274040211921387638, 190450687675494048, 100326942952217018}, + A1: fp.Element{4080141112519796596, 14389619698824585061, 15572076811388758383, 5573262239497616930, 5714216936392065098, 10910945353280475}, + }, + { + A0: fp.Element{12050383421129197508, 7679000367015579641, 4181895471589351098, 4488864303009131705, 1755297417051974713, 33780283701258651}, + A1: fp.Element{11393221592097145268, 10835918896706663346, 4746287363995169177, 6169630568067228482, 11259555703140136465, 52771734216395635}, + }, + { + A0: fp.Element{4577617767559140265, 568504000295320317, 4739467389388831592, 9537638546299567945, 11669151734363428413, 119097732794758712}, + A1: fp.Element{5691235310984308451, 13601281267571106288, 7819292534586961743, 11652278682059157182, 2231701566242469994, 110966193728844398}, + }, + { + A0: fp.Element{8957158313166077105, 5669155713645675267, 17333896861619738764, 4892240835897020648, 8492829473755858526, 70767002641220602}, + A1: fp.Element{8355305174234995113, 16726408794609999189, 6819868380250046496, 9302398329327482182, 3371252083110614225, 32903157732774708}, + }, + { + A0: fp.Element{3562726361589542410, 15642076536163677636, 3828009540728039550, 5513538145598570884, 1202255355797680138, 19209968154720986}, + A1: fp.Element{2433342667414904247, 14430646666116795259, 7881503288178112304, 10086912537277758921, 14321155618236575013, 84224128485096326}, + }, + { + A0: fp.Element{7543845460144717594, 14101022520017632284, 6419288061290617259, 11326768478076341964, 18432026940412127132, 85359846879027793}, + A1: fp.Element{17142157839755119212, 5159976764710014065, 6393633352893279233, 8672509349035392886, 7859431465567482570, 62163334379266093}, + }, + { + A0: fp.Element{2954881934412060022, 10898916794193723070, 10915833338735408379, 703491535562714344, 14589964434689495439, 90051679935520087}, + A1: fp.Element{18417998714611085978, 11039054240270137506, 9972891257774348246, 13263552626589315210, 4522668809484918556, 63885995997825101}, + }, + { + A0: fp.Element{9864134077459603571, 12525567282624341376, 5205345924937688700, 12649124091757575439, 14636003906379491067, 96025183135833306}, + A1: fp.Element{10316403063861314867, 10750711173072110600, 4513675589861596212, 2635673197095740125, 16720951430549947037, 31390298180493148}, + }, + { + A0: fp.Element{3003952238586646516, 3250841642932517220, 7061834734009117554, 16259415476002355236, 1626926148029432162, 77189086665928784}, + A1: fp.Element{14450051585993059472, 11823315281584113748, 6929304997500454604, 15344892292748160673, 15787768514545706202, 69813057053620435}, + }, + { + A0: fp.Element{4228110392233474072, 18010581486575392207, 13699345898545483049, 17704744337446085874, 5487913134051621310, 112205105149111207}, + A1: fp.Element{14824585485470590037, 7637124239293942071, 1041102438278370701, 4207950142422409777, 9639439542389544094, 106832755917361143}, + }, + { + A0: fp.Element{10744145886747796703, 8741979218876153119, 4537642647264646058, 9645243825719833866, 16643801652280184094, 57528843479739428}, + A1: fp.Element{5785935421797206370, 847985697064985249, 11478142027129258160, 12741057482356268413, 10148591557028647803, 106797667835022069}, + }, + { + A0: fp.Element{6454832842704992412, 9977685523482313420, 413111938383295655, 13594952949000658414, 17807487788385728582, 108984464456649540}, + A1: fp.Element{17048359867690489456, 2859252502285541521, 10818623701995947153, 7550564651763690537, 459333235977057482, 37663478480017988}, + }, + { + A0: fp.Element{8658783637463168087, 13532094408327228336, 12875492560745818922, 6809856611120372218, 2853890452345629690, 87034840621524077}, + A1: fp.Element{16301307707120111515, 9104654412985804807, 12475785366789695268, 4024450921325678435, 5626908908910088752, 56687303925216568}, + }, + { + A0: fp.Element{9729408098285946449, 14379177692720606450, 15077053755146607368, 1299576162980711320, 13990524355831736308, 88070216003513722}, + A1: fp.Element{5766436769337206504, 1093294963802231624, 1118315683159380206, 16238633443172785277, 5463682062430385614, 116508026946667814}, + }, + { + A0: fp.Element{16584249698770136319, 8326278446225484560, 3131917383401484830, 4756633391835977312, 7642636045510739113, 6547192373501023}, + A1: fp.Element{10803045440816594384, 6133821182275761752, 7762705812675926549, 15035799326051880159, 10201360843527298396, 76693252438359195}, + }, + { + A0: fp.Element{3621702609341817994, 1179514540952803843, 9695126383219869545, 4861853798003230532, 15648444733987506481, 103088924877589738}, + A1: fp.Element{0}, + }, + } + g2IsogenyXDenominatorMap = []fptower.E2{ + { + A0: fp.Element{1063048776114699222, 13419136991291290443, 17670140655952814712, 17007170270485437006, 2714055472280753035, 14919040757258909}, + A1: fp.Element{16666868668043867029, 10413023948165423527, 2513282340300795191, 5135056029366772344, 18074639060500180041, 66260525510488187}, + }, + { + A0: fp.Element{10940415603117103310, 2845175453419864190, 16971099885047235913, 4517542951822462583, 12015180195047358700, 101962474939260879}, + A1: fp.Element{1812172074217037271, 9040376510937171745, 1548369375982775200, 5323713323104515663, 11625954855074087334, 4220230277540083}, + }, + { + A0: fp.Element{8797262280793960976, 17802450974932240081, 10157003283304584770, 593225980605733121, 14184353532500093055, 108979035901112461}, + A1: fp.Element{15554837140147424903, 1512405638789788986, 3262333938884419786, 4638305243452530609, 139542405126620667, 54024907639584882}, + }, + { + A0: fp.Element{11424716963860540790, 13456329776215064369, 1929697779149270213, 6306593112502705131, 13859057472975507250, 41785102954052035}, + A1: fp.Element{7602541488494927932, 4897344463908346766, 17005994653424089316, 17216735712046963938, 3756018940504096168, 5402674048264985}, + }, + { + A0: fp.Element{2416535722849524790, 4831233808757576698, 17297774284520319797, 6772473332127607735, 18174962172090050489, 58994994344686536}, + A1: fp.Element{15610410799617712282, 9543692017702705957, 8970286522052539731, 12714219237879632746, 2449975609997710437, 10121059733973512}, + }, + { + A0: fp.Element{15388608950644940213, 15178518612850901922, 4663566445208062329, 3999751164791233677, 7358895960008222342, 33044898311505685}, + A1: fp.Element{2356569524239497521, 4634121806982763800, 13294827248503187097, 18379906191200424608, 13949207972645393879, 37350653623873291}, + }, + { + A0: fp.Element{4970487283568561993, 8451944303783250587, 10744185545939488302, 297910826254460501, 5663064319185246782, 55864728573479562}, + A1: fp.Element{13676619861655804765, 9740179349809417716, 1447466405783296044, 7262347140551810932, 4460517809397706328, 48696693541469882}, + }, + { + A0: fp.Element{4218670501850515232, 1300837062036343562, 6322288902222626865, 2517640049285419442, 15933997662514683752, 35742655751559900}, + A1: fp.Element{8671399843829082486, 10727571055999201132, 18066412728811459184, 2077243532292929295, 18402906919639961112, 11053564656556137}, + }, + { + A0: fp.Element{13549293427847064273, 13454861990004702789, 12625716182603551974, 16289223817658875114, 709786698748164395, 79373748066056979}, + A1: fp.Element{9755261456181601166, 8062867867952015070, 11667298511884909423, 12783693965971962594, 5335701901003645771, 118924945769569072}, + }, + { + A0: fp.Element{5024330816113629597, 9162185537450801251, 14637535063833510048, 5042964231794706299, 10987285991634226322, 46336617111585333}, + A1: fp.Element{17451698037621354790, 10238258568486351103, 10306732172443683782, 16783673474705190959, 2366024509224094980, 27102949281362657}, + }, + { + A0: fp.Element{1779719694787807439, 13682444363499832102, 319805876265464201, 10878143779945294209, 5260570358490406259, 111384964548942529}, + A1: fp.Element{10364815279125342799, 5955681787042171859, 16259776976357711022, 698420282628335564, 14458917752432688041, 9951241155641633}, + }, + { + A0: fp.Element{9860169129499874274, 4710132861939245083, 16729683163954203081, 1163919786098698325, 16999533791398931846, 45007426249965870}, + A1: fp.Element{1554156753268998897, 13001788039766734041, 13083055690099472212, 15457335577166095794, 9225717367159961098, 40091861438122274}, + }, + { + A0: fp.Element{15170394446649694794, 515688257282406708, 7546053921359572147, 2040402108618036352, 14910633907967741865, 51620635462170312}, + A1: fp.Element{14097816726424606264, 12505549891408832791, 13993079436736795338, 10172463092702817360, 608991345474995671, 70034669163571313}, + }, + { + A0: fp.Element{4643108199199003526, 15736620484932148216, 15681664113334307244, 17299685843716562967, 13906356132799386736, 93346316071232156}, + A1: fp.Element{4605618257264761423, 18021103018327472901, 16108946406338519358, 9045268489748282166, 5059321869053749600, 110536556169650965}, + }, + { + A0: fp.Element{11517108407780568371, 7978619811691229504, 9264608640258152436, 8451802924690124465, 4675285626878377699, 109463398958344863}, + A1: fp.Element{3597960821476001565, 3759680844169152876, 14302414818654496990, 17433096654117785124, 17967041042193057544, 85366167313641495}, + }, + { + A0: fp.Element{9939822412604413185, 13452127979624463736, 5130248585009642508, 3885932386715663181, 5051687816649505884, 77901780572240613}, + A1: fp.Element{519763984047258436, 9600915485628319569, 15140529797299450996, 9971542775239334883, 8807015558507490608, 948222705021672}, + }, + { + A0: fp.Element{2827339587428175511, 6895834130469522434, 13331059522798479027, 13955187059915735579, 14378880524037078149, 37849146151734053}, + A1: fp.Element{5659129353366385472, 1315670479643534676, 5263307416551198333, 6925817959331280727, 2077163856293267360, 78059303625906606}, + }, + { + A0: fp.Element{12063007979636530410, 11856928215255593909, 11875394835884852884, 7779285203935234969, 6621016507099994054, 58081312732574672}, + A1: fp.Element{16883486087598545310, 13020319043706888256, 13790070886127375971, 1584348143126996741, 14269751476430075034, 39520851290632316}, + }, + { + A0: fp.Element{10496651096160116529, 17447330314090714314, 7901980568892205616, 12523643767284114259, 14047697587913173436, 75967257029771325}, + A1: fp.Element{928850053641029162, 14269106311960337185, 16222409674828338261, 5805191570224440459, 18405225593952050465, 81611267238126250}, + }, + { + A0: fp.Element{11963245856892367752, 10425756598646938656, 18335238837348744770, 15086772981218061512, 16514870314421827966, 31505685309500160}, + A1: fp.Element{12503518650914401765, 9253053408485518576, 7574198415595259890, 9578781703355827570, 4997060354564847196, 4129967821132897}, + }, + { + A0: fp.Element{2031421031641935199, 11357963626711833272, 3216176135850906142, 18356175605205399499, 14930266308542898024, 45166487627178747}, + A1: fp.Element{4224679465464892278, 5162816687557914011, 9625001313214472999, 9646089844316603379, 3042432097393437616, 116654205222221531}, + }, + { + A0: fp.Element{707631102761073363, 4675040476129639901, 7917747947488915690, 10109499984363985170, 8993410474198507338, 72712009800189820}, + A1: fp.Element{13149412355826661761, 13738163990683470943, 2035497293527985654, 18119267602401018212, 2631647798265895027, 2795783216290358}, + }, + } + g2IsogenyYNumeratorMap = []fptower.E2{ + { + A0: fp.Element{17926225976816550695, 14023720841551579195, 6357178813752170559, 1429363592569423041, 10398153225153858948, 33711798988254397}, + A1: fp.Element{2451854115792992988, 8983506616720050336, 2910564589437158732, 14075622914381394491, 9210830493684175792, 3356683084380210}, + }, + { + A0: fp.Element{5363401642911389912, 1675875184098052872, 15320530934239994732, 16287584047609698426, 10234580471621189795, 40152057551620421}, + A1: fp.Element{2205557896318444105, 4065007897235623968, 4049591920488634456, 16004168804099107709, 13290522222905374988, 70089339901218536}, + }, + { + A0: fp.Element{1887285394871164447, 7142690945990485012, 11190732658400833066, 6881717282640585612, 12116088968278807379, 103071704289665226}, + A1: fp.Element{15968649428224979513, 622837296484333259, 15527184444320989860, 2221190225062639140, 16647213690505955661, 110449865605275384}, + }, + { + A0: fp.Element{8732294600695513394, 7924365878303510912, 12588020556237861366, 10068029016225118132, 785053188876688927, 120347068207419939}, + A1: fp.Element{14514622768737464893, 5553264648606662629, 12707457796658055665, 6066303778837734141, 8279024849745683367, 3564406469625657}, + }, + { + A0: fp.Element{10035254538193759291, 9758866910217654439, 2724217928072676653, 3087232989313988901, 14980280964270815877, 34590022796322467}, + A1: fp.Element{15702474365778911803, 7256912742043165018, 1566344877835261304, 4035729625101537726, 16346625826270990512, 84087754076446931}, + }, + { + A0: fp.Element{8353555275402615800, 6017666668033757053, 13076202439893933084, 1913164921831891521, 13296563472388407395, 43485447354470561}, + A1: fp.Element{12571296156797641372, 13988198528186614994, 5672291450663514913, 7033607850615758657, 16846880911077910300, 44471894806759326}, + }, + { + A0: fp.Element{1319289899879823718, 1591088360172441240, 7805677496653365276, 5569897284498525554, 5635591756513279404, 74901024143303203}, + A1: fp.Element{10251017843654697682, 10395107644570958416, 3071938417266745181, 16127666859700570668, 5111665418914357408, 2168588371926498}, + }, + { + A0: fp.Element{7692831217085618076, 6702179445852008930, 11308520252707392151, 12038365346701529390, 7201289518723110646, 24757234241788495}, + A1: fp.Element{17948859968330001914, 10144279887227452625, 5167544611537672341, 4094514978127885079, 17912079766649616973, 45691468580901020}, + }, + { + A0: fp.Element{3911440855998194160, 13198838254872822648, 13301641437413064797, 11598620320741753383, 6260523097595092689, 78284230929812985}, + A1: fp.Element{7876366075466990529, 13523468790275433139, 982512625724968021, 2122595334378906057, 14803785928219626498, 71415583741911053}, + }, + { + A0: fp.Element{14923926944529083273, 3172840012894527710, 8293434476071337387, 16713256045335958267, 14057165773167995662, 57626475506313562}, + A1: fp.Element{1362417042314121750, 3304417561071796103, 17626406775105189491, 11748219015558348173, 14151421547261463616, 82460535821434588}, + }, + { + A0: fp.Element{3641967463568066103, 8959416625663108732, 5147508997828480363, 16811352377666989046, 1441182181356889676, 52012247235371457}, + A1: fp.Element{17686146190561162997, 11457769513035421935, 11629039572857129752, 16013548565551254584, 3489389447040062088, 108111902919606578}, + }, + { + A0: fp.Element{3810472718885394006, 2981020169366520013, 2816385682378197235, 153866317221550159, 11847618666936524337, 45551005605881971}, + A1: fp.Element{3468095351662354134, 4642197759139584052, 4233923780028877603, 17495173774535575422, 6042084483130094534, 67695926977382460}, + }, + { + A0: fp.Element{1324953063484934482, 15924484690572898301, 11397027945012096698, 2650928770069584769, 15779309286157100138, 107280353846472153}, + A1: fp.Element{7825813464319090460, 9031312139767459777, 142189155675192148, 6582610291000324889, 17102396003811978688, 22084094988625284}, + }, + { + A0: fp.Element{5210064249141309135, 1705543797894948713, 2628665872375881350, 13536211673960271710, 18420806283098729881, 115824256193502087}, + A1: fp.Element{15082907751180860242, 6568697878451242210, 16244491021091296231, 17790448340613041754, 7733097786923840729, 14504831353209381}, + }, + { + A0: fp.Element{1708526764431582271, 13958279355051552323, 14990211071762970223, 7884242526085975541, 16332397605884981291, 80533848446738849}, + A1: fp.Element{14979957683309612745, 6077136825354362762, 8344075647158254715, 10162044015152162839, 5892600246835629906, 87516868768986919}, + }, + { + A0: fp.Element{13823384149985104375, 400062563487168190, 14946453239900597346, 3063239780002983931, 12307299790663558215, 82575345472847758}, + A1: fp.Element{4955387593349539956, 11580263215419679285, 13810204272372323220, 15118104627613044122, 5709821153764726112, 97792497530186865}, + }, + { + A0: fp.Element{8029106480647627463, 9339835209992361362, 2257747803917390435, 13841766612482081060, 11846105036367819521, 10985089103756089}, + A1: fp.Element{12896564185217823813, 11446288085903243988, 7990576940036837900, 3323202217483830000, 8230734762253073878, 36590510406546600}, + }, + { + A0: fp.Element{9258620980666570289, 14799769271847025124, 3337623733744503313, 7847288847664005088, 4443979768963902018, 60018570132140318}, + A1: fp.Element{2675246192261018596, 15150250319428322656, 8044595947793549351, 17819017498503740634, 8168003399719773701, 50802205070212383}, + }, + { + A0: fp.Element{6416675551757596528, 11137110755893373387, 12196234615749865580, 10261229930898283794, 16443034629854739148, 92762661836396101}, + A1: fp.Element{2617757450501858457, 13481841765161333192, 14399351126797435540, 14845648777279341476, 16479218442290092360, 58694504406226241}, + }, + { + A0: fp.Element{2498292483400110656, 17577335584861186499, 17782334663901894811, 2829649086165738601, 1498570879458573752, 54126946483698861}, + A1: fp.Element{13664305368410221366, 15519373467383236285, 6930373704919785768, 5035259077705758702, 15118622066815350587, 76218461077450180}, + }, + { + A0: fp.Element{2359464294290896887, 15126005627433822176, 8745471049496239338, 16249169944251666409, 5887779353961924474, 9756279022859315}, + A1: fp.Element{4564346538121733135, 7083224900235365477, 12708889282498498077, 7850548098138279688, 14178174888234998222, 79663491154927524}, + }, + { + A0: fp.Element{2363371748841007386, 8201543480932182326, 3606722496785934427, 11335897361905574349, 7238564335142183540, 28370763379089425}, + A1: fp.Element{17773120842166679454, 6968817275085296949, 589078002303466881, 11901496965136831973, 17508389603594408067, 105726710734816064}, + }, + { + A0: fp.Element{7295712044514929446, 1419749005841863626, 15921158613862149232, 9464988326326595083, 4254037448365833139, 69144288462579473}, + A1: fp.Element{2330521880128496868, 6942731841460529291, 16753201799444057524, 5125438220420299042, 743707329901356982, 86418732453789215}, + }, + { + A0: fp.Element{10073672469351267894, 7530218602938011234, 12150950127635720924, 14699101300080070173, 3657462378365608060, 50677269975209252}, + A1: fp.Element{16217326474471800173, 12182932688121705224, 9523557196391803719, 13559107473982584173, 14264388955497449506, 89155196038187526}, + }, + { + A0: fp.Element{8500524953883552338, 13471246252006481381, 399342016929624192, 15321780621361720165, 1735807610194144505, 81584295376527434}, + A1: fp.Element{3028140852425956403, 9738549527114127103, 13145547273810927, 15439064114192138046, 15332022320720552951, 84308032823666865}, + }, + { + A0: fp.Element{8795699974103596314, 642987394252844125, 12559698238980671421, 15439596853334509309, 8192837603484177265, 86858193154220713}, + A1: fp.Element{13665577425741482529, 6924526015867702055, 8773433633434605845, 4385776193759960181, 14751123844375383386, 84259094466106596}, + }, + { + A0: fp.Element{6308743764871173820, 14529376135552483358, 3992864522868188832, 16018150786687814926, 14942376479240309869, 30721880050281254}, + A1: fp.Element{8640235552523037016, 9835096537876469025, 789797926152341591, 17554386444425767744, 2184317346571194421, 105569965705365467}, + }, + { + A0: fp.Element{10895141504918788686, 5671269070898752172, 9721970862384110947, 6958416614840799556, 18087813302866953828, 120526621462965167}, + A1: fp.Element{4966785024859028542, 18182687130036955400, 10092534947477547130, 11367367723010839926, 7417818378683193783, 94369912047147779}, + }, + { + A0: fp.Element{5709922971951703245, 10382852257937442526, 3453842328747730539, 16133368957829378910, 8271517063962590774, 9539719803485949}, + A1: fp.Element{1704900793320796784, 8995901783485359023, 9994857694012530400, 7408202244508772902, 18055801701001909838, 109149704128086904}, + }, + { + A0: fp.Element{8357460663115985094, 5765296628618444602, 6421674075164890879, 1651079036919805888, 1287520506307076832, 98975482931648514}, + A1: fp.Element{8078944849704442787, 4038716179863104913, 8864619430523621449, 11983583689047803099, 2541042365160408900, 28281336919305267}, + }, + { + A0: fp.Element{13472601104608613638, 521231156844377864, 4649313698209759510, 5796371833735044995, 8684999192663632207, 51033152603009675}, + A1: fp.Element{3409558318672010377, 10145443448574304058, 3995874611835909177, 15021984820089990008, 15242143999191686238, 73656911605031936}, + }, + { + A0: fp.Element{9770462122700591808, 17547477902406858790, 14010124614813851222, 4165622522809648336, 16982670942141592785, 28856170353703120}, + A1: fp.Element{15290128055618535720, 17454664547186830394, 2442682438806360163, 18129275600450347134, 4187898517238597724, 22281223126461925}, + }, + { + A0: fp.Element{12998303454550796060, 5752293956714303316, 6752814987597331313, 3166668351495264669, 9929418606104908953, 29385282975911842}, + A1: fp.Element{8756413506556179286, 143408982899135549, 2705277708630136288, 5154523209628123430, 6318572504564936509, 15532021916109921}, + }, + { + A0: fp.Element{18250508560718013179, 7486164413457419330, 8732750857092323232, 457033717118918321, 12167888022606617966, 20277559260742340}, + A1: fp.Element{0}, + }, + } + g2IsogenyYDenominatorMap = []fptower.E2{ + { + A0: fp.Element{2775408832476871526, 9008699192344519496, 1102884431771657931, 11532306452895462867, 5856674524343862704, 99430919144638985}, + A1: fp.Element{15551301223123894338, 11614654532478001117, 17328204268627498271, 15544698294678786409, 1484472732893154418, 94605104690421825}, + }, + { + A0: fp.Element{15538486723908094425, 10978766348102143722, 15056964343960721360, 8732109610906448146, 8620899699042055528, 1351681984895437}, + A1: fp.Element{3175104032835843731, 9314571151837830613, 14059118678096680542, 2500500275627160283, 18190796245603721369, 49058560079762280}, + }, + { + A0: fp.Element{2177050294381443304, 18124514285214412099, 9381797198372716589, 8046190315005422985, 9931273159159670369, 8036418831901820}, + A1: fp.Element{1549742439238596983, 15619417821567290543, 9431498181016104480, 2850048082163302555, 17545915875775834651, 72687252788290726}, + }, + { + A0: fp.Element{16572119218800158686, 13113809656757589233, 12872678318679566545, 3255385198038960565, 17070551903094984362, 19742086936927308}, + A1: fp.Element{12635717383520653743, 12204869003999147728, 8256611698395114158, 12382254302890131233, 603685913325391887, 60927550204070150}, + }, + { + A0: fp.Element{15497795759006280655, 16847324196958114585, 8218328297664216257, 15353718428023978640, 6357440186573265200, 109435672289072692}, + A1: fp.Element{17126430308003109280, 8510055147921463837, 2424009275722614739, 9284383313721206596, 12867548350984534889, 46750493171897961}, + }, + { + A0: fp.Element{6993808529266055670, 10024278910497662817, 6638820395273369627, 17550512930522052164, 11971278025880956390, 4218694435301565}, + A1: fp.Element{4117072311900938869, 8052759146924035127, 1883914237959498468, 843437547616490150, 1332392274725871932, 100467415201018114}, + }, + { + A0: fp.Element{10031273074038578964, 6635740043384123318, 2357760728051263554, 12405057037224522557, 2967360385882286162, 53130165628915609}, + A1: fp.Element{9340276074750471546, 8779557686584984578, 12118682911992514942, 8792287004994786286, 11729922744948342197, 97115621599174349}, + }, + { + A0: fp.Element{8243258075199662251, 789646305137795307, 9501755430432007632, 15339245131080115010, 3036491630055907252, 4720358405852701}, + A1: fp.Element{6272873484523042114, 18180794113363272037, 10135093694274252446, 13006427779172872075, 12612518697452888675, 4088970499189038}, + }, + { + A0: fp.Element{12559327402496405011, 13162954855686166920, 2622361684062280170, 16985128559432625018, 10671934355632922492, 22106668982430516}, + A1: fp.Element{10342048742210368049, 4070662490021521195, 9050590024293164750, 6778744574336170333, 16385669267342466637, 110676722503289309}, + }, + { + A0: fp.Element{8257142434361782318, 11625188549524762434, 4162174183904813140, 15534648919830235837, 15345786270187761745, 49274740272907617}, + A1: fp.Element{17452699565973497082, 1589725784862892127, 17590303103109791779, 8233530623701537904, 717929863606521126, 42679722481449639}, + }, + { + A0: fp.Element{17135289411523873787, 11725292909156152853, 16347014946116696110, 13323937426977246609, 8703182288833044255, 99079409785168386}, + A1: fp.Element{9130446173903866415, 12010725389601806440, 9146179391205715125, 12338366065383252573, 9136251064810045627, 19315728226188373}, + }, + { + A0: fp.Element{13754907156191096138, 22846764546901886, 362622052532339515, 17013010775786408901, 13860043181928645305, 41171875858186406}, + A1: fp.Element{16141340011263075417, 18360728019638818576, 16264128300543356196, 12473458415555386384, 18336837302801391285, 63727493440743041}, + }, + { + A0: fp.Element{3658804449581456923, 1347747705877184398, 3978302900333357541, 5081865331785059868, 1329643100050532471, 64102076251113639}, + A1: fp.Element{6980160750786278877, 11782099681251246419, 5400025369843657828, 9848695260591786723, 7987487093370334558, 27115517650078156}, + }, + { + A0: fp.Element{408044901411159465, 18068234941175928745, 2992890619264445487, 8810813216534328625, 4005157550725594837, 26065038549738560}, + A1: fp.Element{10975300981822504330, 15715038812214651197, 7602692888794350386, 12917547374269268270, 422938878523833779, 36305463980543648}, + }, + { + A0: fp.Element{10382180122959422967, 15807168734599653808, 18372044240449882372, 17642941170379477011, 10340644338271517361, 36063527972088465}, + A1: fp.Element{17969075460977832752, 9177853432360197657, 2917850475625504299, 7079850467696515295, 787036529903063845, 107077168732108508}, + }, + { + A0: fp.Element{6502963492633373835, 9890663567118850708, 12445720805224431135, 6172862156806685987, 16576315346783950860, 5856337016358393}, + A1: fp.Element{4476660199518722374, 3771101137683024451, 489075951782192448, 6489873046594013732, 280944977367484653, 69709094171715534}, + }, + { + A0: fp.Element{5629815848909521275, 5316587566230943622, 7982019375390215350, 15543803108203970386, 5941855484214597918, 5142365312974746}, + A1: fp.Element{3442509802156923890, 6170315030905476396, 2122926024914179804, 17368567939581660282, 12200117156652989113, 7492215668086454}, + }, + { + A0: fp.Element{15017092692882720799, 2306085001940265068, 6863750251390498522, 772425548835188093, 7866794496176459304, 119478713276832042}, + A1: fp.Element{539473290914229032, 10680532665300974652, 2401493774971219183, 771791041055281045, 17266300769954562072, 46203199265737132}, + }, + { + A0: fp.Element{12080185159744170157, 6121786867780957883, 13378966825252880343, 16978399570563241468, 13189121794372052505, 31306179382417939}, + A1: fp.Element{6033582013845463960, 10201637616554513673, 3729832524646428556, 2564427389283182369, 662893124657004215, 101996692818942248}, + }, + { + A0: fp.Element{14864583376459179927, 16267452113314442715, 14135040057928255187, 712462212063179204, 12089188474131830930, 36841165809084721}, + A1: fp.Element{13089068048776542239, 1568107234484844315, 4262841373517201534, 572974140393742986, 13114372614372436015, 221271375458892}, + }, + { + A0: fp.Element{15352358256255559128, 14776149476170502093, 13834021062045579807, 16108249515581661111, 7563707564996631205, 86582638494403858}, + A1: fp.Element{16813570010660423536, 3065722476932153407, 8938713923763210470, 2255995557158728394, 8016474455897300271, 84052925693202818}, + }, + { + A0: fp.Element{15615825726181497195, 5658715128964929728, 13877560309241249627, 15409847795806183219, 382506108092986341, 33112756833083889}, + A1: fp.Element{4921115267284233431, 2093038862301396370, 11859221373400371788, 14840702906540650688, 3187022540654844811, 12940014803022939}, + }, + { + A0: fp.Element{10653597201928750109, 13006094245282229535, 13295987796930539448, 16777781019019743602, 516306931828031556, 114717773318043797}, + A1: fp.Element{235309942988776203, 14860563794932685398, 4559874204394395321, 16639699308077583607, 9227151754747780541, 15908917446924874}, + }, + { + A0: fp.Element{17337820088369903748, 8586614709689721762, 1507576901396006569, 12700849903501888588, 17971589925911161601, 108264042385722694}, + A1: fp.Element{16945398252920060844, 12661842631743740793, 3757011696927843364, 15267617233875676717, 4747339870779259550, 34661428542359791}, + }, + { + A0: fp.Element{16466466374773138846, 14279763770124955377, 2253148650834359538, 7990858085823320889, 7124676177871440280, 94151727797031734}, + A1: fp.Element{15321139925728056718, 15122461222407649886, 17533799169860262777, 16804941505997951982, 1600681788854461369, 44486672743339990}, + }, + { + A0: fp.Element{8867142699562737491, 18199028041645162481, 3517239929170429351, 775467166380995197, 5868381756625215392, 6197719424154602}, + A1: fp.Element{9737125075096738524, 9629792455358261596, 11564279494282885105, 5089237230157463720, 17189088638807565425, 106712839297101083}, + }, + { + A0: fp.Element{10270843696704620770, 13223598872017291793, 9010388952516938805, 15912131807459901749, 6846913031975448418, 86431140578472953}, + A1: fp.Element{15439335117817990542, 18208862128889198852, 1680174721576182500, 13180416124629130962, 7418066627384568449, 3653571306187636}, + }, + { + A0: fp.Element{1131060365675191416, 10374247235014096023, 5274169106847399340, 9643591707517384578, 8354961201546942085, 16860653124975415}, + A1: fp.Element{7591061314547569259, 3687653994280978709, 14906524746128876973, 7376139658567228596, 3304769414542873433, 39389809689964413}, + }, + { + A0: fp.Element{15061500520004024506, 13781868913987378153, 1311923405823490306, 13614698003779137726, 2734567429318555742, 41565578486180068}, + A1: fp.Element{2264606496492496938, 7463181801259856780, 4974231603582406689, 12631973597673125932, 13768142234619696863, 69859376569568629}, + }, + { + A0: fp.Element{12977806950220507699, 9598682745345891240, 12727041082031765282, 13876739454320532788, 16731345162096153922, 52377912619410421}, + A1: fp.Element{9749487977108607359, 9452745135768007871, 17734899000824388188, 6032906020241168466, 3891046964558379200, 42965172988847872}, + }, + { + A0: fp.Element{15134142718037669741, 2650609953202022541, 18444582952265559358, 10072051383647105272, 1614233522361858494, 6353896085976033}, + A1: fp.Element{1244819074686382314, 16827930012669440062, 7409202602064068605, 7833164804348414003, 14093967246945573989, 91886691830462491}, + }, + { + A0: fp.Element{3481568382353274479, 1454015438048276221, 18321294391133087854, 11721714833000613979, 10732204074831352562, 71241856315356756}, + A1: fp.Element{2091942538387325776, 9875355486415603002, 12623384858601965052, 7559030465493899268, 7674739998354242578, 75767137192853634}, + }, + { + A0: fp.Element{5491757234451068988, 6182298996664147147, 1538132785577256287, 4999224323735886804, 6348107227722746450, 48518858347037381}, + A1: fp.Element{15293807953430533698, 2990763629845967503, 13391735075948095730, 9673810945847290845, 11089480180973857099, 64742831177682886}, + }, + } +) + +// G2IsogenyMap returns the isogeny map for the curve. +// The isogeny map is a list of polynomial coefficients for the x and y coordinate computation. +// The order of the coefficients is as follows: +// - x numerator, x denominator, y numerator, y denominator. +func G2IsogenyMap() [4][]fptower.E2 { + return [4][]fptower.E2{ + g2IsogenyXNumeratorMap, + g2IsogenyXDenominatorMap, + g2IsogenyYNumeratorMap, + g2IsogenyYDenominatorMap, + } +} + +func g2IsogenyXNumerator(dst *fptower.E2, x *fptower.E2) { + g2EvalPolynomial(dst, false, g2IsogenyXNumeratorMap, x) +} + +func g2IsogenyXDenominator(dst *fptower.E2, x *fptower.E2) { + g2EvalPolynomial(dst, true, g2IsogenyXDenominatorMap, x) +} + +func g2IsogenyYNumerator(dst *fptower.E2, x *fptower.E2, y *fptower.E2) { + var _dst fptower.E2 + g2EvalPolynomial(&_dst, false, g2IsogenyYNumeratorMap, x) + dst.Mul(&_dst, y) +} + +func g2IsogenyYDenominator(dst *fptower.E2, x *fptower.E2) { + g2EvalPolynomial(dst, true, g2IsogenyYDenominatorMap, x) +} + +// G2 computes the isogeny map of the curve element, given by its coordinates pX and pY. +// It mutates the coordinates pX and pY to the new coordinates of the isogeny map. +func G2Isogeny(pX, pY *fptower.E2) { + + den := make([]fptower.E2, 2) + + g2IsogenyYDenominator(&den[1], pX) + g2IsogenyXDenominator(&den[0], pX) + + g2IsogenyYNumerator(pY, pX, pY) + g2IsogenyXNumerator(pX, pX) + + den = fptower.BatchInvertE2(den) + + pX.Mul(pX, &den[0]) + pY.Mul(pY, &den[1]) +} + +// G2SqrtRatio computes the square root of u/v and returns 0 iff u/v was indeed a quadratic residue. +// If not, we get sqrt(Z * u / v). Recall that Z is non-residue. +// If v = 0, u/v is meaningless and the output is unspecified, without raising an error. +// The main idea is that since the computation of the square root involves taking large powers of u/v, the inversion of v can be avoided +func G2SqrtRatio(z *fptower.E2, u *fptower.E2, v *fptower.E2) uint64 { + + // https://www.rfc-editor.org/rfc/rfc9380.html#name-sqrt_ratio-for-any-field + + tv1 := fptower.E2{ + A0: fp.Element{0}, + A1: fp.Element{9669507733633691314, 13074846433352412541, 11948543988290594071, 11104573675215509690, 878729975203857826, 120237394476367878}, + } //tv1 = c6 + + var tv2, tv3, tv4, tv5 fptower.E2 + var exp big.Int + // c4 = 140737488355327 = 2⁴⁷ - 1 + // q is odd so c1 is at least 1. + exp.SetBytes([]byte{127, 255, 255, 255, 255, 255}) + + tv2.Exp(*v, &exp) // 2. tv2 = vᶜ⁴ + tv3.Square(&tv2) // 3. tv3 = tv2² + tv3.Mul(&tv3, v) // 4. tv3 = tv3 * v + tv5.Mul(u, &tv3) // 5. tv5 = u * tv3 + + // c3 = 237702427642072544657662731610863241996908072983433720914596829155825880635712864411696995402952020023758239370111403151139377997388748144480691770738487127695940799749981367718443673617185911789718419957467908625 + exp.SetBytes([]byte{2, 211, 7, 208, 187, 175, 251, 34, 86, 145, 59, 179, 97, 38, 60, 75, 184, 184, 125, 164, 174, 233, 63, 31, 94, 113, 65, 61, 218, 77, 92, 9, 208, 24, 175, 185, 6, 96, 205, 192, 20, 231, 18, 80, 42, 77, 108, 70, 10, 170, 170, 139, 183, 10, 224, 49, 131, 36, 185, 88, 99, 140, 157, 107, 203, 251, 210, 53, 241, 192, 154, 74, 218, 38, 143, 46, 27, 216, 0, 115, 56, 210, 84, 240, 0, 0, 1, 10, 17}) + + tv5.Exp(tv5, &exp) // 6. tv5 = tv5ᶜ³ + tv5.Mul(&tv5, &tv2) // 7. tv5 = tv5 * tv2 + tv2.Mul(&tv5, v) // 8. tv2 = tv5 * v + tv3.Mul(&tv5, u) // 9. tv3 = tv5 * u + tv4.Mul(&tv3, &tv2) // 10. tv4 = tv3 * tv2 + + // c5 = 70368744177664 + exp.SetBytes([]byte{64, 0, 0, 0, 0, 0}) + tv5.Exp(tv4, &exp) // 11. tv5 = tv4ᶜ⁵ + isQNr := g2NotOne(&tv5) // 12. isQR = tv5 == 1 + c7 := fptower.E2{ + A0: fp.Element{1479358275892676257, 2814264704614556731, 13691179386454739330, 7530671302001941842, 60362263363904715, 37906327945374822}, + A1: fp.Element{5350190547200862053, 10822704806123199611, 5122684409451163826, 10616884767534481491, 1436196917100294910, 20226740120672211}, + } + tv2.Mul(&tv3, &c7) // 13. tv2 = tv3 * c7 + tv5.Mul(&tv4, &tv1) // 14. tv5 = tv4 * tv1 + tv3.Select(int(isQNr), &tv3, &tv2) // 15. tv3 = CMOV(tv2, tv3, isQR) + tv4.Select(int(isQNr), &tv4, &tv5) // 16. tv4 = CMOV(tv5, tv4, isQR) + exp.Lsh(big.NewInt(1), 47-2) // 18, 19: tv5 = 2ⁱ⁻² for i = c1 + + for i := 47; i >= 2; i-- { // 17. for i in (c1, c1 - 1, ..., 2): + + tv5.Exp(tv4, &exp) // 20. tv5 = tv4ᵗᵛ⁵ + nE1 := g2NotOne(&tv5) // 21. e1 = tv5 == 1 + tv2.Mul(&tv3, &tv1) // 22. tv2 = tv3 * tv1 + tv1.Mul(&tv1, &tv1) // 23. tv1 = tv1 * tv1 Why not write square? + tv5.Mul(&tv4, &tv1) // 24. tv5 = tv4 * tv1 + tv3.Select(int(nE1), &tv3, &tv2) // 25. tv3 = CMOV(tv2, tv3, e1) + tv4.Select(int(nE1), &tv4, &tv5) // 26. tv4 = CMOV(tv5, tv4, e1) + + if i > 2 { + exp.Rsh(&exp, 1) // 18, 19. tv5 = 2ⁱ⁻² + } + } + + *z = tv3 + return isQNr +} + +func g2NotOne(x *fptower.E2) uint64 { + + //Assuming hash is implemented for G1 and that the curve is over Fp + var one fp.Element + return one.SetOne().NotEqual(&x.A0) | G1NotZero(&x.A1) + +} + +// G2MulByZ multiplies x by [12, 1] and stores the result in z +func G2MulByZ(z *fptower.E2, x *fptower.E2) { + + z.Mul(x, &fptower.E2{ + A0: fp.Element{10560307807486212317, 9936456306313395274, 2092561269709285211, 8738829082964617622, 5243865315912343348, 114311569748804731}, + A1: fp.Element{202099033278250856, 5854854902718660529, 11492539364873682930, 8885205928937022213, 5545221690922665192, 39800542322357402}, + }) + +} + +func g2EvalPolynomial(z *fptower.E2, monic bool, coefficients []fptower.E2, x *fptower.E2) { + dst := coefficients[len(coefficients)-1] + + if monic { + dst.Add(&dst, x) + } + + for i := len(coefficients) - 2; i >= 0; i-- { + dst.Mul(&dst, x) + dst.Add(&dst, &coefficients[i]) + } + + z.Set(&dst) +} + +// G2Sgn0 is an algebraic substitute for the notion of sign in ordered fields. +// Namely, every non-zero quadratic residue in a finite field of characteristic =/= 2 has exactly two square roots, one of each sign. +// +// See: https://www.rfc-editor.org/rfc/rfc9380.html#name-the-sgn0-function +// +// The sign of an element is not obviously related to that of its Montgomery form +func G2Sgn0(z *fptower.E2) uint64 { + + nonMont := z.Bits() + + sign := uint64(0) // 1. sign = 0 + zero := uint64(1) // 2. zero = 1 + var signI uint64 + var zeroI uint64 + + // 3. i = 1 + signI = nonMont.A0[0] % 2 // 4. sign_i = x_i mod 2 + zeroI = G1NotZero(&nonMont.A0) + zeroI = 1 ^ (zeroI|-zeroI)>>63 // 5. zero_i = x_i == 0 + sign = sign | (zero & signI) // 6. sign = sign OR (zero AND sign_i) # Avoid short-circuit logic ops + zero = zero & zeroI // 7. zero = zero AND zero_i + // 3. i = 2 + signI = nonMont.A1[0] % 2 // 4. sign_i = x_i mod 2 + // 5. zero_i = x_i == 0 + sign = sign | (zero & signI) // 6. sign = sign OR (zero AND sign_i) # Avoid short-circuit logic ops + // 7. zero = zero AND zero_i + return sign + +} + +func G2NotZero(x *fptower.E2) uint64 { + //Assuming G1 is over Fp and that if hashing is available for G2, it also is for G1 + return G1NotZero(&x.A0) | G1NotZero(&x.A1) + +} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/hash_to_g1.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/hash_to_g1.go index 20306ba879b..916ce286200 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/hash_to_g1.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/hash_to_g1.go @@ -1,16 +1,5 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -18,166 +7,78 @@ package bls12377 import ( "github.com/consensys/gnark-crypto/ecc/bls12-377/fp" - - "math/big" + "github.com/consensys/gnark-crypto/ecc/bls12-377/hash_to_curve" ) -//Note: This only works for simple extensions - -func g1IsogenyXNumerator(dst *fp.Element, x *fp.Element) { - g1EvalPolynomial(dst, - false, - []fp.Element{ - {9381318728011785451, 8795417190580748876, 15171640721257608922, 11815547924113428908, 15499908520243100994, 75408755324413256}, - {12414498063752772717, 9915153185132073893, 5598625970987438951, 3342254783599619135, 3349592178919125510, 9993871847068096}, - {4662210776746950618, 10687085762534440940, 7484820859645808636, 2221301482234255553, 10609677459585442106, 9950135580589350}, - }, - x) -} - -func g1IsogenyXDenominator(dst *fp.Element, x *fp.Element) { - g1EvalPolynomial(dst, - true, - []fp.Element{ - {12764504107591987636, 2767124593109192342, 3947759810240204190, 13369019134398476541, 13398368715676502040, 39975487388272384}, - }, - x) -} - -func g1IsogenyYNumerator(dst *fp.Element, x *fp.Element, y *fp.Element) { - var _dst fp.Element - g1EvalPolynomial(&_dst, - false, - []fp.Element{ - {13844135623281082635, 637899392157745290, 5176720401210677272, 4780940929980393029, 13803251044890140836, 51447363642369244}, - {512010462697120695, 609509684909242946, 13763343875136563934, 2839514380057330869, 15407015190976871917, 114223893455203604}, - {14191436515319700132, 6479619458373647736, 9513056055282499867, 15178407828209519654, 12166396751953702822, 75539964123849493}, - {2331105388373475309, 5343542881267220470, 12965782466677680126, 1110650741117127776, 5304838729792721053, 4975067790294675}, - }, - x) - - dst.Mul(&_dst, y) -} - -func g1IsogenyYDenominator(dst *fp.Element, x *fp.Element) { - g1EvalPolynomial(dst, - true, - []fp.Element{ - {8694832399336342723, 13482963304561246841, 6984108042366343277, 8355250559073919616, 16937021447778317421, 44890599540624877}, - {1100361703846424922, 5005767817281133373, 917019320419705433, 14251746270386956490, 5522097789867984932, 4443041874334878}, - {1400024175356859676, 8301373779327577028, 11843279430720612570, 3213569255776326391, 3301617999610402890, 119926462164817154}, - }, - x) +// MapToG1 invokes the SSWU map, and guarantees that the result is in G1. +func MapToG1(u fp.Element) G1Affine { + res := MapToCurve1(&u) + //this is in an isogenous curve + hash_to_curve.G1Isogeny(&res.X, &res.Y) + res.ClearCofactor(&res) + return res } -func g1Isogeny(p *G1Affine) { - - den := make([]fp.Element, 2) - - g1IsogenyYDenominator(&den[1], &p.X) - g1IsogenyXDenominator(&den[0], &p.X) +// EncodeToG1 hashes a message to a point on the G1 curve using the SSWU map. +// It is faster than [HashToG1], but the result is not uniformly distributed. Unsuitable as a random oracle. +// dst stands for "domain separation tag", a string unique to the construction using the hash function +// +// See: https://www.rfc-editor.org/rfc/rfc9380.html#roadmap +func EncodeToG1(msg, dst []byte) (G1Affine, error) { - g1IsogenyYNumerator(&p.Y, &p.X, &p.Y) - g1IsogenyXNumerator(&p.X, &p.X) + var res G1Affine + u, err := fp.Hash(msg, dst, 1) + if err != nil { + return res, err + } - den = fp.BatchInvert(den) + res = MapToCurve1(&u[0]) - p.X.Mul(&p.X, &den[0]) - p.Y.Mul(&p.Y, &den[1]) + //this is in an isogenous curve + hash_to_curve.G1Isogeny(&res.X, &res.Y) + res.ClearCofactor(&res) + return res, nil } -// g1SqrtRatio computes the square root of u/v and returns 0 iff u/v was indeed a quadratic residue -// if not, we get sqrt(Z * u / v). Recall that Z is non-residue -// If v = 0, u/v is meaningless and the output is unspecified, without raising an error. -// The main idea is that since the computation of the square root involves taking large powers of u/v, the inversion of v can be avoided -func g1SqrtRatio(z *fp.Element, u *fp.Element, v *fp.Element) uint64 { - - // https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-sqrt_ratio-for-any-field - - tv1 := fp.Element{7563926049028936178, 2688164645460651601, 12112688591437172399, 3177973240564633687, 14764383749841851163, 52487407124055189} //tv1 = c6 - - var tv2, tv3, tv4, tv5 fp.Element - var exp big.Int - // c4 = 70368744177663 = 2⁴⁶ - 1 - // q is odd so c1 is at least 1. - exp.SetBytes([]byte{63, 255, 255, 255, 255, 255}) - - tv2.Exp(*v, &exp) // 2. tv2 = vᶜ⁴ - tv3.Square(&tv2) // 3. tv3 = tv2² - tv3.Mul(&tv3, v) // 4. tv3 = tv3 * v - tv5.Mul(u, &tv3) // 5. tv5 = u * tv3 - - // c3 = 1837921289030710838195067919506396475074392872918698035817074744121558668640693829665401097909504529 - exp.SetBytes([]byte{3, 92, 116, 140, 47, 138, 33, 213, 140, 118, 11, 128, 217, 66, 146, 118, 52, 69, 179, 230, 1, 234, 39, 30, 61, 230, 196, 95, 116, 18, 144, 0, 46, 22, 186, 136, 96, 0, 0, 1, 10, 17}) - - tv5.Exp(tv5, &exp) // 6. tv5 = tv5ᶜ³ - tv5.Mul(&tv5, &tv2) // 7. tv5 = tv5 * tv2 - tv2.Mul(&tv5, v) // 8. tv2 = tv5 * v - tv3.Mul(&tv5, u) // 9. tv3 = tv5 * u - tv4.Mul(&tv3, &tv2) // 10. tv4 = tv3 * tv2 - - // c5 = 35184372088832 - exp.SetBytes([]byte{32, 0, 0, 0, 0, 0}) - tv5.Exp(tv4, &exp) // 11. tv5 = tv4ᶜ⁵ - isQNr := g1NotOne(&tv5) // 12. isQR = tv5 == 1 - c7 := fp.Element{13262060633605929793, 16269117706405780335, 1787999441809606207, 11078968899094441280, 17534011895423012165, 96686002316065324} - tv2.Mul(&tv3, &c7) // 13. tv2 = tv3 * c7 - tv5.Mul(&tv4, &tv1) // 14. tv5 = tv4 * tv1 - tv3.Select(int(isQNr), &tv3, &tv2) // 15. tv3 = CMOV(tv2, tv3, isQR) - tv4.Select(int(isQNr), &tv4, &tv5) // 16. tv4 = CMOV(tv5, tv4, isQR) - exp.Lsh(big.NewInt(1), 46-2) // 18, 19: tv5 = 2ⁱ⁻² for i = c1 - - for i := 46; i >= 2; i-- { // 17. for i in (c1, c1 - 1, ..., 2): - - tv5.Exp(tv4, &exp) // 20. tv5 = tv4ᵗᵛ⁵ - nE1 := g1NotOne(&tv5) // 21. e1 = tv5 == 1 - tv2.Mul(&tv3, &tv1) // 22. tv2 = tv3 * tv1 - tv1.Mul(&tv1, &tv1) // 23. tv1 = tv1 * tv1 Why not write square? - tv5.Mul(&tv4, &tv1) // 24. tv5 = tv4 * tv1 - tv3.Select(int(nE1), &tv3, &tv2) // 25. tv3 = CMOV(tv2, tv3, e1) - tv4.Select(int(nE1), &tv4, &tv5) // 26. tv4 = CMOV(tv5, tv4, e1) - - if i > 2 { - exp.Rsh(&exp, 1) // 18, 19. tv5 = 2ⁱ⁻² - } +// HashToG1 hashes a message to a point on the G1 curve using the SSWU map. +// Slower than [EncodeToG1], but usable as a random oracle. +// dst stands for "domain separation tag", a string unique to the construction using the hash function. +// +// See https://www.rfc-editor.org/rfc/rfc9380.html#roadmap +func HashToG1(msg, dst []byte) (G1Affine, error) { + u, err := fp.Hash(msg, dst, 2*1) + if err != nil { + return G1Affine{}, err } - *z = tv3 - return isQNr -} - -func g1NotOne(x *fp.Element) uint64 { - - var one fp.Element - return one.SetOne().NotEqual(x) - -} + Q0 := MapToCurve1(&u[0]) + Q1 := MapToCurve1(&u[1]) -// g1MulByZ multiplies x by [5] and stores the result in z -func g1MulByZ(z *fp.Element, x *fp.Element) { + //TODO (perf): Add in E' first, then apply isogeny + hash_to_curve.G1Isogeny(&Q0.X, &Q0.Y) + hash_to_curve.G1Isogeny(&Q1.X, &Q1.Y) - res := *x + var _Q0, _Q1 G1Jac + _Q0.FromAffine(&Q0) + _Q1.FromAffine(&Q1).AddAssign(&_Q0) - res.Double(&res) - res.Double(&res) - res.Add(&res, x) + _Q1.ClearCofactor(&_Q1) - *z = res + Q1.FromJacobian(&_Q1) + return Q1, nil } -// https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-simplified-swu-method -// MapToCurve1 implements the SSWU map -// No cofactor clearing or isogeny +// MapToCurve1 implements the SSWU map. It does not perform cofactor clearing nor isogeny. For map to group, use [MapToG1]. +// +// See: https://www.rfc-editor.org/rfc/rfc9380.html#name-simplified-swu-method func MapToCurve1(u *fp.Element) G1Affine { - - var sswuIsoCurveCoeffA = fp.Element{17252667382019449424, 8408110001211059699, 18415587021986261264, 10797086888535946954, 9462758283094809199, 54995354010328751} - var sswuIsoCurveCoeffB = fp.Element{11130294635325289193, 6502679372128844082, 15863297759487624914, 16270683149854112145, 3560014356538878812, 27923742146399959} + sswuIsoCurveCoeffA, sswuIsoCurveCoeffB := hash_to_curve.G1SSWUIsogenyCurveCoefficients() var tv1 fp.Element tv1.Square(u) // 1. tv1 = u² //mul tv1 by Z - g1MulByZ(&tv1, &tv1) // 2. tv1 = Z * tv1 + hash_to_curve.G1MulByZ(&tv1, &tv1) // 2. tv1 = Z * tv1 var tv2 fp.Element tv2.Square(&tv1) // 3. tv2 = tv1² @@ -189,10 +90,10 @@ func MapToCurve1(u *fp.Element) G1Affine { tv3.Add(&tv2, &tv4) // 5. tv3 = tv2 + 1 tv3.Mul(&tv3, &sswuIsoCurveCoeffB) // 6. tv3 = B * tv3 - tv2NZero := g1NotZero(&tv2) + tv2NZero := hash_to_curve.G1NotZero(&tv2) // tv4 = Z - tv4 = fp.Element{9871116327010172167, 9167007004823125620, 18338974479346628539, 5649234265355377548, 13442091487463296847, 77904398905292312} + tv4 = hash_to_curve.G1SSWUIsogenyZ() tv2.Neg(&tv2) tv4.Select(int(tv2NZero), &tv4, &tv2) // 7. tv4 = CMOV(Z, -tv2, tv2 != 0) @@ -217,7 +118,7 @@ func MapToCurve1(u *fp.Element) G1Affine { x.Mul(&tv1, &tv3) // 17. x = tv1 * tv3 var y1 fp.Element - gx1NSquare := g1SqrtRatio(&y1, &tv2, &tv6) // 18. (is_gx1_square, y1) = sqrt_ratio(tv2, tv6) + gx1NSquare := hash_to_curve.G1SqrtRatio(&y1, &tv2, &tv6) // 18. (is_gx1_square, y1) = sqrt_ratio(tv2, tv6) var y fp.Element y.Mul(&tv1, u) // 19. y = tv1 * u @@ -228,7 +129,7 @@ func MapToCurve1(u *fp.Element) G1Affine { y.Select(int(gx1NSquare), &y1, &y) // 22. y = CMOV(y, y1, is_gx1_square) y1.Neg(&y) - y.Select(int(g1Sgn0(u)^g1Sgn0(&y)), &y, &y1) + y.Select(int(hash_to_curve.G1Sgn0(u)^hash_to_curve.G1Sgn0(&y)), &y, &y1) // 23. e1 = sgn0(u) == sgn0(y) // 24. y = CMOV(-y, y, e1) @@ -237,93 +138,3 @@ func MapToCurve1(u *fp.Element) G1Affine { return G1Affine{x, y} } - -func g1EvalPolynomial(z *fp.Element, monic bool, coefficients []fp.Element, x *fp.Element) { - dst := coefficients[len(coefficients)-1] - - if monic { - dst.Add(&dst, x) - } - - for i := len(coefficients) - 2; i >= 0; i-- { - dst.Mul(&dst, x) - dst.Add(&dst, &coefficients[i]) - } - - z.Set(&dst) -} - -// g1Sgn0 is an algebraic substitute for the notion of sign in ordered fields -// Namely, every non-zero quadratic residue in a finite field of characteristic =/= 2 has exactly two square roots, one of each sign -// https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-the-sgn0-function -// The sign of an element is not obviously related to that of its Montgomery form -func g1Sgn0(z *fp.Element) uint64 { - - nonMont := z.Bits() - - // m == 1 - return nonMont[0] % 2 - -} - -// MapToG1 invokes the SSWU map, and guarantees that the result is in g1 -func MapToG1(u fp.Element) G1Affine { - res := MapToCurve1(&u) - //this is in an isogenous curve - g1Isogeny(&res) - res.ClearCofactor(&res) - return res -} - -// EncodeToG1 hashes a message to a point on the G1 curve using the SSWU map. -// It is faster than HashToG1, but the result is not uniformly distributed. Unsuitable as a random oracle. -// dst stands for "domain separation tag", a string unique to the construction using the hash function -// https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#roadmap -func EncodeToG1(msg, dst []byte) (G1Affine, error) { - - var res G1Affine - u, err := fp.Hash(msg, dst, 1) - if err != nil { - return res, err - } - - res = MapToCurve1(&u[0]) - - //this is in an isogenous curve - g1Isogeny(&res) - res.ClearCofactor(&res) - return res, nil -} - -// HashToG1 hashes a message to a point on the G1 curve using the SSWU map. -// Slower than EncodeToG1, but usable as a random oracle. -// dst stands for "domain separation tag", a string unique to the construction using the hash function -// https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#roadmap -func HashToG1(msg, dst []byte) (G1Affine, error) { - u, err := fp.Hash(msg, dst, 2*1) - if err != nil { - return G1Affine{}, err - } - - Q0 := MapToCurve1(&u[0]) - Q1 := MapToCurve1(&u[1]) - - //TODO (perf): Add in E' first, then apply isogeny - g1Isogeny(&Q0) - g1Isogeny(&Q1) - - var _Q0, _Q1 G1Jac - _Q0.FromAffine(&Q0) - _Q1.FromAffine(&Q1).AddAssign(&_Q0) - - _Q1.ClearCofactor(&_Q1) - - Q1.FromJacobian(&_Q1) - return Q1, nil -} - -func g1NotZero(x *fp.Element) uint64 { - - return x[0] | x[1] | x[2] | x[3] | x[4] | x[5] - -} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/hash_to_g2.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/hash_to_g2.go index 66aae9fcc79..e8835998492 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/hash_to_g2.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/hash_to_g2.go @@ -1,16 +1,5 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -18,619 +7,88 @@ package bls12377 import ( "github.com/consensys/gnark-crypto/ecc/bls12-377/fp" + "github.com/consensys/gnark-crypto/ecc/bls12-377/hash_to_curve" "github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower" - - "math/big" ) -//Note: This only works for simple extensions - -func g2IsogenyXNumerator(dst *fptower.E2, x *fptower.E2) { - g2EvalPolynomial(dst, - false, - []fptower.E2{ - { - A0: fp.Element{3551783286045471771, 15672698349814166255, 7201714524012399751, 9685135133462022557, 11459791422433132438, 34279211894444158}, - A1: fp.Element{6733784119909728882, 8027365598504339614, 9826395261252013434, 17766961605401961078, 16718790361550578585, 8827310132881948}, - }, - { - A0: fp.Element{10039326048219096853, 8025585753053690704, 15692757884719051200, 14081267914923412694, 12483400733579637594, 41501995942887693}, - A1: fp.Element{3285050121746765179, 16424976010740556635, 13525960835401060630, 8230390587856081588, 332312595686915068, 58693565636984574}, - }, - { - A0: fp.Element{17569899329826403508, 9637548884483664645, 11559603533194429416, 509473447889017775, 16843450937194425803, 11820413515158522}, - A1: fp.Element{18082143759519379917, 7350976797508953919, 8718515184478260262, 11424641547646470649, 12610734036362352161, 109931236078585740}, - }, - { - A0: fp.Element{14344095877598929896, 14770204065590636976, 13870643972022067464, 14327299415926938990, 2100218127689809229, 111985606372347998}, - A1: fp.Element{18166912950538149334, 7903342274102247275, 11235613814926762637, 6048582781848067329, 9865957781737849443, 72257053590751229}, - }, - { - A0: fp.Element{9289693438943775070, 611273684478921638, 3161020385710416475, 2286858861996231773, 14631078872284738786, 101751379483637100}, - A1: fp.Element{218371821390517888, 3239557307852648611, 7956123978234311251, 4433191957359481551, 7602230667186897987, 36183482319693410}, - }, - { - A0: fp.Element{7524026848147356443, 15899508093607509001, 9269755160329214834, 12526651159477248728, 3756002781809695765, 101164747683440023}, - A1: fp.Element{6220885675233469595, 1070578225745722143, 9028649589122227273, 241265531361573072, 17722097355684345537, 59426317598728635}, - }, - { - A0: fp.Element{1147337684740884862, 11995598217907408439, 6334092051568104396, 4490620767408292574, 16484486820571077628, 32056264099725884}, - A1: fp.Element{1626504798254052117, 15843967556282260399, 3222912561813979091, 1092398256542226755, 15613117580878270463, 35759440311789519}, - }, - { - A0: fp.Element{9456818710433496904, 8738575976265225627, 17481785322204872502, 10252666647792359788, 13007033241788380867, 54062177864773120}, - A1: fp.Element{7857657292788377886, 18159261954362575139, 6957043223229770024, 101887390030524213, 7411469664095682342, 17462521019270966}, - }, - { - A0: fp.Element{5935437080311313022, 4869272223104979307, 14892623520420170949, 6274040211921387638, 190450687675494048, 100326942952217018}, - A1: fp.Element{4080141112519796596, 14389619698824585061, 15572076811388758383, 5573262239497616930, 5714216936392065098, 10910945353280475}, - }, - { - A0: fp.Element{12050383421129197508, 7679000367015579641, 4181895471589351098, 4488864303009131705, 1755297417051974713, 33780283701258651}, - A1: fp.Element{11393221592097145268, 10835918896706663346, 4746287363995169177, 6169630568067228482, 11259555703140136465, 52771734216395635}, - }, - { - A0: fp.Element{4577617767559140265, 568504000295320317, 4739467389388831592, 9537638546299567945, 11669151734363428413, 119097732794758712}, - A1: fp.Element{5691235310984308451, 13601281267571106288, 7819292534586961743, 11652278682059157182, 2231701566242469994, 110966193728844398}, - }, - { - A0: fp.Element{8957158313166077105, 5669155713645675267, 17333896861619738764, 4892240835897020648, 8492829473755858526, 70767002641220602}, - A1: fp.Element{8355305174234995113, 16726408794609999189, 6819868380250046496, 9302398329327482182, 3371252083110614225, 32903157732774708}, - }, - { - A0: fp.Element{3562726361589542410, 15642076536163677636, 3828009540728039550, 5513538145598570884, 1202255355797680138, 19209968154720986}, - A1: fp.Element{2433342667414904247, 14430646666116795259, 7881503288178112304, 10086912537277758921, 14321155618236575013, 84224128485096326}, - }, - { - A0: fp.Element{7543845460144717594, 14101022520017632284, 6419288061290617259, 11326768478076341964, 18432026940412127132, 85359846879027793}, - A1: fp.Element{17142157839755119212, 5159976764710014065, 6393633352893279233, 8672509349035392886, 7859431465567482570, 62163334379266093}, - }, - { - A0: fp.Element{2954881934412060022, 10898916794193723070, 10915833338735408379, 703491535562714344, 14589964434689495439, 90051679935520087}, - A1: fp.Element{18417998714611085978, 11039054240270137506, 9972891257774348246, 13263552626589315210, 4522668809484918556, 63885995997825101}, - }, - { - A0: fp.Element{9864134077459603571, 12525567282624341376, 5205345924937688700, 12649124091757575439, 14636003906379491067, 96025183135833306}, - A1: fp.Element{10316403063861314867, 10750711173072110600, 4513675589861596212, 2635673197095740125, 16720951430549947037, 31390298180493148}, - }, - { - A0: fp.Element{3003952238586646516, 3250841642932517220, 7061834734009117554, 16259415476002355236, 1626926148029432162, 77189086665928784}, - A1: fp.Element{14450051585993059472, 11823315281584113748, 6929304997500454604, 15344892292748160673, 15787768514545706202, 69813057053620435}, - }, - { - A0: fp.Element{4228110392233474072, 18010581486575392207, 13699345898545483049, 17704744337446085874, 5487913134051621310, 112205105149111207}, - A1: fp.Element{14824585485470590037, 7637124239293942071, 1041102438278370701, 4207950142422409777, 9639439542389544094, 106832755917361143}, - }, - { - A0: fp.Element{10744145886747796703, 8741979218876153119, 4537642647264646058, 9645243825719833866, 16643801652280184094, 57528843479739428}, - A1: fp.Element{5785935421797206370, 847985697064985249, 11478142027129258160, 12741057482356268413, 10148591557028647803, 106797667835022069}, - }, - { - A0: fp.Element{6454832842704992412, 9977685523482313420, 413111938383295655, 13594952949000658414, 17807487788385728582, 108984464456649540}, - A1: fp.Element{17048359867690489456, 2859252502285541521, 10818623701995947153, 7550564651763690537, 459333235977057482, 37663478480017988}, - }, - { - A0: fp.Element{8658783637463168087, 13532094408327228336, 12875492560745818922, 6809856611120372218, 2853890452345629690, 87034840621524077}, - A1: fp.Element{16301307707120111515, 9104654412985804807, 12475785366789695268, 4024450921325678435, 5626908908910088752, 56687303925216568}, - }, - { - A0: fp.Element{9729408098285946449, 14379177692720606450, 15077053755146607368, 1299576162980711320, 13990524355831736308, 88070216003513722}, - A1: fp.Element{5766436769337206504, 1093294963802231624, 1118315683159380206, 16238633443172785277, 5463682062430385614, 116508026946667814}, - }, - { - A0: fp.Element{16584249698770136319, 8326278446225484560, 3131917383401484830, 4756633391835977312, 7642636045510739113, 6547192373501023}, - A1: fp.Element{10803045440816594384, 6133821182275761752, 7762705812675926549, 15035799326051880159, 10201360843527298396, 76693252438359195}, - }, - { - A0: fp.Element{3621702609341817994, 1179514540952803843, 9695126383219869545, 4861853798003230532, 15648444733987506481, 103088924877589738}, - A1: fp.Element{0}, - }, - }, - x) -} - -func g2IsogenyXDenominator(dst *fptower.E2, x *fptower.E2) { - g2EvalPolynomial(dst, - true, - []fptower.E2{ - { - A0: fp.Element{1063048776114699222, 13419136991291290443, 17670140655952814712, 17007170270485437006, 2714055472280753035, 14919040757258909}, - A1: fp.Element{16666868668043867029, 10413023948165423527, 2513282340300795191, 5135056029366772344, 18074639060500180041, 66260525510488187}, - }, - { - A0: fp.Element{10940415603117103310, 2845175453419864190, 16971099885047235913, 4517542951822462583, 12015180195047358700, 101962474939260879}, - A1: fp.Element{1812172074217037271, 9040376510937171745, 1548369375982775200, 5323713323104515663, 11625954855074087334, 4220230277540083}, - }, - { - A0: fp.Element{8797262280793960976, 17802450974932240081, 10157003283304584770, 593225980605733121, 14184353532500093055, 108979035901112461}, - A1: fp.Element{15554837140147424903, 1512405638789788986, 3262333938884419786, 4638305243452530609, 139542405126620667, 54024907639584882}, - }, - { - A0: fp.Element{11424716963860540790, 13456329776215064369, 1929697779149270213, 6306593112502705131, 13859057472975507250, 41785102954052035}, - A1: fp.Element{7602541488494927932, 4897344463908346766, 17005994653424089316, 17216735712046963938, 3756018940504096168, 5402674048264985}, - }, - { - A0: fp.Element{2416535722849524790, 4831233808757576698, 17297774284520319797, 6772473332127607735, 18174962172090050489, 58994994344686536}, - A1: fp.Element{15610410799617712282, 9543692017702705957, 8970286522052539731, 12714219237879632746, 2449975609997710437, 10121059733973512}, - }, - { - A0: fp.Element{15388608950644940213, 15178518612850901922, 4663566445208062329, 3999751164791233677, 7358895960008222342, 33044898311505685}, - A1: fp.Element{2356569524239497521, 4634121806982763800, 13294827248503187097, 18379906191200424608, 13949207972645393879, 37350653623873291}, - }, - { - A0: fp.Element{4970487283568561993, 8451944303783250587, 10744185545939488302, 297910826254460501, 5663064319185246782, 55864728573479562}, - A1: fp.Element{13676619861655804765, 9740179349809417716, 1447466405783296044, 7262347140551810932, 4460517809397706328, 48696693541469882}, - }, - { - A0: fp.Element{4218670501850515232, 1300837062036343562, 6322288902222626865, 2517640049285419442, 15933997662514683752, 35742655751559900}, - A1: fp.Element{8671399843829082486, 10727571055999201132, 18066412728811459184, 2077243532292929295, 18402906919639961112, 11053564656556137}, - }, - { - A0: fp.Element{13549293427847064273, 13454861990004702789, 12625716182603551974, 16289223817658875114, 709786698748164395, 79373748066056979}, - A1: fp.Element{9755261456181601166, 8062867867952015070, 11667298511884909423, 12783693965971962594, 5335701901003645771, 118924945769569072}, - }, - { - A0: fp.Element{5024330816113629597, 9162185537450801251, 14637535063833510048, 5042964231794706299, 10987285991634226322, 46336617111585333}, - A1: fp.Element{17451698037621354790, 10238258568486351103, 10306732172443683782, 16783673474705190959, 2366024509224094980, 27102949281362657}, - }, - { - A0: fp.Element{1779719694787807439, 13682444363499832102, 319805876265464201, 10878143779945294209, 5260570358490406259, 111384964548942529}, - A1: fp.Element{10364815279125342799, 5955681787042171859, 16259776976357711022, 698420282628335564, 14458917752432688041, 9951241155641633}, - }, - { - A0: fp.Element{9860169129499874274, 4710132861939245083, 16729683163954203081, 1163919786098698325, 16999533791398931846, 45007426249965870}, - A1: fp.Element{1554156753268998897, 13001788039766734041, 13083055690099472212, 15457335577166095794, 9225717367159961098, 40091861438122274}, - }, - { - A0: fp.Element{15170394446649694794, 515688257282406708, 7546053921359572147, 2040402108618036352, 14910633907967741865, 51620635462170312}, - A1: fp.Element{14097816726424606264, 12505549891408832791, 13993079436736795338, 10172463092702817360, 608991345474995671, 70034669163571313}, - }, - { - A0: fp.Element{4643108199199003526, 15736620484932148216, 15681664113334307244, 17299685843716562967, 13906356132799386736, 93346316071232156}, - A1: fp.Element{4605618257264761423, 18021103018327472901, 16108946406338519358, 9045268489748282166, 5059321869053749600, 110536556169650965}, - }, - { - A0: fp.Element{11517108407780568371, 7978619811691229504, 9264608640258152436, 8451802924690124465, 4675285626878377699, 109463398958344863}, - A1: fp.Element{3597960821476001565, 3759680844169152876, 14302414818654496990, 17433096654117785124, 17967041042193057544, 85366167313641495}, - }, - { - A0: fp.Element{9939822412604413185, 13452127979624463736, 5130248585009642508, 3885932386715663181, 5051687816649505884, 77901780572240613}, - A1: fp.Element{519763984047258436, 9600915485628319569, 15140529797299450996, 9971542775239334883, 8807015558507490608, 948222705021672}, - }, - { - A0: fp.Element{2827339587428175511, 6895834130469522434, 13331059522798479027, 13955187059915735579, 14378880524037078149, 37849146151734053}, - A1: fp.Element{5659129353366385472, 1315670479643534676, 5263307416551198333, 6925817959331280727, 2077163856293267360, 78059303625906606}, - }, - { - A0: fp.Element{12063007979636530410, 11856928215255593909, 11875394835884852884, 7779285203935234969, 6621016507099994054, 58081312732574672}, - A1: fp.Element{16883486087598545310, 13020319043706888256, 13790070886127375971, 1584348143126996741, 14269751476430075034, 39520851290632316}, - }, - { - A0: fp.Element{10496651096160116529, 17447330314090714314, 7901980568892205616, 12523643767284114259, 14047697587913173436, 75967257029771325}, - A1: fp.Element{928850053641029162, 14269106311960337185, 16222409674828338261, 5805191570224440459, 18405225593952050465, 81611267238126250}, - }, - { - A0: fp.Element{11963245856892367752, 10425756598646938656, 18335238837348744770, 15086772981218061512, 16514870314421827966, 31505685309500160}, - A1: fp.Element{12503518650914401765, 9253053408485518576, 7574198415595259890, 9578781703355827570, 4997060354564847196, 4129967821132897}, - }, - { - A0: fp.Element{2031421031641935199, 11357963626711833272, 3216176135850906142, 18356175605205399499, 14930266308542898024, 45166487627178747}, - A1: fp.Element{4224679465464892278, 5162816687557914011, 9625001313214472999, 9646089844316603379, 3042432097393437616, 116654205222221531}, - }, - { - A0: fp.Element{707631102761073363, 4675040476129639901, 7917747947488915690, 10109499984363985170, 8993410474198507338, 72712009800189820}, - A1: fp.Element{13149412355826661761, 13738163990683470943, 2035497293527985654, 18119267602401018212, 2631647798265895027, 2795783216290358}, - }, - }, - x) -} - -func g2IsogenyYNumerator(dst *fptower.E2, x *fptower.E2, y *fptower.E2) { - var _dst fptower.E2 - g2EvalPolynomial(&_dst, - false, - []fptower.E2{ - { - A0: fp.Element{17926225976816550695, 14023720841551579195, 6357178813752170559, 1429363592569423041, 10398153225153858948, 33711798988254397}, - A1: fp.Element{2451854115792992988, 8983506616720050336, 2910564589437158732, 14075622914381394491, 9210830493684175792, 3356683084380210}, - }, - { - A0: fp.Element{5363401642911389912, 1675875184098052872, 15320530934239994732, 16287584047609698426, 10234580471621189795, 40152057551620421}, - A1: fp.Element{2205557896318444105, 4065007897235623968, 4049591920488634456, 16004168804099107709, 13290522222905374988, 70089339901218536}, - }, - { - A0: fp.Element{1887285394871164447, 7142690945990485012, 11190732658400833066, 6881717282640585612, 12116088968278807379, 103071704289665226}, - A1: fp.Element{15968649428224979513, 622837296484333259, 15527184444320989860, 2221190225062639140, 16647213690505955661, 110449865605275384}, - }, - { - A0: fp.Element{8732294600695513394, 7924365878303510912, 12588020556237861366, 10068029016225118132, 785053188876688927, 120347068207419939}, - A1: fp.Element{14514622768737464893, 5553264648606662629, 12707457796658055665, 6066303778837734141, 8279024849745683367, 3564406469625657}, - }, - { - A0: fp.Element{10035254538193759291, 9758866910217654439, 2724217928072676653, 3087232989313988901, 14980280964270815877, 34590022796322467}, - A1: fp.Element{15702474365778911803, 7256912742043165018, 1566344877835261304, 4035729625101537726, 16346625826270990512, 84087754076446931}, - }, - { - A0: fp.Element{8353555275402615800, 6017666668033757053, 13076202439893933084, 1913164921831891521, 13296563472388407395, 43485447354470561}, - A1: fp.Element{12571296156797641372, 13988198528186614994, 5672291450663514913, 7033607850615758657, 16846880911077910300, 44471894806759326}, - }, - { - A0: fp.Element{1319289899879823718, 1591088360172441240, 7805677496653365276, 5569897284498525554, 5635591756513279404, 74901024143303203}, - A1: fp.Element{10251017843654697682, 10395107644570958416, 3071938417266745181, 16127666859700570668, 5111665418914357408, 2168588371926498}, - }, - { - A0: fp.Element{7692831217085618076, 6702179445852008930, 11308520252707392151, 12038365346701529390, 7201289518723110646, 24757234241788495}, - A1: fp.Element{17948859968330001914, 10144279887227452625, 5167544611537672341, 4094514978127885079, 17912079766649616973, 45691468580901020}, - }, - { - A0: fp.Element{3911440855998194160, 13198838254872822648, 13301641437413064797, 11598620320741753383, 6260523097595092689, 78284230929812985}, - A1: fp.Element{7876366075466990529, 13523468790275433139, 982512625724968021, 2122595334378906057, 14803785928219626498, 71415583741911053}, - }, - { - A0: fp.Element{14923926944529083273, 3172840012894527710, 8293434476071337387, 16713256045335958267, 14057165773167995662, 57626475506313562}, - A1: fp.Element{1362417042314121750, 3304417561071796103, 17626406775105189491, 11748219015558348173, 14151421547261463616, 82460535821434588}, - }, - { - A0: fp.Element{3641967463568066103, 8959416625663108732, 5147508997828480363, 16811352377666989046, 1441182181356889676, 52012247235371457}, - A1: fp.Element{17686146190561162997, 11457769513035421935, 11629039572857129752, 16013548565551254584, 3489389447040062088, 108111902919606578}, - }, - { - A0: fp.Element{3810472718885394006, 2981020169366520013, 2816385682378197235, 153866317221550159, 11847618666936524337, 45551005605881971}, - A1: fp.Element{3468095351662354134, 4642197759139584052, 4233923780028877603, 17495173774535575422, 6042084483130094534, 67695926977382460}, - }, - { - A0: fp.Element{1324953063484934482, 15924484690572898301, 11397027945012096698, 2650928770069584769, 15779309286157100138, 107280353846472153}, - A1: fp.Element{7825813464319090460, 9031312139767459777, 142189155675192148, 6582610291000324889, 17102396003811978688, 22084094988625284}, - }, - { - A0: fp.Element{5210064249141309135, 1705543797894948713, 2628665872375881350, 13536211673960271710, 18420806283098729881, 115824256193502087}, - A1: fp.Element{15082907751180860242, 6568697878451242210, 16244491021091296231, 17790448340613041754, 7733097786923840729, 14504831353209381}, - }, - { - A0: fp.Element{1708526764431582271, 13958279355051552323, 14990211071762970223, 7884242526085975541, 16332397605884981291, 80533848446738849}, - A1: fp.Element{14979957683309612745, 6077136825354362762, 8344075647158254715, 10162044015152162839, 5892600246835629906, 87516868768986919}, - }, - { - A0: fp.Element{13823384149985104375, 400062563487168190, 14946453239900597346, 3063239780002983931, 12307299790663558215, 82575345472847758}, - A1: fp.Element{4955387593349539956, 11580263215419679285, 13810204272372323220, 15118104627613044122, 5709821153764726112, 97792497530186865}, - }, - { - A0: fp.Element{8029106480647627463, 9339835209992361362, 2257747803917390435, 13841766612482081060, 11846105036367819521, 10985089103756089}, - A1: fp.Element{12896564185217823813, 11446288085903243988, 7990576940036837900, 3323202217483830000, 8230734762253073878, 36590510406546600}, - }, - { - A0: fp.Element{9258620980666570289, 14799769271847025124, 3337623733744503313, 7847288847664005088, 4443979768963902018, 60018570132140318}, - A1: fp.Element{2675246192261018596, 15150250319428322656, 8044595947793549351, 17819017498503740634, 8168003399719773701, 50802205070212383}, - }, - { - A0: fp.Element{6416675551757596528, 11137110755893373387, 12196234615749865580, 10261229930898283794, 16443034629854739148, 92762661836396101}, - A1: fp.Element{2617757450501858457, 13481841765161333192, 14399351126797435540, 14845648777279341476, 16479218442290092360, 58694504406226241}, - }, - { - A0: fp.Element{2498292483400110656, 17577335584861186499, 17782334663901894811, 2829649086165738601, 1498570879458573752, 54126946483698861}, - A1: fp.Element{13664305368410221366, 15519373467383236285, 6930373704919785768, 5035259077705758702, 15118622066815350587, 76218461077450180}, - }, - { - A0: fp.Element{2359464294290896887, 15126005627433822176, 8745471049496239338, 16249169944251666409, 5887779353961924474, 9756279022859315}, - A1: fp.Element{4564346538121733135, 7083224900235365477, 12708889282498498077, 7850548098138279688, 14178174888234998222, 79663491154927524}, - }, - { - A0: fp.Element{2363371748841007386, 8201543480932182326, 3606722496785934427, 11335897361905574349, 7238564335142183540, 28370763379089425}, - A1: fp.Element{17773120842166679454, 6968817275085296949, 589078002303466881, 11901496965136831973, 17508389603594408067, 105726710734816064}, - }, - { - A0: fp.Element{7295712044514929446, 1419749005841863626, 15921158613862149232, 9464988326326595083, 4254037448365833139, 69144288462579473}, - A1: fp.Element{2330521880128496868, 6942731841460529291, 16753201799444057524, 5125438220420299042, 743707329901356982, 86418732453789215}, - }, - { - A0: fp.Element{10073672469351267894, 7530218602938011234, 12150950127635720924, 14699101300080070173, 3657462378365608060, 50677269975209252}, - A1: fp.Element{16217326474471800173, 12182932688121705224, 9523557196391803719, 13559107473982584173, 14264388955497449506, 89155196038187526}, - }, - { - A0: fp.Element{8500524953883552338, 13471246252006481381, 399342016929624192, 15321780621361720165, 1735807610194144505, 81584295376527434}, - A1: fp.Element{3028140852425956403, 9738549527114127103, 13145547273810927, 15439064114192138046, 15332022320720552951, 84308032823666865}, - }, - { - A0: fp.Element{8795699974103596314, 642987394252844125, 12559698238980671421, 15439596853334509309, 8192837603484177265, 86858193154220713}, - A1: fp.Element{13665577425741482529, 6924526015867702055, 8773433633434605845, 4385776193759960181, 14751123844375383386, 84259094466106596}, - }, - { - A0: fp.Element{6308743764871173820, 14529376135552483358, 3992864522868188832, 16018150786687814926, 14942376479240309869, 30721880050281254}, - A1: fp.Element{8640235552523037016, 9835096537876469025, 789797926152341591, 17554386444425767744, 2184317346571194421, 105569965705365467}, - }, - { - A0: fp.Element{10895141504918788686, 5671269070898752172, 9721970862384110947, 6958416614840799556, 18087813302866953828, 120526621462965167}, - A1: fp.Element{4966785024859028542, 18182687130036955400, 10092534947477547130, 11367367723010839926, 7417818378683193783, 94369912047147779}, - }, - { - A0: fp.Element{5709922971951703245, 10382852257937442526, 3453842328747730539, 16133368957829378910, 8271517063962590774, 9539719803485949}, - A1: fp.Element{1704900793320796784, 8995901783485359023, 9994857694012530400, 7408202244508772902, 18055801701001909838, 109149704128086904}, - }, - { - A0: fp.Element{8357460663115985094, 5765296628618444602, 6421674075164890879, 1651079036919805888, 1287520506307076832, 98975482931648514}, - A1: fp.Element{8078944849704442787, 4038716179863104913, 8864619430523621449, 11983583689047803099, 2541042365160408900, 28281336919305267}, - }, - { - A0: fp.Element{13472601104608613638, 521231156844377864, 4649313698209759510, 5796371833735044995, 8684999192663632207, 51033152603009675}, - A1: fp.Element{3409558318672010377, 10145443448574304058, 3995874611835909177, 15021984820089990008, 15242143999191686238, 73656911605031936}, - }, - { - A0: fp.Element{9770462122700591808, 17547477902406858790, 14010124614813851222, 4165622522809648336, 16982670942141592785, 28856170353703120}, - A1: fp.Element{15290128055618535720, 17454664547186830394, 2442682438806360163, 18129275600450347134, 4187898517238597724, 22281223126461925}, - }, - { - A0: fp.Element{12998303454550796060, 5752293956714303316, 6752814987597331313, 3166668351495264669, 9929418606104908953, 29385282975911842}, - A1: fp.Element{8756413506556179286, 143408982899135549, 2705277708630136288, 5154523209628123430, 6318572504564936509, 15532021916109921}, - }, - { - A0: fp.Element{18250508560718013179, 7486164413457419330, 8732750857092323232, 457033717118918321, 12167888022606617966, 20277559260742340}, - A1: fp.Element{0}, - }, - }, - x) - - dst.Mul(&_dst, y) -} - -func g2IsogenyYDenominator(dst *fptower.E2, x *fptower.E2) { - g2EvalPolynomial(dst, - true, - []fptower.E2{ - { - A0: fp.Element{2775408832476871526, 9008699192344519496, 1102884431771657931, 11532306452895462867, 5856674524343862704, 99430919144638985}, - A1: fp.Element{15551301223123894338, 11614654532478001117, 17328204268627498271, 15544698294678786409, 1484472732893154418, 94605104690421825}, - }, - { - A0: fp.Element{15538486723908094425, 10978766348102143722, 15056964343960721360, 8732109610906448146, 8620899699042055528, 1351681984895437}, - A1: fp.Element{3175104032835843731, 9314571151837830613, 14059118678096680542, 2500500275627160283, 18190796245603721369, 49058560079762280}, - }, - { - A0: fp.Element{2177050294381443304, 18124514285214412099, 9381797198372716589, 8046190315005422985, 9931273159159670369, 8036418831901820}, - A1: fp.Element{1549742439238596983, 15619417821567290543, 9431498181016104480, 2850048082163302555, 17545915875775834651, 72687252788290726}, - }, - { - A0: fp.Element{16572119218800158686, 13113809656757589233, 12872678318679566545, 3255385198038960565, 17070551903094984362, 19742086936927308}, - A1: fp.Element{12635717383520653743, 12204869003999147728, 8256611698395114158, 12382254302890131233, 603685913325391887, 60927550204070150}, - }, - { - A0: fp.Element{15497795759006280655, 16847324196958114585, 8218328297664216257, 15353718428023978640, 6357440186573265200, 109435672289072692}, - A1: fp.Element{17126430308003109280, 8510055147921463837, 2424009275722614739, 9284383313721206596, 12867548350984534889, 46750493171897961}, - }, - { - A0: fp.Element{6993808529266055670, 10024278910497662817, 6638820395273369627, 17550512930522052164, 11971278025880956390, 4218694435301565}, - A1: fp.Element{4117072311900938869, 8052759146924035127, 1883914237959498468, 843437547616490150, 1332392274725871932, 100467415201018114}, - }, - { - A0: fp.Element{10031273074038578964, 6635740043384123318, 2357760728051263554, 12405057037224522557, 2967360385882286162, 53130165628915609}, - A1: fp.Element{9340276074750471546, 8779557686584984578, 12118682911992514942, 8792287004994786286, 11729922744948342197, 97115621599174349}, - }, - { - A0: fp.Element{8243258075199662251, 789646305137795307, 9501755430432007632, 15339245131080115010, 3036491630055907252, 4720358405852701}, - A1: fp.Element{6272873484523042114, 18180794113363272037, 10135093694274252446, 13006427779172872075, 12612518697452888675, 4088970499189038}, - }, - { - A0: fp.Element{12559327402496405011, 13162954855686166920, 2622361684062280170, 16985128559432625018, 10671934355632922492, 22106668982430516}, - A1: fp.Element{10342048742210368049, 4070662490021521195, 9050590024293164750, 6778744574336170333, 16385669267342466637, 110676722503289309}, - }, - { - A0: fp.Element{8257142434361782318, 11625188549524762434, 4162174183904813140, 15534648919830235837, 15345786270187761745, 49274740272907617}, - A1: fp.Element{17452699565973497082, 1589725784862892127, 17590303103109791779, 8233530623701537904, 717929863606521126, 42679722481449639}, - }, - { - A0: fp.Element{17135289411523873787, 11725292909156152853, 16347014946116696110, 13323937426977246609, 8703182288833044255, 99079409785168386}, - A1: fp.Element{9130446173903866415, 12010725389601806440, 9146179391205715125, 12338366065383252573, 9136251064810045627, 19315728226188373}, - }, - { - A0: fp.Element{13754907156191096138, 22846764546901886, 362622052532339515, 17013010775786408901, 13860043181928645305, 41171875858186406}, - A1: fp.Element{16141340011263075417, 18360728019638818576, 16264128300543356196, 12473458415555386384, 18336837302801391285, 63727493440743041}, - }, - { - A0: fp.Element{3658804449581456923, 1347747705877184398, 3978302900333357541, 5081865331785059868, 1329643100050532471, 64102076251113639}, - A1: fp.Element{6980160750786278877, 11782099681251246419, 5400025369843657828, 9848695260591786723, 7987487093370334558, 27115517650078156}, - }, - { - A0: fp.Element{408044901411159465, 18068234941175928745, 2992890619264445487, 8810813216534328625, 4005157550725594837, 26065038549738560}, - A1: fp.Element{10975300981822504330, 15715038812214651197, 7602692888794350386, 12917547374269268270, 422938878523833779, 36305463980543648}, - }, - { - A0: fp.Element{10382180122959422967, 15807168734599653808, 18372044240449882372, 17642941170379477011, 10340644338271517361, 36063527972088465}, - A1: fp.Element{17969075460977832752, 9177853432360197657, 2917850475625504299, 7079850467696515295, 787036529903063845, 107077168732108508}, - }, - { - A0: fp.Element{6502963492633373835, 9890663567118850708, 12445720805224431135, 6172862156806685987, 16576315346783950860, 5856337016358393}, - A1: fp.Element{4476660199518722374, 3771101137683024451, 489075951782192448, 6489873046594013732, 280944977367484653, 69709094171715534}, - }, - { - A0: fp.Element{5629815848909521275, 5316587566230943622, 7982019375390215350, 15543803108203970386, 5941855484214597918, 5142365312974746}, - A1: fp.Element{3442509802156923890, 6170315030905476396, 2122926024914179804, 17368567939581660282, 12200117156652989113, 7492215668086454}, - }, - { - A0: fp.Element{15017092692882720799, 2306085001940265068, 6863750251390498522, 772425548835188093, 7866794496176459304, 119478713276832042}, - A1: fp.Element{539473290914229032, 10680532665300974652, 2401493774971219183, 771791041055281045, 17266300769954562072, 46203199265737132}, - }, - { - A0: fp.Element{12080185159744170157, 6121786867780957883, 13378966825252880343, 16978399570563241468, 13189121794372052505, 31306179382417939}, - A1: fp.Element{6033582013845463960, 10201637616554513673, 3729832524646428556, 2564427389283182369, 662893124657004215, 101996692818942248}, - }, - { - A0: fp.Element{14864583376459179927, 16267452113314442715, 14135040057928255187, 712462212063179204, 12089188474131830930, 36841165809084721}, - A1: fp.Element{13089068048776542239, 1568107234484844315, 4262841373517201534, 572974140393742986, 13114372614372436015, 221271375458892}, - }, - { - A0: fp.Element{15352358256255559128, 14776149476170502093, 13834021062045579807, 16108249515581661111, 7563707564996631205, 86582638494403858}, - A1: fp.Element{16813570010660423536, 3065722476932153407, 8938713923763210470, 2255995557158728394, 8016474455897300271, 84052925693202818}, - }, - { - A0: fp.Element{15615825726181497195, 5658715128964929728, 13877560309241249627, 15409847795806183219, 382506108092986341, 33112756833083889}, - A1: fp.Element{4921115267284233431, 2093038862301396370, 11859221373400371788, 14840702906540650688, 3187022540654844811, 12940014803022939}, - }, - { - A0: fp.Element{10653597201928750109, 13006094245282229535, 13295987796930539448, 16777781019019743602, 516306931828031556, 114717773318043797}, - A1: fp.Element{235309942988776203, 14860563794932685398, 4559874204394395321, 16639699308077583607, 9227151754747780541, 15908917446924874}, - }, - { - A0: fp.Element{17337820088369903748, 8586614709689721762, 1507576901396006569, 12700849903501888588, 17971589925911161601, 108264042385722694}, - A1: fp.Element{16945398252920060844, 12661842631743740793, 3757011696927843364, 15267617233875676717, 4747339870779259550, 34661428542359791}, - }, - { - A0: fp.Element{16466466374773138846, 14279763770124955377, 2253148650834359538, 7990858085823320889, 7124676177871440280, 94151727797031734}, - A1: fp.Element{15321139925728056718, 15122461222407649886, 17533799169860262777, 16804941505997951982, 1600681788854461369, 44486672743339990}, - }, - { - A0: fp.Element{8867142699562737491, 18199028041645162481, 3517239929170429351, 775467166380995197, 5868381756625215392, 6197719424154602}, - A1: fp.Element{9737125075096738524, 9629792455358261596, 11564279494282885105, 5089237230157463720, 17189088638807565425, 106712839297101083}, - }, - { - A0: fp.Element{10270843696704620770, 13223598872017291793, 9010388952516938805, 15912131807459901749, 6846913031975448418, 86431140578472953}, - A1: fp.Element{15439335117817990542, 18208862128889198852, 1680174721576182500, 13180416124629130962, 7418066627384568449, 3653571306187636}, - }, - { - A0: fp.Element{1131060365675191416, 10374247235014096023, 5274169106847399340, 9643591707517384578, 8354961201546942085, 16860653124975415}, - A1: fp.Element{7591061314547569259, 3687653994280978709, 14906524746128876973, 7376139658567228596, 3304769414542873433, 39389809689964413}, - }, - { - A0: fp.Element{15061500520004024506, 13781868913987378153, 1311923405823490306, 13614698003779137726, 2734567429318555742, 41565578486180068}, - A1: fp.Element{2264606496492496938, 7463181801259856780, 4974231603582406689, 12631973597673125932, 13768142234619696863, 69859376569568629}, - }, - { - A0: fp.Element{12977806950220507699, 9598682745345891240, 12727041082031765282, 13876739454320532788, 16731345162096153922, 52377912619410421}, - A1: fp.Element{9749487977108607359, 9452745135768007871, 17734899000824388188, 6032906020241168466, 3891046964558379200, 42965172988847872}, - }, - { - A0: fp.Element{15134142718037669741, 2650609953202022541, 18444582952265559358, 10072051383647105272, 1614233522361858494, 6353896085976033}, - A1: fp.Element{1244819074686382314, 16827930012669440062, 7409202602064068605, 7833164804348414003, 14093967246945573989, 91886691830462491}, - }, - { - A0: fp.Element{3481568382353274479, 1454015438048276221, 18321294391133087854, 11721714833000613979, 10732204074831352562, 71241856315356756}, - A1: fp.Element{2091942538387325776, 9875355486415603002, 12623384858601965052, 7559030465493899268, 7674739998354242578, 75767137192853634}, - }, - { - A0: fp.Element{5491757234451068988, 6182298996664147147, 1538132785577256287, 4999224323735886804, 6348107227722746450, 48518858347037381}, - A1: fp.Element{15293807953430533698, 2990763629845967503, 13391735075948095730, 9673810945847290845, 11089480180973857099, 64742831177682886}, - }, - }, - x) +// MapToG2 invokes the SSWU map, and guarantees that the result is in G2. +func MapToG2(u fptower.E2) G2Affine { + res := MapToCurve2(&u) + //this is in an isogenous curve + hash_to_curve.G2Isogeny(&res.X, &res.Y) + res.ClearCofactor(&res) + return res } -func g2Isogeny(p *G2Affine) { - - den := make([]fptower.E2, 2) - - g2IsogenyYDenominator(&den[1], &p.X) - g2IsogenyXDenominator(&den[0], &p.X) +// EncodeToG2 hashes a message to a point on the G2 curve using the SSWU map. +// It is faster than [HashToG2], but the result is not uniformly distributed. Unsuitable as a random oracle. +// dst stands for "domain separation tag", a string unique to the construction using the hash function +// +// See: https://www.rfc-editor.org/rfc/rfc9380.html#roadmap +func EncodeToG2(msg, dst []byte) (G2Affine, error) { - g2IsogenyYNumerator(&p.Y, &p.X, &p.Y) - g2IsogenyXNumerator(&p.X, &p.X) + var res G2Affine + u, err := fp.Hash(msg, dst, 2) + if err != nil { + return res, err + } - den = fptower.BatchInvertE2(den) + res = MapToCurve2(&fptower.E2{ + A0: u[0], + A1: u[1], + }) - p.X.Mul(&p.X, &den[0]) - p.Y.Mul(&p.Y, &den[1]) + //this is in an isogenous curve + hash_to_curve.G2Isogeny(&res.X, &res.Y) + res.ClearCofactor(&res) + return res, nil } -// g2SqrtRatio computes the square root of u/v and returns 0 iff u/v was indeed a quadratic residue -// if not, we get sqrt(Z * u / v). Recall that Z is non-residue -// If v = 0, u/v is meaningless and the output is unspecified, without raising an error. -// The main idea is that since the computation of the square root involves taking large powers of u/v, the inversion of v can be avoided -func g2SqrtRatio(z *fptower.E2, u *fptower.E2, v *fptower.E2) uint64 { - - // https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-sqrt_ratio-for-any-field - - tv1 := fptower.E2{ - A0: fp.Element{0}, - A1: fp.Element{9669507733633691314, 13074846433352412541, 11948543988290594071, 11104573675215509690, 878729975203857826, 120237394476367878}, - } //tv1 = c6 - - var tv2, tv3, tv4, tv5 fptower.E2 - var exp big.Int - // c4 = 140737488355327 = 2⁴⁷ - 1 - // q is odd so c1 is at least 1. - exp.SetBytes([]byte{127, 255, 255, 255, 255, 255}) - - tv2.Exp(*v, &exp) // 2. tv2 = vᶜ⁴ - tv3.Square(&tv2) // 3. tv3 = tv2² - tv3.Mul(&tv3, v) // 4. tv3 = tv3 * v - tv5.Mul(u, &tv3) // 5. tv5 = u * tv3 - - // c3 = 237702427642072544657662731610863241996908072983433720914596829155825880635712864411696995402952020023758239370111403151139377997388748144480691770738487127695940799749981367718443673617185911789718419957467908625 - exp.SetBytes([]byte{2, 211, 7, 208, 187, 175, 251, 34, 86, 145, 59, 179, 97, 38, 60, 75, 184, 184, 125, 164, 174, 233, 63, 31, 94, 113, 65, 61, 218, 77, 92, 9, 208, 24, 175, 185, 6, 96, 205, 192, 20, 231, 18, 80, 42, 77, 108, 70, 10, 170, 170, 139, 183, 10, 224, 49, 131, 36, 185, 88, 99, 140, 157, 107, 203, 251, 210, 53, 241, 192, 154, 74, 218, 38, 143, 46, 27, 216, 0, 115, 56, 210, 84, 240, 0, 0, 1, 10, 17}) - - tv5.Exp(tv5, &exp) // 6. tv5 = tv5ᶜ³ - tv5.Mul(&tv5, &tv2) // 7. tv5 = tv5 * tv2 - tv2.Mul(&tv5, v) // 8. tv2 = tv5 * v - tv3.Mul(&tv5, u) // 9. tv3 = tv5 * u - tv4.Mul(&tv3, &tv2) // 10. tv4 = tv3 * tv2 - - // c5 = 70368744177664 - exp.SetBytes([]byte{64, 0, 0, 0, 0, 0}) - tv5.Exp(tv4, &exp) // 11. tv5 = tv4ᶜ⁵ - isQNr := g2NotOne(&tv5) // 12. isQR = tv5 == 1 - c7 := fptower.E2{ - A0: fp.Element{1479358275892676257, 2814264704614556731, 13691179386454739330, 7530671302001941842, 60362263363904715, 37906327945374822}, - A1: fp.Element{5350190547200862053, 10822704806123199611, 5122684409451163826, 10616884767534481491, 1436196917100294910, 20226740120672211}, - } - tv2.Mul(&tv3, &c7) // 13. tv2 = tv3 * c7 - tv5.Mul(&tv4, &tv1) // 14. tv5 = tv4 * tv1 - tv3.Select(int(isQNr), &tv3, &tv2) // 15. tv3 = CMOV(tv2, tv3, isQR) - tv4.Select(int(isQNr), &tv4, &tv5) // 16. tv4 = CMOV(tv5, tv4, isQR) - exp.Lsh(big.NewInt(1), 47-2) // 18, 19: tv5 = 2ⁱ⁻² for i = c1 - - for i := 47; i >= 2; i-- { // 17. for i in (c1, c1 - 1, ..., 2): - - tv5.Exp(tv4, &exp) // 20. tv5 = tv4ᵗᵛ⁵ - nE1 := g2NotOne(&tv5) // 21. e1 = tv5 == 1 - tv2.Mul(&tv3, &tv1) // 22. tv2 = tv3 * tv1 - tv1.Mul(&tv1, &tv1) // 23. tv1 = tv1 * tv1 Why not write square? - tv5.Mul(&tv4, &tv1) // 24. tv5 = tv4 * tv1 - tv3.Select(int(nE1), &tv3, &tv2) // 25. tv3 = CMOV(tv2, tv3, e1) - tv4.Select(int(nE1), &tv4, &tv5) // 26. tv4 = CMOV(tv5, tv4, e1) - - if i > 2 { - exp.Rsh(&exp, 1) // 18, 19. tv5 = 2ⁱ⁻² - } +// HashToG2 hashes a message to a point on the G2 curve using the SSWU map. +// Slower than [EncodeToG2], but usable as a random oracle. +// dst stands for "domain separation tag", a string unique to the construction using the hash function. +// +// See https://www.rfc-editor.org/rfc/rfc9380.html#roadmap +func HashToG2(msg, dst []byte) (G2Affine, error) { + u, err := fp.Hash(msg, dst, 2*2) + if err != nil { + return G2Affine{}, err } - *z = tv3 - return isQNr -} - -func g2NotOne(x *fptower.E2) uint64 { - - //Assuming hash is implemented for G1 and that the curve is over Fp - var one fp.Element - return one.SetOne().NotEqual(&x.A0) | g1NotZero(&x.A1) + Q0 := MapToCurve2(&fptower.E2{ + A0: u[0], + A1: u[1], + }) + Q1 := MapToCurve2(&fptower.E2{ + A0: u[2+0], + A1: u[2+1], + }) -} + //TODO (perf): Add in E' first, then apply isogeny + hash_to_curve.G2Isogeny(&Q0.X, &Q0.Y) + hash_to_curve.G2Isogeny(&Q1.X, &Q1.Y) -// g2MulByZ multiplies x by [12, 1] and stores the result in z -func g2MulByZ(z *fptower.E2, x *fptower.E2) { + var _Q0, _Q1 G2Jac + _Q0.FromAffine(&Q0) + _Q1.FromAffine(&Q1).AddAssign(&_Q0) - z.Mul(x, &fptower.E2{ - A0: fp.Element{10560307807486212317, 9936456306313395274, 2092561269709285211, 8738829082964617622, 5243865315912343348, 114311569748804731}, - A1: fp.Element{202099033278250856, 5854854902718660529, 11492539364873682930, 8885205928937022213, 5545221690922665192, 39800542322357402}, - }) + _Q1.ClearCofactor(&_Q1) + Q1.FromJacobian(&_Q1) + return Q1, nil } -// https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-simplified-swu-method -// MapToCurve2 implements the SSWU map -// No cofactor clearing or isogeny +// MapToCurve2 implements the SSWU map. It does not perform cofactor clearing nor isogeny. For map to group, use [MapToG2]. +// +// See: https://www.rfc-editor.org/rfc/rfc9380.html#name-simplified-swu-method func MapToCurve2(u *fptower.E2) G2Affine { - - var sswuIsoCurveCoeffA = fptower.E2{ - A0: fp.Element{4274545572028848265, 14157081418478689358, 13123833976752631407, 4466041663276938746, 9062541850312583986, 90030181981586611}, - A1: fp.Element{4627353644986202063, 14941155654691983603, 14266958733709189881, 10264689865410103271, 10052798319587953375, 111844286035220969}, - } - var sswuIsoCurveCoeffB = fptower.E2{ - A0: fp.Element{10237434857876739089, 8476639787604822147, 6641637803208190023, 1721529389316620686, 8656544759275761743, 38999476160258021}, - A1: fp.Element{2360755569119276357, 10390833517265838837, 12467133771585386911, 8219721226907645480, 3130947551623757939, 83517800164149569}, - } + sswuIsoCurveCoeffA, sswuIsoCurveCoeffB := hash_to_curve.G2SSWUIsogenyCurveCoefficients() var tv1 fptower.E2 tv1.Square(u) // 1. tv1 = u² //mul tv1 by Z - g2MulByZ(&tv1, &tv1) // 2. tv1 = Z * tv1 + hash_to_curve.G2MulByZ(&tv1, &tv1) // 2. tv1 = Z * tv1 var tv2 fptower.E2 tv2.Square(&tv1) // 3. tv2 = tv1² @@ -642,13 +100,10 @@ func MapToCurve2(u *fptower.E2) G2Affine { tv3.Add(&tv2, &tv4) // 5. tv3 = tv2 + 1 tv3.Mul(&tv3, &sswuIsoCurveCoeffB) // 6. tv3 = B * tv3 - tv2NZero := g2NotZero(&tv2) + tv2NZero := hash_to_curve.G2NotZero(&tv2) // tv4 = Z - tv4 = fptower.E2{ - A0: fp.Element{10560307807486212317, 9936456306313395274, 2092561269709285211, 8738829082964617622, 5243865315912343348, 114311569748804731}, - A1: fp.Element{202099033278250856, 5854854902718660529, 11492539364873682930, 8885205928937022213, 5545221690922665192, 39800542322357402}, - } + tv4 = hash_to_curve.G2SSWUIsogenyZ() tv2.Neg(&tv2) tv4.Select(int(tv2NZero), &tv4, &tv2) // 7. tv4 = CMOV(Z, -tv2, tv2 != 0) @@ -673,7 +128,7 @@ func MapToCurve2(u *fptower.E2) G2Affine { x.Mul(&tv1, &tv3) // 17. x = tv1 * tv3 var y1 fptower.E2 - gx1NSquare := g2SqrtRatio(&y1, &tv2, &tv6) // 18. (is_gx1_square, y1) = sqrt_ratio(tv2, tv6) + gx1NSquare := hash_to_curve.G2SqrtRatio(&y1, &tv2, &tv6) // 18. (is_gx1_square, y1) = sqrt_ratio(tv2, tv6) var y fptower.E2 y.Mul(&tv1, u) // 19. y = tv1 * u @@ -684,7 +139,7 @@ func MapToCurve2(u *fptower.E2) G2Affine { y.Select(int(gx1NSquare), &y1, &y) // 22. y = CMOV(y, y1, is_gx1_square) y1.Neg(&y) - y.Select(int(g2Sgn0(u)^g2Sgn0(&y)), &y, &y1) + y.Select(int(hash_to_curve.G2Sgn0(u)^hash_to_curve.G2Sgn0(&y)), &y, &y1) // 23. e1 = sgn0(u) == sgn0(y) // 24. y = CMOV(-y, y, e1) @@ -693,117 +148,3 @@ func MapToCurve2(u *fptower.E2) G2Affine { return G2Affine{x, y} } - -func g2EvalPolynomial(z *fptower.E2, monic bool, coefficients []fptower.E2, x *fptower.E2) { - dst := coefficients[len(coefficients)-1] - - if monic { - dst.Add(&dst, x) - } - - for i := len(coefficients) - 2; i >= 0; i-- { - dst.Mul(&dst, x) - dst.Add(&dst, &coefficients[i]) - } - - z.Set(&dst) -} - -// g2Sgn0 is an algebraic substitute for the notion of sign in ordered fields -// Namely, every non-zero quadratic residue in a finite field of characteristic =/= 2 has exactly two square roots, one of each sign -// https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-the-sgn0-function -// The sign of an element is not obviously related to that of its Montgomery form -func g2Sgn0(z *fptower.E2) uint64 { - - nonMont := z.Bits() - - sign := uint64(0) // 1. sign = 0 - zero := uint64(1) // 2. zero = 1 - var signI uint64 - var zeroI uint64 - - // 3. i = 1 - signI = nonMont.A0[0] % 2 // 4. sign_i = x_i mod 2 - zeroI = g1NotZero(&nonMont.A0) - zeroI = 1 ^ (zeroI|-zeroI)>>63 // 5. zero_i = x_i == 0 - sign = sign | (zero & signI) // 6. sign = sign OR (zero AND sign_i) # Avoid short-circuit logic ops - zero = zero & zeroI // 7. zero = zero AND zero_i - // 3. i = 2 - signI = nonMont.A1[0] % 2 // 4. sign_i = x_i mod 2 - // 5. zero_i = x_i == 0 - sign = sign | (zero & signI) // 6. sign = sign OR (zero AND sign_i) # Avoid short-circuit logic ops - // 7. zero = zero AND zero_i - return sign - -} - -// MapToG2 invokes the SSWU map, and guarantees that the result is in g2 -func MapToG2(u fptower.E2) G2Affine { - res := MapToCurve2(&u) - //this is in an isogenous curve - g2Isogeny(&res) - res.ClearCofactor(&res) - return res -} - -// EncodeToG2 hashes a message to a point on the G2 curve using the SSWU map. -// It is faster than HashToG2, but the result is not uniformly distributed. Unsuitable as a random oracle. -// dst stands for "domain separation tag", a string unique to the construction using the hash function -// https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#roadmap -func EncodeToG2(msg, dst []byte) (G2Affine, error) { - - var res G2Affine - u, err := fp.Hash(msg, dst, 2) - if err != nil { - return res, err - } - - res = MapToCurve2(&fptower.E2{ - A0: u[0], - A1: u[1], - }) - - //this is in an isogenous curve - g2Isogeny(&res) - res.ClearCofactor(&res) - return res, nil -} - -// HashToG2 hashes a message to a point on the G2 curve using the SSWU map. -// Slower than EncodeToG2, but usable as a random oracle. -// dst stands for "domain separation tag", a string unique to the construction using the hash function -// https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#roadmap -func HashToG2(msg, dst []byte) (G2Affine, error) { - u, err := fp.Hash(msg, dst, 2*2) - if err != nil { - return G2Affine{}, err - } - - Q0 := MapToCurve2(&fptower.E2{ - A0: u[0], - A1: u[1], - }) - Q1 := MapToCurve2(&fptower.E2{ - A0: u[2+0], - A1: u[2+1], - }) - - //TODO (perf): Add in E' first, then apply isogeny - g2Isogeny(&Q0) - g2Isogeny(&Q1) - - var _Q0, _Q1 G2Jac - _Q0.FromAffine(&Q0) - _Q1.FromAffine(&Q1).AddAssign(&_Q0) - - _Q1.ClearCofactor(&_Q1) - - Q1.FromJacobian(&_Q1) - return Q1, nil -} - -func g2NotZero(x *fptower.E2) uint64 { - //Assuming G1 is over Fp and that if hashing is available for G2, it also is for G1 - return g1NotZero(&x.A0) | g1NotZero(&x.A1) - -} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/asm.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/asm.go index 49751a93969..83956e0b4c0 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/asm.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/asm.go @@ -1,28 +1,16 @@ //go:build !noadx -// +build !noadx -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT package fptower -import "golang.org/x/sys/cpu" +import "github.com/consensys/gnark-crypto/utils/cpu" // supportAdx will be set only on amd64 that has MULX and ADDX instructions var ( - supportAdx = cpu.X86.HasADX && cpu.X86.HasBMI2 + supportAdx = cpu.SupportADX _ = supportAdx // used in asm ) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/asm_noadx.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/asm_noadx.go index c6a97081fca..1dc20b49918 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/asm_noadx.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/asm_noadx.go @@ -1,19 +1,7 @@ //go:build noadx -// +build noadx -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/e12.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/e12.go index 45056247321..14e111341cc 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/e12.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/e12.go @@ -1,16 +1,5 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -67,14 +56,14 @@ func (z *E12) SetOne() *E12 { return z } -// Add set z=x+y in E12 and return z +// Add sets z=x+y in E12 and returns z func (z *E12) Add(x, y *E12) *E12 { z.C0.Add(&x.C0, &y.C0) z.C1.Add(&x.C1, &y.C1) return z } -// Sub sets z to x sub y and return z +// Sub sets z to x-y and returns z func (z *E12) Sub(x, y *E12) *E12 { z.C0.Sub(&x.C0, &y.C0) z.C1.Sub(&x.C1, &y.C1) @@ -99,16 +88,25 @@ func (z *E12) SetRandom() (*E12, error) { return z, nil } -// IsZero returns true if the two elements are equal, false otherwise +// MustSetRandom sets a0 and a1 to random values. +// It panics if reading form crypto/rand fails +func (z *E12) MustSetRandom() { + if _, err := z.SetRandom(); err != nil { + panic(err) + } +} + +// IsZero returns true if z is zero, false otherwise func (z *E12) IsZero() bool { return z.C0.IsZero() && z.C1.IsZero() } +// IsOne returns true if z is one, false otherwise func (z *E12) IsOne() bool { return z.C0.IsOne() && z.C1.IsZero() } -// Mul set z=x*y in E12 and return z +// Mul sets z=x*y in E12 and returns z func (z *E12) Mul(x, y *E12) *E12 { var a, b, c E6 a.Add(&x.C0, &x.C1) @@ -121,7 +119,7 @@ func (z *E12) Mul(x, y *E12) *E12 { return z } -// Square set z=x*x in E12 and return z +// Square sets z=x*x in E12 and returns z func (z *E12) Square(x *E12) *E12 { //Algorithm 22 from https://eprint.iacr.org/2010/354.pdf @@ -406,7 +404,7 @@ func (z *E12) CyclotomicSquare(x *E12) *E12 { return z } -// Inverse set z to the inverse of x in E12 and return z +// Inverse sets z to the inverse of x in E12 and returns z // // if x == 0, sets and returns z = x func (z *E12) Inverse(x *E12) *E12 { @@ -424,8 +422,8 @@ func (z *E12) Inverse(x *E12) *E12 { return z } -// BatchInvertE12 returns a new slice with every element inverted. -// Uses Montgomery batch inversion trick +// BatchInvertE12 returns a new slice with every element in a inverted. +// It uses Montgomery batch inversion trick. // // if a[i] == 0, returns result[i] = a[i] func BatchInvertE12(a []E12) []E12 { @@ -635,12 +633,12 @@ func (z *E12) ExpGLV(x E12, k *big.Int) *E12 { return z } -// InverseUnitary inverse a unitary element +// InverseUnitary inverses a unitary element func (z *E12) InverseUnitary(x *E12) *E12 { return z.Conjugate(x) } -// Conjugate set z to x conjugated and return z +// Conjugate sets z to x conjugated and returns z func (z *E12) Conjugate(x *E12) *E12 { *z = *x z.C1.Neg(&z.C1) @@ -846,6 +844,8 @@ func BatchDecompressTorus(x []E6) ([]E12, error) { return res, nil } +// Select is conditional move. +// If cond = 0, it sets z to caseZ and returns it. otherwise caseNz. func (z *E12) Select(cond int, caseZ *E12, caseNz *E12) *E12 { //Might be able to save a nanosecond or two by an aggregate implementation @@ -855,6 +855,7 @@ func (z *E12) Select(cond int, caseZ *E12, caseNz *E12) *E12 { return z } +// Div divides an element in E12 by an element in E12 func (z *E12) Div(x *E12, y *E12) *E12 { var r E12 r.Inverse(y).Mul(x, &r) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/e12_pairing.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/e12_pairing.go index 6888dfc4fca..3af62247399 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/e12_pairing.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/e12_pairing.go @@ -52,9 +52,31 @@ func (z *E12) MulBy034(c0, c3, c4 *E2) *E12 { b.Set(&z.C1) b.MulBy01(c3, c4) - c0.Add(c0, c3) + var d0 E2 + d0.Add(c0, c3) d.Add(&z.C0, &z.C1) - d.MulBy01(c0, c4) + d.MulBy01(&d0, c4) + + z.C1.Add(&a, &b).Neg(&z.C1).Add(&z.C1, &d) + z.C0.MulByNonResidue(&b).Add(&z.C0, &a) + + return z +} + +// MulBy34 multiplication by sparse element (1,0,0,c3,c4,0) +func (z *E12) MulBy34(c3, c4 *E2) *E12 { + + var a, b, d E6 + + a.Set(&z.C0) + + b.Set(&z.C1) + b.MulBy01(c3, c4) + + var d0 E2 + d0.SetOne().Add(&d0, c3) + d.Add(&z.C0, &z.C1) + d.MulBy01(&d0, c4) z.C1.Add(&a, &b).Neg(&z.C1).Add(&z.C1, &d) z.C0.MulByNonResidue(&b).Add(&z.C0, &a) @@ -90,6 +112,26 @@ func Mul034By034(d0, d3, d4, c0, c3, c4 *E2) [5]E2 { return [5]E2{z00, x3, x34, x03, x04} } +// Mul34By34 multiplication of sparse element (1,0,0,c3,c4,0) by sparse element (1,0,0,d3,d4,0) +func Mul34By34(d3, d4, c3, c4 *E2) [5]E2 { + var z00, tmp, x0, x3, x4, x04, x03, x34 E2 + x3.Mul(c3, d3) + x4.Mul(c4, d4) + x04.Add(c4, d4) + x03.Add(c3, d3) + tmp.Add(c3, c4) + x34.Add(d3, d4). + Mul(&x34, &tmp). + Sub(&x34, &x3). + Sub(&x34, &x4) + + x0.SetOne() + z00.MulByNonResidue(&x4). + Add(&z00, &x0) + + return [5]E2{z00, x3, x34, x03, x04} +} + // MulBy01234 multiplies z by an E12 sparse element of the form (x0, x1, x2, x3, x4, 0) func (z *E12) MulBy01234(x *[5]E2) *E12 { var c1, a, b, c, z0, z1 E6 diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/e2.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/e2.go index 874802d7433..e8793a0c769 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/e2.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/e2.go @@ -1,16 +1,5 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -101,11 +90,20 @@ func (z *E2) SetRandom() (*E2, error) { return z, nil } -// IsZero returns true if the two elements are equal, false otherwise +// MustSetRandom sets a0 and a1 to random values. +// It panics if reading form crypto/rand fails +func (z *E2) MustSetRandom() { + if _, err := z.SetRandom(); err != nil { + panic(err) + } +} + +// IsZero returns true if z is zero, false otherwise func (z *E2) IsZero() bool { return z.A0.IsZero() && z.A1.IsZero() } +// IsOne returns true if z is one, false otherwise func (z *E2) IsOne() bool { return z.A0.IsOne() && z.A1.IsZero() } @@ -116,7 +114,7 @@ func (z *E2) Add(x, y *E2) *E2 { return z } -// Sub two elements of E2 +// Sub subtracts two elements of E2 func (z *E2) Sub(x, y *E2) *E2 { subE2(z, x, y) return z @@ -155,7 +153,7 @@ func (z *E2) Conjugate(x *E2) *E2 { return z } -// Halve sets z = z / 2 +// Halve sets z to z / 2 func (z *E2) Halve() { z.A0.Halve() z.A1.Halve() @@ -242,8 +240,8 @@ func (z *E2) Sqrt(x *E2) *E2 { return z } -// BatchInvertE2 returns a new slice with every element inverted. -// Uses Montgomery batch inversion trick +// BatchInvertE2 returns a new slice with every element in a inverted. +// It uses Montgomery batch inversion trick. // // if a[i] == 0, returns result[i] = a[i] func BatchInvertE2(a []E2) []E2 { @@ -278,6 +276,8 @@ func BatchInvertE2(a []E2) []E2 { return res } +// Select is conditional move. +// If cond = 0, it sets z to caseZ and returns it. otherwise caseNz. func (z *E2) Select(cond int, caseZ *E2, caseNz *E2) *E2 { //Might be able to save a nanosecond or two by an aggregate implementation @@ -287,6 +287,7 @@ func (z *E2) Select(cond int, caseZ *E2, caseNz *E2) *E2 { return z } +// Div divides an element in E2 by an element in E2 func (z *E2) Div(x *E2, y *E2) *E2 { var r E2 r.Inverse(y).Mul(x, &r) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/e2_amd64.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/e2_amd64.go index ac68ffa5782..0089530007e 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/e2_amd64.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/e2_amd64.go @@ -1,21 +1,37 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT package fptower +import ( + "github.com/consensys/gnark-crypto/ecc/bls12-377/fp" +) + +// q + r'.r = 1, i.e., qInvNeg = - q⁻¹ mod r +// used for Montgomery reduction +const qInvNeg uint64 = 9586122913090633727 + +// Field modulus q (Fp) +const ( + q0 uint64 = 9586122913090633729 + q1 uint64 = 1660523435060625408 + q2 uint64 = 2230234197602682880 + q3 uint64 = 1883307231910630287 + q4 uint64 = 14284016967150029115 + q5 uint64 = 121098312706494698 +) + +var qElement = fp.Element{ + q0, + q1, + q2, + q3, + q4, + q5, +} + //go:noescape func addE2(res, x, y *E2) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/e2_amd64.s b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/e2_amd64.s index 053bd8ded17..e40a4d91e01 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/e2_amd64.s +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/e2_amd64.s @@ -1,52 +1,29 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. #include "textflag.h" #include "funcdata.h" - -// modulus q -DATA q<>+0(SB)/8, $0x8508c00000000001 -DATA q<>+8(SB)/8, $0x170b5d4430000000 -DATA q<>+16(SB)/8, $0x1ef3622fba094800 -DATA q<>+24(SB)/8, $0x1a22d9f300f5138f -DATA q<>+32(SB)/8, $0xc63b05c06ca1493b -DATA q<>+40(SB)/8, $0x01ae3a4617c510ea -GLOBL q<>(SB), (RODATA+NOPTR), $48 - -// qInv0 q'[0] -DATA qInv0<>(SB)/8, $0x8508bfffffffffff -GLOBL qInv0<>(SB), (RODATA+NOPTR), $8 +#include "go_asm.h" #define REDUCE(ra0, ra1, ra2, ra3, ra4, ra5, rb0, rb1, rb2, rb3, rb4, rb5) \ - MOVQ ra0, rb0; \ - SUBQ q<>(SB), ra0; \ - MOVQ ra1, rb1; \ - SBBQ q<>+8(SB), ra1; \ - MOVQ ra2, rb2; \ - SBBQ q<>+16(SB), ra2; \ - MOVQ ra3, rb3; \ - SBBQ q<>+24(SB), ra3; \ - MOVQ ra4, rb4; \ - SBBQ q<>+32(SB), ra4; \ - MOVQ ra5, rb5; \ - SBBQ q<>+40(SB), ra5; \ - CMOVQCS rb0, ra0; \ - CMOVQCS rb1, ra1; \ - CMOVQCS rb2, ra2; \ - CMOVQCS rb3, ra3; \ - CMOVQCS rb4, ra4; \ - CMOVQCS rb5, ra5; \ + MOVQ ra0, rb0; \ + SUBQ ·qElement(SB), ra0; \ + MOVQ ra1, rb1; \ + SBBQ ·qElement+8(SB), ra1; \ + MOVQ ra2, rb2; \ + SBBQ ·qElement+16(SB), ra2; \ + MOVQ ra3, rb3; \ + SBBQ ·qElement+24(SB), ra3; \ + MOVQ ra4, rb4; \ + SBBQ ·qElement+32(SB), ra4; \ + MOVQ ra5, rb5; \ + SBBQ ·qElement+40(SB), ra5; \ + CMOVQCS rb0, ra0; \ + CMOVQCS rb1, ra1; \ + CMOVQCS rb2, ra2; \ + CMOVQCS rb3, ra3; \ + CMOVQCS rb4, ra4; \ + CMOVQCS rb5, ra5; \ TEXT ·addE2(SB), NOSPLIT, $0-24 MOVQ x+8(FP), AX diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/e2_bls377.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/e2_bls377.go index 9505d531533..8e744274f13 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/e2_bls377.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/e2_bls377.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys AG -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. package fptower diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/e2_fallback.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/e2_fallback.go index 6fe47c4111b..7a2461ec533 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/e2_fallback.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/e2_fallback.go @@ -1,19 +1,7 @@ //go:build !amd64 -// +build !amd64 -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/e6.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/e6.go index 128007df278..4c932208b41 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/e6.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/e6.go @@ -1,16 +1,5 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -63,11 +52,20 @@ func (z *E6) SetRandom() (*E6, error) { return z, nil } -// IsZero returns true if the two elements are equal, false otherwise +// MustSetRandom sets a0 and a1 to random values. +// It panics if reading form crypto/rand fails +func (z *E6) MustSetRandom() { + if _, err := z.SetRandom(); err != nil { + panic(err) + } +} + +// IsZero returns true if z is zero, false otherwise func (z *E6) IsZero() bool { return z.B0.IsZero() && z.B1.IsZero() && z.B2.IsZero() } +// IsOne returns true if z is one, false otherwise func (z *E6) IsOne() bool { return z.B0.IsOne() && z.B1.IsZero() && z.B2.IsZero() } @@ -88,7 +86,7 @@ func (z *E6) Neg(x *E6) *E6 { return z } -// Sub two elements of E6 +// Sub subtracts two elements of E6 func (z *E6) Sub(x, y *E6) *E6 { z.B0.Sub(&x.B0, &y.B0) z.B1.Sub(&x.B1, &y.B1) @@ -286,8 +284,8 @@ func (z *E6) Inverse(x *E6) *E6 { return z } -// BatchInvertE6 returns a new slice with every element inverted. -// Uses Montgomery batch inversion trick +// BatchInvertE6 returns a new slice with every element in a inverted. +// It uses Montgomery batch inversion trick. // // if a[i] == 0, returns result[i] = a[i] func BatchInvertE6(a []E6) []E6 { @@ -322,6 +320,8 @@ func BatchInvertE6(a []E6) []E6 { return res } +// Select is conditional move. +// If cond = 0, it sets z to caseZ and returns it. otherwise caseNz. func (z *E6) Select(cond int, caseZ *E6, caseNz *E6) *E6 { //Might be able to save a nanosecond or two by an aggregate implementation @@ -332,6 +332,7 @@ func (z *E6) Select(cond int, caseZ *E6, caseNz *E6) *E6 { return z } +// Div divides an element in E6 by an element in E6 func (z *E6) Div(x *E6, y *E6) *E6 { var r E6 r.Inverse(y).Mul(x, &r) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/frobenius.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/frobenius.go index a7e1b2a812a..44ca7315bdf 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/frobenius.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/frobenius.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys AG -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. package fptower diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/parameters.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/parameters.go index 6f2b1d6c7e2..374a13edeea 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/parameters.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower/parameters.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys AG -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. package fptower diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/marshal.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/marshal.go index 317f7c53541..770f18c7e12 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/marshal.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/marshal.go @@ -1,16 +1,5 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -171,6 +160,26 @@ func (dec *Decoder) Decode(v interface{}) (err error) { dec.n += read64 } return + case *[][][]fr.Element: + if sliceLen, err = dec.readUint32(); err != nil { + return + } + if len(*t) != int(sliceLen) { + *t = make([][][]fr.Element, sliceLen) + } + for i := range *t { + if sliceLen, err = dec.readUint32(); err != nil { + return + } + if len((*t)[i]) != int(sliceLen) { + (*t)[i] = make([][]fr.Element, sliceLen) + } + for j := range (*t)[i] { + read64, err = (*fr.Vector)(&(*t)[i][j]).ReadFrom(dec.r) + dec.n += read64 + } + } + return case *G1Affine: // we start by reading compressed point size, if metadata tells us it is uncompressed, we read more. read, err = io.ReadFull(dec.r, buf[:SizeOfG1AffineCompressed]) @@ -426,7 +435,7 @@ func NewEncoder(w io.Writer, options ...func(*Encoder)) *Encoder { } // Encode writes the binary encoding of v to the stream -// type must be uint64, *fr.Element, *fp.Element, *G1Affine, *G2Affine, []G1Affine or []G2Affine +// type must be uint64, *fr.Element, *fp.Element, *G1Affine, *G2Affine, []G1Affine, []G2Affine, *[]G1Affine or *[]G2Affine func (enc *Encoder) Encode(v interface{}) (err error) { if enc.raw { return enc.encodeRaw(v) @@ -537,6 +546,27 @@ func (enc *Encoder) encode(v interface{}) (err error) { enc.n += written64 } return + case [][][]fr.Element: + // number of collections + if err = binary.Write(enc.w, binary.BigEndian, uint32(len(t))); err != nil { + return + } + enc.n += 4 + for i := range t { + // size of current collection + if err = binary.Write(enc.w, binary.BigEndian, uint32(len(t[i]))); err != nil { + return + } + enc.n += 4 + // write each vector of the current collection + for j := range t[i] { + written64, err = (*fr.Vector)(&t[i][j]).WriteTo(enc.w) + enc.n += written64 + } + } + return + case *[]G1Affine: + return enc.encode(*t) case []G1Affine: // write slice length err = binary.Write(enc.w, binary.BigEndian, uint32(len(t))) @@ -556,6 +586,8 @@ func (enc *Encoder) encode(v interface{}) (err error) { } } return nil + case *[]G2Affine: + return enc.encode(*t) case []G2Affine: // write slice length err = binary.Write(enc.w, binary.BigEndian, uint32(len(t))) @@ -655,6 +687,27 @@ func (enc *Encoder) encodeRaw(v interface{}) (err error) { enc.n += written64 } return + case [][][]fr.Element: + // number of collections + if err = binary.Write(enc.w, binary.BigEndian, uint32(len(t))); err != nil { + return + } + enc.n += 4 + for i := range t { + // size of current collection + if err = binary.Write(enc.w, binary.BigEndian, uint32(len(t[i]))); err != nil { + return + } + enc.n += 4 + // write each vector of the current collection + for j := range t[i] { + written64, err = (*fr.Vector)(&t[i][j]).WriteTo(enc.w) + enc.n += written64 + } + } + return + case *[]G1Affine: + return enc.encodeRaw(*t) case []G1Affine: // write slice length err = binary.Write(enc.w, binary.BigEndian, uint32(len(t))) @@ -674,6 +727,8 @@ func (enc *Encoder) encodeRaw(v interface{}) (err error) { } } return nil + case *[]G2Affine: + return enc.encodeRaw(*t) case []G2Affine: // write slice length err = binary.Write(enc.w, binary.BigEndian, uint32(len(t))) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/multiexp.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/multiexp.go index 8ae82e0a3bd..93bbfa633dd 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/multiexp.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/multiexp.go @@ -1,16 +1,5 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -323,6 +312,31 @@ func msmReduceChunkG1Affine(p *G1Jac, c int, chChunks []chan g1JacExtended) *G1J return p.unsafeFromJacExtended(&_p) } +// Fold computes the multi-exponentiation \sum_{i=0}^{len(points)-1} points[i] * +// combinationCoeff^i and stores the result in p. It returns error in case +// configuration is invalid. +func (p *G1Affine) Fold(points []G1Affine, combinationCoeff fr.Element, config ecc.MultiExpConfig) (*G1Affine, error) { + var _p G1Jac + if _, err := _p.Fold(points, combinationCoeff, config); err != nil { + return nil, err + } + p.FromJacobian(&_p) + return p, nil +} + +// Fold computes the multi-exponentiation \sum_{i=0}^{len(points)-1} points[i] * +// combinationCoeff^i and stores the result in p. It returns error in case +// configuration is invalid. +func (p *G1Jac) Fold(points []G1Affine, combinationCoeff fr.Element, config ecc.MultiExpConfig) (*G1Jac, error) { + scalars := make([]fr.Element, len(points)) + scalar := fr.NewElement(1) + for i := 0; i < len(points); i++ { + scalars[i].Set(&scalar) + scalar.Mul(&scalar, &combinationCoeff) + } + return p.MultiExp(points, scalars, config) +} + // MultiExp implements section 4 of https://eprint.iacr.org/2012/549.pdf // // This call return an error if len(scalars) != len(points) or if provided config is invalid. @@ -621,6 +635,31 @@ func msmReduceChunkG2Affine(p *G2Jac, c int, chChunks []chan g2JacExtended) *G2J return p.unsafeFromJacExtended(&_p) } +// Fold computes the multi-exponentiation \sum_{i=0}^{len(points)-1} points[i] * +// combinationCoeff^i and stores the result in p. It returns error in case +// configuration is invalid. +func (p *G2Affine) Fold(points []G2Affine, combinationCoeff fr.Element, config ecc.MultiExpConfig) (*G2Affine, error) { + var _p G2Jac + if _, err := _p.Fold(points, combinationCoeff, config); err != nil { + return nil, err + } + p.FromJacobian(&_p) + return p, nil +} + +// Fold computes the multi-exponentiation \sum_{i=0}^{len(points)-1} points[i] * +// combinationCoeff^i and stores the result in p. It returns error in case +// configuration is invalid. +func (p *G2Jac) Fold(points []G2Affine, combinationCoeff fr.Element, config ecc.MultiExpConfig) (*G2Jac, error) { + scalars := make([]fr.Element, len(points)) + scalar := fr.NewElement(1) + for i := 0; i < len(points); i++ { + scalars[i].Set(&scalar) + scalar.Mul(&scalar, &combinationCoeff) + } + return p.MultiExp(points, scalars, config) +} + // selector stores the index, mask and shifts needed to select bits from a scalar // it is used during the multiExp algorithm or the batch scalar multiplication type selector struct { diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/multiexp_affine.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/multiexp_affine.go index 422862c77a4..d82f02e47b1 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/multiexp_affine.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/multiexp_affine.go @@ -1,16 +1,5 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -30,7 +19,7 @@ type batchOpG1Affine struct { // using affine coordinates for the buckets. To amortize the cost of the inverse in the affine addition // we use a batch affine addition. // -// this is derived from a PR by 0x0ece : https://github.com/ConsenSys/gnark-crypto/pull/249 +// this is derived from a PR by 0x0ece : https://github.com/Consensys/gnark-crypto/pull/249 // See Section 5.3: ia.cr/2022/1396 func processChunkG1BatchAffine[BJE ibg1JacExtended, B ibG1Affine, BS bitSet, TP pG1Affine, TPP ppG1Affine, TQ qOpsG1Affine, TC cG1Affine]( chunk uint64, @@ -60,11 +49,10 @@ func processChunkG1BatchAffine[BJE ibg1JacExtended, B ibG1Affine, BS bitSet, TP // note that we have 2 sets of buckets // 1 in G1Affine used with the batch affine additions // 1 in g1JacExtended used in case the queue of conflicting points - var buckets B + var buckets B // in G1Affine coordinates, infinity point is represented as (0,0), no need to init var bucketsJE BJE for i := 0; i < len(buckets); i++ { - buckets[i].setInfinity() - bucketsJE[i].setInfinity() + bucketsJE[i].SetInfinity() } // setup for the batch affine; @@ -107,7 +95,7 @@ func processChunkG1BatchAffine[BJE ibg1JacExtended, B ibG1Affine, BS bitSet, TP bucketsJE[op.bucketID].addMixed(&op.point) return } - BK.setInfinity() + BK.SetInfinity() return } @@ -135,12 +123,12 @@ func processChunkG1BatchAffine[BJE ibg1JacExtended, B ibG1Affine, BS bitSet, TP if isAdd { bucketsJE[bucketID].addMixed(PP) } else { - BK.setInfinity() + BK.SetInfinity() } return } if isAdd { - BK.setInfinity() + BK.SetInfinity() } else { bucketsJE[bucketID].subMixed(PP) } @@ -222,11 +210,11 @@ func processChunkG1BatchAffine[BJE ibg1JacExtended, B ibG1Affine, BS bitSet, TP // reduce buckets into total // total = bucket[0] + 2*bucket[1] + 3*bucket[2] ... + n*bucket[n-1] var runningSum, total g1JacExtended - runningSum.setInfinity() - total.setInfinity() + runningSum.SetInfinity() + total.SetInfinity() for k := len(buckets) - 1; k >= 0; k-- { runningSum.addMixed(&buckets[k]) - if !bucketsJE[k].IsZero() { + if !bucketsJE[k].IsInfinity() { runningSum.add(&bucketsJE[k]) } total.add(&runningSum) @@ -358,7 +346,7 @@ type batchOpG2Affine struct { // using affine coordinates for the buckets. To amortize the cost of the inverse in the affine addition // we use a batch affine addition. // -// this is derived from a PR by 0x0ece : https://github.com/ConsenSys/gnark-crypto/pull/249 +// this is derived from a PR by 0x0ece : https://github.com/Consensys/gnark-crypto/pull/249 // See Section 5.3: ia.cr/2022/1396 func processChunkG2BatchAffine[BJE ibg2JacExtended, B ibG2Affine, BS bitSet, TP pG2Affine, TPP ppG2Affine, TQ qOpsG2Affine, TC cG2Affine]( chunk uint64, @@ -388,11 +376,10 @@ func processChunkG2BatchAffine[BJE ibg2JacExtended, B ibG2Affine, BS bitSet, TP // note that we have 2 sets of buckets // 1 in G2Affine used with the batch affine additions // 1 in g2JacExtended used in case the queue of conflicting points - var buckets B + var buckets B // in G2Affine coordinates, infinity point is represented as (0,0), no need to init var bucketsJE BJE for i := 0; i < len(buckets); i++ { - buckets[i].setInfinity() - bucketsJE[i].setInfinity() + bucketsJE[i].SetInfinity() } // setup for the batch affine; @@ -435,7 +422,7 @@ func processChunkG2BatchAffine[BJE ibg2JacExtended, B ibG2Affine, BS bitSet, TP bucketsJE[op.bucketID].addMixed(&op.point) return } - BK.setInfinity() + BK.SetInfinity() return } @@ -463,12 +450,12 @@ func processChunkG2BatchAffine[BJE ibg2JacExtended, B ibG2Affine, BS bitSet, TP if isAdd { bucketsJE[bucketID].addMixed(PP) } else { - BK.setInfinity() + BK.SetInfinity() } return } if isAdd { - BK.setInfinity() + BK.SetInfinity() } else { bucketsJE[bucketID].subMixed(PP) } @@ -550,11 +537,11 @@ func processChunkG2BatchAffine[BJE ibg2JacExtended, B ibG2Affine, BS bitSet, TP // reduce buckets into total // total = bucket[0] + 2*bucket[1] + 3*bucket[2] ... + n*bucket[n-1] var runningSum, total g2JacExtended - runningSum.setInfinity() - total.setInfinity() + runningSum.SetInfinity() + total.SetInfinity() for k := len(buckets) - 1; k >= 0; k-- { runningSum.addMixed(&buckets[k]) - if !bucketsJE[k].IsZero() { + if !bucketsJE[k].IsInfinity() { runningSum.add(&bucketsJE[k]) } total.add(&runningSum) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/multiexp_jacobian.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/multiexp_jacobian.go index 0df516f5b9e..5bc761f3045 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/multiexp_jacobian.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/multiexp_jacobian.go @@ -1,16 +1,5 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -30,7 +19,7 @@ func processChunkG1Jacobian[B ibg1JacExtended](chunk uint64, var buckets B for i := 0; i < len(buckets); i++ { - buckets[i].setInfinity() + buckets[i].SetInfinity() } // for each scalars, get the digit corresponding to the chunk we're processing. @@ -53,10 +42,10 @@ func processChunkG1Jacobian[B ibg1JacExtended](chunk uint64, // total = bucket[0] + 2*bucket[1] + 3*bucket[2] ... + n*bucket[n-1] var runningSum, total g1JacExtended - runningSum.setInfinity() - total.setInfinity() + runningSum.SetInfinity() + total.SetInfinity() for k := len(buckets) - 1; k >= 0; k-- { - if !buckets[k].IsZero() { + if !buckets[k].IsInfinity() { runningSum.add(&buckets[k]) } total.add(&runningSum) @@ -119,7 +108,7 @@ func processChunkG2Jacobian[B ibg2JacExtended](chunk uint64, var buckets B for i := 0; i < len(buckets); i++ { - buckets[i].setInfinity() + buckets[i].SetInfinity() } // for each scalars, get the digit corresponding to the chunk we're processing. @@ -142,10 +131,10 @@ func processChunkG2Jacobian[B ibg2JacExtended](chunk uint64, // total = bucket[0] + 2*bucket[1] + 3*bucket[2] ... + n*bucket[n-1] var runningSum, total g2JacExtended - runningSum.setInfinity() - total.setInfinity() + runningSum.SetInfinity() + total.SetInfinity() for k := len(buckets) - 1; k >= 0; k-- { - if !buckets[k].IsZero() { + if !buckets[k].IsInfinity() { runningSum.add(&buckets[k]) } total.add(&runningSum) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/pairing.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/pairing.go index f670902e4b0..bdef731e1c1 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/pairing.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-377/pairing.go @@ -1,22 +1,12 @@ -// Copyright 2020 ConsenSys AG -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. package bls12377 import ( "errors" + "github.com/consensys/gnark-crypto/ecc/bls12-377/fp" "github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower" ) @@ -147,7 +137,7 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) { if n >= 1 { // i = 62, separately to avoid an E12 Square // (Square(res) = 1² = 1) - // loopCounter[62] = 0 + // LoopCounter[62] = 0 // k = 0, separately to avoid MulBy034 (res × ℓ) // (assign line to res) @@ -189,7 +179,7 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) { } // i <= 61 - for i := len(loopCounter) - 3; i >= 1; i-- { + for i := len(LoopCounter) - 3; i >= 1; i-- { // mutualize the square among n Miller loops // (∏ᵢfᵢ)² result.Square(&result) @@ -201,7 +191,7 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) { l1.r0.MulByElement(&l1.r0, &p[k].Y) l1.r1.MulByElement(&l1.r1, &p[k].X) - if loopCounter[i] == 0 { + if LoopCounter[i] == 0 { // ℓ × res result.MulBy034(&l1.r0, &l1.r1, &l1.r2) } else { @@ -221,7 +211,7 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) { } // i = 0, separately to avoid a point addition - // loopCounter[0] = 1 + // LoopCounter[0] = 1 result.Square(&result) for k := 0; k < n; k++ { // qProj[k] ← 2qProj[k] and l1 the tangent ℓ passing 2qProj[k] @@ -341,3 +331,279 @@ func (p *g2Proj) lineCompute(evaluations *lineEvaluation, a *G2Affine) { evaluations.r1.Neg(&O) evaluations.r2.Set(&J) } + +// ---------------------- +// Fixed-argument pairing +// ---------------------- + +type LineEvaluationAff struct { + R0 fptower.E2 + R1 fptower.E2 +} + +// PairFixedQ calculates the reduced pairing for a set of points +// ∏ᵢ e(Pᵢ, Qᵢ) where Q are fixed points in G2. +// +// This function doesn't check that the inputs are in the correct subgroup. See IsInSubGroup. +func PairFixedQ(P []G1Affine, lines [][2][len(LoopCounter) - 1]LineEvaluationAff) (GT, error) { + f, err := MillerLoopFixedQ(P, lines) + if err != nil { + return GT{}, err + } + return FinalExponentiation(&f), nil +} + +// PairingCheckFixedQ calculates the reduced pairing for a set of points and returns True if the result is One +// ∏ᵢ e(Pᵢ, Qᵢ) =? 1 where Q are fixed points in G2. +// +// This function doesn't check that the inputs are in the correct subgroup. See IsInSubGroup. +func PairingCheckFixedQ(P []G1Affine, lines [][2][len(LoopCounter) - 1]LineEvaluationAff) (bool, error) { + f, err := PairFixedQ(P, lines) + if err != nil { + return false, err + } + var one GT + one.SetOne() + return f.Equal(&one), nil +} + +// PrecomputeLines precomputes the lines for the fixed-argument Miller loop +func PrecomputeLines(Q G2Affine) (PrecomputedLines [2][len(LoopCounter) - 1]LineEvaluationAff) { + var accQ G2Affine + accQ.Set(&Q) + + for i := len(LoopCounter) - 2; i >= 0; i-- { + if LoopCounter[i] == 0 { + accQ.doubleStep(&PrecomputedLines[0][i]) + } else { + accQ.doubleAndAddStep(&PrecomputedLines[0][i], &PrecomputedLines[1][i], &Q) + } + } + return PrecomputedLines +} + +// MillerLoopFixedQ computes the multi-Miller loop as in MillerLoop +// but Qᵢ are fixed points in G2 known in advance. +func MillerLoopFixedQ(P []G1Affine, lines [][2][len(LoopCounter) - 1]LineEvaluationAff) (GT, error) { + n := len(P) + if n == 0 || n != len(lines) { + return GT{}, errors.New("invalid inputs sizes") + } + + // no need to filter infinity points: + // 1. if Pᵢ=(0,0) then -x/y=1/y=0 by gnark-crypto convention and so + // lines R0 and R1 are 0. At the end it happens that result will stay + // 1 through the Miller loop because MulBy34(1,0,0)==1 + // Mul34By34(1,0,0,1,0,0)==1 and MulBy01234(1,0,0,0,0)==1. + // + // 2. if Qᵢ=(0,0) then PrecomputeLines(Qᵢ) will return lines R0 and R1 + // that are 0 because of gnark-convention (*/0==0) in doubleStep and + // addStep. Similarly to Pᵢ=(0,0) it happens that result stays 1 + // throughout the MillerLoop. + + // precomputations + yInv := make([]fp.Element, n) + xNegOverY := make([]fp.Element, n) + for k := 0; k < n; k++ { + yInv[k].Set(&P[k].Y) + } + yInv = fp.BatchInvert(yInv) + for k := 0; k < n; k++ { + xNegOverY[k].Mul(&P[k].X, &yInv[k]). + Neg(&xNegOverY[k]) + } + + var result GT + result.SetOne() + var prodLines [5]E2 + + // Compute ∏ᵢ { fᵢ_{x₀,Q}(P) } + if n >= 1 { + // i = 62, separately to avoid an E12 Square + // (Square(res) = 1² = 1) + // LoopCounter[62] = 0 + // k = 0, separately to avoid MulBy34 (res × ℓ) + // (assign line to res) + + // line evaluation at P[0] (assign) + result.C1.B0.MulByElement(&lines[0][0][62].R0, &xNegOverY[0]) + result.C1.B1.MulByElement(&lines[0][0][62].R1, &yInv[0]) + // the coefficient which MulBy34 sets to 1 happens to be already 1 (result = 1) + } + + if n >= 2 { + // k = 1, separately to avoid MulBy34 (res × ℓ) + // (res is also a line at this point, so we use Mul34By34 ℓ × ℓ) + // line evaluation at P[1] + lines[1][0][62].R0.MulByElement(&lines[1][0][62].R0, &xNegOverY[1]) + lines[1][0][62].R1.MulByElement(&lines[1][0][62].R1, &yInv[1]) + // ℓ × res + prodLines = fptower.Mul34By34(&lines[1][0][62].R0, &lines[1][0][62].R1, &result.C1.B0, &result.C1.B1) + result.C0.B0 = prodLines[0] + result.C0.B1 = prodLines[1] + result.C0.B2 = prodLines[2] + result.C1.B0 = prodLines[3] + result.C1.B1 = prodLines[4] + } + + // k >= 2 + for k := 2; k < n; k++ { + // line evaluation at P[k] + lines[k][0][62].R0.MulByElement(&lines[k][0][62].R0, &xNegOverY[k]) + lines[k][0][62].R1.MulByElement(&lines[k][0][62].R1, &yInv[k]) + // ℓ × res + result.MulBy34( + &lines[k][0][62].R0, + &lines[k][0][62].R1, + ) + } + + for i := len(LoopCounter) - 3; i >= 0; i-- { + // mutualize the square among n Miller loops + // (∏ᵢfᵢ)² + result.Square(&result) + + for k := 0; k < n; k++ { + // line evaluation at P[k] + lines[k][0][i].R0. + MulByElement( + &lines[k][0][i].R0, + &xNegOverY[k], + ) + lines[k][0][i].R1. + MulByElement( + &lines[k][0][i].R1, + &yInv[k], + ) + + if LoopCounter[i] == 0 { + // ℓ × res + result.MulBy34( + &lines[k][0][i].R0, + &lines[k][0][i].R1, + ) + } else { + // line evaluation at P[k] + lines[k][1][i].R0. + MulByElement( + &lines[k][1][i].R0, + &xNegOverY[k], + ) + lines[k][1][i].R1. + MulByElement( + &lines[k][1][i].R1, + &yInv[k], + ) + // ℓ × ℓ + prodLines = fptower.Mul34By34( + &lines[k][0][i].R0, &lines[k][0][i].R1, + &lines[k][1][i].R0, &lines[k][1][i].R1, + ) + // (ℓ × ℓ) × res + result.MulBy01234(&prodLines) + } + } + } + + return result, nil +} + +func (p *G2Affine) doubleStep(evaluations *LineEvaluationAff) { + + var n, d, λ, xr, yr fptower.E2 + // λ = 3x²/2y + n.Square(&p.X) + λ.Double(&n). + Add(&λ, &n) + d.Double(&p.Y) + λ.Div(&λ, &d) + + // xr = λ²-2x + xr.Square(&λ). + Sub(&xr, &p.X). + Sub(&xr, &p.X) + + // yr = λ(x-xr)-y + yr.Sub(&p.X, &xr). + Mul(&yr, &λ). + Sub(&yr, &p.Y) + + evaluations.R0.Set(&λ) + evaluations.R1.Mul(&λ, &p.X). + Sub(&evaluations.R1, &p.Y) + + p.X.Set(&xr) + p.Y.Set(&yr) +} + +func (p *G2Affine) addStep(evaluations *LineEvaluationAff, a *G2Affine) { + var n, d, λ, λλ, xr, yr fptower.E2 + + // compute λ = (y2-y1)/(x2-x1) + n.Sub(&a.Y, &p.Y) + d.Sub(&a.X, &p.X) + λ.Div(&n, &d) + + // xr = λ²-x1-x2 + λλ.Square(&λ) + n.Add(&p.X, &a.X) + xr.Sub(&λλ, &n) + + // yr = λ(x1-xr) - y1 + yr.Sub(&p.X, &xr). + Mul(&yr, &λ). + Sub(&yr, &p.Y) + + evaluations.R0.Set(&λ) + evaluations.R1.Mul(&λ, &p.X). + Sub(&evaluations.R1, &p.Y) + + p.X.Set(&xr) + p.Y.Set(&yr) +} + +func (p *G2Affine) doubleAndAddStep(evaluations1, evaluations2 *LineEvaluationAff, a *G2Affine) { + var n, d, l1, x3, l2, x4, y4 fptower.E2 + + // compute λ1 = (y2-y1)/(x2-x1) + n.Sub(&p.Y, &a.Y) + d.Sub(&p.X, &a.X) + l1.Div(&n, &d) + + // compute x3 =λ1²-x1-x2 + x3.Square(&l1) + x3.Sub(&x3, &p.X) + x3.Sub(&x3, &a.X) + + // omit y3 computation + + // compute line1 + evaluations1.R0.Set(&l1) + evaluations1.R1.Mul(&l1, &p.X) + evaluations1.R1.Sub(&evaluations1.R1, &p.Y) + + // compute λ2 = -λ1-2y1/(x3-x1) + n.Double(&p.Y) + d.Sub(&x3, &p.X) + l2.Div(&n, &d) + l2.Add(&l2, &l1) + l2.Neg(&l2) + + // compute x4 = λ2²-x1-x3 + x4.Square(&l2) + x4.Sub(&x4, &p.X) + x4.Sub(&x4, &x3) + + // compute y4 = λ2(x1 - x4)-y1 + y4.Sub(&p.X, &x4) + y4.Mul(&l2, &y4) + y4.Sub(&y4, &p.Y) + + // compute line2 + evaluations2.R0.Set(&l2) + evaluations2.R1.Mul(&l2, &p.X) + evaluations2.R1.Sub(&evaluations2.R1, &p.Y) + + p.X.Set(&x4) + p.Y.Set(&y4) +} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/bls12-381.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/bls12-381.go index 86ab933a19f..aa9acbf34c4 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/bls12-381.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/bls12-381.go @@ -62,7 +62,7 @@ var g1Infinity G1Jac var g2Infinity G2Jac // optimal Ate loop counter -var loopCounter [64]int8 +var LoopCounter [64]int8 // Parameters useful for the GLV scalar multiplication. The third roots define the // endomorphisms ϕ₁ and ϕ₂ for and . lambda is such that lies above @@ -135,7 +135,7 @@ func init() { endo.v.A1.SetString("1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257") // binary decomposition of -x₀ little endian - loopCounter = [64]int8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1} + LoopCounter = [64]int8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1} // -x₀ xGen.SetString("15132376222941642752", 10) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/arith.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/arith.go index 6f281563b3d..5c9905de801 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/arith.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/arith.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -58,16 +47,3 @@ func madd3(a, b, c, d, e uint64) (hi uint64, lo uint64) { hi, _ = bits.Add64(hi, e, carry) return } -func max(a int, b int) int { - if a > b { - return a - } - return b -} - -func min(a int, b int) int { - if a < b { - return a - } - return b -} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/asm.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/asm.go deleted file mode 100644 index 0481989ec6a..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/asm.go +++ /dev/null @@ -1,27 +0,0 @@ -//go:build !noadx -// +build !noadx - -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by consensys/gnark-crypto DO NOT EDIT - -package fp - -import "golang.org/x/sys/cpu" - -var ( - supportAdx = cpu.X86.HasADX && cpu.X86.HasBMI2 - _ = supportAdx -) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/asm_noadx.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/asm_noadx.go deleted file mode 100644 index 92f8cc0f424..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/asm_noadx.go +++ /dev/null @@ -1,28 +0,0 @@ -//go:build noadx -// +build noadx - -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by consensys/gnark-crypto DO NOT EDIT - -package fp - -// note: this is needed for test purposes, as dynamically changing supportAdx doesn't flag -// certain errors (like fatal error: missing stackmap) -// this ensures we test all asm path. -var ( - supportAdx = false - _ = supportAdx -) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/doc.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/doc.go index bf5b82c113b..5d70da537c8 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/doc.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/doc.go @@ -1,22 +1,13 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT // Package fp contains field arithmetic operations for modulus = 0x1a0111...ffaaab. // -// The API is similar to math/big (big.Int), but the operations are significantly faster (up to 20x for the modular multiplication on amd64, see also https://hackmd.io/@gnark/modular_multiplication) +// The API is similar to math/big (big.Int), but the operations are significantly faster (up to 20x). +// +// Additionally fp.Vector offers an API to manipulate []Element. // // The modulus is hardcoded in all the operations. // @@ -49,5 +40,7 @@ // // # Warning // -// This code has not been audited and is provided as-is. In particular, there is no security guarantees such as constant time implementation or side-channel attack resistance. +// There is no security guarantees such as constant time implementation or side-channel attack resistance. +// This code is provided as-is. Partially audited, see https://github.com/Consensys/gnark/tree/master/audits +// for more details. package fp diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element.go index f5c2df0c28a..7cdee07d76a 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -54,12 +43,12 @@ const ( // Field modulus q const ( - q0 uint64 = 13402431016077863595 - q1 uint64 = 2210141511517208575 - q2 uint64 = 7435674573564081700 - q3 uint64 = 7239337960414712511 - q4 uint64 = 5412103778470702295 - q5 uint64 = 1873798617647539866 + q0 = 13402431016077863595 + q1 = 2210141511517208575 + q2 = 7435674573564081700 + q3 = 7239337960414712511 + q4 = 5412103778470702295 + q5 = 1873798617647539866 ) var qElement = Element{ @@ -83,7 +72,7 @@ func Modulus() *big.Int { // q + r'.r = 1, i.e., qInvNeg = - q⁻¹ mod r // used for Montgomery reduction -const qInvNeg uint64 = 9940570264628428797 +const qInvNeg = 9940570264628428797 func init() { _modulus.SetString("1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab", 16) @@ -374,6 +363,16 @@ func (z *Element) SetRandom() (*Element, error) { } } +// MustSetRandom sets z to a uniform random value in [0, q). +// +// It panics if reading from crypto/rand.Reader errors. +func (z *Element) MustSetRandom() *Element { + if _, err := z.SetRandom(); err != nil { + panic(err) + } + return z +} + // smallerThanModulus returns true if z < q // This is not constant time func (z *Element) smallerThanModulus() bool { @@ -521,32 +520,8 @@ func (z *Element) Select(c int, x0 *Element, x1 *Element) *Element { // and is used for testing purposes. func _mulGeneric(z, x, y *Element) { - // Implements CIOS multiplication -- section 2.3.2 of Tolga Acar's thesis - // https://www.microsoft.com/en-us/research/wp-content/uploads/1998/06/97Acar.pdf - // - // The algorithm: - // - // for i=0 to N-1 - // C := 0 - // for j=0 to N-1 - // (C,t[j]) := t[j] + x[j]*y[i] + C - // (t[N+1],t[N]) := t[N] + C - // - // C := 0 - // m := t[0]*q'[0] mod D - // (C,_) := t[0] + m*q[0] - // for j=1 to N-1 - // (C,t[j-1]) := t[j] + m*q[j] + C - // - // (C,t[N-1]) := t[N] + C - // t[N] := t[N+1] + C - // - // → N is the number of machine words needed to store the modulus q - // → D is the word size. For example, on a 64-bit architecture D is 2 64 - // → x[i], y[i], q[i] is the ith word of the numbers x,y,q - // → q'[0] is the lowest word of the number -q⁻¹ mod r. This quantity is pre-computed, as it does not depend on the inputs. - // → t is a temporary array of size N+2 - // → C, S are machine words. A pair (C,S) refers to (hi-bits, lo-bits) of a two-word number + // Algorithm 2 of "Faster Montgomery Multiplication and Multi-Scalar-Multiplication for SNARKS" + // by Y. El Housni and G. Botrel https://doi.org/10.46586/tches.v2023.i3.504-521 var t [7]uint64 var D uint64 @@ -1122,7 +1097,7 @@ func (z *Element) SetBigInt(v *big.Int) *Element { // v == 0 return z } else if c != 1 && v.Cmp(&zero) != -1 { - // 0 < v < q + // 0 <= v < q return z.setBigInt(v) } @@ -1249,6 +1224,8 @@ type ByteOrder interface { String() string } +var errInvalidEncoding = errors.New("invalid fp.Element encoding") + // BigEndian is the big-endian implementation of ByteOrder and AppendByteOrder. var BigEndian bigEndian @@ -1266,7 +1243,7 @@ func (bigEndian) Element(b *[Bytes]byte) (Element, error) { z[5] = binary.BigEndian.Uint64((*b)[0:8]) if !z.smallerThanModulus() { - return Element{}, errors.New("invalid fp.Element encoding") + return Element{}, errInvalidEncoding } z.toMont() @@ -1300,7 +1277,7 @@ func (littleEndian) Element(b *[Bytes]byte) (Element, error) { z[5] = binary.LittleEndian.Uint64((*b)[40:48]) if !z.smallerThanModulus() { - return Element{}, errors.New("invalid fp.Element encoding") + return Element{}, errInvalidEncoding } z.toMont() diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element_amd64.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element_amd64.go new file mode 100644 index 00000000000..ff2159178d8 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element_amd64.go @@ -0,0 +1,62 @@ +//go:build !purego + +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fp + +import ( + _ "github.com/consensys/gnark-crypto/field/asm/element_6w" + "github.com/consensys/gnark-crypto/utils/cpu" +) + +var supportAdx = cpu.SupportADX + +//go:noescape +func MulBy3(x *Element) + +//go:noescape +func MulBy5(x *Element) + +//go:noescape +func MulBy13(x *Element) + +//go:noescape +func mul(res, x, y *Element) + +//go:noescape +func fromMont(res *Element) + +//go:noescape +func reduce(res *Element) + +// Butterfly sets +// +// a = a + b (mod q) +// b = a - b (mod q) +// +//go:noescape +func Butterfly(a, b *Element) + +// Mul z = x * y (mod q) +// +// x and y must be less than q +func (z *Element) Mul(x, y *Element) *Element { + + // Algorithm 2 of "Faster Montgomery Multiplication and Multi-Scalar-Multiplication for SNARKS" + // by Y. El Housni and G. Botrel https://doi.org/10.46586/tches.v2023.i3.504-521 + + mul(z, x, y) + return z +} + +// Square z = x * x (mod q) +// +// x must be less than q +func (z *Element) Square(x *Element) *Element { + // see Mul for doc. + mul(z, x, x) + return z +} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element_amd64.s b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element_amd64.s new file mode 100644 index 00000000000..822bdf56a50 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element_amd64.s @@ -0,0 +1,10 @@ +//go:build !purego + +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +// We include the hash to force the Go compiler to recompile: 18408829383245254329 +#include "../../../field/asm/element_6w/element_6w_amd64.s" + diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element_arm64.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element_arm64.go new file mode 100644 index 00000000000..6cbd040cdb8 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element_arm64.go @@ -0,0 +1,72 @@ +//go:build !purego + +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fp + +import ( + _ "github.com/consensys/gnark-crypto/field/asm/element_6w" +) + +// Butterfly sets +// +// a = a + b (mod q) +// b = a - b (mod q) +// +//go:noescape +func Butterfly(a, b *Element) + +//go:noescape +func mul(res, x, y *Element) + +// Mul z = x * y (mod q) +// +// x and y must be less than q +func (z *Element) Mul(x, y *Element) *Element { + mul(z, x, y) + return z +} + +// Square z = x * x (mod q) +// +// x must be less than q +func (z *Element) Square(x *Element) *Element { + // see Mul for doc. + mul(z, x, x) + return z +} + +// MulBy3 x *= 3 (mod q) +func MulBy3(x *Element) { + _x := *x + x.Double(x).Add(x, &_x) +} + +// MulBy5 x *= 5 (mod q) +func MulBy5(x *Element) { + _x := *x + x.Double(x).Double(x).Add(x, &_x) +} + +// MulBy13 x *= 13 (mod q) +func MulBy13(x *Element) { + var y = Element{ + 13438459813099623723, + 14459933216667336738, + 14900020990258308116, + 2941282712809091851, + 13639094935183769893, + 1835248516986607988, + } + x.Mul(x, &y) +} + +func fromMont(z *Element) { + _fromMontGeneric(z) +} + +//go:noescape +func reduce(res *Element) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element_arm64.s b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element_arm64.s new file mode 100644 index 00000000000..2defbe4c21a --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element_arm64.s @@ -0,0 +1,10 @@ +//go:build !purego + +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +// We include the hash to force the Go compiler to recompile: 15397482240260640864 +#include "../../../field/asm/element_6w/element_6w_arm64.s" + diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element_exp.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element_exp.go index 4d7fafa0a1a..b21cc6041ef 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element_exp.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element_exp.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element_mul_amd64.s b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element_mul_amd64.s deleted file mode 100644 index 9e03b1c0ace..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element_mul_amd64.s +++ /dev/null @@ -1,857 +0,0 @@ -// +build !purego - -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "textflag.h" -#include "funcdata.h" - -// modulus q -DATA q<>+0(SB)/8, $0xb9feffffffffaaab -DATA q<>+8(SB)/8, $0x1eabfffeb153ffff -DATA q<>+16(SB)/8, $0x6730d2a0f6b0f624 -DATA q<>+24(SB)/8, $0x64774b84f38512bf -DATA q<>+32(SB)/8, $0x4b1ba7b6434bacd7 -DATA q<>+40(SB)/8, $0x1a0111ea397fe69a -GLOBL q<>(SB), (RODATA+NOPTR), $48 - -// qInv0 q'[0] -DATA qInv0<>(SB)/8, $0x89f3fffcfffcfffd -GLOBL qInv0<>(SB), (RODATA+NOPTR), $8 - -#define REDUCE(ra0, ra1, ra2, ra3, ra4, ra5, rb0, rb1, rb2, rb3, rb4, rb5) \ - MOVQ ra0, rb0; \ - SUBQ q<>(SB), ra0; \ - MOVQ ra1, rb1; \ - SBBQ q<>+8(SB), ra1; \ - MOVQ ra2, rb2; \ - SBBQ q<>+16(SB), ra2; \ - MOVQ ra3, rb3; \ - SBBQ q<>+24(SB), ra3; \ - MOVQ ra4, rb4; \ - SBBQ q<>+32(SB), ra4; \ - MOVQ ra5, rb5; \ - SBBQ q<>+40(SB), ra5; \ - CMOVQCS rb0, ra0; \ - CMOVQCS rb1, ra1; \ - CMOVQCS rb2, ra2; \ - CMOVQCS rb3, ra3; \ - CMOVQCS rb4, ra4; \ - CMOVQCS rb5, ra5; \ - -// mul(res, x, y *Element) -TEXT ·mul(SB), $24-24 - - // the algorithm is described in the Element.Mul declaration (.go) - // however, to benefit from the ADCX and ADOX carry chains - // we split the inner loops in 2: - // for i=0 to N-1 - // for j=0 to N-1 - // (A,t[j]) := t[j] + x[j]*y[i] + A - // m := t[0]*q'[0] mod W - // C,_ := t[0] + m*q[0] - // for j=1 to N-1 - // (C,t[j-1]) := t[j] + m*q[j] + C - // t[N-1] = C + A - - NO_LOCAL_POINTERS - CMPB ·supportAdx(SB), $1 - JNE l1 - MOVQ x+8(FP), R8 - - // x[0] -> R10 - // x[1] -> R11 - // x[2] -> R12 - MOVQ 0(R8), R10 - MOVQ 8(R8), R11 - MOVQ 16(R8), R12 - MOVQ y+16(FP), R13 - - // A -> BP - // t[0] -> R14 - // t[1] -> R15 - // t[2] -> CX - // t[3] -> BX - // t[4] -> SI - // t[5] -> DI - // clear the flags - XORQ AX, AX - MOVQ 0(R13), DX - - // (A,t[0]) := x[0]*y[0] + A - MULXQ R10, R14, R15 - - // (A,t[1]) := x[1]*y[0] + A - MULXQ R11, AX, CX - ADOXQ AX, R15 - - // (A,t[2]) := x[2]*y[0] + A - MULXQ R12, AX, BX - ADOXQ AX, CX - - // (A,t[3]) := x[3]*y[0] + A - MULXQ 24(R8), AX, SI - ADOXQ AX, BX - - // (A,t[4]) := x[4]*y[0] + A - MULXQ 32(R8), AX, DI - ADOXQ AX, SI - - // (A,t[5]) := x[5]*y[0] + A - MULXQ 40(R8), AX, BP - ADOXQ AX, DI - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADOXQ AX, BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, R9 - ADCXQ R14, AX - MOVQ R9, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R15, R14 - MULXQ q<>+8(SB), AX, R15 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R15 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R15 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ SI, BX - MULXQ q<>+32(SB), AX, SI - ADOXQ AX, BX - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ DI, SI - MULXQ q<>+40(SB), AX, DI - ADOXQ AX, SI - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, DI - ADOXQ BP, DI - - // clear the flags - XORQ AX, AX - MOVQ 8(R13), DX - - // (A,t[0]) := t[0] + x[0]*y[1] + A - MULXQ R10, AX, BP - ADOXQ AX, R14 - - // (A,t[1]) := t[1] + x[1]*y[1] + A - ADCXQ BP, R15 - MULXQ R11, AX, BP - ADOXQ AX, R15 - - // (A,t[2]) := t[2] + x[2]*y[1] + A - ADCXQ BP, CX - MULXQ R12, AX, BP - ADOXQ AX, CX - - // (A,t[3]) := t[3] + x[3]*y[1] + A - ADCXQ BP, BX - MULXQ 24(R8), AX, BP - ADOXQ AX, BX - - // (A,t[4]) := t[4] + x[4]*y[1] + A - ADCXQ BP, SI - MULXQ 32(R8), AX, BP - ADOXQ AX, SI - - // (A,t[5]) := t[5] + x[5]*y[1] + A - ADCXQ BP, DI - MULXQ 40(R8), AX, BP - ADOXQ AX, DI - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, R9 - ADCXQ R14, AX - MOVQ R9, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R15, R14 - MULXQ q<>+8(SB), AX, R15 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R15 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R15 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ SI, BX - MULXQ q<>+32(SB), AX, SI - ADOXQ AX, BX - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ DI, SI - MULXQ q<>+40(SB), AX, DI - ADOXQ AX, SI - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, DI - ADOXQ BP, DI - - // clear the flags - XORQ AX, AX - MOVQ 16(R13), DX - - // (A,t[0]) := t[0] + x[0]*y[2] + A - MULXQ R10, AX, BP - ADOXQ AX, R14 - - // (A,t[1]) := t[1] + x[1]*y[2] + A - ADCXQ BP, R15 - MULXQ R11, AX, BP - ADOXQ AX, R15 - - // (A,t[2]) := t[2] + x[2]*y[2] + A - ADCXQ BP, CX - MULXQ R12, AX, BP - ADOXQ AX, CX - - // (A,t[3]) := t[3] + x[3]*y[2] + A - ADCXQ BP, BX - MULXQ 24(R8), AX, BP - ADOXQ AX, BX - - // (A,t[4]) := t[4] + x[4]*y[2] + A - ADCXQ BP, SI - MULXQ 32(R8), AX, BP - ADOXQ AX, SI - - // (A,t[5]) := t[5] + x[5]*y[2] + A - ADCXQ BP, DI - MULXQ 40(R8), AX, BP - ADOXQ AX, DI - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, R9 - ADCXQ R14, AX - MOVQ R9, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R15, R14 - MULXQ q<>+8(SB), AX, R15 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R15 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R15 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ SI, BX - MULXQ q<>+32(SB), AX, SI - ADOXQ AX, BX - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ DI, SI - MULXQ q<>+40(SB), AX, DI - ADOXQ AX, SI - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, DI - ADOXQ BP, DI - - // clear the flags - XORQ AX, AX - MOVQ 24(R13), DX - - // (A,t[0]) := t[0] + x[0]*y[3] + A - MULXQ R10, AX, BP - ADOXQ AX, R14 - - // (A,t[1]) := t[1] + x[1]*y[3] + A - ADCXQ BP, R15 - MULXQ R11, AX, BP - ADOXQ AX, R15 - - // (A,t[2]) := t[2] + x[2]*y[3] + A - ADCXQ BP, CX - MULXQ R12, AX, BP - ADOXQ AX, CX - - // (A,t[3]) := t[3] + x[3]*y[3] + A - ADCXQ BP, BX - MULXQ 24(R8), AX, BP - ADOXQ AX, BX - - // (A,t[4]) := t[4] + x[4]*y[3] + A - ADCXQ BP, SI - MULXQ 32(R8), AX, BP - ADOXQ AX, SI - - // (A,t[5]) := t[5] + x[5]*y[3] + A - ADCXQ BP, DI - MULXQ 40(R8), AX, BP - ADOXQ AX, DI - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, R9 - ADCXQ R14, AX - MOVQ R9, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R15, R14 - MULXQ q<>+8(SB), AX, R15 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R15 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R15 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ SI, BX - MULXQ q<>+32(SB), AX, SI - ADOXQ AX, BX - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ DI, SI - MULXQ q<>+40(SB), AX, DI - ADOXQ AX, SI - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, DI - ADOXQ BP, DI - - // clear the flags - XORQ AX, AX - MOVQ 32(R13), DX - - // (A,t[0]) := t[0] + x[0]*y[4] + A - MULXQ R10, AX, BP - ADOXQ AX, R14 - - // (A,t[1]) := t[1] + x[1]*y[4] + A - ADCXQ BP, R15 - MULXQ R11, AX, BP - ADOXQ AX, R15 - - // (A,t[2]) := t[2] + x[2]*y[4] + A - ADCXQ BP, CX - MULXQ R12, AX, BP - ADOXQ AX, CX - - // (A,t[3]) := t[3] + x[3]*y[4] + A - ADCXQ BP, BX - MULXQ 24(R8), AX, BP - ADOXQ AX, BX - - // (A,t[4]) := t[4] + x[4]*y[4] + A - ADCXQ BP, SI - MULXQ 32(R8), AX, BP - ADOXQ AX, SI - - // (A,t[5]) := t[5] + x[5]*y[4] + A - ADCXQ BP, DI - MULXQ 40(R8), AX, BP - ADOXQ AX, DI - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, R9 - ADCXQ R14, AX - MOVQ R9, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R15, R14 - MULXQ q<>+8(SB), AX, R15 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R15 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R15 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ SI, BX - MULXQ q<>+32(SB), AX, SI - ADOXQ AX, BX - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ DI, SI - MULXQ q<>+40(SB), AX, DI - ADOXQ AX, SI - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, DI - ADOXQ BP, DI - - // clear the flags - XORQ AX, AX - MOVQ 40(R13), DX - - // (A,t[0]) := t[0] + x[0]*y[5] + A - MULXQ R10, AX, BP - ADOXQ AX, R14 - - // (A,t[1]) := t[1] + x[1]*y[5] + A - ADCXQ BP, R15 - MULXQ R11, AX, BP - ADOXQ AX, R15 - - // (A,t[2]) := t[2] + x[2]*y[5] + A - ADCXQ BP, CX - MULXQ R12, AX, BP - ADOXQ AX, CX - - // (A,t[3]) := t[3] + x[3]*y[5] + A - ADCXQ BP, BX - MULXQ 24(R8), AX, BP - ADOXQ AX, BX - - // (A,t[4]) := t[4] + x[4]*y[5] + A - ADCXQ BP, SI - MULXQ 32(R8), AX, BP - ADOXQ AX, SI - - // (A,t[5]) := t[5] + x[5]*y[5] + A - ADCXQ BP, DI - MULXQ 40(R8), AX, BP - ADOXQ AX, DI - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, R9 - ADCXQ R14, AX - MOVQ R9, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R15, R14 - MULXQ q<>+8(SB), AX, R15 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R15 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R15 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ SI, BX - MULXQ q<>+32(SB), AX, SI - ADOXQ AX, BX - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ DI, SI - MULXQ q<>+40(SB), AX, DI - ADOXQ AX, SI - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, DI - ADOXQ BP, DI - - // reduce element(R14,R15,CX,BX,SI,DI) using temp registers (R9,R8,R13,R10,R11,R12) - REDUCE(R14,R15,CX,BX,SI,DI,R9,R8,R13,R10,R11,R12) - - MOVQ res+0(FP), AX - MOVQ R14, 0(AX) - MOVQ R15, 8(AX) - MOVQ CX, 16(AX) - MOVQ BX, 24(AX) - MOVQ SI, 32(AX) - MOVQ DI, 40(AX) - RET - -l1: - MOVQ res+0(FP), AX - MOVQ AX, (SP) - MOVQ x+8(FP), AX - MOVQ AX, 8(SP) - MOVQ y+16(FP), AX - MOVQ AX, 16(SP) - CALL ·_mulGeneric(SB) - RET - -TEXT ·fromMont(SB), $8-8 - NO_LOCAL_POINTERS - - // the algorithm is described here - // https://hackmd.io/@gnark/modular_multiplication - // when y = 1 we have: - // for i=0 to N-1 - // t[i] = x[i] - // for i=0 to N-1 - // m := t[0]*q'[0] mod W - // C,_ := t[0] + m*q[0] - // for j=1 to N-1 - // (C,t[j-1]) := t[j] + m*q[j] + C - // t[N-1] = C - CMPB ·supportAdx(SB), $1 - JNE l2 - MOVQ res+0(FP), DX - MOVQ 0(DX), R14 - MOVQ 8(DX), R15 - MOVQ 16(DX), CX - MOVQ 24(DX), BX - MOVQ 32(DX), SI - MOVQ 40(DX), DI - XORQ DX, DX - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R14, AX - MOVQ BP, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R15, R14 - MULXQ q<>+8(SB), AX, R15 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R15 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R15 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ SI, BX - MULXQ q<>+32(SB), AX, SI - ADOXQ AX, BX - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ DI, SI - MULXQ q<>+40(SB), AX, DI - ADOXQ AX, SI - MOVQ $0, AX - ADCXQ AX, DI - ADOXQ AX, DI - XORQ DX, DX - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R14, AX - MOVQ BP, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R15, R14 - MULXQ q<>+8(SB), AX, R15 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R15 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R15 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ SI, BX - MULXQ q<>+32(SB), AX, SI - ADOXQ AX, BX - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ DI, SI - MULXQ q<>+40(SB), AX, DI - ADOXQ AX, SI - MOVQ $0, AX - ADCXQ AX, DI - ADOXQ AX, DI - XORQ DX, DX - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R14, AX - MOVQ BP, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R15, R14 - MULXQ q<>+8(SB), AX, R15 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R15 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R15 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ SI, BX - MULXQ q<>+32(SB), AX, SI - ADOXQ AX, BX - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ DI, SI - MULXQ q<>+40(SB), AX, DI - ADOXQ AX, SI - MOVQ $0, AX - ADCXQ AX, DI - ADOXQ AX, DI - XORQ DX, DX - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R14, AX - MOVQ BP, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R15, R14 - MULXQ q<>+8(SB), AX, R15 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R15 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R15 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ SI, BX - MULXQ q<>+32(SB), AX, SI - ADOXQ AX, BX - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ DI, SI - MULXQ q<>+40(SB), AX, DI - ADOXQ AX, SI - MOVQ $0, AX - ADCXQ AX, DI - ADOXQ AX, DI - XORQ DX, DX - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R14, AX - MOVQ BP, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R15, R14 - MULXQ q<>+8(SB), AX, R15 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R15 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R15 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ SI, BX - MULXQ q<>+32(SB), AX, SI - ADOXQ AX, BX - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ DI, SI - MULXQ q<>+40(SB), AX, DI - ADOXQ AX, SI - MOVQ $0, AX - ADCXQ AX, DI - ADOXQ AX, DI - XORQ DX, DX - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R14, AX - MOVQ BP, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R15, R14 - MULXQ q<>+8(SB), AX, R15 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R15 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R15 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ SI, BX - MULXQ q<>+32(SB), AX, SI - ADOXQ AX, BX - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ DI, SI - MULXQ q<>+40(SB), AX, DI - ADOXQ AX, SI - MOVQ $0, AX - ADCXQ AX, DI - ADOXQ AX, DI - - // reduce element(R14,R15,CX,BX,SI,DI) using temp registers (R8,R9,R10,R11,R12,R13) - REDUCE(R14,R15,CX,BX,SI,DI,R8,R9,R10,R11,R12,R13) - - MOVQ res+0(FP), AX - MOVQ R14, 0(AX) - MOVQ R15, 8(AX) - MOVQ CX, 16(AX) - MOVQ BX, 24(AX) - MOVQ SI, 32(AX) - MOVQ DI, 40(AX) - RET - -l2: - MOVQ res+0(FP), AX - MOVQ AX, (SP) - CALL ·_fromMontGeneric(SB) - RET diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element_ops_amd64.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element_ops_amd64.go deleted file mode 100644 index 83bba45aedf..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element_ops_amd64.go +++ /dev/null @@ -1,107 +0,0 @@ -//go:build !purego -// +build !purego - -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by consensys/gnark-crypto DO NOT EDIT - -package fp - -//go:noescape -func MulBy3(x *Element) - -//go:noescape -func MulBy5(x *Element) - -//go:noescape -func MulBy13(x *Element) - -//go:noescape -func mul(res, x, y *Element) - -//go:noescape -func fromMont(res *Element) - -//go:noescape -func reduce(res *Element) - -// Butterfly sets -// -// a = a + b (mod q) -// b = a - b (mod q) -// -//go:noescape -func Butterfly(a, b *Element) - -// Mul z = x * y (mod q) -// -// x and y must be less than q -func (z *Element) Mul(x, y *Element) *Element { - - // Implements CIOS multiplication -- section 2.3.2 of Tolga Acar's thesis - // https://www.microsoft.com/en-us/research/wp-content/uploads/1998/06/97Acar.pdf - // - // The algorithm: - // - // for i=0 to N-1 - // C := 0 - // for j=0 to N-1 - // (C,t[j]) := t[j] + x[j]*y[i] + C - // (t[N+1],t[N]) := t[N] + C - // - // C := 0 - // m := t[0]*q'[0] mod D - // (C,_) := t[0] + m*q[0] - // for j=1 to N-1 - // (C,t[j-1]) := t[j] + m*q[j] + C - // - // (C,t[N-1]) := t[N] + C - // t[N] := t[N+1] + C - // - // → N is the number of machine words needed to store the modulus q - // → D is the word size. For example, on a 64-bit architecture D is 2 64 - // → x[i], y[i], q[i] is the ith word of the numbers x,y,q - // → q'[0] is the lowest word of the number -q⁻¹ mod r. This quantity is pre-computed, as it does not depend on the inputs. - // → t is a temporary array of size N+2 - // → C, S are machine words. A pair (C,S) refers to (hi-bits, lo-bits) of a two-word number - // - // As described here https://hackmd.io/@gnark/modular_multiplication we can get rid of one carry chain and simplify: - // (also described in https://eprint.iacr.org/2022/1400.pdf annex) - // - // for i=0 to N-1 - // (A,t[0]) := t[0] + x[0]*y[i] - // m := t[0]*q'[0] mod W - // C,_ := t[0] + m*q[0] - // for j=1 to N-1 - // (A,t[j]) := t[j] + x[j]*y[i] + A - // (C,t[j-1]) := t[j] + m*q[j] + C - // - // t[N-1] = C + A - // - // This optimization saves 5N + 2 additions in the algorithm, and can be used whenever the highest bit - // of the modulus is zero (and not all of the remaining bits are set). - - mul(z, x, y) - return z -} - -// Square z = x * x (mod q) -// -// x must be less than q -func (z *Element) Square(x *Element) *Element { - // see Mul for doc. - mul(z, x, x) - return z -} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element_ops_amd64.s b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element_ops_amd64.s deleted file mode 100644 index 830b2dd63f9..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element_ops_amd64.s +++ /dev/null @@ -1,306 +0,0 @@ -// +build !purego - -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "textflag.h" -#include "funcdata.h" - -// modulus q -DATA q<>+0(SB)/8, $0xb9feffffffffaaab -DATA q<>+8(SB)/8, $0x1eabfffeb153ffff -DATA q<>+16(SB)/8, $0x6730d2a0f6b0f624 -DATA q<>+24(SB)/8, $0x64774b84f38512bf -DATA q<>+32(SB)/8, $0x4b1ba7b6434bacd7 -DATA q<>+40(SB)/8, $0x1a0111ea397fe69a -GLOBL q<>(SB), (RODATA+NOPTR), $48 - -// qInv0 q'[0] -DATA qInv0<>(SB)/8, $0x89f3fffcfffcfffd -GLOBL qInv0<>(SB), (RODATA+NOPTR), $8 - -#define REDUCE(ra0, ra1, ra2, ra3, ra4, ra5, rb0, rb1, rb2, rb3, rb4, rb5) \ - MOVQ ra0, rb0; \ - SUBQ q<>(SB), ra0; \ - MOVQ ra1, rb1; \ - SBBQ q<>+8(SB), ra1; \ - MOVQ ra2, rb2; \ - SBBQ q<>+16(SB), ra2; \ - MOVQ ra3, rb3; \ - SBBQ q<>+24(SB), ra3; \ - MOVQ ra4, rb4; \ - SBBQ q<>+32(SB), ra4; \ - MOVQ ra5, rb5; \ - SBBQ q<>+40(SB), ra5; \ - CMOVQCS rb0, ra0; \ - CMOVQCS rb1, ra1; \ - CMOVQCS rb2, ra2; \ - CMOVQCS rb3, ra3; \ - CMOVQCS rb4, ra4; \ - CMOVQCS rb5, ra5; \ - -TEXT ·reduce(SB), NOSPLIT, $0-8 - MOVQ res+0(FP), AX - MOVQ 0(AX), DX - MOVQ 8(AX), CX - MOVQ 16(AX), BX - MOVQ 24(AX), SI - MOVQ 32(AX), DI - MOVQ 40(AX), R8 - - // reduce element(DX,CX,BX,SI,DI,R8) using temp registers (R9,R10,R11,R12,R13,R14) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10,R11,R12,R13,R14) - - MOVQ DX, 0(AX) - MOVQ CX, 8(AX) - MOVQ BX, 16(AX) - MOVQ SI, 24(AX) - MOVQ DI, 32(AX) - MOVQ R8, 40(AX) - RET - -// MulBy3(x *Element) -TEXT ·MulBy3(SB), NOSPLIT, $0-8 - MOVQ x+0(FP), AX - MOVQ 0(AX), DX - MOVQ 8(AX), CX - MOVQ 16(AX), BX - MOVQ 24(AX), SI - MOVQ 32(AX), DI - MOVQ 40(AX), R8 - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - ADCQ DI, DI - ADCQ R8, R8 - - // reduce element(DX,CX,BX,SI,DI,R8) using temp registers (R9,R10,R11,R12,R13,R14) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10,R11,R12,R13,R14) - - ADDQ 0(AX), DX - ADCQ 8(AX), CX - ADCQ 16(AX), BX - ADCQ 24(AX), SI - ADCQ 32(AX), DI - ADCQ 40(AX), R8 - - // reduce element(DX,CX,BX,SI,DI,R8) using temp registers (R15,R9,R10,R11,R12,R13) - REDUCE(DX,CX,BX,SI,DI,R8,R15,R9,R10,R11,R12,R13) - - MOVQ DX, 0(AX) - MOVQ CX, 8(AX) - MOVQ BX, 16(AX) - MOVQ SI, 24(AX) - MOVQ DI, 32(AX) - MOVQ R8, 40(AX) - RET - -// MulBy5(x *Element) -TEXT ·MulBy5(SB), NOSPLIT, $0-8 - MOVQ x+0(FP), AX - MOVQ 0(AX), DX - MOVQ 8(AX), CX - MOVQ 16(AX), BX - MOVQ 24(AX), SI - MOVQ 32(AX), DI - MOVQ 40(AX), R8 - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - ADCQ DI, DI - ADCQ R8, R8 - - // reduce element(DX,CX,BX,SI,DI,R8) using temp registers (R9,R10,R11,R12,R13,R14) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10,R11,R12,R13,R14) - - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - ADCQ DI, DI - ADCQ R8, R8 - - // reduce element(DX,CX,BX,SI,DI,R8) using temp registers (R15,R9,R10,R11,R12,R13) - REDUCE(DX,CX,BX,SI,DI,R8,R15,R9,R10,R11,R12,R13) - - ADDQ 0(AX), DX - ADCQ 8(AX), CX - ADCQ 16(AX), BX - ADCQ 24(AX), SI - ADCQ 32(AX), DI - ADCQ 40(AX), R8 - - // reduce element(DX,CX,BX,SI,DI,R8) using temp registers (R14,R15,R9,R10,R11,R12) - REDUCE(DX,CX,BX,SI,DI,R8,R14,R15,R9,R10,R11,R12) - - MOVQ DX, 0(AX) - MOVQ CX, 8(AX) - MOVQ BX, 16(AX) - MOVQ SI, 24(AX) - MOVQ DI, 32(AX) - MOVQ R8, 40(AX) - RET - -// MulBy13(x *Element) -TEXT ·MulBy13(SB), $40-8 - MOVQ x+0(FP), AX - MOVQ 0(AX), DX - MOVQ 8(AX), CX - MOVQ 16(AX), BX - MOVQ 24(AX), SI - MOVQ 32(AX), DI - MOVQ 40(AX), R8 - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - ADCQ DI, DI - ADCQ R8, R8 - - // reduce element(DX,CX,BX,SI,DI,R8) using temp registers (R9,R10,R11,R12,R13,R14) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10,R11,R12,R13,R14) - - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - ADCQ DI, DI - ADCQ R8, R8 - - // reduce element(DX,CX,BX,SI,DI,R8) using temp registers (R15,s0-8(SP),s1-16(SP),s2-24(SP),s3-32(SP),s4-40(SP)) - REDUCE(DX,CX,BX,SI,DI,R8,R15,s0-8(SP),s1-16(SP),s2-24(SP),s3-32(SP),s4-40(SP)) - - MOVQ DX, R15 - MOVQ CX, s0-8(SP) - MOVQ BX, s1-16(SP) - MOVQ SI, s2-24(SP) - MOVQ DI, s3-32(SP) - MOVQ R8, s4-40(SP) - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - ADCQ DI, DI - ADCQ R8, R8 - - // reduce element(DX,CX,BX,SI,DI,R8) using temp registers (R9,R10,R11,R12,R13,R14) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10,R11,R12,R13,R14) - - ADDQ R15, DX - ADCQ s0-8(SP), CX - ADCQ s1-16(SP), BX - ADCQ s2-24(SP), SI - ADCQ s3-32(SP), DI - ADCQ s4-40(SP), R8 - - // reduce element(DX,CX,BX,SI,DI,R8) using temp registers (R9,R10,R11,R12,R13,R14) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10,R11,R12,R13,R14) - - ADDQ 0(AX), DX - ADCQ 8(AX), CX - ADCQ 16(AX), BX - ADCQ 24(AX), SI - ADCQ 32(AX), DI - ADCQ 40(AX), R8 - - // reduce element(DX,CX,BX,SI,DI,R8) using temp registers (R9,R10,R11,R12,R13,R14) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10,R11,R12,R13,R14) - - MOVQ DX, 0(AX) - MOVQ CX, 8(AX) - MOVQ BX, 16(AX) - MOVQ SI, 24(AX) - MOVQ DI, 32(AX) - MOVQ R8, 40(AX) - RET - -// Butterfly(a, b *Element) sets a = a + b; b = a - b -TEXT ·Butterfly(SB), $48-16 - MOVQ a+0(FP), AX - MOVQ 0(AX), CX - MOVQ 8(AX), BX - MOVQ 16(AX), SI - MOVQ 24(AX), DI - MOVQ 32(AX), R8 - MOVQ 40(AX), R9 - MOVQ CX, R10 - MOVQ BX, R11 - MOVQ SI, R12 - MOVQ DI, R13 - MOVQ R8, R14 - MOVQ R9, R15 - XORQ AX, AX - MOVQ b+8(FP), DX - ADDQ 0(DX), CX - ADCQ 8(DX), BX - ADCQ 16(DX), SI - ADCQ 24(DX), DI - ADCQ 32(DX), R8 - ADCQ 40(DX), R9 - SUBQ 0(DX), R10 - SBBQ 8(DX), R11 - SBBQ 16(DX), R12 - SBBQ 24(DX), R13 - SBBQ 32(DX), R14 - SBBQ 40(DX), R15 - MOVQ CX, s0-8(SP) - MOVQ BX, s1-16(SP) - MOVQ SI, s2-24(SP) - MOVQ DI, s3-32(SP) - MOVQ R8, s4-40(SP) - MOVQ R9, s5-48(SP) - MOVQ $0xb9feffffffffaaab, CX - MOVQ $0x1eabfffeb153ffff, BX - MOVQ $0x6730d2a0f6b0f624, SI - MOVQ $0x64774b84f38512bf, DI - MOVQ $0x4b1ba7b6434bacd7, R8 - MOVQ $0x1a0111ea397fe69a, R9 - CMOVQCC AX, CX - CMOVQCC AX, BX - CMOVQCC AX, SI - CMOVQCC AX, DI - CMOVQCC AX, R8 - CMOVQCC AX, R9 - ADDQ CX, R10 - ADCQ BX, R11 - ADCQ SI, R12 - ADCQ DI, R13 - ADCQ R8, R14 - ADCQ R9, R15 - MOVQ s0-8(SP), CX - MOVQ s1-16(SP), BX - MOVQ s2-24(SP), SI - MOVQ s3-32(SP), DI - MOVQ s4-40(SP), R8 - MOVQ s5-48(SP), R9 - MOVQ R10, 0(DX) - MOVQ R11, 8(DX) - MOVQ R12, 16(DX) - MOVQ R13, 24(DX) - MOVQ R14, 32(DX) - MOVQ R15, 40(DX) - - // reduce element(CX,BX,SI,DI,R8,R9) using temp registers (R10,R11,R12,R13,R14,R15) - REDUCE(CX,BX,SI,DI,R8,R9,R10,R11,R12,R13,R14,R15) - - MOVQ a+0(FP), AX - MOVQ CX, 0(AX) - MOVQ BX, 8(AX) - MOVQ SI, 16(AX) - MOVQ DI, 24(AX) - MOVQ R8, 32(AX) - MOVQ R9, 40(AX) - RET diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element_ops_purego.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element_purego.go similarity index 88% rename from vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element_ops_purego.go rename to vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element_purego.go index fc10b3df30d..f3170f77e00 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element_ops_purego.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/element_purego.go @@ -1,19 +1,7 @@ -//go:build !amd64 || purego -// +build !amd64 purego +//go:build purego || (!amd64 && !arm64) -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -46,14 +34,6 @@ func MulBy13(x *Element) { x.Mul(x, &y) } -// Butterfly sets -// -// a = a + b (mod q) -// b = a - b (mod q) -func Butterfly(a, b *Element) { - _butterflyGeneric(a, b) -} - func fromMont(z *Element) { _fromMontGeneric(z) } @@ -67,48 +47,8 @@ func reduce(z *Element) { // x and y must be less than q func (z *Element) Mul(x, y *Element) *Element { - // Implements CIOS multiplication -- section 2.3.2 of Tolga Acar's thesis - // https://www.microsoft.com/en-us/research/wp-content/uploads/1998/06/97Acar.pdf - // - // The algorithm: - // - // for i=0 to N-1 - // C := 0 - // for j=0 to N-1 - // (C,t[j]) := t[j] + x[j]*y[i] + C - // (t[N+1],t[N]) := t[N] + C - // - // C := 0 - // m := t[0]*q'[0] mod D - // (C,_) := t[0] + m*q[0] - // for j=1 to N-1 - // (C,t[j-1]) := t[j] + m*q[j] + C - // - // (C,t[N-1]) := t[N] + C - // t[N] := t[N+1] + C - // - // → N is the number of machine words needed to store the modulus q - // → D is the word size. For example, on a 64-bit architecture D is 2 64 - // → x[i], y[i], q[i] is the ith word of the numbers x,y,q - // → q'[0] is the lowest word of the number -q⁻¹ mod r. This quantity is pre-computed, as it does not depend on the inputs. - // → t is a temporary array of size N+2 - // → C, S are machine words. A pair (C,S) refers to (hi-bits, lo-bits) of a two-word number - // - // As described here https://hackmd.io/@gnark/modular_multiplication we can get rid of one carry chain and simplify: - // (also described in https://eprint.iacr.org/2022/1400.pdf annex) - // - // for i=0 to N-1 - // (A,t[0]) := t[0] + x[0]*y[i] - // m := t[0]*q'[0] mod W - // C,_ := t[0] + m*q[0] - // for j=1 to N-1 - // (A,t[j]) := t[j] + x[j]*y[i] + A - // (C,t[j-1]) := t[j] + m*q[j] + C - // - // t[N-1] = C + A - // - // This optimization saves 5N + 2 additions in the algorithm, and can be used whenever the highest bit - // of the modulus is zero (and not all of the remaining bits are set). + // Algorithm 2 of "Faster Montgomery Multiplication and Multi-Scalar-Multiplication for SNARKS" + // by Y. El Housni and G. Botrel https://doi.org/10.46586/tches.v2023.i3.504-521 var t0, t1, t2, t3, t4, t5 uint64 var u0, u1, u2, u3, u4, u5 uint64 @@ -743,3 +683,11 @@ func (z *Element) Square(x *Element) *Element { } return z } + +// Butterfly sets +// +// a = a + b (mod q) +// b = a - b (mod q) +func Butterfly(a, b *Element) { + _butterflyGeneric(a, b) +} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/vector.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/vector.go index 3fe11371029..798d212144d 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/vector.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/vector.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -19,9 +8,12 @@ package fp import ( "bytes" "encoding/binary" + "errors" "fmt" "io" + "math/bits" "runtime" + "slices" "strings" "sync" "sync/atomic" @@ -78,40 +70,84 @@ func (vector *Vector) WriteTo(w io.Writer) (int64, error) { return n, nil } -// AsyncReadFrom reads a vector of big endian encoded Element. -// Length of the vector must be encoded as a uint32 on the first 4 bytes. -// It consumes the needed bytes from the reader and returns the number of bytes read and an error if any. -// It also returns a channel that will be closed when the validation is done. -// The validation consist of checking that the elements are smaller than the modulus, and -// converting them to montgomery form. -func (vector *Vector) AsyncReadFrom(r io.Reader) (int64, error, chan error) { +// AsyncReadFrom implements an asynchronous version of [Vector.ReadFrom]. It +// reads the reader r in full and then performs the validation and conversion to +// Montgomery form separately in a goroutine. Any error encountered during +// reading is returned directly, while errors encountered during +// validation/conversion are sent on the returned channel. Thus the caller must +// wait on the channel to ensure the vector is ready to use. The method +// additionally returns the number of bytes read from r. +// +// The errors during reading can be: +// - an error while reading from r; +// - not enough bytes in r to read the full vector indicated by header. +// +// The reader can contain more bytes than needed to decode the vector, in which +// case the extra bytes are ignored. In that case the reader is not seeked nor +// read further. +// +// The method allocates sufficiently large slice to store the vector. If the +// current slice fits the vector, it is reused, otherwise the slice is grown to +// fit the vector. +// +// The serialized encoding is as follows: +// - first 4 bytes: length of the vector as a big-endian uint32 +// - for each element of the vector, [Bytes] bytes representing the element in +// big-endian encoding. +func (vector *Vector) AsyncReadFrom(r io.Reader) (int64, error, chan error) { // nolint ST1008 chErr := make(chan error, 1) var buf [Bytes]byte if read, err := io.ReadFull(r, buf[:4]); err != nil { close(chErr) return int64(read), err, chErr } - sliceLen := binary.BigEndian.Uint32(buf[:4]) - - n := int64(4) - (*vector) = make(Vector, sliceLen) - if sliceLen == 0 { + headerSliceLen := uint64(binary.BigEndian.Uint32(buf[:4])) + + // to avoid allocating too large slice when the header is tampered, we limit + // the maximum allocation. We set the target to 4GB. This incurs a performance + // hit when reading very large slices, but protects against OOM. + targetSize := uint64(1 << 32) // 4GB + if bits.UintSize == 32 { + // reduce target size to 1GB on 32 bits architectures + targetSize = uint64(1 << 30) // 1GB + } + maxAllocateSliceLength := targetSize / uint64(Bytes) + + totalRead := int64(4) + *vector = (*vector)[:0] + if headerSliceLen == 0 { + // if the vector was nil previously even by reslicing we have a nil vector. + // but we want to have an empty slice to indicate that the vector has zero length. + if *vector == nil { + *vector = []Element{} + } + // we return already here to avoid launching a goroutine doing nothing below close(chErr) - return n, nil, chErr + return totalRead, nil, chErr } - bSlice := unsafe.Slice((*byte)(unsafe.Pointer(&(*vector)[0])), sliceLen*Bytes) - read, err := io.ReadFull(r, bSlice) - n += int64(read) - if err != nil { - close(chErr) - return n, err, chErr + for i := uint64(0); i < headerSliceLen; i += maxAllocateSliceLength { + if len(*vector) <= int(i) { + (*vector) = append(*vector, make([]Element, int(min(headerSliceLen-i, maxAllocateSliceLength)))...) + } + bSlice := unsafe.Slice((*byte)(unsafe.Pointer(&(*vector)[i])), int(min(headerSliceLen-i, maxAllocateSliceLength))*Bytes) + read, err := io.ReadFull(r, bSlice) + totalRead += int64(read) + if errors.Is(err, io.ErrUnexpectedEOF) { + close(chErr) + return totalRead, fmt.Errorf("less data than expected: read %d elements, expected %d", i+uint64(read)/Bytes, headerSliceLen), chErr + } + if err != nil { + close(chErr) + return totalRead, err, chErr + } } + bSlice := unsafe.Slice((*byte)(unsafe.Pointer(&(*vector)[0])), int(headerSliceLen)*Bytes) go func() { var cptErrors uint64 // process the elements in parallel - execute(int(sliceLen), func(start, end int) { + execute(int(headerSliceLen), func(start, end int) { var z Element for i := start; i < end; i++ { @@ -140,35 +176,72 @@ func (vector *Vector) AsyncReadFrom(r io.Reader) (int64, error, chan error) { } close(chErr) }() - return n, nil, chErr + return totalRead, nil, chErr } -// ReadFrom implements io.ReaderFrom and reads a vector of big endian encoded Element. -// Length of the vector must be encoded as a uint32 on the first 4 bytes. +// ReadFrom reads the vector from the reader r. It returns the number of bytes +// read and an error, if any. The errors can be: +// - an error while reading from r; +// - not enough bytes in r to read the full vector indicated by header; +// - when decoding the bytes into elements. +// +// The reader can contain more bytes than needed to decode the vector, in which case +// the extra bytes are ignored. In that case the reader is not seeked nor read further. +// +// The method allocates sufficiently large slice to store the vector. If the current slice fits +// the vector, it is reused, otherwise the slice is grown to fit the vector. +// +// The serialized encoding is as follows: +// - first 4 bytes: length of the vector as a big-endian uint32 +// - for each element of the vector, [Bytes] bytes representing the element in big-endian encoding. +// +// The method implements [io.ReaderFrom] interface. func (vector *Vector) ReadFrom(r io.Reader) (int64, error) { - var buf [Bytes]byte if read, err := io.ReadFull(r, buf[:4]); err != nil { return int64(read), err } - sliceLen := binary.BigEndian.Uint32(buf[:4]) - - n := int64(4) - (*vector) = make(Vector, sliceLen) + headerSliceLen := uint64(binary.BigEndian.Uint32(buf[:4])) + + // to avoid allocating too large slice when the header is tampered, we limit + // the maximum allocation. We set the target to 4GB. This incurs a performance + // hit when reading very large slices, but protects against OOM. + targetSize := uint64(1 << 32) // 4GB + if bits.UintSize == 32 { + // reduce target size to 1GB on 32 bits architectures + targetSize = uint64(1 << 30) // 1GB + } + maxAllocateSliceLength := targetSize / uint64(Bytes) + + totalRead := int64(4) // include already the header length + *vector = (*vector)[:0] + // if the vector was nil previously even by reslicing we have a nil vector. But we want + // to have an empty slice to indicate that the vector has zero length. When headerSliceLen == 0 + // we handle this edge case after reading the header as the loop body below is skipped. + if headerSliceLen == 0 && *vector == nil { + *vector = []Element{} + } - for i := 0; i < int(sliceLen); i++ { + for i := uint64(0); i < headerSliceLen; i++ { read, err := io.ReadFull(r, buf[:]) - n += int64(read) + totalRead += int64(read) + if errors.Is(err, io.ErrUnexpectedEOF) { + return totalRead, fmt.Errorf("less data than expected: read %d elements, expected %d", i, headerSliceLen) + } if err != nil { - return n, err + return totalRead, fmt.Errorf("error reading element %d: %w", i, err) } - (*vector)[i], err = BigEndian.Element(&buf) + if uint64(cap(*vector)) <= i { + (*vector) = slices.Grow(*vector, int(min(headerSliceLen-i, maxAllocateSliceLength))) + } + el, err := BigEndian.Element(&buf) if err != nil { - return n, err + return totalRead, fmt.Errorf("error decoding element %d: %w", i, err) } + *vector = append(*vector, el) } - return n, nil + return totalRead, nil } // String implements fmt.Stringer interface @@ -201,6 +274,88 @@ func (vector Vector) Swap(i, j int) { vector[i], vector[j] = vector[j], vector[i] } +// SetRandom sets the elements in vector to independent uniform random values in [0, q). +// +// This might error only if reading from crypto/rand.Reader errors, +// in which case the values in vector are undefined. +func (vector Vector) SetRandom() error { + for i := range vector { + if _, err := vector[i].SetRandom(); err != nil { + return err + } + } + return nil +} + +// MustSetRandom sets the elements in vector to independent uniform random values in [0, q). +// +// It panics if reading from crypto/rand.Reader errors. +func (vector Vector) MustSetRandom() { + for i := range vector { + if _, err := vector[i].SetRandom(); err != nil { + panic(err) + } + } +} + +// Equal returns true if vector and other have the same length and same elements. +func (vector Vector) Equal(other Vector) bool { + return slices.Equal(vector, other) +} + +func addVecGeneric(res, a, b Vector) { + if len(a) != len(b) || len(a) != len(res) { + panic("vector.Add: vectors don't have the same length") + } + for i := 0; i < len(a); i++ { + res[i].Add(&a[i], &b[i]) + } +} + +func subVecGeneric(res, a, b Vector) { + if len(a) != len(b) || len(a) != len(res) { + panic("vector.Sub: vectors don't have the same length") + } + for i := 0; i < len(a); i++ { + res[i].Sub(&a[i], &b[i]) + } +} + +func scalarMulVecGeneric(res, a Vector, b *Element) { + if len(a) != len(res) { + panic("vector.ScalarMul: vectors don't have the same length") + } + for i := 0; i < len(a); i++ { + res[i].Mul(&a[i], b) + } +} + +func sumVecGeneric(res *Element, a Vector) { + for i := 0; i < len(a); i++ { + res.Add(res, &a[i]) + } +} + +func innerProductVecGeneric(res *Element, a, b Vector) { + if len(a) != len(b) { + panic("vector.InnerProduct: vectors don't have the same length") + } + var tmp Element + for i := 0; i < len(a); i++ { + tmp.Mul(&a[i], &b[i]) + res.Add(res, &tmp) + } +} + +func mulVecGeneric(res, a, b Vector) { + if len(a) != len(b) || len(a) != len(res) { + panic("vector.Mul: vectors don't have the same length") + } + for i := 0; i < len(a); i++ { + res[i].Mul(&a[i], &b[i]) + } +} + // TODO @gbotrel make a public package out of that. // execute executes the work function in parallel. // this is copy paste from internal/parallel/parallel.go diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/vector_purego.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/vector_purego.go new file mode 100644 index 00000000000..85670501dfe --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fp/vector_purego.go @@ -0,0 +1,43 @@ +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fp + +// Add adds two vectors element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) Add(a, b Vector) { + addVecGeneric(*vector, a, b) +} + +// Sub subtracts two vectors element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) Sub(a, b Vector) { + subVecGeneric(*vector, a, b) +} + +// ScalarMul multiplies a vector by a scalar element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) ScalarMul(a Vector, b *Element) { + scalarMulVecGeneric(*vector, a, b) +} + +// Sum computes the sum of all elements in the vector. +func (vector *Vector) Sum() (res Element) { + sumVecGeneric(&res, *vector) + return +} + +// InnerProduct computes the inner product of two vectors. +// It panics if the vectors don't have the same length. +func (vector *Vector) InnerProduct(other Vector) (res Element) { + innerProductVecGeneric(&res, *vector, other) + return +} + +// Mul multiplies two vectors element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) Mul(a, b Vector) { + mulVecGeneric(*vector, a, b) +} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/arith.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/arith.go index 7cfd55da199..8dbae56e320 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/arith.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/arith.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -58,16 +47,3 @@ func madd3(a, b, c, d, e uint64) (hi uint64, lo uint64) { hi, _ = bits.Add64(hi, e, carry) return } -func max(a int, b int) int { - if a > b { - return a - } - return b -} - -func min(a int, b int) int { - if a < b { - return a - } - return b -} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/asm.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/asm.go deleted file mode 100644 index da061913ba7..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/asm.go +++ /dev/null @@ -1,27 +0,0 @@ -//go:build !noadx -// +build !noadx - -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by consensys/gnark-crypto DO NOT EDIT - -package fr - -import "golang.org/x/sys/cpu" - -var ( - supportAdx = cpu.X86.HasADX && cpu.X86.HasBMI2 - _ = supportAdx -) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/asm_noadx.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/asm_noadx.go deleted file mode 100644 index 7f52ffa197b..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/asm_noadx.go +++ /dev/null @@ -1,28 +0,0 @@ -//go:build noadx -// +build noadx - -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by consensys/gnark-crypto DO NOT EDIT - -package fr - -// note: this is needed for test purposes, as dynamically changing supportAdx doesn't flag -// certain errors (like fatal error: missing stackmap) -// this ensures we test all asm path. -var ( - supportAdx = false - _ = supportAdx -) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/doc.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/doc.go index 71ea8a2dc97..89c78bd60d2 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/doc.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/doc.go @@ -1,22 +1,13 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT // Package fr contains field arithmetic operations for modulus = 0x73eda7...000001. // -// The API is similar to math/big (big.Int), but the operations are significantly faster (up to 20x for the modular multiplication on amd64, see also https://hackmd.io/@gnark/modular_multiplication) +// The API is similar to math/big (big.Int), but the operations are significantly faster (up to 20x). +// +// Additionally fr.Vector offers an API to manipulate []Element using AVX512 instructions if available. // // The modulus is hardcoded in all the operations. // @@ -49,5 +40,7 @@ // // # Warning // -// This code has not been audited and is provided as-is. In particular, there is no security guarantees such as constant time implementation or side-channel attack resistance. +// There is no security guarantees such as constant time implementation or side-channel attack resistance. +// This code is provided as-is. Partially audited, see https://github.com/Consensys/gnark/tree/master/audits +// for more details. package fr diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element.go index aa6c47cdd13..7482877b97c 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -54,10 +43,10 @@ const ( // Field modulus q const ( - q0 uint64 = 18446744069414584321 - q1 uint64 = 6034159408538082302 - q2 uint64 = 3691218898639771653 - q3 uint64 = 8353516859464449352 + q0 = 18446744069414584321 + q1 = 6034159408538082302 + q2 = 3691218898639771653 + q3 = 8353516859464449352 ) var qElement = Element{ @@ -79,7 +68,10 @@ func Modulus() *big.Int { // q + r'.r = 1, i.e., qInvNeg = - q⁻¹ mod r // used for Montgomery reduction -const qInvNeg uint64 = 18446744069414584319 +const qInvNeg = 18446744069414584319 + +// mu = 2^288 / q needed for partial Barrett reduction +const mu uint64 = 9484408045 func init() { _modulus.SetString("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", 16) @@ -350,6 +342,16 @@ func (z *Element) SetRandom() (*Element, error) { } } +// MustSetRandom sets z to a uniform random value in [0, q). +// +// It panics if reading from crypto/rand.Reader errors. +func (z *Element) MustSetRandom() *Element { + if _, err := z.SetRandom(); err != nil { + panic(err) + } + return z +} + // smallerThanModulus returns true if z < q // This is not constant time func (z *Element) smallerThanModulus() bool { @@ -477,32 +479,8 @@ func (z *Element) Select(c int, x0 *Element, x1 *Element) *Element { // and is used for testing purposes. func _mulGeneric(z, x, y *Element) { - // Implements CIOS multiplication -- section 2.3.2 of Tolga Acar's thesis - // https://www.microsoft.com/en-us/research/wp-content/uploads/1998/06/97Acar.pdf - // - // The algorithm: - // - // for i=0 to N-1 - // C := 0 - // for j=0 to N-1 - // (C,t[j]) := t[j] + x[j]*y[i] + C - // (t[N+1],t[N]) := t[N] + C - // - // C := 0 - // m := t[0]*q'[0] mod D - // (C,_) := t[0] + m*q[0] - // for j=1 to N-1 - // (C,t[j-1]) := t[j] + m*q[j] + C - // - // (C,t[N-1]) := t[N] + C - // t[N] := t[N+1] + C - // - // → N is the number of machine words needed to store the modulus q - // → D is the word size. For example, on a 64-bit architecture D is 2 64 - // → x[i], y[i], q[i] is the ith word of the numbers x,y,q - // → q'[0] is the lowest word of the number -q⁻¹ mod r. This quantity is pre-computed, as it does not depend on the inputs. - // → t is a temporary array of size N+2 - // → C, S are machine words. A pair (C,S) refers to (hi-bits, lo-bits) of a two-word number + // Algorithm 2 of "Faster Montgomery Multiplication and Multi-Scalar-Multiplication for SNARKS" + // by Y. El Housni and G. Botrel https://doi.org/10.46586/tches.v2023.i3.504-521 var t [5]uint64 var D uint64 @@ -960,7 +938,7 @@ func (z *Element) SetBigInt(v *big.Int) *Element { // v == 0 return z } else if c != 1 && v.Cmp(&zero) != -1 { - // 0 < v < q + // 0 <= v < q return z.setBigInt(v) } @@ -1087,6 +1065,8 @@ type ByteOrder interface { String() string } +var errInvalidEncoding = errors.New("invalid fr.Element encoding") + // BigEndian is the big-endian implementation of ByteOrder and AppendByteOrder. var BigEndian bigEndian @@ -1102,7 +1082,7 @@ func (bigEndian) Element(b *[Bytes]byte) (Element, error) { z[3] = binary.BigEndian.Uint64((*b)[0:8]) if !z.smallerThanModulus() { - return Element{}, errors.New("invalid fr.Element encoding") + return Element{}, errInvalidEncoding } z.toMont() @@ -1132,7 +1112,7 @@ func (littleEndian) Element(b *[Bytes]byte) (Element, error) { z[3] = binary.LittleEndian.Uint64((*b)[24:32]) if !z.smallerThanModulus() { - return Element{}, errors.New("invalid fr.Element encoding") + return Element{}, errInvalidEncoding } z.toMont() diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element_amd64.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element_amd64.go new file mode 100644 index 00000000000..c282ebc9fc8 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element_amd64.go @@ -0,0 +1,62 @@ +//go:build !purego + +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fr + +import ( + _ "github.com/consensys/gnark-crypto/field/asm/element_4w" + "github.com/consensys/gnark-crypto/utils/cpu" +) + +var supportAdx = cpu.SupportADX + +//go:noescape +func MulBy3(x *Element) + +//go:noescape +func MulBy5(x *Element) + +//go:noescape +func MulBy13(x *Element) + +//go:noescape +func mul(res, x, y *Element) + +//go:noescape +func fromMont(res *Element) + +//go:noescape +func reduce(res *Element) + +// Butterfly sets +// +// a = a + b (mod q) +// b = a - b (mod q) +// +//go:noescape +func Butterfly(a, b *Element) + +// Mul z = x * y (mod q) +// +// x and y must be less than q +func (z *Element) Mul(x, y *Element) *Element { + + // Algorithm 2 of "Faster Montgomery Multiplication and Multi-Scalar-Multiplication for SNARKS" + // by Y. El Housni and G. Botrel https://doi.org/10.46586/tches.v2023.i3.504-521 + + mul(z, x, y) + return z +} + +// Square z = x * x (mod q) +// +// x must be less than q +func (z *Element) Square(x *Element) *Element { + // see Mul for doc. + mul(z, x, x) + return z +} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element_amd64.s b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element_amd64.s new file mode 100644 index 00000000000..b45615aa361 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element_amd64.s @@ -0,0 +1,10 @@ +//go:build !purego + +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +// We include the hash to force the Go compiler to recompile: 14652627197992229521 +#include "../../../field/asm/element_4w/element_4w_amd64.s" + diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element_arm64.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element_arm64.go new file mode 100644 index 00000000000..e8b6cb4d0f5 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element_arm64.go @@ -0,0 +1,70 @@ +//go:build !purego + +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fr + +import ( + _ "github.com/consensys/gnark-crypto/field/asm/element_4w" +) + +// Butterfly sets +// +// a = a + b (mod q) +// b = a - b (mod q) +// +//go:noescape +func Butterfly(a, b *Element) + +//go:noescape +func mul(res, x, y *Element) + +// Mul z = x * y (mod q) +// +// x and y must be less than q +func (z *Element) Mul(x, y *Element) *Element { + mul(z, x, y) + return z +} + +// Square z = x * x (mod q) +// +// x must be less than q +func (z *Element) Square(x *Element) *Element { + // see Mul for doc. + mul(z, x, x) + return z +} + +// MulBy3 x *= 3 (mod q) +func MulBy3(x *Element) { + _x := *x + x.Double(x).Add(x, &_x) +} + +// MulBy5 x *= 5 (mod q) +func MulBy5(x *Element) { + _x := *x + x.Double(x).Double(x).Add(x, &_x) +} + +// MulBy13 x *= 13 (mod q) +func MulBy13(x *Element) { + var y = Element{ + 120259084260, + 15510977298029211676, + 7326335280343703402, + 5909200893219589146, + } + x.Mul(x, &y) +} + +func fromMont(z *Element) { + _fromMontGeneric(z) +} + +//go:noescape +func reduce(res *Element) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element_arm64.s b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element_arm64.s new file mode 100644 index 00000000000..c8df07e3454 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element_arm64.s @@ -0,0 +1,10 @@ +//go:build !purego + +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +// We include the hash to force the Go compiler to recompile: 1501560133179981797 +#include "../../../field/asm/element_4w/element_4w_arm64.s" + diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element_exp.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element_exp.go index 48073af8e64..9c01c57f9c6 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element_exp.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element_exp.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element_mul_amd64.s b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element_mul_amd64.s deleted file mode 100644 index ef89cc5dfd6..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element_mul_amd64.s +++ /dev/null @@ -1,487 +0,0 @@ -// +build !purego - -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "textflag.h" -#include "funcdata.h" - -// modulus q -DATA q<>+0(SB)/8, $0xffffffff00000001 -DATA q<>+8(SB)/8, $0x53bda402fffe5bfe -DATA q<>+16(SB)/8, $0x3339d80809a1d805 -DATA q<>+24(SB)/8, $0x73eda753299d7d48 -GLOBL q<>(SB), (RODATA+NOPTR), $32 - -// qInv0 q'[0] -DATA qInv0<>(SB)/8, $0xfffffffeffffffff -GLOBL qInv0<>(SB), (RODATA+NOPTR), $8 - -#define REDUCE(ra0, ra1, ra2, ra3, rb0, rb1, rb2, rb3) \ - MOVQ ra0, rb0; \ - SUBQ q<>(SB), ra0; \ - MOVQ ra1, rb1; \ - SBBQ q<>+8(SB), ra1; \ - MOVQ ra2, rb2; \ - SBBQ q<>+16(SB), ra2; \ - MOVQ ra3, rb3; \ - SBBQ q<>+24(SB), ra3; \ - CMOVQCS rb0, ra0; \ - CMOVQCS rb1, ra1; \ - CMOVQCS rb2, ra2; \ - CMOVQCS rb3, ra3; \ - -// mul(res, x, y *Element) -TEXT ·mul(SB), $24-24 - - // the algorithm is described in the Element.Mul declaration (.go) - // however, to benefit from the ADCX and ADOX carry chains - // we split the inner loops in 2: - // for i=0 to N-1 - // for j=0 to N-1 - // (A,t[j]) := t[j] + x[j]*y[i] + A - // m := t[0]*q'[0] mod W - // C,_ := t[0] + m*q[0] - // for j=1 to N-1 - // (C,t[j-1]) := t[j] + m*q[j] + C - // t[N-1] = C + A - - NO_LOCAL_POINTERS - CMPB ·supportAdx(SB), $1 - JNE l1 - MOVQ x+8(FP), SI - - // x[0] -> DI - // x[1] -> R8 - // x[2] -> R9 - // x[3] -> R10 - MOVQ 0(SI), DI - MOVQ 8(SI), R8 - MOVQ 16(SI), R9 - MOVQ 24(SI), R10 - MOVQ y+16(FP), R11 - - // A -> BP - // t[0] -> R14 - // t[1] -> R13 - // t[2] -> CX - // t[3] -> BX - // clear the flags - XORQ AX, AX - MOVQ 0(R11), DX - - // (A,t[0]) := x[0]*y[0] + A - MULXQ DI, R14, R13 - - // (A,t[1]) := x[1]*y[0] + A - MULXQ R8, AX, CX - ADOXQ AX, R13 - - // (A,t[2]) := x[2]*y[0] + A - MULXQ R9, AX, BX - ADOXQ AX, CX - - // (A,t[3]) := x[3]*y[0] + A - MULXQ R10, AX, BP - ADOXQ AX, BX - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADOXQ AX, BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, R12 - ADCXQ R14, AX - MOVQ R12, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R13, R14 - MULXQ q<>+8(SB), AX, R13 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R13 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R13 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // t[3] = C + A - MOVQ $0, AX - ADCXQ AX, BX - ADOXQ BP, BX - - // clear the flags - XORQ AX, AX - MOVQ 8(R11), DX - - // (A,t[0]) := t[0] + x[0]*y[1] + A - MULXQ DI, AX, BP - ADOXQ AX, R14 - - // (A,t[1]) := t[1] + x[1]*y[1] + A - ADCXQ BP, R13 - MULXQ R8, AX, BP - ADOXQ AX, R13 - - // (A,t[2]) := t[2] + x[2]*y[1] + A - ADCXQ BP, CX - MULXQ R9, AX, BP - ADOXQ AX, CX - - // (A,t[3]) := t[3] + x[3]*y[1] + A - ADCXQ BP, BX - MULXQ R10, AX, BP - ADOXQ AX, BX - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, R12 - ADCXQ R14, AX - MOVQ R12, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R13, R14 - MULXQ q<>+8(SB), AX, R13 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R13 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R13 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // t[3] = C + A - MOVQ $0, AX - ADCXQ AX, BX - ADOXQ BP, BX - - // clear the flags - XORQ AX, AX - MOVQ 16(R11), DX - - // (A,t[0]) := t[0] + x[0]*y[2] + A - MULXQ DI, AX, BP - ADOXQ AX, R14 - - // (A,t[1]) := t[1] + x[1]*y[2] + A - ADCXQ BP, R13 - MULXQ R8, AX, BP - ADOXQ AX, R13 - - // (A,t[2]) := t[2] + x[2]*y[2] + A - ADCXQ BP, CX - MULXQ R9, AX, BP - ADOXQ AX, CX - - // (A,t[3]) := t[3] + x[3]*y[2] + A - ADCXQ BP, BX - MULXQ R10, AX, BP - ADOXQ AX, BX - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, R12 - ADCXQ R14, AX - MOVQ R12, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R13, R14 - MULXQ q<>+8(SB), AX, R13 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R13 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R13 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // t[3] = C + A - MOVQ $0, AX - ADCXQ AX, BX - ADOXQ BP, BX - - // clear the flags - XORQ AX, AX - MOVQ 24(R11), DX - - // (A,t[0]) := t[0] + x[0]*y[3] + A - MULXQ DI, AX, BP - ADOXQ AX, R14 - - // (A,t[1]) := t[1] + x[1]*y[3] + A - ADCXQ BP, R13 - MULXQ R8, AX, BP - ADOXQ AX, R13 - - // (A,t[2]) := t[2] + x[2]*y[3] + A - ADCXQ BP, CX - MULXQ R9, AX, BP - ADOXQ AX, CX - - // (A,t[3]) := t[3] + x[3]*y[3] + A - ADCXQ BP, BX - MULXQ R10, AX, BP - ADOXQ AX, BX - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, R12 - ADCXQ R14, AX - MOVQ R12, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R13, R14 - MULXQ q<>+8(SB), AX, R13 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R13 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R13 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // t[3] = C + A - MOVQ $0, AX - ADCXQ AX, BX - ADOXQ BP, BX - - // reduce element(R14,R13,CX,BX) using temp registers (SI,R12,R11,DI) - REDUCE(R14,R13,CX,BX,SI,R12,R11,DI) - - MOVQ res+0(FP), AX - MOVQ R14, 0(AX) - MOVQ R13, 8(AX) - MOVQ CX, 16(AX) - MOVQ BX, 24(AX) - RET - -l1: - MOVQ res+0(FP), AX - MOVQ AX, (SP) - MOVQ x+8(FP), AX - MOVQ AX, 8(SP) - MOVQ y+16(FP), AX - MOVQ AX, 16(SP) - CALL ·_mulGeneric(SB) - RET - -TEXT ·fromMont(SB), $8-8 - NO_LOCAL_POINTERS - - // the algorithm is described here - // https://hackmd.io/@gnark/modular_multiplication - // when y = 1 we have: - // for i=0 to N-1 - // t[i] = x[i] - // for i=0 to N-1 - // m := t[0]*q'[0] mod W - // C,_ := t[0] + m*q[0] - // for j=1 to N-1 - // (C,t[j-1]) := t[j] + m*q[j] + C - // t[N-1] = C - CMPB ·supportAdx(SB), $1 - JNE l2 - MOVQ res+0(FP), DX - MOVQ 0(DX), R14 - MOVQ 8(DX), R13 - MOVQ 16(DX), CX - MOVQ 24(DX), BX - XORQ DX, DX - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R14, AX - MOVQ BP, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R13, R14 - MULXQ q<>+8(SB), AX, R13 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R13 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R13 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - MOVQ $0, AX - ADCXQ AX, BX - ADOXQ AX, BX - XORQ DX, DX - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R14, AX - MOVQ BP, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R13, R14 - MULXQ q<>+8(SB), AX, R13 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R13 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R13 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - MOVQ $0, AX - ADCXQ AX, BX - ADOXQ AX, BX - XORQ DX, DX - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R14, AX - MOVQ BP, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R13, R14 - MULXQ q<>+8(SB), AX, R13 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R13 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R13 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - MOVQ $0, AX - ADCXQ AX, BX - ADOXQ AX, BX - XORQ DX, DX - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R14, AX - MOVQ BP, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R13, R14 - MULXQ q<>+8(SB), AX, R13 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R13 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R13 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - MOVQ $0, AX - ADCXQ AX, BX - ADOXQ AX, BX - - // reduce element(R14,R13,CX,BX) using temp registers (SI,DI,R8,R9) - REDUCE(R14,R13,CX,BX,SI,DI,R8,R9) - - MOVQ res+0(FP), AX - MOVQ R14, 0(AX) - MOVQ R13, 8(AX) - MOVQ CX, 16(AX) - MOVQ BX, 24(AX) - RET - -l2: - MOVQ res+0(FP), AX - MOVQ AX, (SP) - CALL ·_fromMontGeneric(SB) - RET diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element_ops_amd64.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element_ops_amd64.go deleted file mode 100644 index e40a9caed55..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element_ops_amd64.go +++ /dev/null @@ -1,107 +0,0 @@ -//go:build !purego -// +build !purego - -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by consensys/gnark-crypto DO NOT EDIT - -package fr - -//go:noescape -func MulBy3(x *Element) - -//go:noescape -func MulBy5(x *Element) - -//go:noescape -func MulBy13(x *Element) - -//go:noescape -func mul(res, x, y *Element) - -//go:noescape -func fromMont(res *Element) - -//go:noescape -func reduce(res *Element) - -// Butterfly sets -// -// a = a + b (mod q) -// b = a - b (mod q) -// -//go:noescape -func Butterfly(a, b *Element) - -// Mul z = x * y (mod q) -// -// x and y must be less than q -func (z *Element) Mul(x, y *Element) *Element { - - // Implements CIOS multiplication -- section 2.3.2 of Tolga Acar's thesis - // https://www.microsoft.com/en-us/research/wp-content/uploads/1998/06/97Acar.pdf - // - // The algorithm: - // - // for i=0 to N-1 - // C := 0 - // for j=0 to N-1 - // (C,t[j]) := t[j] + x[j]*y[i] + C - // (t[N+1],t[N]) := t[N] + C - // - // C := 0 - // m := t[0]*q'[0] mod D - // (C,_) := t[0] + m*q[0] - // for j=1 to N-1 - // (C,t[j-1]) := t[j] + m*q[j] + C - // - // (C,t[N-1]) := t[N] + C - // t[N] := t[N+1] + C - // - // → N is the number of machine words needed to store the modulus q - // → D is the word size. For example, on a 64-bit architecture D is 2 64 - // → x[i], y[i], q[i] is the ith word of the numbers x,y,q - // → q'[0] is the lowest word of the number -q⁻¹ mod r. This quantity is pre-computed, as it does not depend on the inputs. - // → t is a temporary array of size N+2 - // → C, S are machine words. A pair (C,S) refers to (hi-bits, lo-bits) of a two-word number - // - // As described here https://hackmd.io/@gnark/modular_multiplication we can get rid of one carry chain and simplify: - // (also described in https://eprint.iacr.org/2022/1400.pdf annex) - // - // for i=0 to N-1 - // (A,t[0]) := t[0] + x[0]*y[i] - // m := t[0]*q'[0] mod W - // C,_ := t[0] + m*q[0] - // for j=1 to N-1 - // (A,t[j]) := t[j] + x[j]*y[i] + A - // (C,t[j-1]) := t[j] + m*q[j] + C - // - // t[N-1] = C + A - // - // This optimization saves 5N + 2 additions in the algorithm, and can be used whenever the highest bit - // of the modulus is zero (and not all of the remaining bits are set). - - mul(z, x, y) - return z -} - -// Square z = x * x (mod q) -// -// x must be less than q -func (z *Element) Square(x *Element) *Element { - // see Mul for doc. - mul(z, x, x) - return z -} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element_ops_amd64.s b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element_ops_amd64.s deleted file mode 100644 index dde38132813..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element_ops_amd64.s +++ /dev/null @@ -1,230 +0,0 @@ -// +build !purego - -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "textflag.h" -#include "funcdata.h" - -// modulus q -DATA q<>+0(SB)/8, $0xffffffff00000001 -DATA q<>+8(SB)/8, $0x53bda402fffe5bfe -DATA q<>+16(SB)/8, $0x3339d80809a1d805 -DATA q<>+24(SB)/8, $0x73eda753299d7d48 -GLOBL q<>(SB), (RODATA+NOPTR), $32 - -// qInv0 q'[0] -DATA qInv0<>(SB)/8, $0xfffffffeffffffff -GLOBL qInv0<>(SB), (RODATA+NOPTR), $8 - -#define REDUCE(ra0, ra1, ra2, ra3, rb0, rb1, rb2, rb3) \ - MOVQ ra0, rb0; \ - SUBQ q<>(SB), ra0; \ - MOVQ ra1, rb1; \ - SBBQ q<>+8(SB), ra1; \ - MOVQ ra2, rb2; \ - SBBQ q<>+16(SB), ra2; \ - MOVQ ra3, rb3; \ - SBBQ q<>+24(SB), ra3; \ - CMOVQCS rb0, ra0; \ - CMOVQCS rb1, ra1; \ - CMOVQCS rb2, ra2; \ - CMOVQCS rb3, ra3; \ - -TEXT ·reduce(SB), NOSPLIT, $0-8 - MOVQ res+0(FP), AX - MOVQ 0(AX), DX - MOVQ 8(AX), CX - MOVQ 16(AX), BX - MOVQ 24(AX), SI - - // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) - - MOVQ DX, 0(AX) - MOVQ CX, 8(AX) - MOVQ BX, 16(AX) - MOVQ SI, 24(AX) - RET - -// MulBy3(x *Element) -TEXT ·MulBy3(SB), NOSPLIT, $0-8 - MOVQ x+0(FP), AX - MOVQ 0(AX), DX - MOVQ 8(AX), CX - MOVQ 16(AX), BX - MOVQ 24(AX), SI - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - - // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) - - ADDQ 0(AX), DX - ADCQ 8(AX), CX - ADCQ 16(AX), BX - ADCQ 24(AX), SI - - // reduce element(DX,CX,BX,SI) using temp registers (R11,R12,R13,R14) - REDUCE(DX,CX,BX,SI,R11,R12,R13,R14) - - MOVQ DX, 0(AX) - MOVQ CX, 8(AX) - MOVQ BX, 16(AX) - MOVQ SI, 24(AX) - RET - -// MulBy5(x *Element) -TEXT ·MulBy5(SB), NOSPLIT, $0-8 - MOVQ x+0(FP), AX - MOVQ 0(AX), DX - MOVQ 8(AX), CX - MOVQ 16(AX), BX - MOVQ 24(AX), SI - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - - // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) - - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - - // reduce element(DX,CX,BX,SI) using temp registers (R11,R12,R13,R14) - REDUCE(DX,CX,BX,SI,R11,R12,R13,R14) - - ADDQ 0(AX), DX - ADCQ 8(AX), CX - ADCQ 16(AX), BX - ADCQ 24(AX), SI - - // reduce element(DX,CX,BX,SI) using temp registers (R15,DI,R8,R9) - REDUCE(DX,CX,BX,SI,R15,DI,R8,R9) - - MOVQ DX, 0(AX) - MOVQ CX, 8(AX) - MOVQ BX, 16(AX) - MOVQ SI, 24(AX) - RET - -// MulBy13(x *Element) -TEXT ·MulBy13(SB), NOSPLIT, $0-8 - MOVQ x+0(FP), AX - MOVQ 0(AX), DX - MOVQ 8(AX), CX - MOVQ 16(AX), BX - MOVQ 24(AX), SI - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - - // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) - - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - - // reduce element(DX,CX,BX,SI) using temp registers (R11,R12,R13,R14) - REDUCE(DX,CX,BX,SI,R11,R12,R13,R14) - - MOVQ DX, R11 - MOVQ CX, R12 - MOVQ BX, R13 - MOVQ SI, R14 - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - - // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) - - ADDQ R11, DX - ADCQ R12, CX - ADCQ R13, BX - ADCQ R14, SI - - // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) - - ADDQ 0(AX), DX - ADCQ 8(AX), CX - ADCQ 16(AX), BX - ADCQ 24(AX), SI - - // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) - - MOVQ DX, 0(AX) - MOVQ CX, 8(AX) - MOVQ BX, 16(AX) - MOVQ SI, 24(AX) - RET - -// Butterfly(a, b *Element) sets a = a + b; b = a - b -TEXT ·Butterfly(SB), NOSPLIT, $0-16 - MOVQ a+0(FP), AX - MOVQ 0(AX), CX - MOVQ 8(AX), BX - MOVQ 16(AX), SI - MOVQ 24(AX), DI - MOVQ CX, R8 - MOVQ BX, R9 - MOVQ SI, R10 - MOVQ DI, R11 - XORQ AX, AX - MOVQ b+8(FP), DX - ADDQ 0(DX), CX - ADCQ 8(DX), BX - ADCQ 16(DX), SI - ADCQ 24(DX), DI - SUBQ 0(DX), R8 - SBBQ 8(DX), R9 - SBBQ 16(DX), R10 - SBBQ 24(DX), R11 - MOVQ $0xffffffff00000001, R12 - MOVQ $0x53bda402fffe5bfe, R13 - MOVQ $0x3339d80809a1d805, R14 - MOVQ $0x73eda753299d7d48, R15 - CMOVQCC AX, R12 - CMOVQCC AX, R13 - CMOVQCC AX, R14 - CMOVQCC AX, R15 - ADDQ R12, R8 - ADCQ R13, R9 - ADCQ R14, R10 - ADCQ R15, R11 - MOVQ R8, 0(DX) - MOVQ R9, 8(DX) - MOVQ R10, 16(DX) - MOVQ R11, 24(DX) - - // reduce element(CX,BX,SI,DI) using temp registers (R8,R9,R10,R11) - REDUCE(CX,BX,SI,DI,R8,R9,R10,R11) - - MOVQ a+0(FP), AX - MOVQ CX, 0(AX) - MOVQ BX, 8(AX) - MOVQ SI, 16(AX) - MOVQ DI, 24(AX) - RET diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element_ops_purego.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element_purego.go similarity index 80% rename from vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element_ops_purego.go rename to vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element_purego.go index 258157ab792..42ba2b9bbc7 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element_ops_purego.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/element_purego.go @@ -1,19 +1,7 @@ -//go:build !amd64 || purego -// +build !amd64 purego +//go:build purego || (!amd64 && !arm64) -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -44,14 +32,6 @@ func MulBy13(x *Element) { x.Mul(x, &y) } -// Butterfly sets -// -// a = a + b (mod q) -// b = a - b (mod q) -func Butterfly(a, b *Element) { - _butterflyGeneric(a, b) -} - func fromMont(z *Element) { _fromMontGeneric(z) } @@ -65,48 +45,8 @@ func reduce(z *Element) { // x and y must be less than q func (z *Element) Mul(x, y *Element) *Element { - // Implements CIOS multiplication -- section 2.3.2 of Tolga Acar's thesis - // https://www.microsoft.com/en-us/research/wp-content/uploads/1998/06/97Acar.pdf - // - // The algorithm: - // - // for i=0 to N-1 - // C := 0 - // for j=0 to N-1 - // (C,t[j]) := t[j] + x[j]*y[i] + C - // (t[N+1],t[N]) := t[N] + C - // - // C := 0 - // m := t[0]*q'[0] mod D - // (C,_) := t[0] + m*q[0] - // for j=1 to N-1 - // (C,t[j-1]) := t[j] + m*q[j] + C - // - // (C,t[N-1]) := t[N] + C - // t[N] := t[N+1] + C - // - // → N is the number of machine words needed to store the modulus q - // → D is the word size. For example, on a 64-bit architecture D is 2 64 - // → x[i], y[i], q[i] is the ith word of the numbers x,y,q - // → q'[0] is the lowest word of the number -q⁻¹ mod r. This quantity is pre-computed, as it does not depend on the inputs. - // → t is a temporary array of size N+2 - // → C, S are machine words. A pair (C,S) refers to (hi-bits, lo-bits) of a two-word number - // - // As described here https://hackmd.io/@gnark/modular_multiplication we can get rid of one carry chain and simplify: - // (also described in https://eprint.iacr.org/2022/1400.pdf annex) - // - // for i=0 to N-1 - // (A,t[0]) := t[0] + x[0]*y[i] - // m := t[0]*q'[0] mod W - // C,_ := t[0] + m*q[0] - // for j=1 to N-1 - // (A,t[j]) := t[j] + x[j]*y[i] + A - // (C,t[j-1]) := t[j] + m*q[j] + C - // - // t[N-1] = C + A - // - // This optimization saves 5N + 2 additions in the algorithm, and can be used whenever the highest bit - // of the modulus is zero (and not all of the remaining bits are set). + // Algorithm 2 of "Faster Montgomery Multiplication and Multi-Scalar-Multiplication for SNARKS" + // by Y. El Housni and G. Botrel https://doi.org/10.46586/tches.v2023.i3.504-521 var t0, t1, t2, t3 uint64 var u0, u1, u2, u3 uint64 @@ -441,3 +381,11 @@ func (z *Element) Square(x *Element) *Element { } return z } + +// Butterfly sets +// +// a = a + b (mod q) +// b = a - b (mod q) +func Butterfly(a, b *Element) { + _butterflyGeneric(a, b) +} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/generator.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/generator.go new file mode 100644 index 00000000000..a0d24d2b346 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/generator.go @@ -0,0 +1,36 @@ +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fr + +import ( + "fmt" + "math/big" + "math/bits" + + "github.com/consensys/gnark-crypto/ecc" +) + +// Generator returns a generator for Z/2^(log(m))Z +// or an error if m is too big (required root of unity doesn't exist) +func Generator(m uint64) (Element, error) { + x := ecc.NextPowerOfTwo(m) + + var rootOfUnity Element + + rootOfUnity.SetString("10238227357739495823651030575849232062558860180284477541189508159991286009131") + const maxOrderRoot uint64 = 32 + + // find generator for Z/2^(log(m))Z + logx := uint64(bits.TrailingZeros64(x)) + if logx > maxOrderRoot { + return Element{}, fmt.Errorf("m (%d) is too big: the required root of unity does not exist", m) + } + + expo := uint64(1 << (maxOrderRoot - logx)) + var generator Element + generator.Exp(rootOfUnity, big.NewInt(int64(expo))) // order x + return generator, nil +} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/vector.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/vector.go index 00ad8a8986b..eee2062de72 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/vector.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/vector.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -19,9 +8,12 @@ package fr import ( "bytes" "encoding/binary" + "errors" "fmt" "io" + "math/bits" "runtime" + "slices" "strings" "sync" "sync/atomic" @@ -78,40 +70,84 @@ func (vector *Vector) WriteTo(w io.Writer) (int64, error) { return n, nil } -// AsyncReadFrom reads a vector of big endian encoded Element. -// Length of the vector must be encoded as a uint32 on the first 4 bytes. -// It consumes the needed bytes from the reader and returns the number of bytes read and an error if any. -// It also returns a channel that will be closed when the validation is done. -// The validation consist of checking that the elements are smaller than the modulus, and -// converting them to montgomery form. -func (vector *Vector) AsyncReadFrom(r io.Reader) (int64, error, chan error) { +// AsyncReadFrom implements an asynchronous version of [Vector.ReadFrom]. It +// reads the reader r in full and then performs the validation and conversion to +// Montgomery form separately in a goroutine. Any error encountered during +// reading is returned directly, while errors encountered during +// validation/conversion are sent on the returned channel. Thus the caller must +// wait on the channel to ensure the vector is ready to use. The method +// additionally returns the number of bytes read from r. +// +// The errors during reading can be: +// - an error while reading from r; +// - not enough bytes in r to read the full vector indicated by header. +// +// The reader can contain more bytes than needed to decode the vector, in which +// case the extra bytes are ignored. In that case the reader is not seeked nor +// read further. +// +// The method allocates sufficiently large slice to store the vector. If the +// current slice fits the vector, it is reused, otherwise the slice is grown to +// fit the vector. +// +// The serialized encoding is as follows: +// - first 4 bytes: length of the vector as a big-endian uint32 +// - for each element of the vector, [Bytes] bytes representing the element in +// big-endian encoding. +func (vector *Vector) AsyncReadFrom(r io.Reader) (int64, error, chan error) { // nolint ST1008 chErr := make(chan error, 1) var buf [Bytes]byte if read, err := io.ReadFull(r, buf[:4]); err != nil { close(chErr) return int64(read), err, chErr } - sliceLen := binary.BigEndian.Uint32(buf[:4]) - - n := int64(4) - (*vector) = make(Vector, sliceLen) - if sliceLen == 0 { + headerSliceLen := uint64(binary.BigEndian.Uint32(buf[:4])) + + // to avoid allocating too large slice when the header is tampered, we limit + // the maximum allocation. We set the target to 4GB. This incurs a performance + // hit when reading very large slices, but protects against OOM. + targetSize := uint64(1 << 32) // 4GB + if bits.UintSize == 32 { + // reduce target size to 1GB on 32 bits architectures + targetSize = uint64(1 << 30) // 1GB + } + maxAllocateSliceLength := targetSize / uint64(Bytes) + + totalRead := int64(4) + *vector = (*vector)[:0] + if headerSliceLen == 0 { + // if the vector was nil previously even by reslicing we have a nil vector. + // but we want to have an empty slice to indicate that the vector has zero length. + if *vector == nil { + *vector = []Element{} + } + // we return already here to avoid launching a goroutine doing nothing below close(chErr) - return n, nil, chErr + return totalRead, nil, chErr } - bSlice := unsafe.Slice((*byte)(unsafe.Pointer(&(*vector)[0])), sliceLen*Bytes) - read, err := io.ReadFull(r, bSlice) - n += int64(read) - if err != nil { - close(chErr) - return n, err, chErr + for i := uint64(0); i < headerSliceLen; i += maxAllocateSliceLength { + if len(*vector) <= int(i) { + (*vector) = append(*vector, make([]Element, int(min(headerSliceLen-i, maxAllocateSliceLength)))...) + } + bSlice := unsafe.Slice((*byte)(unsafe.Pointer(&(*vector)[i])), int(min(headerSliceLen-i, maxAllocateSliceLength))*Bytes) + read, err := io.ReadFull(r, bSlice) + totalRead += int64(read) + if errors.Is(err, io.ErrUnexpectedEOF) { + close(chErr) + return totalRead, fmt.Errorf("less data than expected: read %d elements, expected %d", i+uint64(read)/Bytes, headerSliceLen), chErr + } + if err != nil { + close(chErr) + return totalRead, err, chErr + } } + bSlice := unsafe.Slice((*byte)(unsafe.Pointer(&(*vector)[0])), int(headerSliceLen)*Bytes) go func() { var cptErrors uint64 // process the elements in parallel - execute(int(sliceLen), func(start, end int) { + execute(int(headerSliceLen), func(start, end int) { var z Element for i := start; i < end; i++ { @@ -138,35 +174,72 @@ func (vector *Vector) AsyncReadFrom(r io.Reader) (int64, error, chan error) { } close(chErr) }() - return n, nil, chErr + return totalRead, nil, chErr } -// ReadFrom implements io.ReaderFrom and reads a vector of big endian encoded Element. -// Length of the vector must be encoded as a uint32 on the first 4 bytes. +// ReadFrom reads the vector from the reader r. It returns the number of bytes +// read and an error, if any. The errors can be: +// - an error while reading from r; +// - not enough bytes in r to read the full vector indicated by header; +// - when decoding the bytes into elements. +// +// The reader can contain more bytes than needed to decode the vector, in which case +// the extra bytes are ignored. In that case the reader is not seeked nor read further. +// +// The method allocates sufficiently large slice to store the vector. If the current slice fits +// the vector, it is reused, otherwise the slice is grown to fit the vector. +// +// The serialized encoding is as follows: +// - first 4 bytes: length of the vector as a big-endian uint32 +// - for each element of the vector, [Bytes] bytes representing the element in big-endian encoding. +// +// The method implements [io.ReaderFrom] interface. func (vector *Vector) ReadFrom(r io.Reader) (int64, error) { - var buf [Bytes]byte if read, err := io.ReadFull(r, buf[:4]); err != nil { return int64(read), err } - sliceLen := binary.BigEndian.Uint32(buf[:4]) - - n := int64(4) - (*vector) = make(Vector, sliceLen) + headerSliceLen := uint64(binary.BigEndian.Uint32(buf[:4])) + + // to avoid allocating too large slice when the header is tampered, we limit + // the maximum allocation. We set the target to 4GB. This incurs a performance + // hit when reading very large slices, but protects against OOM. + targetSize := uint64(1 << 32) // 4GB + if bits.UintSize == 32 { + // reduce target size to 1GB on 32 bits architectures + targetSize = uint64(1 << 30) // 1GB + } + maxAllocateSliceLength := targetSize / uint64(Bytes) + + totalRead := int64(4) // include already the header length + *vector = (*vector)[:0] + // if the vector was nil previously even by reslicing we have a nil vector. But we want + // to have an empty slice to indicate that the vector has zero length. When headerSliceLen == 0 + // we handle this edge case after reading the header as the loop body below is skipped. + if headerSliceLen == 0 && *vector == nil { + *vector = []Element{} + } - for i := 0; i < int(sliceLen); i++ { + for i := uint64(0); i < headerSliceLen; i++ { read, err := io.ReadFull(r, buf[:]) - n += int64(read) + totalRead += int64(read) + if errors.Is(err, io.ErrUnexpectedEOF) { + return totalRead, fmt.Errorf("less data than expected: read %d elements, expected %d", i, headerSliceLen) + } if err != nil { - return n, err + return totalRead, fmt.Errorf("error reading element %d: %w", i, err) } - (*vector)[i], err = BigEndian.Element(&buf) + if uint64(cap(*vector)) <= i { + (*vector) = slices.Grow(*vector, int(min(headerSliceLen-i, maxAllocateSliceLength))) + } + el, err := BigEndian.Element(&buf) if err != nil { - return n, err + return totalRead, fmt.Errorf("error decoding element %d: %w", i, err) } + *vector = append(*vector, el) } - return n, nil + return totalRead, nil } // String implements fmt.Stringer interface @@ -199,6 +272,88 @@ func (vector Vector) Swap(i, j int) { vector[i], vector[j] = vector[j], vector[i] } +// SetRandom sets the elements in vector to independent uniform random values in [0, q). +// +// This might error only if reading from crypto/rand.Reader errors, +// in which case the values in vector are undefined. +func (vector Vector) SetRandom() error { + for i := range vector { + if _, err := vector[i].SetRandom(); err != nil { + return err + } + } + return nil +} + +// MustSetRandom sets the elements in vector to independent uniform random values in [0, q). +// +// It panics if reading from crypto/rand.Reader errors. +func (vector Vector) MustSetRandom() { + for i := range vector { + if _, err := vector[i].SetRandom(); err != nil { + panic(err) + } + } +} + +// Equal returns true if vector and other have the same length and same elements. +func (vector Vector) Equal(other Vector) bool { + return slices.Equal(vector, other) +} + +func addVecGeneric(res, a, b Vector) { + if len(a) != len(b) || len(a) != len(res) { + panic("vector.Add: vectors don't have the same length") + } + for i := 0; i < len(a); i++ { + res[i].Add(&a[i], &b[i]) + } +} + +func subVecGeneric(res, a, b Vector) { + if len(a) != len(b) || len(a) != len(res) { + panic("vector.Sub: vectors don't have the same length") + } + for i := 0; i < len(a); i++ { + res[i].Sub(&a[i], &b[i]) + } +} + +func scalarMulVecGeneric(res, a Vector, b *Element) { + if len(a) != len(res) { + panic("vector.ScalarMul: vectors don't have the same length") + } + for i := 0; i < len(a); i++ { + res[i].Mul(&a[i], b) + } +} + +func sumVecGeneric(res *Element, a Vector) { + for i := 0; i < len(a); i++ { + res.Add(res, &a[i]) + } +} + +func innerProductVecGeneric(res *Element, a, b Vector) { + if len(a) != len(b) { + panic("vector.InnerProduct: vectors don't have the same length") + } + var tmp Element + for i := 0; i < len(a); i++ { + tmp.Mul(&a[i], &b[i]) + res.Add(res, &tmp) + } +} + +func mulVecGeneric(res, a, b Vector) { + if len(a) != len(b) || len(a) != len(res) { + panic("vector.Mul: vectors don't have the same length") + } + for i := 0; i < len(a); i++ { + res[i].Mul(&a[i], &b[i]) + } +} + // TODO @gbotrel make a public package out of that. // execute executes the work function in parallel. // this is copy paste from internal/parallel/parallel.go diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/vector_amd64.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/vector_amd64.go new file mode 100644 index 00000000000..8b6df0b4026 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/vector_amd64.go @@ -0,0 +1,154 @@ +//go:build !purego + +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fr + +import ( + _ "github.com/consensys/gnark-crypto/field/asm/element_4w" + "github.com/consensys/gnark-crypto/utils/cpu" +) + +// Add adds two vectors element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) Add(a, b Vector) { + if len(a) != len(b) || len(a) != len(*vector) { + panic("vector.Add: vectors don't have the same length") + } + n := uint64(len(a)) + addVec(&(*vector)[0], &a[0], &b[0], n) +} + +//go:noescape +func addVec(res, a, b *Element, n uint64) + +// Sub subtracts two vectors element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) Sub(a, b Vector) { + if len(a) != len(b) || len(a) != len(*vector) { + panic("vector.Sub: vectors don't have the same length") + } + subVec(&(*vector)[0], &a[0], &b[0], uint64(len(a))) +} + +//go:noescape +func subVec(res, a, b *Element, n uint64) + +// ScalarMul multiplies a vector by a scalar element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) ScalarMul(a Vector, b *Element) { + if len(a) != len(*vector) { + panic("vector.ScalarMul: vectors don't have the same length") + } + const maxN = (1 << 32) - 1 + if !cpu.SupportAVX512 || uint64(len(a)) >= maxN { + // call scalarMulVecGeneric + scalarMulVecGeneric(*vector, a, b) + return + } + n := uint64(len(a)) + if n == 0 { + return + } + // the code for scalarMul is identical to mulVec; and it expects at least + // 2 elements in the vector to fill the Z registers + var bb [2]Element + bb[0] = *b + bb[1] = *b + const blockSize = 16 + scalarMulVec(&(*vector)[0], &a[0], &bb[0], n/blockSize, qInvNeg) + if n%blockSize != 0 { + // call scalarMulVecGeneric on the rest + start := n - n%blockSize + scalarMulVecGeneric((*vector)[start:], a[start:], b) + } +} + +//go:noescape +func scalarMulVec(res, a, b *Element, n uint64, qInvNeg uint64) + +// Sum computes the sum of all elements in the vector. +func (vector *Vector) Sum() (res Element) { + n := uint64(len(*vector)) + if n == 0 { + return + } + const minN = 16 * 7 // AVX512 slower than generic for small n + const maxN = (1 << 32) - 1 + if !cpu.SupportAVX512 || n <= minN || n >= maxN { + // call sumVecGeneric + sumVecGeneric(&res, *vector) + return + } + sumVec(&res, &(*vector)[0], uint64(len(*vector))) + return +} + +//go:noescape +func sumVec(res *Element, a *Element, n uint64) + +// InnerProduct computes the inner product of two vectors. +// It panics if the vectors don't have the same length. +func (vector *Vector) InnerProduct(other Vector) (res Element) { + n := uint64(len(*vector)) + if n == 0 { + return + } + if n != uint64(len(other)) { + panic("vector.InnerProduct: vectors don't have the same length") + } + const maxN = (1 << 32) - 1 + if !cpu.SupportAVX512 || n >= maxN { + // call innerProductVecGeneric + // note; we could split the vector into smaller chunks and call innerProductVec + innerProductVecGeneric(&res, *vector, other) + return + } + innerProdVec(&res[0], &(*vector)[0], &other[0], uint64(len(*vector))) + + return +} + +//go:noescape +func innerProdVec(res *uint64, a, b *Element, n uint64) + +// Mul multiplies two vectors element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) Mul(a, b Vector) { + if len(a) != len(b) || len(a) != len(*vector) { + panic("vector.Mul: vectors don't have the same length") + } + n := uint64(len(a)) + if n == 0 { + return + } + const maxN = (1 << 32) - 1 + if !cpu.SupportAVX512 || n >= maxN { + // call mulVecGeneric + mulVecGeneric(*vector, a, b) + return + } + + const blockSize = 16 + mulVec(&(*vector)[0], &a[0], &b[0], n/blockSize, qInvNeg) + if n%blockSize != 0 { + // call mulVecGeneric on the rest + start := n - n%blockSize + mulVecGeneric((*vector)[start:], a[start:], b[start:]) + } + +} + +// Patterns use for transposing the vectors in mulVec +var ( + pattern1 = [8]uint64{0, 8, 1, 9, 2, 10, 3, 11} + pattern2 = [8]uint64{12, 4, 13, 5, 14, 6, 15, 7} + pattern3 = [8]uint64{0, 1, 8, 9, 2, 3, 10, 11} + pattern4 = [8]uint64{12, 13, 4, 5, 14, 15, 6, 7} +) + +//go:noescape +func mulVec(res, a, b *Element, n uint64, qInvNeg uint64) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/vector_purego.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/vector_purego.go new file mode 100644 index 00000000000..6608e394c79 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/fr/vector_purego.go @@ -0,0 +1,45 @@ +//go:build purego || !amd64 + +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fr + +// Add adds two vectors element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) Add(a, b Vector) { + addVecGeneric(*vector, a, b) +} + +// Sub subtracts two vectors element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) Sub(a, b Vector) { + subVecGeneric(*vector, a, b) +} + +// ScalarMul multiplies a vector by a scalar element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) ScalarMul(a Vector, b *Element) { + scalarMulVecGeneric(*vector, a, b) +} + +// Sum computes the sum of all elements in the vector. +func (vector *Vector) Sum() (res Element) { + sumVecGeneric(&res, *vector) + return +} + +// InnerProduct computes the inner product of two vectors. +// It panics if the vectors don't have the same length. +func (vector *Vector) InnerProduct(other Vector) (res Element) { + innerProductVecGeneric(&res, *vector, other) + return +} + +// Mul multiplies two vectors element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) Mul(a, b Vector) { + mulVecGeneric(*vector, a, b) +} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/g1.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/g1.go index c24a82cda65..e3f7c18d746 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/g1.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/g1.go @@ -1,16 +1,5 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -20,43 +9,46 @@ import ( "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark-crypto/ecc/bls12-381/fp" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" + "github.com/consensys/gnark-crypto/ecc/bls12-381/hash_to_curve" "github.com/consensys/gnark-crypto/internal/parallel" "math/big" "runtime" ) -// G1Affine point in affine coordinates +// G1Affine is a point in affine coordinates (x,y) type G1Affine struct { X, Y fp.Element } -// G1Jac is a point with fp.Element coordinates +// G1Jac is a point in Jacobian coordinates (x=X/Z², y=Y/Z³) type G1Jac struct { X, Y, Z fp.Element } -// g1JacExtended parameterized Jacobian coordinates (x=X/ZZ, y=Y/ZZZ, ZZ³=ZZZ²) +// g1JacExtended is a point in extended Jacobian coordinates (x=X/ZZ, y=Y/ZZZ, ZZ³=ZZZ²) type g1JacExtended struct { X, Y, ZZ, ZZZ fp.Element } // ------------------------------------------------------------------------------------------------- -// Affine +// Affine coordinates -// Set sets p to the provided point +// Set sets p to a in affine coordinates. func (p *G1Affine) Set(a *G1Affine) *G1Affine { p.X, p.Y = a.X, a.Y return p } -// setInfinity sets p to O -func (p *G1Affine) setInfinity() *G1Affine { +// SetInfinity sets p to the infinity point, which is encoded as (0,0). +// N.B.: (0,0) is never on the curve for j=0 curves (Y²=X³+B). +func (p *G1Affine) SetInfinity() *G1Affine { p.X.SetZero() p.Y.SetZero() return p } -// ScalarMultiplication computes and returns p = a ⋅ s +// ScalarMultiplication computes and returns p = [s]a +// where p and a are affine points. func (p *G1Affine) ScalarMultiplication(a *G1Affine, s *big.Int) *G1Affine { var _p G1Jac _p.FromAffine(a) @@ -65,15 +57,8 @@ func (p *G1Affine) ScalarMultiplication(a *G1Affine, s *big.Int) *G1Affine { return p } -// ScalarMultiplicationAffine computes and returns p = a ⋅ s -// Takes an affine point and returns a Jacobian point (useful for KZG) -func (p *G1Jac) ScalarMultiplicationAffine(a *G1Affine, s *big.Int) *G1Jac { - p.FromAffine(a) - p.mulGLV(p, s) - return p -} - -// ScalarMultiplicationBase computes and returns p = g ⋅ s where g is the prime subgroup generator +// ScalarMultiplicationBase computes and returns p = [s]g +// where g is the affine point generating the prime subgroup. func (p *G1Affine) ScalarMultiplicationBase(s *big.Int) *G1Affine { var _p G1Jac _p.mulGLV(&g1Gen, s) @@ -81,51 +66,88 @@ func (p *G1Affine) ScalarMultiplicationBase(s *big.Int) *G1Affine { return p } -// Add adds two point in affine coordinates. -// This should rarely be used as it is very inefficient compared to Jacobian +// Add adds two points in affine coordinates. +// It uses the Jacobian addition with a.Z=b.Z=1 and converts the result to affine coordinates. +// +// https://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-mmadd-2007-bl func (p *G1Affine) Add(a, b *G1Affine) *G1Affine { - var p1, p2 G1Jac - p1.FromAffine(a) - p2.FromAffine(b) - p1.AddAssign(&p2) - p.FromJacobian(&p1) - return p + var q G1Jac + // a is infinity, return b + if a.IsInfinity() { + p.Set(b) + return p + } + // b is infinity, return a + if b.IsInfinity() { + p.Set(a) + return p + } + if a.X.Equal(&b.X) { + // if b == a, we double instead + if a.Y.Equal(&b.Y) { + q.DoubleMixed(a) + return p.FromJacobian(&q) + } else { + // if b == -a, we return 0 + return p.SetInfinity() + } + } + var H, HH, I, J, r, V fp.Element + H.Sub(&b.X, &a.X) + HH.Square(&H) + I.Double(&HH).Double(&I) + J.Mul(&H, &I) + r.Sub(&b.Y, &a.Y) + r.Double(&r) + V.Mul(&a.X, &I) + q.X.Square(&r). + Sub(&q.X, &J). + Sub(&q.X, &V). + Sub(&q.X, &V) + q.Y.Sub(&V, &q.X). + Mul(&q.Y, &r) + J.Mul(&a.Y, &J).Double(&J) + q.Y.Sub(&q.Y, &J) + q.Z.Double(&H) + + return p.FromJacobian(&q) } // Double doubles a point in affine coordinates. -// This should rarely be used as it is very inefficient compared to Jacobian +// It converts the point to Jacobian coordinates, doubles it using Jacobian +// addition with a.Z=1, and converts it back to affine coordinates. +// +// http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-mdbl-2007-bl func (p *G1Affine) Double(a *G1Affine) *G1Affine { - var p1 G1Jac - p1.FromAffine(a) - p1.Double(&p1) - p.FromJacobian(&p1) + var q G1Jac + q.FromAffine(a) + q.DoubleMixed(a) + p.FromJacobian(&q) return p } -// Sub subs two point in affine coordinates. -// This should rarely be used as it is very inefficient compared to Jacobian +// Sub subtracts two points in affine coordinates. +// It uses a similar approach to Add, but negates the second point before adding. func (p *G1Affine) Sub(a, b *G1Affine) *G1Affine { - var p1, p2 G1Jac - p1.FromAffine(a) - p2.FromAffine(b) - p1.SubAssign(&p2) - p.FromJacobian(&p1) + var bneg G1Affine + bneg.Neg(b) + p.Add(a, &bneg) return p } -// Equal tests if two points (in Affine coordinates) are equal +// Equal tests if two points in affine coordinates are equal. func (p *G1Affine) Equal(a *G1Affine) bool { return p.X.Equal(&a.X) && p.Y.Equal(&a.Y) } -// Neg computes -G +// Neg sets p to the affine negative point -a = (a.X, -a.Y). func (p *G1Affine) Neg(a *G1Affine) *G1Affine { p.X = a.X p.Y.Neg(&a.Y) return p } -// FromJacobian rescales a point in Jacobian coord in z=1 plane +// FromJacobian converts a point p1 from Jacobian to affine coordinates. func (p *G1Affine) FromJacobian(p1 *G1Jac) *G1Affine { var a, b fp.Element @@ -144,7 +166,7 @@ func (p *G1Affine) FromJacobian(p1 *G1Jac) *G1Affine { return p } -// String returns the string representation of the point or "O" if it is infinity +// String returns the string representation E(x,y) of the affine point p or "O" if it is infinity. func (p *G1Affine) String() string { if p.IsInfinity() { return "O" @@ -152,106 +174,110 @@ func (p *G1Affine) String() string { return "E([" + p.X.String() + "," + p.Y.String() + "])" } -// IsInfinity checks if the point is infinity -// in affine, it's encoded as (0,0) -// (0,0) is never on the curve for j=0 curves +// IsInfinity checks if the affine point p is infinity, which is encoded as (0,0). +// N.B.: (0,0) is never on the curve for j=0 curves (Y²=X³+B). func (p *G1Affine) IsInfinity() bool { return p.X.IsZero() && p.Y.IsZero() } -// IsOnCurve returns true if p in on the curve +// IsOnCurve returns true if the affine point p in on the curve. func (p *G1Affine) IsOnCurve() bool { - var point G1Jac - point.FromAffine(p) - return point.IsOnCurve() // call this function to handle infinity point + if p.IsInfinity() { + return true + } + var left, right fp.Element + left.Square(&p.Y) + right.Square(&p.X).Mul(&right, &p.X) + right.Add(&right, &bCurveCoeff) + return left.Equal(&right) } -// IsInSubGroup returns true if p is in the correct subgroup, false otherwise +// IsInSubGroup returns true if the affine point p is in the correct subgroup, false otherwise. func (p *G1Affine) IsInSubGroup() bool { - var _p G1Jac + if !p.IsOnCurve() { + return false + } + var res, _p G1Jac _p.FromAffine(p) - return _p.IsInSubGroup() + res.phi(&_p). + mulBySeed(&res). + mulBySeed(&res). + Neg(&res) + + return res.Equal(&_p) } // ------------------------------------------------------------------------------------------------- -// Jacobian +// Jacobian coordinates -// Set sets p to the provided point -func (p *G1Jac) Set(a *G1Jac) *G1Jac { - p.X, p.Y, p.Z = a.X, a.Y, a.Z +// Set sets p to a in Jacobian coordinates. +func (p *G1Jac) Set(q *G1Jac) *G1Jac { + p.X, p.Y, p.Z = q.X, q.Y, q.Z return p } -// Equal tests if two points (in Jacobian coordinates) are equal -func (p *G1Jac) Equal(a *G1Jac) bool { +// Equal tests if two points in Jacobian coordinates are equal. +func (p *G1Jac) Equal(q *G1Jac) bool { // If one point is infinity, the other must also be infinity. if p.Z.IsZero() { - return a.Z.IsZero() + return q.Z.IsZero() } // If the other point is infinity, return false since we can't // the following checks would be incorrect. - if a.Z.IsZero() { + if q.Z.IsZero() { return false } var pZSquare, aZSquare fp.Element pZSquare.Square(&p.Z) - aZSquare.Square(&a.Z) + aZSquare.Square(&q.Z) var lhs, rhs fp.Element lhs.Mul(&p.X, &aZSquare) - rhs.Mul(&a.X, &pZSquare) + rhs.Mul(&q.X, &pZSquare) if !lhs.Equal(&rhs) { return false } - lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &a.Z) - rhs.Mul(&a.Y, &pZSquare).Mul(&rhs, &p.Z) + lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &q.Z) + rhs.Mul(&q.Y, &pZSquare).Mul(&rhs, &p.Z) return lhs.Equal(&rhs) } -// Neg computes -G -func (p *G1Jac) Neg(a *G1Jac) *G1Jac { - *p = *a - p.Y.Neg(&a.Y) - return p -} - -// SubAssign subtracts two points on the curve -func (p *G1Jac) SubAssign(a *G1Jac) *G1Jac { - var tmp G1Jac - tmp.Set(a) - tmp.Y.Neg(&tmp.Y) - p.AddAssign(&tmp) +// Neg sets p to the Jacobian negative point -q = (q.X, -q.Y, q.Z). +func (p *G1Jac) Neg(q *G1Jac) *G1Jac { + *p = *q + p.Y.Neg(&q.Y) return p } -// AddAssign point addition in montgomery form +// AddAssign sets p to p+a in Jacobian coordinates. +// // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl -func (p *G1Jac) AddAssign(a *G1Jac) *G1Jac { +func (p *G1Jac) AddAssign(q *G1Jac) *G1Jac { - // p is infinity, return a + // p is infinity, return q if p.Z.IsZero() { - p.Set(a) + p.Set(q) return p } - // a is infinity, return p - if a.Z.IsZero() { + // q is infinity, return p + if q.Z.IsZero() { return p } var Z1Z1, Z2Z2, U1, U2, S1, S2, H, I, J, r, V fp.Element - Z1Z1.Square(&a.Z) + Z1Z1.Square(&q.Z) Z2Z2.Square(&p.Z) - U1.Mul(&a.X, &Z2Z2) + U1.Mul(&q.X, &Z2Z2) U2.Mul(&p.X, &Z1Z1) - S1.Mul(&a.Y, &p.Z). + S1.Mul(&q.Y, &p.Z). Mul(&S1, &Z2Z2) - S2.Mul(&p.Y, &a.Z). + S2.Mul(&p.Y, &q.Z). Mul(&S2, &Z1Z1) - // if p == a, we double instead + // if p == q, we double instead if U1.Equal(&U2) && S1.Equal(&S2) { return p.DoubleAssign() } @@ -270,7 +296,7 @@ func (p *G1Jac) AddAssign(a *G1Jac) *G1Jac { Mul(&p.Y, &r) S1.Mul(&S1, &J).Double(&S1) p.Y.Sub(&p.Y, &S1) - p.Z.Add(&p.Z, &a.Z) + p.Z.Add(&p.Z, &q.Z) p.Z.Square(&p.Z). Sub(&p.Z, &Z1Z1). Sub(&p.Z, &Z2Z2). @@ -279,7 +305,48 @@ func (p *G1Jac) AddAssign(a *G1Jac) *G1Jac { return p } -// AddMixed point addition +// SubAssign sets p to p-a in Jacobian coordinates. +// It uses a similar approach to AddAssign, but negates the point a before adding. +func (p *G1Jac) SubAssign(q *G1Jac) *G1Jac { + var tmp G1Jac + tmp.Set(q) + tmp.Y.Neg(&tmp.Y) + p.AddAssign(&tmp) + return p +} + +// Double sets p to [2]q in Jacobian coordinates. +// +// https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl +func (p *G1Jac) DoubleMixed(a *G1Affine) *G1Jac { + var XX, YY, YYYY, S, M, T fp.Element + XX.Square(&a.X) + YY.Square(&a.Y) + YYYY.Square(&YY) + S.Add(&a.X, &YY). + Square(&S). + Sub(&S, &XX). + Sub(&S, &YYYY). + Double(&S) + M.Double(&XX). + Add(&M, &XX) // -> + A, but A=0 here + T.Square(&M). + Sub(&T, &S). + Sub(&T, &S) + p.X.Set(&T) + p.Y.Sub(&S, &T). + Mul(&p.Y, &M) + YYYY.Double(&YYYY). + Double(&YYYY). + Double(&YYYY) + p.Y.Sub(&p.Y, &YYYY) + p.Z.Double(&a.Y) + + return p +} + +// AddMixed sets p to p+a in Jacobian coordinates, where a.Z = 1. +// // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-madd-2007-bl func (p *G1Jac) AddMixed(a *G1Affine) *G1Jac { @@ -303,7 +370,7 @@ func (p *G1Jac) AddMixed(a *G1Affine) *G1Jac { // if p == a, we double instead if U2.Equal(&p.X) && S2.Equal(&p.Y) { - return p.DoubleAssign() + return p.DoubleMixed(a) } H.Sub(&U2, &p.X) @@ -328,7 +395,8 @@ func (p *G1Jac) AddMixed(a *G1Affine) *G1Jac { return p } -// Double doubles a point in Jacobian coordinates +// Double sets p to [2]q in Jacobian coordinates. +// // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl func (p *G1Jac) Double(q *G1Jac) *G1Jac { p.Set(q) @@ -336,7 +404,8 @@ func (p *G1Jac) Double(q *G1Jac) *G1Jac { return p } -// DoubleAssign doubles a point in Jacobian coordinates +// DoubleAssign doubles p in Jacobian coordinates. +// // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl func (p *G1Jac) DoubleAssign() *G1Jac { @@ -368,43 +437,51 @@ func (p *G1Jac) DoubleAssign() *G1Jac { return p } -// ScalarMultiplication computes and returns p = a ⋅ s +// ScalarMultiplication computes and returns p = [s]a +// where p and a are Jacobian points. +// using the GLV technique. // see https://www.iacr.org/archive/crypto2001/21390189.pdf -func (p *G1Jac) ScalarMultiplication(a *G1Jac, s *big.Int) *G1Jac { - return p.mulGLV(a, s) +func (p *G1Jac) ScalarMultiplication(q *G1Jac, s *big.Int) *G1Jac { + return p.mulGLV(q, s) +} + +// ScalarMultiplicationBase computes and returns p = [s]g +// where g is the prime subgroup generator. +func (p *G1Jac) ScalarMultiplicationBase(s *big.Int) *G1Jac { + return p.mulGLV(&g1Gen, s) + } -// String returns canonical representation of the point in affine coordinates +// String converts p to affine coordinates and returns its string representation E(x,y) or "O" if it is infinity. func (p *G1Jac) String() string { _p := G1Affine{} _p.FromJacobian(p) return _p.String() } -// FromAffine sets p = Q, p in Jacobian, Q in affine -func (p *G1Jac) FromAffine(Q *G1Affine) *G1Jac { - if Q.IsInfinity() { +// FromAffine converts a point a from affine to Jacobian coordinates. +func (p *G1Jac) FromAffine(a *G1Affine) *G1Jac { + if a.IsInfinity() { p.Z.SetZero() p.X.SetOne() p.Y.SetOne() return p } p.Z.SetOne() - p.X.Set(&Q.X) - p.Y.Set(&Q.Y) + p.X.Set(&a.X) + p.Y.Set(&a.Y) return p } -// IsOnCurve returns true if p in on the curve +// IsOnCurve returns true if the Jacobian point p in on the curve. func (p *G1Jac) IsOnCurve() bool { - var left, right, tmp fp.Element + var left, right, tmp, ZZ fp.Element left.Square(&p.Y) right.Square(&p.X).Mul(&right, &p.X) - tmp.Square(&p.Z). - Square(&tmp). - Mul(&tmp, &p.Z). - Mul(&tmp, &p.Z). - Mul(&tmp, &bCurveCoeff) + ZZ.Square(&p.Z) + tmp.Square(&ZZ).Mul(&tmp, &ZZ) + // Mul tmp by bCurveCoeff=4 + tmp.Double(&tmp).Double(&tmp) right.Add(&right, &tmp) return left.Equal(&right) } @@ -416,25 +493,41 @@ func (p *G1Jac) IsOnCurve() bool { // 1, x². So we check that p+x²ϕ(p) // is the infinity. func (p *G1Jac) IsInSubGroup() bool { - + if !p.IsOnCurve() { + return false + } var res G1Jac res.phi(p). - ScalarMultiplication(&res, &xGen). - ScalarMultiplication(&res, &xGen). - AddAssign(p) + mulBySeed(&res). + mulBySeed(&res). + Neg(&res) + + return res.Equal(p) - return res.IsOnCurve() && res.Z.IsZero() +} +func GeneratePointNotInG1(f fp.Element) G1Jac { + var res, jac G1Jac + aff := MapToCurve1(&f) + hash_to_curve.G1Isogeny(&aff.X, &aff.Y) + jac.FromAffine(&aff) + // p+x²ϕ(p) = [r]p + res.phi(&jac). + mulBySeed(&res). + mulBySeed(&res). + AddAssign(&jac) + return res } -// mulWindowed computes a 2-bits windowed scalar multiplication -func (p *G1Jac) mulWindowed(a *G1Jac, s *big.Int) *G1Jac { +// mulWindowed computes the 2-bits windowed double-and-add scalar +// multiplication p=[s]q in Jacobian coordinates. +func (p *G1Jac) mulWindowed(q *G1Jac, s *big.Int) *G1Jac { var res G1Jac var ops [3]G1Jac - ops[0].Set(a) + ops[0].Set(q) if s.Sign() == -1 { ops[0].Neg(&ops[0]) } @@ -461,17 +554,50 @@ func (p *G1Jac) mulWindowed(a *G1Jac, s *big.Int) *G1Jac { } -// ϕ assigns p to ϕ(a) where ϕ: (x,y) → (w x,y), and returns p -// where w is a third root of unity in 𝔽p -func (p *G1Jac) phi(a *G1Jac) *G1Jac { - p.Set(a) +// mulBySeed multiplies the point q by the seed xGen in Jacobian coordinates +// using an optimized addition chain. +func (p *G1Jac) mulBySeed(q *G1Jac) *G1Jac { + // Generated by github.com/mmcloughlin/addchain v0.4.0. + // Operations: 63 doublings 5 additions + + var res G1Jac + res.Double(q) + res.AddAssign(q) + for i := 0; i < 2; i++ { + res.Double(&res) + } + res.AddAssign(q) + for i := 0; i < 3; i++ { + res.Double(&res) + } + res.AddAssign(q) + for i := 0; i < 9; i++ { + res.Double(&res) + } + res.AddAssign(q) + for i := 0; i < 32; i++ { + res.Double(&res) + } + res.AddAssign(q) + for i := 0; i < 16; i++ { + res.Double(&res) + } + p.Set(&res) + return p +} + +// phi sets p to ϕ(a) where ϕ: (x,y) → (w x,y), +// where w is a third root of unity. +func (p *G1Jac) phi(q *G1Jac) *G1Jac { + p.Set(q) p.X.Mul(&p.X, &thirdRootOneG1) return p } // mulGLV computes the scalar multiplication using a windowed-GLV method +// // see https://www.iacr.org/archive/crypto2001/21390189.pdf -func (p *G1Jac) mulGLV(a *G1Jac, s *big.Int) *G1Jac { +func (p *G1Jac) mulGLV(q *G1Jac, s *big.Int) *G1Jac { var table [15]G1Jac var res G1Jac @@ -479,11 +605,11 @@ func (p *G1Jac) mulGLV(a *G1Jac, s *big.Int) *G1Jac { res.Set(&g1Infinity) - // table[b3b2b1b0-1] = b3b2 ⋅ ϕ(a) + b1b0*a - table[0].Set(a) - table[3].phi(a) + // table[b3b2b1b0-1] = b3b2 ⋅ ϕ(q) + b1b0*q + table[0].Set(q) + table[3].phi(q) - // split the scalar, modifies ±a, ϕ(a) accordingly + // split the scalar, modifies ±q, ϕ(q) accordingly k := ecc.SplitScalar(s, &glvBasis) if k[0].Sign() == -1 { @@ -496,7 +622,7 @@ func (p *G1Jac) mulGLV(a *G1Jac, s *big.Int) *G1Jac { } // precompute table (2 bits sliding window) - // table[b3b2b1b0-1] = b3b2 ⋅ ϕ(a) + b1b0 ⋅ a if b3b2b1b0 != 0 + // table[b3b2b1b0-1] = b3b2 ⋅ ϕ(q) + b1b0 ⋅ q if b3b2b1b0 != 0 table[1].Double(&table[0]) table[2].Set(&table[1]).AddAssign(&table[0]) table[4].Set(&table[3]).AddAssign(&table[0]) @@ -552,23 +678,23 @@ func (p *G1Affine) ClearCofactor(a *G1Affine) *G1Affine { } // ClearCofactor maps a point in E(Fp) to E(Fp)[r] -func (p *G1Jac) ClearCofactor(a *G1Jac) *G1Jac { +func (p *G1Jac) ClearCofactor(q *G1Jac) *G1Jac { // cf https://eprint.iacr.org/2019/403.pdf, 5 var res G1Jac - res.ScalarMultiplication(a, &xGen).AddAssign(a) + res.mulBySeed(q).AddAssign(q) p.Set(&res) return p } -// JointScalarMultiplicationBase computes [s1]g+[s2]a using Straus-Shamir technique -// where g is the prime subgroup generator -func (p *G1Jac) JointScalarMultiplicationBase(a *G1Affine, s1, s2 *big.Int) *G1Jac { +// JointScalarMultiplication computes [s1]a1+[s2]a2 using Strauss-Shamir technique +// where a1 and a2 are affine points. +func (p *G1Jac) JointScalarMultiplication(a1, a2 *G1Affine, s1, s2 *big.Int) *G1Jac { var res, p1, p2 G1Jac res.Set(&g1Infinity) - p1.Set(&g1Gen) - p2.FromAffine(a) + p1.FromAffine(a1) + p2.FromAffine(a2) var table [15]G1Jac @@ -632,17 +758,24 @@ func (p *G1Jac) JointScalarMultiplicationBase(a *G1Affine, s1, s2 *big.Int) *G1J } +// JointScalarMultiplicationBase computes [s1]g+[s2]a using Straus-Shamir technique +// where g is the prime subgroup generator. +func (p *G1Jac) JointScalarMultiplicationBase(a *G1Affine, s1, s2 *big.Int) *G1Jac { + return p.JointScalarMultiplication(&g1GenAff, a, s1, s2) + +} + // ------------------------------------------------------------------------------------------------- -// Jacobian extended +// extended Jacobian coordinates -// Set sets p to the provided point -func (p *g1JacExtended) Set(a *g1JacExtended) *g1JacExtended { - p.X, p.Y, p.ZZ, p.ZZZ = a.X, a.Y, a.ZZ, a.ZZZ +// Set sets p to a in extended Jacobian coordinates. +func (p *g1JacExtended) Set(q *g1JacExtended) *g1JacExtended { + p.X, p.Y, p.ZZ, p.ZZZ = q.X, q.Y, q.ZZ, q.ZZZ return p } -// setInfinity sets p to O -func (p *g1JacExtended) setInfinity() *g1JacExtended { +// SetInfinity sets p to the infinity point (1,1,0,0). +func (p *g1JacExtended) SetInfinity() *g1JacExtended { p.X.SetOne() p.Y.SetOne() p.ZZ = fp.Element{} @@ -650,43 +783,45 @@ func (p *g1JacExtended) setInfinity() *g1JacExtended { return p } -func (p *g1JacExtended) IsZero() bool { +// IsInfinity checks if the p is infinity, i.e. p.ZZ=0. +func (p *g1JacExtended) IsInfinity() bool { return p.ZZ.IsZero() } -// fromJacExtended sets Q in affine coordinates -func (p *G1Affine) fromJacExtended(Q *g1JacExtended) *G1Affine { - if Q.ZZ.IsZero() { +// fromJacExtended converts an extended Jacobian point to an affine point. +func (p *G1Affine) fromJacExtended(q *g1JacExtended) *G1Affine { + if q.ZZ.IsZero() { p.X = fp.Element{} p.Y = fp.Element{} return p } - p.X.Inverse(&Q.ZZ).Mul(&p.X, &Q.X) - p.Y.Inverse(&Q.ZZZ).Mul(&p.Y, &Q.Y) + p.X.Inverse(&q.ZZ).Mul(&p.X, &q.X) + p.Y.Inverse(&q.ZZZ).Mul(&p.Y, &q.Y) return p } -// fromJacExtended sets Q in Jacobian coordinates -func (p *G1Jac) fromJacExtended(Q *g1JacExtended) *G1Jac { - if Q.ZZ.IsZero() { +// fromJacExtended converts an extended Jacobian point to a Jacobian point. +func (p *G1Jac) fromJacExtended(q *g1JacExtended) *G1Jac { + if q.ZZ.IsZero() { p.Set(&g1Infinity) return p } - p.X.Mul(&Q.ZZ, &Q.X).Mul(&p.X, &Q.ZZ) - p.Y.Mul(&Q.ZZZ, &Q.Y).Mul(&p.Y, &Q.ZZZ) - p.Z.Set(&Q.ZZZ) + p.X.Mul(&q.ZZ, &q.X).Mul(&p.X, &q.ZZ) + p.Y.Mul(&q.ZZZ, &q.Y).Mul(&p.Y, &q.ZZZ) + p.Z.Set(&q.ZZZ) return p } -// unsafeFromJacExtended sets p in Jacobian coordinates, but don't check for infinity -func (p *G1Jac) unsafeFromJacExtended(Q *g1JacExtended) *G1Jac { - p.X.Square(&Q.ZZ).Mul(&p.X, &Q.X) - p.Y.Square(&Q.ZZZ).Mul(&p.Y, &Q.Y) - p.Z = Q.ZZZ +// unsafeFromJacExtended converts an extended Jacobian point, distinct from Infinity, to a Jacobian point. +func (p *G1Jac) unsafeFromJacExtended(q *g1JacExtended) *G1Jac { + p.X.Square(&q.ZZ).Mul(&p.X, &q.X) + p.Y.Square(&q.ZZZ).Mul(&p.Y, &q.Y) + p.Z = q.ZZZ return p } -// add point in Jacobian extended coordinates +// add sets p to p+q in extended Jacobian coordinates. +// // https://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-add-2008-s func (p *g1JacExtended) add(q *g1JacExtended) *g1JacExtended { //if q is infinity return p @@ -742,10 +877,11 @@ func (p *g1JacExtended) add(q *g1JacExtended) *g1JacExtended { return p } -// double point in Jacobian extended coordinates +// double sets p to [2]q in Jacobian extended coordinates. +// // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#doubling-dbl-2008-s-1 -// since we consider any point on Z=0 as the point at infinity -// this doubling formula works for infinity points as well +// N.B.: since we consider any point on Z=0 as the point at infinity +// this doubling formula works for infinity points as well. func (p *g1JacExtended) double(q *g1JacExtended) *g1JacExtended { var U, V, W, S, XX, M fp.Element @@ -755,7 +891,7 @@ func (p *g1JacExtended) double(q *g1JacExtended) *g1JacExtended { S.Mul(&q.X, &V) XX.Square(&q.X) M.Double(&XX). - Add(&M, &XX) // -> + a, but a=0 here + Add(&M, &XX) // -> + A, but A=0 here U.Mul(&W, &q.Y) p.X.Square(&M). @@ -770,9 +906,10 @@ func (p *g1JacExtended) double(q *g1JacExtended) *g1JacExtended { return p } -// subMixed same as addMixed, but will negate a.Y +// addMixed sets p to p+q in extended Jacobian coordinates, where a.ZZ=1. +// // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-madd-2008-s -func (p *g1JacExtended) subMixed(a *G1Affine) *g1JacExtended { +func (p *g1JacExtended) addMixed(a *G1Affine) *g1JacExtended { //if a is infinity return p if a.IsInfinity() { @@ -781,7 +918,7 @@ func (p *g1JacExtended) subMixed(a *G1Affine) *g1JacExtended { // p is infinity, return a if p.ZZ.IsZero() { p.X = a.X - p.Y.Neg(&a.Y) + p.Y = a.Y p.ZZ.SetOne() p.ZZZ.SetOne() return p @@ -794,12 +931,11 @@ func (p *g1JacExtended) subMixed(a *G1Affine) *g1JacExtended { P.Sub(&P, &p.X) R.Mul(&a.Y, &p.ZZZ) - R.Neg(&R) R.Sub(&R, &p.Y) if P.IsZero() { if R.IsZero() { - return p.doubleNegMixed(a) + return p.doubleMixed(a) } p.ZZ = fp.Element{} @@ -826,9 +962,10 @@ func (p *g1JacExtended) subMixed(a *G1Affine) *g1JacExtended { } -// addMixed +// subMixed works the same as addMixed, but negates a.Y. +// // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-madd-2008-s -func (p *g1JacExtended) addMixed(a *G1Affine) *g1JacExtended { +func (p *g1JacExtended) subMixed(a *G1Affine) *g1JacExtended { //if a is infinity return p if a.IsInfinity() { @@ -837,7 +974,7 @@ func (p *g1JacExtended) addMixed(a *G1Affine) *g1JacExtended { // p is infinity, return a if p.ZZ.IsZero() { p.X = a.X - p.Y = a.Y + p.Y.Neg(&a.Y) p.ZZ.SetOne() p.ZZZ.SetOne() return p @@ -850,11 +987,12 @@ func (p *g1JacExtended) addMixed(a *G1Affine) *g1JacExtended { P.Sub(&P, &p.X) R.Mul(&a.Y, &p.ZZZ) + R.Neg(&R) R.Sub(&R, &p.Y) if P.IsZero() { if R.IsZero() { - return p.doubleMixed(a) + return p.doubleNegMixed(a) } p.ZZ = fp.Element{} @@ -881,21 +1019,21 @@ func (p *g1JacExtended) addMixed(a *G1Affine) *g1JacExtended { } -// doubleNegMixed same as double, but will negate q.Y -func (p *g1JacExtended) doubleNegMixed(q *G1Affine) *g1JacExtended { +// doubleNegMixed works the same as double, but negates q.Y. +func (p *g1JacExtended) doubleNegMixed(a *G1Affine) *g1JacExtended { var U, V, W, S, XX, M, S2, L fp.Element - U.Double(&q.Y) + U.Double(&a.Y) U.Neg(&U) V.Square(&U) W.Mul(&U, &V) - S.Mul(&q.X, &V) - XX.Square(&q.X) + S.Mul(&a.X, &V) + XX.Square(&a.X) M.Double(&XX). - Add(&M, &XX) // -> + a, but a=0 here + Add(&M, &XX) // -> + A, but A=0 here S2.Double(&S) - L.Mul(&W, &q.Y) + L.Mul(&W, &a.Y) p.X.Square(&M). Sub(&p.X, &S2) @@ -908,21 +1046,22 @@ func (p *g1JacExtended) doubleNegMixed(q *G1Affine) *g1JacExtended { return p } -// doubleMixed point in Jacobian extended coordinates +// doubleMixed sets p to [2]a in Jacobian extended coordinates, where a.ZZ=1. +// // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#doubling-dbl-2008-s-1 -func (p *g1JacExtended) doubleMixed(q *G1Affine) *g1JacExtended { +func (p *g1JacExtended) doubleMixed(a *G1Affine) *g1JacExtended { var U, V, W, S, XX, M, S2, L fp.Element - U.Double(&q.Y) + U.Double(&a.Y) V.Square(&U) W.Mul(&U, &V) - S.Mul(&q.X, &V) - XX.Square(&q.X) + S.Mul(&a.X, &V) + XX.Square(&a.X) M.Double(&XX). - Add(&M, &XX) // -> + a, but a=0 here + Add(&M, &XX) // -> + A, but A=0 here S2.Double(&S) - L.Mul(&W, &q.Y) + L.Mul(&W, &a.Y) p.X.Square(&M). Sub(&p.X, &S2) @@ -936,7 +1075,7 @@ func (p *g1JacExtended) doubleMixed(q *G1Affine) *g1JacExtended { } // BatchJacobianToAffineG1 converts points in Jacobian coordinates to Affine coordinates -// performing a single field inversion (Montgomery batch inversion trick). +// performing a single field inversion using the Montgomery batch inversion trick. func BatchJacobianToAffineG1(points []G1Jac) []G1Affine { result := make([]G1Affine, len(points)) zeroes := make([]bool, len(points)) @@ -986,7 +1125,7 @@ func BatchJacobianToAffineG1(points []G1Jac) []G1Affine { // BatchScalarMultiplicationG1 multiplies the same base by all scalars // and return resulting points in affine coordinates -// uses a simple windowed-NAF like exponentiation algorithm +// uses a simple windowed-NAF-like multiplication algorithm. func BatchScalarMultiplicationG1(base *G1Affine, scalars []fr.Element) []G1Affine { // approximate cost in group ops is // cost = 2^{c-1} + n(scalar.nbBits+nbChunks) @@ -1068,18 +1207,29 @@ func BatchScalarMultiplicationG1(base *G1Affine, scalars []fr.Element) []G1Affin return toReturnAff } -// batch add affine coordinates -// using batch inversion -// special cases (doubling, infinity) must be filtered out before this call +// batchAddG1Affine adds affine points using the Montgomery batch inversion trick. +// Special cases (doubling, infinity) must be filtered out before this call. func batchAddG1Affine[TP pG1Affine, TPP ppG1Affine, TC cG1Affine](R *TPP, P *TP, batchSize int) { var lambda, lambdain TC - // add part + // from https://docs.zkproof.org/pages/standards/accepted-workshop3/proposal-turbo_plonk.pdf + // affine point addition formula + // R(X1, Y1) + P(X2, Y2) = Q(X3, Y3) + // λ = (Y2 - Y1) / (X2 - X1) + // X3 = λ² - (X1 + X2) + // Y3 = λ * (X1 - X3) - Y1 + + // first we compute the 1 / (X2 - X1) for all points using Montgomery batch inversion trick + + // X2 - X1 for j := 0; j < batchSize; j++ { lambdain[j].Sub(&(*P)[j].X, &(*R)[j].X) } - // invert denominator using montgomery batch invert technique + // montgomery batch inversion; + // lambda[0] = 1 / (P[0].X - R[0].X) + // lambda[1] = 1 / (P[1].X - R[1].X) + // ... { var accumulator fp.Element lambda[0].SetOne() @@ -1099,22 +1249,24 @@ func batchAddG1Affine[TP pG1Affine, TPP ppG1Affine, TC cG1Affine](R *TPP, P *TP, lambda[0].Set(&accumulator) } - var d fp.Element - var rr G1Affine + var t fp.Element + var Q G1Affine - // add part for j := 0; j < batchSize; j++ { - // computa lambda - d.Sub(&(*P)[j].Y, &(*R)[j].Y) - lambda[j].Mul(&lambda[j], &d) - - // compute X, Y - rr.X.Square(&lambda[j]) - rr.X.Sub(&rr.X, &(*R)[j].X) - rr.X.Sub(&rr.X, &(*P)[j].X) - d.Sub(&(*R)[j].X, &rr.X) - rr.Y.Mul(&lambda[j], &d) - rr.Y.Sub(&rr.Y, &(*R)[j].Y) - (*R)[j].Set(&rr) + // λ = (Y2 - Y1) / (X2 - X1) + t.Sub(&(*P)[j].Y, &(*R)[j].Y) + lambda[j].Mul(&lambda[j], &t) + + // X3 = λ² - (X1 + X2) + Q.X.Square(&lambda[j]) + Q.X.Sub(&Q.X, &(*R)[j].X) + Q.X.Sub(&Q.X, &(*P)[j].X) + + // Y3 = λ * (X1 - X3) - Y1 + t.Sub(&(*R)[j].X, &Q.X) + Q.Y.Mul(&lambda[j], &t) + Q.Y.Sub(&Q.Y, &(*R)[j].Y) + + (*R)[j].Set(&Q) } } diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/g2.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/g2.go index cd32bfb46b0..127c47a8c9a 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/g2.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/g2.go @@ -1,41 +1,33 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT package bls12381 import ( + "crypto/rand" "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" "github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower" "github.com/consensys/gnark-crypto/internal/parallel" "math/big" "runtime" + + "github.com/consensys/gnark-crypto/ecc/bls12-381/hash_to_curve" ) -// G2Affine point in affine coordinates +// G2Affine is a point in affine coordinates (x,y) type G2Affine struct { X, Y fptower.E2 } -// G2Jac is a point with fptower.E2 coordinates +// G2Jac is a point in Jacobian coordinates (x=X/Z², y=Y/Z³) type G2Jac struct { X, Y, Z fptower.E2 } -// g2JacExtended parameterized Jacobian coordinates (x=X/ZZ, y=Y/ZZZ, ZZ³=ZZZ²) +// g2JacExtended is a point in extended Jacobian coordinates (x=X/ZZ, y=Y/ZZZ, ZZ³=ZZZ²) type g2JacExtended struct { X, Y, ZZ, ZZZ fptower.E2 } @@ -46,22 +38,24 @@ type g2Proj struct { } // ------------------------------------------------------------------------------------------------- -// Affine +// Affine coordinates -// Set sets p to the provided point +// Set sets p to a in affine coordinates. func (p *G2Affine) Set(a *G2Affine) *G2Affine { p.X, p.Y = a.X, a.Y return p } -// setInfinity sets p to O -func (p *G2Affine) setInfinity() *G2Affine { +// SetInfinity sets p to the infinity point, which is encoded as (0,0). +// N.B.: (0,0) is never on the curve for j=0 curves (Y²=X³+B). +func (p *G2Affine) SetInfinity() *G2Affine { p.X.SetZero() p.Y.SetZero() return p } -// ScalarMultiplication computes and returns p = a ⋅ s +// ScalarMultiplication computes and returns p = [s]a +// where p and a are affine points. func (p *G2Affine) ScalarMultiplication(a *G2Affine, s *big.Int) *G2Affine { var _p G2Jac _p.FromAffine(a) @@ -70,51 +64,97 @@ func (p *G2Affine) ScalarMultiplication(a *G2Affine, s *big.Int) *G2Affine { return p } -// Add adds two point in affine coordinates. -// This should rarely be used as it is very inefficient compared to Jacobian -func (p *G2Affine) Add(a, b *G2Affine) *G2Affine { - var p1, p2 G2Jac - p1.FromAffine(a) - p2.FromAffine(b) - p1.AddAssign(&p2) - p.FromJacobian(&p1) +// ScalarMultiplicationBase computes and returns p = [s]g +// where g is the affine point generating the prime subgroup. +func (p *G2Affine) ScalarMultiplicationBase(s *big.Int) *G2Affine { + var _p G2Jac + _p.mulGLV(&g2Gen, s) + p.FromJacobian(&_p) return p } +// Add adds two points in affine coordinates. +// It uses the Jacobian addition with a.Z=b.Z=1 and converts the result to affine coordinates. +// +// https://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-mmadd-2007-bl +func (p *G2Affine) Add(a, b *G2Affine) *G2Affine { + var q G2Jac + // a is infinity, return b + if a.IsInfinity() { + p.Set(b) + return p + } + // b is infinity, return a + if b.IsInfinity() { + p.Set(a) + return p + } + if a.X.Equal(&b.X) { + // if b == a, we double instead + if a.Y.Equal(&b.Y) { + q.DoubleMixed(a) + return p.FromJacobian(&q) + } else { + // if b == -a, we return 0 + return p.SetInfinity() + } + } + var H, HH, I, J, r, V fptower.E2 + H.Sub(&b.X, &a.X) + HH.Square(&H) + I.Double(&HH).Double(&I) + J.Mul(&H, &I) + r.Sub(&b.Y, &a.Y) + r.Double(&r) + V.Mul(&a.X, &I) + q.X.Square(&r). + Sub(&q.X, &J). + Sub(&q.X, &V). + Sub(&q.X, &V) + q.Y.Sub(&V, &q.X). + Mul(&q.Y, &r) + J.Mul(&a.Y, &J).Double(&J) + q.Y.Sub(&q.Y, &J) + q.Z.Double(&H) + + return p.FromJacobian(&q) +} + // Double doubles a point in affine coordinates. -// This should rarely be used as it is very inefficient compared to Jacobian +// It converts the point to Jacobian coordinates, doubles it using Jacobian +// addition with a.Z=1, and converts it back to affine coordinates. +// +// http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-mdbl-2007-bl func (p *G2Affine) Double(a *G2Affine) *G2Affine { - var p1 G2Jac - p1.FromAffine(a) - p1.Double(&p1) - p.FromJacobian(&p1) + var q G2Jac + q.FromAffine(a) + q.DoubleMixed(a) + p.FromJacobian(&q) return p } -// Sub subs two point in affine coordinates. -// This should rarely be used as it is very inefficient compared to Jacobian +// Sub subtracts two points in affine coordinates. +// It uses a similar approach to Add, but negates the second point before adding. func (p *G2Affine) Sub(a, b *G2Affine) *G2Affine { - var p1, p2 G2Jac - p1.FromAffine(a) - p2.FromAffine(b) - p1.SubAssign(&p2) - p.FromJacobian(&p1) + var bneg G2Affine + bneg.Neg(b) + p.Add(a, &bneg) return p } -// Equal tests if two points (in Affine coordinates) are equal +// Equal tests if two points in affine coordinates are equal. func (p *G2Affine) Equal(a *G2Affine) bool { return p.X.Equal(&a.X) && p.Y.Equal(&a.Y) } -// Neg computes -G +// Neg sets p to the affine negative point -a = (a.X, -a.Y). func (p *G2Affine) Neg(a *G2Affine) *G2Affine { p.X = a.X p.Y.Neg(&a.Y) return p } -// FromJacobian rescales a point in Jacobian coord in z=1 plane +// FromJacobian converts a point p1 from Jacobian to affine coordinates. func (p *G2Affine) FromJacobian(p1 *G2Jac) *G2Affine { var a, b fptower.E2 @@ -133,7 +173,7 @@ func (p *G2Affine) FromJacobian(p1 *G2Jac) *G2Affine { return p } -// String returns the string representation of the point or "O" if it is infinity +// String returns the string representation E(x,y) of the affine point p or "O" if it is infinity. func (p *G2Affine) String() string { if p.IsInfinity() { return "O" @@ -141,106 +181,108 @@ func (p *G2Affine) String() string { return "E([" + p.X.String() + "," + p.Y.String() + "])" } -// IsInfinity checks if the point is infinity -// in affine, it's encoded as (0,0) -// (0,0) is never on the curve for j=0 curves +// IsInfinity checks if the affine point p is infinity, which is encoded as (0,0). +// N.B.: (0,0) is never on the curve for j=0 curves (Y²=X³+B). func (p *G2Affine) IsInfinity() bool { return p.X.IsZero() && p.Y.IsZero() } -// IsOnCurve returns true if p in on the curve +// IsOnCurve returns true if the affine point p in on the curve. func (p *G2Affine) IsOnCurve() bool { - var point G2Jac - point.FromAffine(p) - return point.IsOnCurve() // call this function to handle infinity point + if p.IsInfinity() { + return true + } + var left, right fptower.E2 + left.Square(&p.Y) + right.Square(&p.X).Mul(&right, &p.X) + right.Add(&right, &bTwistCurveCoeff) + return left.Equal(&right) } -// IsInSubGroup returns true if p is in the correct subgroup, false otherwise +// IsInSubGroup returns true if the affine point p is in the correct subgroup, false otherwise. func (p *G2Affine) IsInSubGroup() bool { - var _p G2Jac + if !p.IsOnCurve() { + return false + } + var _p, res, img G2Jac _p.FromAffine(p) - return _p.IsInSubGroup() + img.psi(&_p) + res.mulBySeed(&_p).Neg(&res) + + return res.Equal(&img) } // ------------------------------------------------------------------------------------------------- -// Jacobian +// Jacobian coordinates -// Set sets p to the provided point -func (p *G2Jac) Set(a *G2Jac) *G2Jac { - p.X, p.Y, p.Z = a.X, a.Y, a.Z +// Set sets p to a in Jacobian coordinates. +func (p *G2Jac) Set(q *G2Jac) *G2Jac { + p.X, p.Y, p.Z = q.X, q.Y, q.Z return p } -// Equal tests if two points (in Jacobian coordinates) are equal -func (p *G2Jac) Equal(a *G2Jac) bool { +// Equal tests if two points in Jacobian coordinates are equal. +func (p *G2Jac) Equal(q *G2Jac) bool { // If one point is infinity, the other must also be infinity. if p.Z.IsZero() { - return a.Z.IsZero() + return q.Z.IsZero() } // If the other point is infinity, return false since we can't // the following checks would be incorrect. - if a.Z.IsZero() { + if q.Z.IsZero() { return false } var pZSquare, aZSquare fptower.E2 pZSquare.Square(&p.Z) - aZSquare.Square(&a.Z) + aZSquare.Square(&q.Z) var lhs, rhs fptower.E2 lhs.Mul(&p.X, &aZSquare) - rhs.Mul(&a.X, &pZSquare) + rhs.Mul(&q.X, &pZSquare) if !lhs.Equal(&rhs) { return false } - lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &a.Z) - rhs.Mul(&a.Y, &pZSquare).Mul(&rhs, &p.Z) + lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &q.Z) + rhs.Mul(&q.Y, &pZSquare).Mul(&rhs, &p.Z) return lhs.Equal(&rhs) } -// Neg computes -G -func (p *G2Jac) Neg(a *G2Jac) *G2Jac { - *p = *a - p.Y.Neg(&a.Y) - return p -} - -// SubAssign subtracts two points on the curve -func (p *G2Jac) SubAssign(a *G2Jac) *G2Jac { - var tmp G2Jac - tmp.Set(a) - tmp.Y.Neg(&tmp.Y) - p.AddAssign(&tmp) +// Neg sets p to the Jacobian negative point -q = (q.X, -q.Y, q.Z). +func (p *G2Jac) Neg(q *G2Jac) *G2Jac { + *p = *q + p.Y.Neg(&q.Y) return p } -// AddAssign point addition in montgomery form +// AddAssign sets p to p+a in Jacobian coordinates. +// // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl -func (p *G2Jac) AddAssign(a *G2Jac) *G2Jac { +func (p *G2Jac) AddAssign(q *G2Jac) *G2Jac { - // p is infinity, return a + // p is infinity, return q if p.Z.IsZero() { - p.Set(a) + p.Set(q) return p } - // a is infinity, return p - if a.Z.IsZero() { + // q is infinity, return p + if q.Z.IsZero() { return p } var Z1Z1, Z2Z2, U1, U2, S1, S2, H, I, J, r, V fptower.E2 - Z1Z1.Square(&a.Z) + Z1Z1.Square(&q.Z) Z2Z2.Square(&p.Z) - U1.Mul(&a.X, &Z2Z2) + U1.Mul(&q.X, &Z2Z2) U2.Mul(&p.X, &Z1Z1) - S1.Mul(&a.Y, &p.Z). + S1.Mul(&q.Y, &p.Z). Mul(&S1, &Z2Z2) - S2.Mul(&p.Y, &a.Z). + S2.Mul(&p.Y, &q.Z). Mul(&S2, &Z1Z1) - // if p == a, we double instead + // if p == q, we double instead if U1.Equal(&U2) && S1.Equal(&S2) { return p.DoubleAssign() } @@ -259,7 +301,7 @@ func (p *G2Jac) AddAssign(a *G2Jac) *G2Jac { Mul(&p.Y, &r) S1.Mul(&S1, &J).Double(&S1) p.Y.Sub(&p.Y, &S1) - p.Z.Add(&p.Z, &a.Z) + p.Z.Add(&p.Z, &q.Z) p.Z.Square(&p.Z). Sub(&p.Z, &Z1Z1). Sub(&p.Z, &Z2Z2). @@ -268,7 +310,48 @@ func (p *G2Jac) AddAssign(a *G2Jac) *G2Jac { return p } -// AddMixed point addition +// SubAssign sets p to p-a in Jacobian coordinates. +// It uses a similar approach to AddAssign, but negates the point a before adding. +func (p *G2Jac) SubAssign(q *G2Jac) *G2Jac { + var tmp G2Jac + tmp.Set(q) + tmp.Y.Neg(&tmp.Y) + p.AddAssign(&tmp) + return p +} + +// Double sets p to [2]q in Jacobian coordinates. +// +// https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl +func (p *G2Jac) DoubleMixed(a *G2Affine) *G2Jac { + var XX, YY, YYYY, S, M, T fptower.E2 + XX.Square(&a.X) + YY.Square(&a.Y) + YYYY.Square(&YY) + S.Add(&a.X, &YY). + Square(&S). + Sub(&S, &XX). + Sub(&S, &YYYY). + Double(&S) + M.Double(&XX). + Add(&M, &XX) // -> + A, but A=0 here + T.Square(&M). + Sub(&T, &S). + Sub(&T, &S) + p.X.Set(&T) + p.Y.Sub(&S, &T). + Mul(&p.Y, &M) + YYYY.Double(&YYYY). + Double(&YYYY). + Double(&YYYY) + p.Y.Sub(&p.Y, &YYYY) + p.Z.Double(&a.Y) + + return p +} + +// AddMixed sets p to p+a in Jacobian coordinates, where a.Z = 1. +// // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-madd-2007-bl func (p *G2Jac) AddMixed(a *G2Affine) *G2Jac { @@ -292,7 +375,7 @@ func (p *G2Jac) AddMixed(a *G2Affine) *G2Jac { // if p == a, we double instead if U2.Equal(&p.X) && S2.Equal(&p.Y) { - return p.DoubleAssign() + return p.DoubleMixed(a) } H.Sub(&U2, &p.X) @@ -317,7 +400,8 @@ func (p *G2Jac) AddMixed(a *G2Affine) *G2Jac { return p } -// Double doubles a point in Jacobian coordinates +// Double sets p to [2]q in Jacobian coordinates. +// // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl func (p *G2Jac) Double(q *G2Jac) *G2Jac { p.Set(q) @@ -325,7 +409,8 @@ func (p *G2Jac) Double(q *G2Jac) *G2Jac { return p } -// DoubleAssign doubles a point in Jacobian coordinates +// DoubleAssign doubles p in Jacobian coordinates. +// // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl func (p *G2Jac) DoubleAssign() *G2Jac { @@ -357,43 +442,50 @@ func (p *G2Jac) DoubleAssign() *G2Jac { return p } -// ScalarMultiplication computes and returns p = a ⋅ s +// ScalarMultiplication computes and returns p = [s]a +// where p and a are Jacobian points. +// using the GLV technique. // see https://www.iacr.org/archive/crypto2001/21390189.pdf -func (p *G2Jac) ScalarMultiplication(a *G2Jac, s *big.Int) *G2Jac { - return p.mulGLV(a, s) +func (p *G2Jac) ScalarMultiplication(q *G2Jac, s *big.Int) *G2Jac { + return p.mulGLV(q, s) } -// String returns canonical representation of the point in affine coordinates +// ScalarMultiplicationBase computes and returns p = [s]g +// where g is the prime subgroup generator. +func (p *G2Jac) ScalarMultiplicationBase(s *big.Int) *G2Jac { + return p.mulGLV(&g2Gen, s) + +} + +// String converts p to affine coordinates and returns its string representation E(x,y) or "O" if it is infinity. func (p *G2Jac) String() string { _p := G2Affine{} _p.FromJacobian(p) return _p.String() } -// FromAffine sets p = Q, p in Jacobian, Q in affine -func (p *G2Jac) FromAffine(Q *G2Affine) *G2Jac { - if Q.IsInfinity() { +// FromAffine converts a point a from affine to Jacobian coordinates. +func (p *G2Jac) FromAffine(a *G2Affine) *G2Jac { + if a.IsInfinity() { p.Z.SetZero() p.X.SetOne() p.Y.SetOne() return p } p.Z.SetOne() - p.X.Set(&Q.X) - p.Y.Set(&Q.Y) + p.X.Set(&a.X) + p.Y.Set(&a.Y) return p } -// IsOnCurve returns true if p in on the curve +// IsOnCurve returns true if the Jacobian point p in on the curve. func (p *G2Jac) IsOnCurve() bool { - var left, right, tmp fptower.E2 + var left, right, tmp, ZZ fptower.E2 left.Square(&p.Y) right.Square(&p.X).Mul(&right, &p.X) - tmp.Square(&p.Z). - Square(&tmp). - Mul(&tmp, &p.Z). - Mul(&tmp, &p.Z). - Mul(&tmp, &bTwistCurveCoeff) + ZZ.Square(&p.Z) + tmp.Square(&ZZ).Mul(&tmp, &ZZ) + tmp.MulBybTwistCurveCoeff(&tmp) right.Add(&right, &tmp) return left.Equal(&right) } @@ -403,21 +495,36 @@ func (p *G2Jac) IsOnCurve() bool { // and https://eprint.iacr.org/2022/352.pdf, sec. 4.2 // ψ(p) = [x₀]P func (p *G2Jac) IsInSubGroup() bool { - var res, tmp G2Jac - tmp.psi(p) - res.ScalarMultiplication(p, &xGen). - AddAssign(&tmp) + if !p.IsOnCurve() { + return false + } + var res, img G2Jac + img.psi(p) + res.mulBySeed(p).Neg(&res) + + return res.Equal(&img) +} - return res.IsOnCurve() && res.Z.IsZero() +func GeneratePointNotInG2(f E2) G2Jac { + var res, jac G2Jac + aff := MapToCurve2(&f) + hash_to_curve.G2Isogeny(&aff.X, &aff.Y) + jac.FromAffine(&aff) + // ψ(p)-[x₀]P = [r]p + res.mulBySeed(&jac) + jac.psi(&jac) + res.AddAssign(&jac) + return res } -// mulWindowed computes a 2-bits windowed scalar multiplication -func (p *G2Jac) mulWindowed(a *G2Jac, s *big.Int) *G2Jac { +// mulWindowed computes the 2-bits windowed double-and-add scalar +// multiplication p=[s]q in Jacobian coordinates. +func (p *G2Jac) mulWindowed(q *G2Jac, s *big.Int) *G2Jac { var res G2Jac var ops [3]G2Jac - ops[0].Set(a) + ops[0].Set(q) if s.Sign() == -1 { ops[0].Neg(&ops[0]) } @@ -444,26 +551,59 @@ func (p *G2Jac) mulWindowed(a *G2Jac, s *big.Int) *G2Jac { } -// ψ(p) = u o π o u⁻¹ where u:E'→E iso from the twist to E -func (p *G2Jac) psi(a *G2Jac) *G2Jac { - p.Set(a) +// mulBySeed multiplies the point q by the seed xGen in Jacobian coordinates +// using an optimized addition chain. +func (p *G2Jac) mulBySeed(q *G2Jac) *G2Jac { + // Generated by github.com/mmcloughlin/addchain v0.4.0. + // Operations: 63 doublings 5 additions + + var res G2Jac + res.Double(q) + res.AddAssign(q) + for i := 0; i < 2; i++ { + res.Double(&res) + } + res.AddAssign(q) + for i := 0; i < 3; i++ { + res.Double(&res) + } + res.AddAssign(q) + for i := 0; i < 9; i++ { + res.Double(&res) + } + res.AddAssign(q) + for i := 0; i < 32; i++ { + res.Double(&res) + } + res.AddAssign(q) + for i := 0; i < 16; i++ { + res.Double(&res) + } + p.Set(&res) + return p +} + +// psi sets p to ψ(q) = u o π o u⁻¹ where u:E'→E is the isomorphism from the twist to the curve E and π is the Frobenius map. +func (p *G2Jac) psi(q *G2Jac) *G2Jac { + p.Set(q) p.X.Conjugate(&p.X).Mul(&p.X, &endo.u) p.Y.Conjugate(&p.Y).Mul(&p.Y, &endo.v) p.Z.Conjugate(&p.Z) return p } -// ϕ assigns p to ϕ(a) where ϕ: (x,y) → (w x,y), and returns p -// where w is a third root of unity in 𝔽p -func (p *G2Jac) phi(a *G2Jac) *G2Jac { - p.Set(a) +// phi sets p to ϕ(a) where ϕ: (x,y) → (w x,y), +// where w is a third root of unity. +func (p *G2Jac) phi(q *G2Jac) *G2Jac { + p.Set(q) p.X.MulByElement(&p.X, &thirdRootOneG2) return p } // mulGLV computes the scalar multiplication using a windowed-GLV method +// // see https://www.iacr.org/archive/crypto2001/21390189.pdf -func (p *G2Jac) mulGLV(a *G2Jac, s *big.Int) *G2Jac { +func (p *G2Jac) mulGLV(q *G2Jac, s *big.Int) *G2Jac { var table [15]G2Jac var res G2Jac @@ -471,11 +611,11 @@ func (p *G2Jac) mulGLV(a *G2Jac, s *big.Int) *G2Jac { res.Set(&g2Infinity) - // table[b3b2b1b0-1] = b3b2 ⋅ ϕ(a) + b1b0*a - table[0].Set(a) - table[3].phi(a) + // table[b3b2b1b0-1] = b3b2 ⋅ ϕ(q) + b1b0*q + table[0].Set(q) + table[3].phi(q) - // split the scalar, modifies ±a, ϕ(a) accordingly + // split the scalar, modifies ±q, ϕ(q) accordingly k := ecc.SplitScalar(s, &glvBasis) if k[0].Sign() == -1 { @@ -488,7 +628,7 @@ func (p *G2Jac) mulGLV(a *G2Jac, s *big.Int) *G2Jac { } // precompute table (2 bits sliding window) - // table[b3b2b1b0-1] = b3b2 ⋅ ϕ(a) + b1b0 ⋅ a if b3b2b1b0 != 0 + // table[b3b2b1b0-1] = b3b2 ⋅ ϕ(q) + b1b0 ⋅ q if b3b2b1b0 != 0 table[1].Double(&table[0]) table[2].Set(&table[1]).AddAssign(&table[0]) table[4].Set(&table[3]).AddAssign(&table[0]) @@ -544,23 +684,23 @@ func (p *G2Affine) ClearCofactor(a *G2Affine) *G2Affine { } // ClearCofactor maps a point in curve to r-torsion -func (p *G2Jac) ClearCofactor(a *G2Jac) *G2Jac { +func (p *G2Jac) ClearCofactor(q *G2Jac) *G2Jac { // https://eprint.iacr.org/2017/419.pdf, 4.1 var xg, xxg, res, t G2Jac - xg.ScalarMultiplication(a, &xGen).Neg(&xg) - xxg.ScalarMultiplication(&xg, &xGen).Neg(&xxg) + xg.mulBySeed(q).Neg(&xg) + xxg.mulBySeed(&xg).Neg(&xxg) res.Set(&xxg). SubAssign(&xg). - SubAssign(a) + SubAssign(q) t.Set(&xg). - SubAssign(a). + SubAssign(q). psi(&t) res.AddAssign(&t) - t.Double(a) + t.Double(q) t.X.MulByElement(&t.X, &thirdRootOneG1) res.SubAssign(&t) @@ -572,16 +712,16 @@ func (p *G2Jac) ClearCofactor(a *G2Jac) *G2Jac { } // ------------------------------------------------------------------------------------------------- -// Jacobian extended +// extended Jacobian coordinates -// Set sets p to the provided point -func (p *g2JacExtended) Set(a *g2JacExtended) *g2JacExtended { - p.X, p.Y, p.ZZ, p.ZZZ = a.X, a.Y, a.ZZ, a.ZZZ +// Set sets p to a in extended Jacobian coordinates. +func (p *g2JacExtended) Set(q *g2JacExtended) *g2JacExtended { + p.X, p.Y, p.ZZ, p.ZZZ = q.X, q.Y, q.ZZ, q.ZZZ return p } -// setInfinity sets p to O -func (p *g2JacExtended) setInfinity() *g2JacExtended { +// SetInfinity sets p to the infinity point (1,1,0,0). +func (p *g2JacExtended) SetInfinity() *g2JacExtended { p.X.SetOne() p.Y.SetOne() p.ZZ = fptower.E2{} @@ -589,43 +729,45 @@ func (p *g2JacExtended) setInfinity() *g2JacExtended { return p } -func (p *g2JacExtended) IsZero() bool { +// IsInfinity checks if the p is infinity, i.e. p.ZZ=0. +func (p *g2JacExtended) IsInfinity() bool { return p.ZZ.IsZero() } -// fromJacExtended sets Q in affine coordinates -func (p *G2Affine) fromJacExtended(Q *g2JacExtended) *G2Affine { - if Q.ZZ.IsZero() { +// fromJacExtended converts an extended Jacobian point to an affine point. +func (p *G2Affine) fromJacExtended(q *g2JacExtended) *G2Affine { + if q.ZZ.IsZero() { p.X = fptower.E2{} p.Y = fptower.E2{} return p } - p.X.Inverse(&Q.ZZ).Mul(&p.X, &Q.X) - p.Y.Inverse(&Q.ZZZ).Mul(&p.Y, &Q.Y) + p.X.Inverse(&q.ZZ).Mul(&p.X, &q.X) + p.Y.Inverse(&q.ZZZ).Mul(&p.Y, &q.Y) return p } -// fromJacExtended sets Q in Jacobian coordinates -func (p *G2Jac) fromJacExtended(Q *g2JacExtended) *G2Jac { - if Q.ZZ.IsZero() { +// fromJacExtended converts an extended Jacobian point to a Jacobian point. +func (p *G2Jac) fromJacExtended(q *g2JacExtended) *G2Jac { + if q.ZZ.IsZero() { p.Set(&g2Infinity) return p } - p.X.Mul(&Q.ZZ, &Q.X).Mul(&p.X, &Q.ZZ) - p.Y.Mul(&Q.ZZZ, &Q.Y).Mul(&p.Y, &Q.ZZZ) - p.Z.Set(&Q.ZZZ) + p.X.Mul(&q.ZZ, &q.X).Mul(&p.X, &q.ZZ) + p.Y.Mul(&q.ZZZ, &q.Y).Mul(&p.Y, &q.ZZZ) + p.Z.Set(&q.ZZZ) return p } -// unsafeFromJacExtended sets p in Jacobian coordinates, but don't check for infinity -func (p *G2Jac) unsafeFromJacExtended(Q *g2JacExtended) *G2Jac { - p.X.Square(&Q.ZZ).Mul(&p.X, &Q.X) - p.Y.Square(&Q.ZZZ).Mul(&p.Y, &Q.Y) - p.Z = Q.ZZZ +// unsafeFromJacExtended converts an extended Jacobian point, distinct from Infinity, to a Jacobian point. +func (p *G2Jac) unsafeFromJacExtended(q *g2JacExtended) *G2Jac { + p.X.Square(&q.ZZ).Mul(&p.X, &q.X) + p.Y.Square(&q.ZZZ).Mul(&p.Y, &q.Y) + p.Z = q.ZZZ return p } -// add point in Jacobian extended coordinates +// add sets p to p+q in extended Jacobian coordinates. +// // https://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-add-2008-s func (p *g2JacExtended) add(q *g2JacExtended) *g2JacExtended { //if q is infinity return p @@ -681,10 +823,11 @@ func (p *g2JacExtended) add(q *g2JacExtended) *g2JacExtended { return p } -// double point in Jacobian extended coordinates +// double sets p to [2]q in Jacobian extended coordinates. +// // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#doubling-dbl-2008-s-1 -// since we consider any point on Z=0 as the point at infinity -// this doubling formula works for infinity points as well +// N.B.: since we consider any point on Z=0 as the point at infinity +// this doubling formula works for infinity points as well. func (p *g2JacExtended) double(q *g2JacExtended) *g2JacExtended { var U, V, W, S, XX, M fptower.E2 @@ -694,7 +837,7 @@ func (p *g2JacExtended) double(q *g2JacExtended) *g2JacExtended { S.Mul(&q.X, &V) XX.Square(&q.X) M.Double(&XX). - Add(&M, &XX) // -> + a, but a=0 here + Add(&M, &XX) // -> + A, but A=0 here U.Mul(&W, &q.Y) p.X.Square(&M). @@ -709,9 +852,10 @@ func (p *g2JacExtended) double(q *g2JacExtended) *g2JacExtended { return p } -// subMixed same as addMixed, but will negate a.Y +// addMixed sets p to p+q in extended Jacobian coordinates, where a.ZZ=1. +// // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-madd-2008-s -func (p *g2JacExtended) subMixed(a *G2Affine) *g2JacExtended { +func (p *g2JacExtended) addMixed(a *G2Affine) *g2JacExtended { //if a is infinity return p if a.IsInfinity() { @@ -720,7 +864,7 @@ func (p *g2JacExtended) subMixed(a *G2Affine) *g2JacExtended { // p is infinity, return a if p.ZZ.IsZero() { p.X = a.X - p.Y.Neg(&a.Y) + p.Y = a.Y p.ZZ.SetOne() p.ZZZ.SetOne() return p @@ -733,12 +877,11 @@ func (p *g2JacExtended) subMixed(a *G2Affine) *g2JacExtended { P.Sub(&P, &p.X) R.Mul(&a.Y, &p.ZZZ) - R.Neg(&R) R.Sub(&R, &p.Y) if P.IsZero() { if R.IsZero() { - return p.doubleNegMixed(a) + return p.doubleMixed(a) } p.ZZ = fptower.E2{} @@ -765,9 +908,10 @@ func (p *g2JacExtended) subMixed(a *G2Affine) *g2JacExtended { } -// addMixed +// subMixed works the same as addMixed, but negates a.Y. +// // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-madd-2008-s -func (p *g2JacExtended) addMixed(a *G2Affine) *g2JacExtended { +func (p *g2JacExtended) subMixed(a *G2Affine) *g2JacExtended { //if a is infinity return p if a.IsInfinity() { @@ -776,7 +920,7 @@ func (p *g2JacExtended) addMixed(a *G2Affine) *g2JacExtended { // p is infinity, return a if p.ZZ.IsZero() { p.X = a.X - p.Y = a.Y + p.Y.Neg(&a.Y) p.ZZ.SetOne() p.ZZZ.SetOne() return p @@ -789,11 +933,12 @@ func (p *g2JacExtended) addMixed(a *G2Affine) *g2JacExtended { P.Sub(&P, &p.X) R.Mul(&a.Y, &p.ZZZ) + R.Neg(&R) R.Sub(&R, &p.Y) if P.IsZero() { if R.IsZero() { - return p.doubleMixed(a) + return p.doubleNegMixed(a) } p.ZZ = fptower.E2{} @@ -820,21 +965,21 @@ func (p *g2JacExtended) addMixed(a *G2Affine) *g2JacExtended { } -// doubleNegMixed same as double, but will negate q.Y -func (p *g2JacExtended) doubleNegMixed(q *G2Affine) *g2JacExtended { +// doubleNegMixed works the same as double, but negates q.Y. +func (p *g2JacExtended) doubleNegMixed(a *G2Affine) *g2JacExtended { var U, V, W, S, XX, M, S2, L fptower.E2 - U.Double(&q.Y) + U.Double(&a.Y) U.Neg(&U) V.Square(&U) W.Mul(&U, &V) - S.Mul(&q.X, &V) - XX.Square(&q.X) + S.Mul(&a.X, &V) + XX.Square(&a.X) M.Double(&XX). - Add(&M, &XX) // -> + a, but a=0 here + Add(&M, &XX) // -> + A, but A=0 here S2.Double(&S) - L.Mul(&W, &q.Y) + L.Mul(&W, &a.Y) p.X.Square(&M). Sub(&p.X, &S2) @@ -847,21 +992,22 @@ func (p *g2JacExtended) doubleNegMixed(q *G2Affine) *g2JacExtended { return p } -// doubleMixed point in Jacobian extended coordinates +// doubleMixed sets p to [2]a in Jacobian extended coordinates, where a.ZZ=1. +// // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#doubling-dbl-2008-s-1 -func (p *g2JacExtended) doubleMixed(q *G2Affine) *g2JacExtended { +func (p *g2JacExtended) doubleMixed(a *G2Affine) *g2JacExtended { var U, V, W, S, XX, M, S2, L fptower.E2 - U.Double(&q.Y) + U.Double(&a.Y) V.Square(&U) W.Mul(&U, &V) - S.Mul(&q.X, &V) - XX.Square(&q.X) + S.Mul(&a.X, &V) + XX.Square(&a.X) M.Double(&XX). - Add(&M, &XX) // -> + a, but a=0 here + Add(&M, &XX) // -> + A, but A=0 here S2.Double(&S) - L.Mul(&W, &q.Y) + L.Mul(&W, &a.Y) p.X.Square(&M). Sub(&p.X, &S2) @@ -875,38 +1021,38 @@ func (p *g2JacExtended) doubleMixed(q *G2Affine) *g2JacExtended { } // ------------------------------------------------------------------------------------------------- -// Homogenous projective +// Homogenous projective coordinates -// Set sets p to the provided point -func (p *g2Proj) Set(a *g2Proj) *g2Proj { - p.x, p.y, p.z = a.x, a.y, a.z +// Set sets p to a in projective coordinates. +func (p *g2Proj) Set(q *g2Proj) *g2Proj { + p.x, p.y, p.z = q.x, q.y, q.z return p } -// Neg computes -G -func (p *g2Proj) Neg(a *g2Proj) *g2Proj { - *p = *a - p.y.Neg(&a.y) +// Neg sets p to the projective negative point -q = (q.X, -q.Y). +func (p *g2Proj) Neg(q *g2Proj) *g2Proj { + *p = *q + p.y.Neg(&q.y) return p } -// FromAffine sets p = Q, p in homogenous projective, Q in affine -func (p *g2Proj) FromAffine(Q *G2Affine) *g2Proj { - if Q.X.IsZero() && Q.Y.IsZero() { +// FromAffine converts q in affine to p in projective coordinates. +func (p *g2Proj) FromAffine(a *G2Affine) *g2Proj { + if a.X.IsZero() && a.Y.IsZero() { p.z.SetZero() p.x.SetOne() p.y.SetOne() return p } p.z.SetOne() - p.x.Set(&Q.X) - p.y.Set(&Q.Y) + p.x.Set(&a.X) + p.y.Set(&a.Y) return p } // BatchScalarMultiplicationG2 multiplies the same base by all scalars // and return resulting points in affine coordinates -// uses a simple windowed-NAF like exponentiation algorithm +// uses a simple windowed-NAF-like multiplication algorithm. func BatchScalarMultiplicationG2(base *G2Affine, scalars []fr.Element) []G2Affine { // approximate cost in group ops is // cost = 2^{c-1} + n(scalar.nbBits+nbChunks) @@ -985,18 +1131,29 @@ func BatchScalarMultiplicationG2(base *G2Affine, scalars []fr.Element) []G2Affin return toReturn } -// batch add affine coordinates -// using batch inversion -// special cases (doubling, infinity) must be filtered out before this call +// batchAddG2Affine adds affine points using the Montgomery batch inversion trick. +// Special cases (doubling, infinity) must be filtered out before this call. func batchAddG2Affine[TP pG2Affine, TPP ppG2Affine, TC cG2Affine](R *TPP, P *TP, batchSize int) { var lambda, lambdain TC - // add part + // from https://docs.zkproof.org/pages/standards/accepted-workshop3/proposal-turbo_plonk.pdf + // affine point addition formula + // R(X1, Y1) + P(X2, Y2) = Q(X3, Y3) + // λ = (Y2 - Y1) / (X2 - X1) + // X3 = λ² - (X1 + X2) + // Y3 = λ * (X1 - X3) - Y1 + + // first we compute the 1 / (X2 - X1) for all points using Montgomery batch inversion trick + + // X2 - X1 for j := 0; j < batchSize; j++ { lambdain[j].Sub(&(*P)[j].X, &(*R)[j].X) } - // invert denominator using montgomery batch invert technique + // montgomery batch inversion; + // lambda[0] = 1 / (P[0].X - R[0].X) + // lambda[1] = 1 / (P[1].X - R[1].X) + // ... { var accumulator fptower.E2 lambda[0].SetOne() @@ -1016,22 +1173,41 @@ func batchAddG2Affine[TP pG2Affine, TPP ppG2Affine, TC cG2Affine](R *TPP, P *TP, lambda[0].Set(&accumulator) } - var d fptower.E2 - var rr G2Affine + var t fptower.E2 + var Q G2Affine - // add part for j := 0; j < batchSize; j++ { - // computa lambda - d.Sub(&(*P)[j].Y, &(*R)[j].Y) - lambda[j].Mul(&lambda[j], &d) - - // compute X, Y - rr.X.Square(&lambda[j]) - rr.X.Sub(&rr.X, &(*R)[j].X) - rr.X.Sub(&rr.X, &(*P)[j].X) - d.Sub(&(*R)[j].X, &rr.X) - rr.Y.Mul(&lambda[j], &d) - rr.Y.Sub(&rr.Y, &(*R)[j].Y) - (*R)[j].Set(&rr) + // λ = (Y2 - Y1) / (X2 - X1) + t.Sub(&(*P)[j].Y, &(*R)[j].Y) + lambda[j].Mul(&lambda[j], &t) + + // X3 = λ² - (X1 + X2) + Q.X.Square(&lambda[j]) + Q.X.Sub(&Q.X, &(*R)[j].X) + Q.X.Sub(&Q.X, &(*P)[j].X) + + // Y3 = λ * (X1 - X3) - Y1 + t.Sub(&(*R)[j].X, &Q.X) + Q.Y.Mul(&lambda[j], &t) + Q.Y.Sub(&Q.Y, &(*R)[j].Y) + + (*R)[j].Set(&Q) + } +} + +// RandomOnG2 produces a random point in G2 +// using standard map-to-curve methods, which means the relative discrete log +// of the generated point with respect to the canonical generator is not known. +func RandomOnG2() (G2Affine, error) { + if gBytes, err := randomFrSizedBytes(); err != nil { + return G2Affine{}, err + } else { + return HashToG2(gBytes, []byte("random on g2")) } } + +func randomFrSizedBytes() ([]byte, error) { + res := make([]byte, fr.Bytes) + _, err := rand.Read(res) + return res, err +} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/hash_to_curve/g1.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/hash_to_curve/g1.go new file mode 100644 index 00000000000..9928ca0e861 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/hash_to_curve/g1.go @@ -0,0 +1,230 @@ +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package hash_to_curve + +import ( + "math/big" + + "github.com/consensys/gnark-crypto/ecc/bls12-381/fp" +) + +// Note: This only works for simple extensions + +var ( + g1sswuCurveACoeff = fp.Element{3415322872136444497, 9675504606121301699, 13284745414851768802, 2873609449387478652, 2897906769629812789, 1536947672689614213} + g1sswuCurveBCoeff = fp.Element{18129637713272545760, 11144507692959411567, 10108153527111632324, 9745270364868568433, 14587922135379007624, 469008097655535723} +) + +var g1sswuCurveZ = fp.Element{9830232086645309404, 1112389714365644829, 8603885298299447491, 11361495444721768256, 5788602283869803809, 543934104870762216} + +// G1SSWUCurveCoefficients returns the coefficients of the SSWU curve. +func G1SSWUIsogenyCurveCoefficients() (A fp.Element, B fp.Element) { + return g1sswuCurveACoeff, g1sswuCurveBCoeff +} + +// G1SSWUIsogenyZ returns the recommended Z value of the SSWU curve. +// +// See https://www.rfc-editor.org/rfc/rfc9380.html#weierstrass +func G1SSWUIsogenyZ() fp.Element { + return g1sswuCurveZ +} + +var ( + g1IsogenyXNumeratorMap = []fp.Element{ + {5555391298090832668, 1871845530032595596, 4551034694774233518, 2584197799339864836, 15085749040064757844, 654075415717002996}, + {9910598932128054667, 4357765064159749802, 1555960221863322426, 9671461638228026285, 1275132148248838779, 507072521670460589}, + {11908177372061066827, 18190436643933350086, 6603102998733829542, 6581045210674032871, 16099974426311393401, 541581077397919012}, + {5282195870529824577, 12365729195083706401, 2807246122435955773, 332702220601507168, 7339422050895811209, 1050416448951884523}, + {10443415753526299973, 8852419397684277637, 1088333252544296036, 1174353327457337436, 1626144519293139599, 716651429285276662}, + {7916646322956281527, 11909818257232418749, 1455301921509471421, 3317627683558310107, 12693445337245173919, 1798273032850409769}, + {2577731109215284733, 8810166123993386985, 3186592767751348067, 15050850291391518479, 18435652654155870871, 1330813445865859326}, + {8787912969482053798, 9653629252694769025, 1358451377919714320, 16331599695590198629, 13519934665722691825, 628078949001449512}, + {16605411443261943819, 9536014432113026165, 8685402948537367476, 16291074259433785035, 407185289045737198, 713426768049972652}, + {1001421273809907975, 724433776290697394, 16309429154639760781, 10003715605277815375, 307249038158020985, 688008371043525493}, + {16622893420529658311, 18333652517857227637, 2139173376235292830, 16496634502105693419, 5355299366650241487, 382770009771704860}, + {8276255265012938363, 9997870203437298645, 16819210142450232135, 5062450688048499179, 12776432501206859311, 1778476024187613533}, + } + g1IsogenyXDenominatorMap = []fp.Element{ + {13358415881952098629, 12009257493157516192, 13928884382876484932, 12988314785833227070, 11244145530317148182, 100673949996487007}, + {2533162896381624793, 10578896196504721258, 4263020647280931071, 1255899686249737875, 17097124965295857733, 590960935246623182}, + {10990404485039254780, 5344458621503091696, 1718862119039451458, 11600049052019063549, 18389973225607751698, 1092616849767867362}, + {16377845895484993601, 15314247056264135931, 14543008873173635408, 4875476272346940127, 2030129768648768484, 1297689274107773964}, + {6376927397170316667, 1460555178565443615, 18156708192400235081, 14761117739963869762, 8361091377443400626, 1421233557303902229}, + {18127417459170613536, 5353764292720778676, 858818813615405862, 3528937506143354306, 12604964186779349896, 489837025077541867}, + {15285065477075910543, 3650488990300576179, 7274499670465195193, 16100555180954076900, 7580582425312971905, 896074979407586822}, + {7582945168915351799, 2506680954090651888, 10272835934257987876, 9924916350558121763, 13577194922650729507, 1698254565890367778}, + {2009730524583761661, 11053280693947850663, 14409256190409559425, 3658799329773368860, 13529638021208614900, 869243908766415668}, + {11058048790650732295, 7059501760293999296, 6596812464094265283, 14567744481299745071, 1591898617514919697, 1344004358835331304}, + } + g1IsogenyYNumeratorMap = []fp.Element{ + {3122824077082063463, 2111517899915568999, 14844585557031220083, 14713720721132803039, 9041847780307969683, 950267513573868304}, + {11079511902567680319, 18338468344530008184, 6769016392463638666, 1504264063027988936, 8098359051856762276, 760455062874047829}, + {1430247552210236986, 3854575382974307965, 14917507996414511245, 207936139448560, 9498310774218301406, 1438631746617682181}, + {6654065794071117243, 2928282753802966791, 4144383358731160429, 12673586709493869907, 12918170109018188791, 844088361957958231}, + {6416330705244672319, 3552017270878949117, 7777490944331917312, 7917192495177481567, 7271851377118683537, 253926972271069325}, + {11903306495973637341, 11622313950541285762, 17991208474928993001, 12280964980743791783, 14941570282955772167, 143516344770893715}, + {7324386472845891920, 16310961984705608217, 14050364318273732029, 410622978843904432, 13407944087243235067, 570579643952782879}, + {10655681039374273828, 3913226275392147601, 9613292388335178165, 11852815148890010639, 17652581670569921892, 780578093363976825}, + {10454026283255684948, 15005802245309313587, 4420421943175638630, 18052347756729021570, 12181908985148691767, 1485233717472293779}, + {5056344670784885274, 15896288289018563095, 11120951801157184493, 7250506164525313606, 9295677455526059106, 1757175036496698059}, + {417067620545670182, 113740147118943311, 7666319924200602156, 1469963335415292317, 13482947512490784447, 1353298443678343909}, + {13069093794065563159, 18364685236451803588, 2235996605706292724, 1007629142299662669, 4077244143222018961, 162586537120788900}, + {12976751790971550752, 10256454045927919861, 8968423978443605586, 91636529236982767, 9459527627289574163, 949550897353139410}, + {10595118024452621845, 8010256778549625402, 10333144214150401956, 17682229685967587631, 8235697699445463546, 317883997785997129}, + {16894283457285346118, 10513943172407809423, 4685513162956315481, 11558261883362075118, 574375951146893083, 1159440548124233311}, + {9739780494108151959, 17207219630538774058, 553911396609642498, 6085929320386029624, 14175410874026216616, 1183751611824804793}, + } + g1IsogenyYDenominatorMap = []fp.Element{ + {16963992846030154524, 1796759822929186144, 15995221960860457854, 8232142361908220707, 5977498266010213481, 759868220591477233}, + {7019489280640006651, 8025136855967848721, 17464762292772824538, 4490335113250743896, 7652702793653159798, 1129822927746498110}, + {3164260796573156764, 2639884922337322818, 1251365706181388855, 13142429936036186189, 359878619957828340, 126848055205862465}, + {17472832885692408710, 9911075278795900735, 2614390623136861791, 14474775734428698630, 6462878218464609418, 1225960780180864957}, + {3586995257703132870, 2143554115308730112, 15207899356205612465, 4372523065560113828, 12811868595146042778, 307251632623424763}, + {14298637377310410728, 10963101290308221781, 8192510423058716701, 1175370967867267532, 1029599188863854120, 678981456155013844}, + {11149806480082726900, 3664985661428410608, 18095361538178773836, 14174906593575241395, 15305104369759711886, 901234928011491053}, + {4727074327869776987, 15736954329525418288, 14642679026711520511, 11429849039208981702, 17333567062758618213, 951235897335772166}, + {9130114290642375589, 14069725355798443159, 6621984191700563591, 270173975669947883, 6218390495944243859, 1077419361593130421}, + {9144875514986933294, 16561351410666797616, 8591333879886582656, 15059370240386191395, 7834396448114781869, 946553772269403391}, + {17809450171377747225, 15896956440537434491, 8451524482089653422, 1694507265233574136, 18224201536921880842, 317503425606567070}, + {13940503876759740187, 8772047862193200131, 6080360161890657205, 7935486160089058373, 9407473295146243021, 1255078947940629503}, + {1160821217138360586, 13542760608074182996, 11595911004531652098, 18158686636947034451, 13330657138280564947, 1773960737279760188}, + {9132548444917292754, 16464415422105000789, 6319313500251671073, 12727658548847517900, 10985275115076354035, 1431541893474124246}, + {662485641082390837, 260809847827618849, 6177381409359357075, 18231947741742261351, 18128540110746580014, 1079107229429227022}, + } +) + +// G1IsogenyMap returns the isogeny map for the curve. +// The isogeny map is a list of polynomial coefficients for the x and y coordinate computation. +// The order of the coefficients is as follows: +// - x numerator, x denominator, y numerator, y denominator. +func G1IsogenyMap() [4][]fp.Element { + return [4][]fp.Element{ + g1IsogenyXNumeratorMap, + g1IsogenyXDenominatorMap, + g1IsogenyYNumeratorMap, + g1IsogenyYDenominatorMap, + } +} + +func g1IsogenyXNumerator(dst *fp.Element, x *fp.Element) { + g1EvalPolynomial(dst, false, g1IsogenyXNumeratorMap, x) +} + +func g1IsogenyXDenominator(dst *fp.Element, x *fp.Element) { + g1EvalPolynomial(dst, true, g1IsogenyXDenominatorMap, x) +} + +func g1IsogenyYNumerator(dst *fp.Element, x *fp.Element, y *fp.Element) { + var _dst fp.Element + g1EvalPolynomial(&_dst, false, g1IsogenyYNumeratorMap, x) + dst.Mul(&_dst, y) +} + +func g1IsogenyYDenominator(dst *fp.Element, x *fp.Element) { + g1EvalPolynomial(dst, true, g1IsogenyYDenominatorMap, x) +} + +// G1 computes the isogeny map of the curve element, given by its coordinates pX and pY. +// It mutates the coordinates pX and pY to the new coordinates of the isogeny map. +func G1Isogeny(pX, pY *fp.Element) { + + den := make([]fp.Element, 2) + + g1IsogenyYDenominator(&den[1], pX) + g1IsogenyXDenominator(&den[0], pX) + + g1IsogenyYNumerator(pY, pX, pY) + g1IsogenyXNumerator(pX, pX) + + den = fp.BatchInvert(den) + + pX.Mul(pX, &den[0]) + pY.Mul(pY, &den[1]) +} + +// G1SqrtRatio computes the square root of u/v and returns 0 iff u/v was indeed a quadratic residue. +// If not, we get sqrt(Z * u / v). Recall that Z is non-residue. +// If v = 0, u/v is meaningless and the output is unspecified, without raising an error. +// The main idea is that since the computation of the square root involves taking large powers of u/v, the inversion of v can be avoided +func G1SqrtRatio(z *fp.Element, u *fp.Element, v *fp.Element) uint64 { + // https://www.rfc-editor.org/rfc/rfc9380.html#name-optimized-sqrt_ratio-for-q- (3 mod 4) + var tv1 fp.Element + tv1.Square(v) // 1. tv1 = v² + var tv2 fp.Element + tv2.Mul(u, v) // 2. tv2 = u * v + tv1.Mul(&tv1, &tv2) // 3. tv1 = tv1 * tv2 + + var y1 fp.Element + { + var c1 big.Int + // c1 = 1000602388805416848354447456433976039139220704984751971333014534031007912622709466110671907282253916009473568139946 + c1.SetBytes([]byte{6, 128, 68, 122, 142, 95, 249, 166, 146, 198, 233, 237, 144, 210, 235, 53, 217, 29, 210, 225, 60, 225, 68, 175, 217, 204, 52, 168, 61, 172, 61, 137, 7, 170, 255, 255, 172, 84, 255, 255, 238, 127, 191, 255, 255, 255, 234, 170}) // c1 = (q - 3) / 4 # Integer arithmetic + + y1.Exp(tv1, &c1) // 4. y1 = tv1ᶜ¹ + } + + y1.Mul(&y1, &tv2) // 5. y1 = y1 * tv2 + + var y2 fp.Element + // c2 = sqrt(-Z) + tv3 := fp.Element{17544630987809824292, 17306709551153317753, 8299808889594647786, 5930295261504720397, 675038575008112577, 167386374569371918} + y2.Mul(&y1, &tv3) // 6. y2 = y1 * c2 + tv3.Square(&y1) // 7. tv3 = y1² + tv3.Mul(&tv3, v) // 8. tv3 = tv3 * v + isQNr := tv3.NotEqual(u) // 9. isQR = tv3 == u + z.Select(int(isQNr), &y1, &y2) // 10. y = CMOV(y2, y1, isQR) + return isQNr +} + +// G1MulByZ multiplies x by [11] and stores the result in z +func G1MulByZ(z *fp.Element, x *fp.Element) { + + res := *x + + res.Double(&res) + res.Double(&res) + res.Add(&res, x) + res.Double(&res) + res.Add(&res, x) + + *z = res +} + +func g1EvalPolynomial(z *fp.Element, monic bool, coefficients []fp.Element, x *fp.Element) { + dst := coefficients[len(coefficients)-1] + + if monic { + dst.Add(&dst, x) + } + + for i := len(coefficients) - 2; i >= 0; i-- { + dst.Mul(&dst, x) + dst.Add(&dst, &coefficients[i]) + } + + z.Set(&dst) +} + +// G1Sgn0 is an algebraic substitute for the notion of sign in ordered fields. +// Namely, every non-zero quadratic residue in a finite field of characteristic =/= 2 has exactly two square roots, one of each sign. +// +// See: https://www.rfc-editor.org/rfc/rfc9380.html#name-the-sgn0-function +// +// The sign of an element is not obviously related to that of its Montgomery form +func G1Sgn0(z *fp.Element) uint64 { + + nonMont := z.Bits() + + // m == 1 + return nonMont[0] % 2 + +} + +func G1NotZero(x *fp.Element) uint64 { + + return x[0] | x[1] | x[2] | x[3] | x[4] | x[5] + +} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/hash_to_curve/g2.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/hash_to_curve/g2.go new file mode 100644 index 00000000000..45c1bc126d0 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/hash_to_curve/g2.go @@ -0,0 +1,290 @@ +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package hash_to_curve + +import ( + "math/big" + + "github.com/consensys/gnark-crypto/ecc/bls12-381/fp" + "github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower" +) + +// Note: This only works for simple extensions + +var ( + g2sswuCurveACoeff = fptower.E2{ + A0: fp.Element{0}, + A1: fp.Element{16517514583386313282, 74322656156451461, 16683759486841714365, 815493829203396097, 204518332920448171, 1306242806803223655}, + } + g2sswuCurveBCoeff = fptower.E2{ + A0: fp.Element{2515823342057463218, 7982686274772798116, 7934098172177393262, 8484566552980779962, 4455086327883106868, 1323173589274087377}, + A1: fp.Element{2515823342057463218, 7982686274772798116, 7934098172177393262, 8484566552980779962, 4455086327883106868, 1323173589274087377}, + } +) + +var g2sswuCurveZ = fptower.E2{ + A0: fp.Element{9794203289623549276, 7309342082925068282, 1139538881605221074, 15659550692327388916, 16008355200866287827, 582484205531694093}, + A1: fp.Element{4897101644811774638, 3654671041462534141, 569769440802610537, 17053147383018470266, 17227549637287919721, 291242102765847046}, +} + +// G2SSWUCurveCoefficients returns the coefficients of the SSWU curve. +func G2SSWUIsogenyCurveCoefficients() (A fptower.E2, B fptower.E2) { + return g2sswuCurveACoeff, g2sswuCurveBCoeff +} + +// G2SSWUIsogenyZ returns the recommended Z value of the SSWU curve. +// +// See https://www.rfc-editor.org/rfc/rfc9380.html#weierstrass +func G2SSWUIsogenyZ() fptower.E2 { + return g2sswuCurveZ +} + +var ( + g2IsogenyXNumeratorMap = []fptower.E2{ + { + A0: fp.Element{5185457120960601698, 494647221959407934, 8971396042087821730, 324544954362548322, 14214792730224113654, 1405280679127738945}, + A1: fp.Element{5185457120960601698, 494647221959407934, 8971396042087821730, 324544954362548322, 14214792730224113654, 1405280679127738945}, + }, + { + A0: fp.Element{0}, + A1: fp.Element{6910023028261548496, 9745789443900091043, 7668299866710145304, 2432656849393633605, 2897729527445498821, 776645607375592125}, + }, + { + A0: fp.Element{724047465092313539, 15783990863276714670, 12824896677063784855, 15246381572572671516, 13186611051602728692, 1485475813959743803}, + A1: fp.Element{12678383550985550056, 4872894721950045521, 13057521970209848460, 10439700461551592610, 10672236800577525218, 388322803687796062}, + }, + { + A0: fp.Element{4659755689450087917, 1804066951354704782, 15570919779568036803, 15592734958806855601, 7597208057374167129, 1841438384006890194}, + A1: fp.Element{0}, + }, + } + g2IsogenyXDenominatorMap = []fptower.E2{ + { + A0: fp.Element{0}, + A1: fp.Element{2250392438786206615, 17463829474098544446, 14571211649711714824, 4495761442775821336, 258811604141191305, 357646605018048850}, + }, + { + A0: fp.Element{4933130441833534766, 15904462746612662304, 8034115857496836953, 12755092135412849606, 7007796720291435703, 252692002104915169}, + A1: fp.Element{8469300574244328829, 4752422838614097887, 17848302789776796362, 12930989898711414520, 16851051131888818207, 1621106615542624696}, + }, + } + g2IsogenyYNumeratorMap = []fptower.E2{ + { + A0: fp.Element{10869708750642247614, 13056187057366814946, 1750362034917495549, 6326189602300757217, 1140223926335695785, 632761649765668291}, + A1: fp.Element{10869708750642247614, 13056187057366814946, 1750362034917495549, 6326189602300757217, 1140223926335695785, 632761649765668291}, + }, + { + A0: fp.Element{0}, + A1: fp.Element{13765940311003083782, 5579209876153186557, 11349908400803699438, 11707848830955952341, 199199289641242246, 899896674917908607}, + }, + { + A0: fp.Element{15562563812347550836, 2436447360975022760, 6528760985104924230, 5219850230775796305, 5336118400288762609, 194161401843898031}, + A1: fp.Element{16286611277439864375, 18220438224251737430, 906913588459157469, 2019487729638916206, 75985378181939686, 1679637215803641835}, + }, + { + A0: fp.Element{11849179119594500956, 13906615243538674725, 14543197362847770509, 2041759640812427310, 2879701092679313252, 1259985822978576468}, + A1: fp.Element{0}, + }, + } + g2IsogenyYDenominatorMap = []fptower.E2{ + { + A0: fp.Element{99923616639376095, 10339114964526300021, 6204619029868000785, 1288486622530663893, 14587509920085997152, 272081012460753233}, + A1: fp.Element{99923616639376095, 10339114964526300021, 6204619029868000785, 1288486622530663893, 14587509920085997152, 272081012460753233}, + }, + { + A0: fp.Element{0}, + A1: fp.Element{6751177316358619845, 15498000274876530106, 6820146801716041242, 13487284328327464010, 776434812423573915, 1072939815054146550}, + }, + { + A0: fp.Element{7399695662750302149, 14633322083064217648, 12051173786245255430, 9909266166264498601, 1288323043582377747, 379038003157372754}, + A1: fp.Element{6002735353327561446, 6023563502162542543, 13831244861028377885, 15776815867859765525, 4123780734888324547, 1494760614490167112}, + }, + } +) + +// G2IsogenyMap returns the isogeny map for the curve. +// The isogeny map is a list of polynomial coefficients for the x and y coordinate computation. +// The order of the coefficients is as follows: +// - x numerator, x denominator, y numerator, y denominator. +func G2IsogenyMap() [4][]fptower.E2 { + return [4][]fptower.E2{ + g2IsogenyXNumeratorMap, + g2IsogenyXDenominatorMap, + g2IsogenyYNumeratorMap, + g2IsogenyYDenominatorMap, + } +} + +func g2IsogenyXNumerator(dst *fptower.E2, x *fptower.E2) { + g2EvalPolynomial(dst, false, g2IsogenyXNumeratorMap, x) +} + +func g2IsogenyXDenominator(dst *fptower.E2, x *fptower.E2) { + g2EvalPolynomial(dst, true, g2IsogenyXDenominatorMap, x) +} + +func g2IsogenyYNumerator(dst *fptower.E2, x *fptower.E2, y *fptower.E2) { + var _dst fptower.E2 + g2EvalPolynomial(&_dst, false, g2IsogenyYNumeratorMap, x) + dst.Mul(&_dst, y) +} + +func g2IsogenyYDenominator(dst *fptower.E2, x *fptower.E2) { + g2EvalPolynomial(dst, true, g2IsogenyYDenominatorMap, x) +} + +// G2 computes the isogeny map of the curve element, given by its coordinates pX and pY. +// It mutates the coordinates pX and pY to the new coordinates of the isogeny map. +func G2Isogeny(pX, pY *fptower.E2) { + + den := make([]fptower.E2, 2) + + g2IsogenyYDenominator(&den[1], pX) + g2IsogenyXDenominator(&den[0], pX) + + g2IsogenyYNumerator(pY, pX, pY) + g2IsogenyXNumerator(pX, pX) + + den = fptower.BatchInvertE2(den) + + pX.Mul(pX, &den[0]) + pY.Mul(pY, &den[1]) +} + +// G2SqrtRatio computes the square root of u/v and returns 0 iff u/v was indeed a quadratic residue. +// If not, we get sqrt(Z * u / v). Recall that Z is non-residue. +// If v = 0, u/v is meaningless and the output is unspecified, without raising an error. +// The main idea is that since the computation of the square root involves taking large powers of u/v, the inversion of v can be avoided +func G2SqrtRatio(z *fptower.E2, u *fptower.E2, v *fptower.E2) uint64 { + + // https://www.rfc-editor.org/rfc/rfc9380.html#name-sqrt_ratio-for-any-field + + tv1 := fptower.E2{ + A0: fp.Element{8921533702591418330, 15859389534032789116, 3389114680249073393, 15116930867080254631, 3288288975085550621, 1021049300055853010}, + A1: fp.Element{8921533702591418330, 15859389534032789116, 3389114680249073393, 15116930867080254631, 3288288975085550621, 1021049300055853010}, + } //tv1 = c6 + + var tv2, tv3, tv4, tv5 fptower.E2 + var exp big.Int + // c4 = 7 = 2³ - 1 + // q is odd so c1 is at least 1. + exp.SetBytes([]byte{7}) + + tv2.Exp(*v, &exp) // 2. tv2 = vᶜ⁴ + tv3.Square(&tv2) // 3. tv3 = tv2² + tv3.Mul(&tv3, v) // 4. tv3 = tv3 * v + tv5.Mul(u, &tv3) // 5. tv5 = u * tv3 + + // c3 = 1001205140483106588246484290269935788605945006208159541241399033561623546780709821462541004956387089373434649096260670658193992783731681621012512651314777238193313314641988297376025498093520728838658813979860931248214124593092835 + exp.SetBytes([]byte{42, 67, 122, 75, 140, 53, 252, 116, 189, 39, 142, 170, 34, 242, 94, 158, 45, 201, 14, 80, 231, 4, 107, 70, 110, 89, 228, 147, 73, 232, 189, 5, 10, 98, 207, 209, 109, 220, 166, 239, 83, 20, 147, 48, 151, 142, 240, 17, 214, 134, 25, 200, 97, 133, 199, 178, 146, 232, 90, 135, 9, 26, 4, 150, 107, 249, 30, 211, 231, 27, 116, 49, 98, 195, 56, 54, 33, 19, 207, 215, 206, 214, 177, 215, 99, 130, 234, 178, 106, 160, 0, 1, 199, 24, 227}) + + tv5.Exp(tv5, &exp) // 6. tv5 = tv5ᶜ³ + tv5.Mul(&tv5, &tv2) // 7. tv5 = tv5 * tv2 + tv2.Mul(&tv5, v) // 8. tv2 = tv5 * v + tv3.Mul(&tv5, u) // 9. tv3 = tv5 * u + tv4.Mul(&tv3, &tv2) // 10. tv4 = tv3 * tv2 + + // c5 = 4 + exp.SetBytes([]byte{4}) + tv5.Exp(tv4, &exp) // 11. tv5 = tv4ᶜ⁵ + isQNr := g2NotOne(&tv5) // 12. isQR = tv5 == 1 + c7 := fptower.E2{ + A0: fp.Element{1921729236329761493, 9193968980645934504, 9862280504246317678, 6861748847800817560, 10375788487011937166, 4460107375738415}, + A1: fp.Element{16821121318233475459, 10183025025229892778, 1779012082459463630, 3442292649700377418, 1061500799026501234, 1352426537312017168}, + } + tv2.Mul(&tv3, &c7) // 13. tv2 = tv3 * c7 + tv5.Mul(&tv4, &tv1) // 14. tv5 = tv4 * tv1 + tv3.Select(int(isQNr), &tv3, &tv2) // 15. tv3 = CMOV(tv2, tv3, isQR) + tv4.Select(int(isQNr), &tv4, &tv5) // 16. tv4 = CMOV(tv5, tv4, isQR) + exp.Lsh(big.NewInt(1), 3-2) // 18, 19: tv5 = 2ⁱ⁻² for i = c1 + + for i := 3; i >= 2; i-- { // 17. for i in (c1, c1 - 1, ..., 2): + + tv5.Exp(tv4, &exp) // 20. tv5 = tv4ᵗᵛ⁵ + nE1 := g2NotOne(&tv5) // 21. e1 = tv5 == 1 + tv2.Mul(&tv3, &tv1) // 22. tv2 = tv3 * tv1 + tv1.Mul(&tv1, &tv1) // 23. tv1 = tv1 * tv1 Why not write square? + tv5.Mul(&tv4, &tv1) // 24. tv5 = tv4 * tv1 + tv3.Select(int(nE1), &tv3, &tv2) // 25. tv3 = CMOV(tv2, tv3, e1) + tv4.Select(int(nE1), &tv4, &tv5) // 26. tv4 = CMOV(tv5, tv4, e1) + + if i > 2 { + exp.Rsh(&exp, 1) // 18, 19. tv5 = 2ⁱ⁻² + } + } + + *z = tv3 + return isQNr +} + +func g2NotOne(x *fptower.E2) uint64 { + + //Assuming hash is implemented for G1 and that the curve is over Fp + var one fp.Element + return one.SetOne().NotEqual(&x.A0) | G1NotZero(&x.A1) + +} + +// G2MulByZ multiplies x by [-2, -1] and stores the result in z +func G2MulByZ(z *fptower.E2, x *fptower.E2) { + + z.Mul(x, &fptower.E2{ + A0: fp.Element{9794203289623549276, 7309342082925068282, 1139538881605221074, 15659550692327388916, 16008355200866287827, 582484205531694093}, + A1: fp.Element{4897101644811774638, 3654671041462534141, 569769440802610537, 17053147383018470266, 17227549637287919721, 291242102765847046}, + }) + +} + +func g2EvalPolynomial(z *fptower.E2, monic bool, coefficients []fptower.E2, x *fptower.E2) { + dst := coefficients[len(coefficients)-1] + + if monic { + dst.Add(&dst, x) + } + + for i := len(coefficients) - 2; i >= 0; i-- { + dst.Mul(&dst, x) + dst.Add(&dst, &coefficients[i]) + } + + z.Set(&dst) +} + +// G2Sgn0 is an algebraic substitute for the notion of sign in ordered fields. +// Namely, every non-zero quadratic residue in a finite field of characteristic =/= 2 has exactly two square roots, one of each sign. +// +// See: https://www.rfc-editor.org/rfc/rfc9380.html#name-the-sgn0-function +// +// The sign of an element is not obviously related to that of its Montgomery form +func G2Sgn0(z *fptower.E2) uint64 { + + nonMont := z.Bits() + + sign := uint64(0) // 1. sign = 0 + zero := uint64(1) // 2. zero = 1 + var signI uint64 + var zeroI uint64 + + // 3. i = 1 + signI = nonMont.A0[0] % 2 // 4. sign_i = x_i mod 2 + zeroI = G1NotZero(&nonMont.A0) + zeroI = 1 ^ (zeroI|-zeroI)>>63 // 5. zero_i = x_i == 0 + sign = sign | (zero & signI) // 6. sign = sign OR (zero AND sign_i) # Avoid short-circuit logic ops + zero = zero & zeroI // 7. zero = zero AND zero_i + // 3. i = 2 + signI = nonMont.A1[0] % 2 // 4. sign_i = x_i mod 2 + // 5. zero_i = x_i == 0 + sign = sign | (zero & signI) // 6. sign = sign OR (zero AND sign_i) # Avoid short-circuit logic ops + // 7. zero = zero AND zero_i + return sign + +} + +func G2NotZero(x *fptower.E2) uint64 { + //Assuming G1 is over Fp and that if hashing is available for G2, it also is for G1 + return G1NotZero(&x.A0) | G1NotZero(&x.A1) + +} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/hash_to_g1.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/hash_to_g1.go index 7152782835b..75722523afb 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/hash_to_g1.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/hash_to_g1.go @@ -1,16 +1,5 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -18,177 +7,78 @@ package bls12381 import ( "github.com/consensys/gnark-crypto/ecc/bls12-381/fp" - - "math/big" + "github.com/consensys/gnark-crypto/ecc/bls12-381/hash_to_curve" ) -//Note: This only works for simple extensions - -func g1IsogenyXNumerator(dst *fp.Element, x *fp.Element) { - g1EvalPolynomial(dst, - false, - []fp.Element{ - {5555391298090832668, 1871845530032595596, 4551034694774233518, 2584197799339864836, 15085749040064757844, 654075415717002996}, - {9910598932128054667, 4357765064159749802, 1555960221863322426, 9671461638228026285, 1275132148248838779, 507072521670460589}, - {11908177372061066827, 18190436643933350086, 6603102998733829542, 6581045210674032871, 16099974426311393401, 541581077397919012}, - {5282195870529824577, 12365729195083706401, 2807246122435955773, 332702220601507168, 7339422050895811209, 1050416448951884523}, - {10443415753526299973, 8852419397684277637, 1088333252544296036, 1174353327457337436, 1626144519293139599, 716651429285276662}, - {7916646322956281527, 11909818257232418749, 1455301921509471421, 3317627683558310107, 12693445337245173919, 1798273032850409769}, - {2577731109215284733, 8810166123993386985, 3186592767751348067, 15050850291391518479, 18435652654155870871, 1330813445865859326}, - {8787912969482053798, 9653629252694769025, 1358451377919714320, 16331599695590198629, 13519934665722691825, 628078949001449512}, - {16605411443261943819, 9536014432113026165, 8685402948537367476, 16291074259433785035, 407185289045737198, 713426768049972652}, - {1001421273809907975, 724433776290697394, 16309429154639760781, 10003715605277815375, 307249038158020985, 688008371043525493}, - {16622893420529658311, 18333652517857227637, 2139173376235292830, 16496634502105693419, 5355299366650241487, 382770009771704860}, - {8276255265012938363, 9997870203437298645, 16819210142450232135, 5062450688048499179, 12776432501206859311, 1778476024187613533}, - }, - x) -} - -func g1IsogenyXDenominator(dst *fp.Element, x *fp.Element) { - g1EvalPolynomial(dst, - true, - []fp.Element{ - {13358415881952098629, 12009257493157516192, 13928884382876484932, 12988314785833227070, 11244145530317148182, 100673949996487007}, - {2533162896381624793, 10578896196504721258, 4263020647280931071, 1255899686249737875, 17097124965295857733, 590960935246623182}, - {10990404485039254780, 5344458621503091696, 1718862119039451458, 11600049052019063549, 18389973225607751698, 1092616849767867362}, - {16377845895484993601, 15314247056264135931, 14543008873173635408, 4875476272346940127, 2030129768648768484, 1297689274107773964}, - {6376927397170316667, 1460555178565443615, 18156708192400235081, 14761117739963869762, 8361091377443400626, 1421233557303902229}, - {18127417459170613536, 5353764292720778676, 858818813615405862, 3528937506143354306, 12604964186779349896, 489837025077541867}, - {15285065477075910543, 3650488990300576179, 7274499670465195193, 16100555180954076900, 7580582425312971905, 896074979407586822}, - {7582945168915351799, 2506680954090651888, 10272835934257987876, 9924916350558121763, 13577194922650729507, 1698254565890367778}, - {2009730524583761661, 11053280693947850663, 14409256190409559425, 3658799329773368860, 13529638021208614900, 869243908766415668}, - {11058048790650732295, 7059501760293999296, 6596812464094265283, 14567744481299745071, 1591898617514919697, 1344004358835331304}, - }, - x) -} - -func g1IsogenyYNumerator(dst *fp.Element, x *fp.Element, y *fp.Element) { - var _dst fp.Element - g1EvalPolynomial(&_dst, - false, - []fp.Element{ - {3122824077082063463, 2111517899915568999, 14844585557031220083, 14713720721132803039, 9041847780307969683, 950267513573868304}, - {11079511902567680319, 18338468344530008184, 6769016392463638666, 1504264063027988936, 8098359051856762276, 760455062874047829}, - {1430247552210236986, 3854575382974307965, 14917507996414511245, 207936139448560, 9498310774218301406, 1438631746617682181}, - {6654065794071117243, 2928282753802966791, 4144383358731160429, 12673586709493869907, 12918170109018188791, 844088361957958231}, - {6416330705244672319, 3552017270878949117, 7777490944331917312, 7917192495177481567, 7271851377118683537, 253926972271069325}, - {11903306495973637341, 11622313950541285762, 17991208474928993001, 12280964980743791783, 14941570282955772167, 143516344770893715}, - {7324386472845891920, 16310961984705608217, 14050364318273732029, 410622978843904432, 13407944087243235067, 570579643952782879}, - {10655681039374273828, 3913226275392147601, 9613292388335178165, 11852815148890010639, 17652581670569921892, 780578093363976825}, - {10454026283255684948, 15005802245309313587, 4420421943175638630, 18052347756729021570, 12181908985148691767, 1485233717472293779}, - {5056344670784885274, 15896288289018563095, 11120951801157184493, 7250506164525313606, 9295677455526059106, 1757175036496698059}, - {417067620545670182, 113740147118943311, 7666319924200602156, 1469963335415292317, 13482947512490784447, 1353298443678343909}, - {13069093794065563159, 18364685236451803588, 2235996605706292724, 1007629142299662669, 4077244143222018961, 162586537120788900}, - {12976751790971550752, 10256454045927919861, 8968423978443605586, 91636529236982767, 9459527627289574163, 949550897353139410}, - {10595118024452621845, 8010256778549625402, 10333144214150401956, 17682229685967587631, 8235697699445463546, 317883997785997129}, - {16894283457285346118, 10513943172407809423, 4685513162956315481, 11558261883362075118, 574375951146893083, 1159440548124233311}, - {9739780494108151959, 17207219630538774058, 553911396609642498, 6085929320386029624, 14175410874026216616, 1183751611824804793}, - }, - x) - - dst.Mul(&_dst, y) -} - -func g1IsogenyYDenominator(dst *fp.Element, x *fp.Element) { - g1EvalPolynomial(dst, - true, - []fp.Element{ - {16963992846030154524, 1796759822929186144, 15995221960860457854, 8232142361908220707, 5977498266010213481, 759868220591477233}, - {7019489280640006651, 8025136855967848721, 17464762292772824538, 4490335113250743896, 7652702793653159798, 1129822927746498110}, - {3164260796573156764, 2639884922337322818, 1251365706181388855, 13142429936036186189, 359878619957828340, 126848055205862465}, - {17472832885692408710, 9911075278795900735, 2614390623136861791, 14474775734428698630, 6462878218464609418, 1225960780180864957}, - {3586995257703132870, 2143554115308730112, 15207899356205612465, 4372523065560113828, 12811868595146042778, 307251632623424763}, - {14298637377310410728, 10963101290308221781, 8192510423058716701, 1175370967867267532, 1029599188863854120, 678981456155013844}, - {11149806480082726900, 3664985661428410608, 18095361538178773836, 14174906593575241395, 15305104369759711886, 901234928011491053}, - {4727074327869776987, 15736954329525418288, 14642679026711520511, 11429849039208981702, 17333567062758618213, 951235897335772166}, - {9130114290642375589, 14069725355798443159, 6621984191700563591, 270173975669947883, 6218390495944243859, 1077419361593130421}, - {9144875514986933294, 16561351410666797616, 8591333879886582656, 15059370240386191395, 7834396448114781869, 946553772269403391}, - {17809450171377747225, 15896956440537434491, 8451524482089653422, 1694507265233574136, 18224201536921880842, 317503425606567070}, - {13940503876759740187, 8772047862193200131, 6080360161890657205, 7935486160089058373, 9407473295146243021, 1255078947940629503}, - {1160821217138360586, 13542760608074182996, 11595911004531652098, 18158686636947034451, 13330657138280564947, 1773960737279760188}, - {9132548444917292754, 16464415422105000789, 6319313500251671073, 12727658548847517900, 10985275115076354035, 1431541893474124246}, - {662485641082390837, 260809847827618849, 6177381409359357075, 18231947741742261351, 18128540110746580014, 1079107229429227022}, - }, - x) +// MapToG1 invokes the SSWU map, and guarantees that the result is in G1. +func MapToG1(u fp.Element) G1Affine { + res := MapToCurve1(&u) + //this is in an isogenous curve + hash_to_curve.G1Isogeny(&res.X, &res.Y) + res.ClearCofactor(&res) + return res } -func g1Isogeny(p *G1Affine) { - - den := make([]fp.Element, 2) - - g1IsogenyYDenominator(&den[1], &p.X) - g1IsogenyXDenominator(&den[0], &p.X) +// EncodeToG1 hashes a message to a point on the G1 curve using the SSWU map. +// It is faster than [HashToG1], but the result is not uniformly distributed. Unsuitable as a random oracle. +// dst stands for "domain separation tag", a string unique to the construction using the hash function +// +// See: https://www.rfc-editor.org/rfc/rfc9380.html#roadmap +func EncodeToG1(msg, dst []byte) (G1Affine, error) { - g1IsogenyYNumerator(&p.Y, &p.X, &p.Y) - g1IsogenyXNumerator(&p.X, &p.X) + var res G1Affine + u, err := fp.Hash(msg, dst, 1) + if err != nil { + return res, err + } - den = fp.BatchInvert(den) + res = MapToCurve1(&u[0]) - p.X.Mul(&p.X, &den[0]) - p.Y.Mul(&p.Y, &den[1]) + //this is in an isogenous curve + hash_to_curve.G1Isogeny(&res.X, &res.Y) + res.ClearCofactor(&res) + return res, nil } -// g1SqrtRatio computes the square root of u/v and returns 0 iff u/v was indeed a quadratic residue -// if not, we get sqrt(Z * u / v). Recall that Z is non-residue -// If v = 0, u/v is meaningless and the output is unspecified, without raising an error. -// The main idea is that since the computation of the square root involves taking large powers of u/v, the inversion of v can be avoided -func g1SqrtRatio(z *fp.Element, u *fp.Element, v *fp.Element) uint64 { - // https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-optimized-sqrt_ratio-for-q- (3 mod 4) - var tv1 fp.Element - tv1.Square(v) // 1. tv1 = v² - var tv2 fp.Element - tv2.Mul(u, v) // 2. tv2 = u * v - tv1.Mul(&tv1, &tv2) // 3. tv1 = tv1 * tv2 - - var y1 fp.Element - { - var c1 big.Int - // c1 = 1000602388805416848354447456433976039139220704984751971333014534031007912622709466110671907282253916009473568139946 - c1.SetBytes([]byte{6, 128, 68, 122, 142, 95, 249, 166, 146, 198, 233, 237, 144, 210, 235, 53, 217, 29, 210, 225, 60, 225, 68, 175, 217, 204, 52, 168, 61, 172, 61, 137, 7, 170, 255, 255, 172, 84, 255, 255, 238, 127, 191, 255, 255, 255, 234, 170}) // c1 = (q - 3) / 4 # Integer arithmetic - - y1.Exp(tv1, &c1) // 4. y1 = tv1ᶜ¹ +// HashToG1 hashes a message to a point on the G1 curve using the SSWU map. +// Slower than [EncodeToG1], but usable as a random oracle. +// dst stands for "domain separation tag", a string unique to the construction using the hash function. +// +// See https://www.rfc-editor.org/rfc/rfc9380.html#roadmap +func HashToG1(msg, dst []byte) (G1Affine, error) { + u, err := fp.Hash(msg, dst, 2*1) + if err != nil { + return G1Affine{}, err } - y1.Mul(&y1, &tv2) // 5. y1 = y1 * tv2 - - var y2 fp.Element - // c2 = sqrt(-Z) - tv3 := fp.Element{17544630987809824292, 17306709551153317753, 8299808889594647786, 5930295261504720397, 675038575008112577, 167386374569371918} - y2.Mul(&y1, &tv3) // 6. y2 = y1 * c2 - tv3.Square(&y1) // 7. tv3 = y1² - tv3.Mul(&tv3, v) // 8. tv3 = tv3 * v - isQNr := tv3.NotEqual(u) // 9. isQR = tv3 == u - z.Select(int(isQNr), &y1, &y2) // 10. y = CMOV(y2, y1, isQR) - return isQNr -} + Q0 := MapToCurve1(&u[0]) + Q1 := MapToCurve1(&u[1]) -// g1MulByZ multiplies x by [11] and stores the result in z -func g1MulByZ(z *fp.Element, x *fp.Element) { + //TODO (perf): Add in E' first, then apply isogeny + hash_to_curve.G1Isogeny(&Q0.X, &Q0.Y) + hash_to_curve.G1Isogeny(&Q1.X, &Q1.Y) - res := *x + var _Q0, _Q1 G1Jac + _Q0.FromAffine(&Q0) + _Q1.FromAffine(&Q1).AddAssign(&_Q0) - res.Double(&res) - res.Double(&res) - res.Add(&res, x) - res.Double(&res) - res.Add(&res, x) + _Q1.ClearCofactor(&_Q1) - *z = res + Q1.FromJacobian(&_Q1) + return Q1, nil } -// https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-simplified-swu-method -// MapToCurve1 implements the SSWU map -// No cofactor clearing or isogeny +// MapToCurve1 implements the SSWU map. It does not perform cofactor clearing nor isogeny. For map to group, use [MapToG1]. +// +// See: https://www.rfc-editor.org/rfc/rfc9380.html#name-simplified-swu-method func MapToCurve1(u *fp.Element) G1Affine { - - var sswuIsoCurveCoeffA = fp.Element{3415322872136444497, 9675504606121301699, 13284745414851768802, 2873609449387478652, 2897906769629812789, 1536947672689614213} - var sswuIsoCurveCoeffB = fp.Element{18129637713272545760, 11144507692959411567, 10108153527111632324, 9745270364868568433, 14587922135379007624, 469008097655535723} + sswuIsoCurveCoeffA, sswuIsoCurveCoeffB := hash_to_curve.G1SSWUIsogenyCurveCoefficients() var tv1 fp.Element tv1.Square(u) // 1. tv1 = u² //mul tv1 by Z - g1MulByZ(&tv1, &tv1) // 2. tv1 = Z * tv1 + hash_to_curve.G1MulByZ(&tv1, &tv1) // 2. tv1 = Z * tv1 var tv2 fp.Element tv2.Square(&tv1) // 3. tv2 = tv1² @@ -200,10 +90,10 @@ func MapToCurve1(u *fp.Element) G1Affine { tv3.Add(&tv2, &tv4) // 5. tv3 = tv2 + 1 tv3.Mul(&tv3, &sswuIsoCurveCoeffB) // 6. tv3 = B * tv3 - tv2NZero := g1NotZero(&tv2) + tv2NZero := hash_to_curve.G1NotZero(&tv2) // tv4 = Z - tv4 = fp.Element{9830232086645309404, 1112389714365644829, 8603885298299447491, 11361495444721768256, 5788602283869803809, 543934104870762216} + tv4 = hash_to_curve.G1SSWUIsogenyZ() tv2.Neg(&tv2) tv4.Select(int(tv2NZero), &tv4, &tv2) // 7. tv4 = CMOV(Z, -tv2, tv2 != 0) @@ -228,7 +118,7 @@ func MapToCurve1(u *fp.Element) G1Affine { x.Mul(&tv1, &tv3) // 17. x = tv1 * tv3 var y1 fp.Element - gx1NSquare := g1SqrtRatio(&y1, &tv2, &tv6) // 18. (is_gx1_square, y1) = sqrt_ratio(tv2, tv6) + gx1NSquare := hash_to_curve.G1SqrtRatio(&y1, &tv2, &tv6) // 18. (is_gx1_square, y1) = sqrt_ratio(tv2, tv6) var y fp.Element y.Mul(&tv1, u) // 19. y = tv1 * u @@ -239,7 +129,7 @@ func MapToCurve1(u *fp.Element) G1Affine { y.Select(int(gx1NSquare), &y1, &y) // 22. y = CMOV(y, y1, is_gx1_square) y1.Neg(&y) - y.Select(int(g1Sgn0(u)^g1Sgn0(&y)), &y, &y1) + y.Select(int(hash_to_curve.G1Sgn0(u)^hash_to_curve.G1Sgn0(&y)), &y, &y1) // 23. e1 = sgn0(u) == sgn0(y) // 24. y = CMOV(-y, y, e1) @@ -248,93 +138,3 @@ func MapToCurve1(u *fp.Element) G1Affine { return G1Affine{x, y} } - -func g1EvalPolynomial(z *fp.Element, monic bool, coefficients []fp.Element, x *fp.Element) { - dst := coefficients[len(coefficients)-1] - - if monic { - dst.Add(&dst, x) - } - - for i := len(coefficients) - 2; i >= 0; i-- { - dst.Mul(&dst, x) - dst.Add(&dst, &coefficients[i]) - } - - z.Set(&dst) -} - -// g1Sgn0 is an algebraic substitute for the notion of sign in ordered fields -// Namely, every non-zero quadratic residue in a finite field of characteristic =/= 2 has exactly two square roots, one of each sign -// https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-the-sgn0-function -// The sign of an element is not obviously related to that of its Montgomery form -func g1Sgn0(z *fp.Element) uint64 { - - nonMont := z.Bits() - - // m == 1 - return nonMont[0] % 2 - -} - -// MapToG1 invokes the SSWU map, and guarantees that the result is in g1 -func MapToG1(u fp.Element) G1Affine { - res := MapToCurve1(&u) - //this is in an isogenous curve - g1Isogeny(&res) - res.ClearCofactor(&res) - return res -} - -// EncodeToG1 hashes a message to a point on the G1 curve using the SSWU map. -// It is faster than HashToG1, but the result is not uniformly distributed. Unsuitable as a random oracle. -// dst stands for "domain separation tag", a string unique to the construction using the hash function -// https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#roadmap -func EncodeToG1(msg, dst []byte) (G1Affine, error) { - - var res G1Affine - u, err := fp.Hash(msg, dst, 1) - if err != nil { - return res, err - } - - res = MapToCurve1(&u[0]) - - //this is in an isogenous curve - g1Isogeny(&res) - res.ClearCofactor(&res) - return res, nil -} - -// HashToG1 hashes a message to a point on the G1 curve using the SSWU map. -// Slower than EncodeToG1, but usable as a random oracle. -// dst stands for "domain separation tag", a string unique to the construction using the hash function -// https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#roadmap -func HashToG1(msg, dst []byte) (G1Affine, error) { - u, err := fp.Hash(msg, dst, 2*1) - if err != nil { - return G1Affine{}, err - } - - Q0 := MapToCurve1(&u[0]) - Q1 := MapToCurve1(&u[1]) - - //TODO (perf): Add in E' first, then apply isogeny - g1Isogeny(&Q0) - g1Isogeny(&Q1) - - var _Q0, _Q1 G1Jac - _Q0.FromAffine(&Q0) - _Q1.FromAffine(&Q1).AddAssign(&_Q0) - - _Q1.ClearCofactor(&_Q1) - - Q1.FromJacobian(&_Q1) - return Q1, nil -} - -func g1NotZero(x *fp.Element) uint64 { - - return x[0] | x[1] | x[2] | x[3] | x[4] | x[5] - -} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/hash_to_g2.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/hash_to_g2.go index 4feafbfb140..43103b90934 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/hash_to_g2.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/hash_to_g2.go @@ -1,16 +1,5 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -18,219 +7,88 @@ package bls12381 import ( "github.com/consensys/gnark-crypto/ecc/bls12-381/fp" + "github.com/consensys/gnark-crypto/ecc/bls12-381/hash_to_curve" "github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower" - - "math/big" ) -//Note: This only works for simple extensions - -func g2IsogenyXNumerator(dst *fptower.E2, x *fptower.E2) { - g2EvalPolynomial(dst, - false, - []fptower.E2{ - { - A0: fp.Element{5185457120960601698, 494647221959407934, 8971396042087821730, 324544954362548322, 14214792730224113654, 1405280679127738945}, - A1: fp.Element{5185457120960601698, 494647221959407934, 8971396042087821730, 324544954362548322, 14214792730224113654, 1405280679127738945}, - }, - { - A0: fp.Element{0}, - A1: fp.Element{6910023028261548496, 9745789443900091043, 7668299866710145304, 2432656849393633605, 2897729527445498821, 776645607375592125}, - }, - { - A0: fp.Element{724047465092313539, 15783990863276714670, 12824896677063784855, 15246381572572671516, 13186611051602728692, 1485475813959743803}, - A1: fp.Element{12678383550985550056, 4872894721950045521, 13057521970209848460, 10439700461551592610, 10672236800577525218, 388322803687796062}, - }, - { - A0: fp.Element{4659755689450087917, 1804066951354704782, 15570919779568036803, 15592734958806855601, 7597208057374167129, 1841438384006890194}, - A1: fp.Element{0}, - }, - }, - x) -} - -func g2IsogenyXDenominator(dst *fptower.E2, x *fptower.E2) { - g2EvalPolynomial(dst, - true, - []fptower.E2{ - { - A0: fp.Element{0}, - A1: fp.Element{2250392438786206615, 17463829474098544446, 14571211649711714824, 4495761442775821336, 258811604141191305, 357646605018048850}, - }, - { - A0: fp.Element{4933130441833534766, 15904462746612662304, 8034115857496836953, 12755092135412849606, 7007796720291435703, 252692002104915169}, - A1: fp.Element{8469300574244328829, 4752422838614097887, 17848302789776796362, 12930989898711414520, 16851051131888818207, 1621106615542624696}, - }, - }, - x) -} - -func g2IsogenyYNumerator(dst *fptower.E2, x *fptower.E2, y *fptower.E2) { - var _dst fptower.E2 - g2EvalPolynomial(&_dst, - false, - []fptower.E2{ - { - A0: fp.Element{10869708750642247614, 13056187057366814946, 1750362034917495549, 6326189602300757217, 1140223926335695785, 632761649765668291}, - A1: fp.Element{10869708750642247614, 13056187057366814946, 1750362034917495549, 6326189602300757217, 1140223926335695785, 632761649765668291}, - }, - { - A0: fp.Element{0}, - A1: fp.Element{13765940311003083782, 5579209876153186557, 11349908400803699438, 11707848830955952341, 199199289641242246, 899896674917908607}, - }, - { - A0: fp.Element{15562563812347550836, 2436447360975022760, 6528760985104924230, 5219850230775796305, 5336118400288762609, 194161401843898031}, - A1: fp.Element{16286611277439864375, 18220438224251737430, 906913588459157469, 2019487729638916206, 75985378181939686, 1679637215803641835}, - }, - { - A0: fp.Element{11849179119594500956, 13906615243538674725, 14543197362847770509, 2041759640812427310, 2879701092679313252, 1259985822978576468}, - A1: fp.Element{0}, - }, - }, - x) - - dst.Mul(&_dst, y) -} - -func g2IsogenyYDenominator(dst *fptower.E2, x *fptower.E2) { - g2EvalPolynomial(dst, - true, - []fptower.E2{ - { - A0: fp.Element{99923616639376095, 10339114964526300021, 6204619029868000785, 1288486622530663893, 14587509920085997152, 272081012460753233}, - A1: fp.Element{99923616639376095, 10339114964526300021, 6204619029868000785, 1288486622530663893, 14587509920085997152, 272081012460753233}, - }, - { - A0: fp.Element{0}, - A1: fp.Element{6751177316358619845, 15498000274876530106, 6820146801716041242, 13487284328327464010, 776434812423573915, 1072939815054146550}, - }, - { - A0: fp.Element{7399695662750302149, 14633322083064217648, 12051173786245255430, 9909266166264498601, 1288323043582377747, 379038003157372754}, - A1: fp.Element{6002735353327561446, 6023563502162542543, 13831244861028377885, 15776815867859765525, 4123780734888324547, 1494760614490167112}, - }, - }, - x) +// MapToG2 invokes the SSWU map, and guarantees that the result is in G2. +func MapToG2(u fptower.E2) G2Affine { + res := MapToCurve2(&u) + //this is in an isogenous curve + hash_to_curve.G2Isogeny(&res.X, &res.Y) + res.ClearCofactor(&res) + return res } -func g2Isogeny(p *G2Affine) { - - den := make([]fptower.E2, 2) - - g2IsogenyYDenominator(&den[1], &p.X) - g2IsogenyXDenominator(&den[0], &p.X) +// EncodeToG2 hashes a message to a point on the G2 curve using the SSWU map. +// It is faster than [HashToG2], but the result is not uniformly distributed. Unsuitable as a random oracle. +// dst stands for "domain separation tag", a string unique to the construction using the hash function +// +// See: https://www.rfc-editor.org/rfc/rfc9380.html#roadmap +func EncodeToG2(msg, dst []byte) (G2Affine, error) { - g2IsogenyYNumerator(&p.Y, &p.X, &p.Y) - g2IsogenyXNumerator(&p.X, &p.X) + var res G2Affine + u, err := fp.Hash(msg, dst, 2) + if err != nil { + return res, err + } - den = fptower.BatchInvertE2(den) + res = MapToCurve2(&fptower.E2{ + A0: u[0], + A1: u[1], + }) - p.X.Mul(&p.X, &den[0]) - p.Y.Mul(&p.Y, &den[1]) + //this is in an isogenous curve + hash_to_curve.G2Isogeny(&res.X, &res.Y) + res.ClearCofactor(&res) + return res, nil } -// g2SqrtRatio computes the square root of u/v and returns 0 iff u/v was indeed a quadratic residue -// if not, we get sqrt(Z * u / v). Recall that Z is non-residue -// If v = 0, u/v is meaningless and the output is unspecified, without raising an error. -// The main idea is that since the computation of the square root involves taking large powers of u/v, the inversion of v can be avoided -func g2SqrtRatio(z *fptower.E2, u *fptower.E2, v *fptower.E2) uint64 { - - // https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-sqrt_ratio-for-any-field - - tv1 := fptower.E2{ - A0: fp.Element{8921533702591418330, 15859389534032789116, 3389114680249073393, 15116930867080254631, 3288288975085550621, 1021049300055853010}, - A1: fp.Element{8921533702591418330, 15859389534032789116, 3389114680249073393, 15116930867080254631, 3288288975085550621, 1021049300055853010}, - } //tv1 = c6 - - var tv2, tv3, tv4, tv5 fptower.E2 - var exp big.Int - // c4 = 7 = 2³ - 1 - // q is odd so c1 is at least 1. - exp.SetBytes([]byte{7}) - - tv2.Exp(*v, &exp) // 2. tv2 = vᶜ⁴ - tv3.Square(&tv2) // 3. tv3 = tv2² - tv3.Mul(&tv3, v) // 4. tv3 = tv3 * v - tv5.Mul(u, &tv3) // 5. tv5 = u * tv3 - - // c3 = 1001205140483106588246484290269935788605945006208159541241399033561623546780709821462541004956387089373434649096260670658193992783731681621012512651314777238193313314641988297376025498093520728838658813979860931248214124593092835 - exp.SetBytes([]byte{42, 67, 122, 75, 140, 53, 252, 116, 189, 39, 142, 170, 34, 242, 94, 158, 45, 201, 14, 80, 231, 4, 107, 70, 110, 89, 228, 147, 73, 232, 189, 5, 10, 98, 207, 209, 109, 220, 166, 239, 83, 20, 147, 48, 151, 142, 240, 17, 214, 134, 25, 200, 97, 133, 199, 178, 146, 232, 90, 135, 9, 26, 4, 150, 107, 249, 30, 211, 231, 27, 116, 49, 98, 195, 56, 54, 33, 19, 207, 215, 206, 214, 177, 215, 99, 130, 234, 178, 106, 160, 0, 1, 199, 24, 227}) - - tv5.Exp(tv5, &exp) // 6. tv5 = tv5ᶜ³ - tv5.Mul(&tv5, &tv2) // 7. tv5 = tv5 * tv2 - tv2.Mul(&tv5, v) // 8. tv2 = tv5 * v - tv3.Mul(&tv5, u) // 9. tv3 = tv5 * u - tv4.Mul(&tv3, &tv2) // 10. tv4 = tv3 * tv2 - - // c5 = 4 - exp.SetBytes([]byte{4}) - tv5.Exp(tv4, &exp) // 11. tv5 = tv4ᶜ⁵ - isQNr := g2NotOne(&tv5) // 12. isQR = tv5 == 1 - c7 := fptower.E2{ - A0: fp.Element{1921729236329761493, 9193968980645934504, 9862280504246317678, 6861748847800817560, 10375788487011937166, 4460107375738415}, - A1: fp.Element{16821121318233475459, 10183025025229892778, 1779012082459463630, 3442292649700377418, 1061500799026501234, 1352426537312017168}, - } - tv2.Mul(&tv3, &c7) // 13. tv2 = tv3 * c7 - tv5.Mul(&tv4, &tv1) // 14. tv5 = tv4 * tv1 - tv3.Select(int(isQNr), &tv3, &tv2) // 15. tv3 = CMOV(tv2, tv3, isQR) - tv4.Select(int(isQNr), &tv4, &tv5) // 16. tv4 = CMOV(tv5, tv4, isQR) - exp.Lsh(big.NewInt(1), 3-2) // 18, 19: tv5 = 2ⁱ⁻² for i = c1 - - for i := 3; i >= 2; i-- { // 17. for i in (c1, c1 - 1, ..., 2): - - tv5.Exp(tv4, &exp) // 20. tv5 = tv4ᵗᵛ⁵ - nE1 := g2NotOne(&tv5) // 21. e1 = tv5 == 1 - tv2.Mul(&tv3, &tv1) // 22. tv2 = tv3 * tv1 - tv1.Mul(&tv1, &tv1) // 23. tv1 = tv1 * tv1 Why not write square? - tv5.Mul(&tv4, &tv1) // 24. tv5 = tv4 * tv1 - tv3.Select(int(nE1), &tv3, &tv2) // 25. tv3 = CMOV(tv2, tv3, e1) - tv4.Select(int(nE1), &tv4, &tv5) // 26. tv4 = CMOV(tv5, tv4, e1) - - if i > 2 { - exp.Rsh(&exp, 1) // 18, 19. tv5 = 2ⁱ⁻² - } +// HashToG2 hashes a message to a point on the G2 curve using the SSWU map. +// Slower than [EncodeToG2], but usable as a random oracle. +// dst stands for "domain separation tag", a string unique to the construction using the hash function. +// +// See https://www.rfc-editor.org/rfc/rfc9380.html#roadmap +func HashToG2(msg, dst []byte) (G2Affine, error) { + u, err := fp.Hash(msg, dst, 2*2) + if err != nil { + return G2Affine{}, err } - *z = tv3 - return isQNr -} - -func g2NotOne(x *fptower.E2) uint64 { - - //Assuming hash is implemented for G1 and that the curve is over Fp - var one fp.Element - return one.SetOne().NotEqual(&x.A0) | g1NotZero(&x.A1) + Q0 := MapToCurve2(&fptower.E2{ + A0: u[0], + A1: u[1], + }) + Q1 := MapToCurve2(&fptower.E2{ + A0: u[2+0], + A1: u[2+1], + }) -} + //TODO (perf): Add in E' first, then apply isogeny + hash_to_curve.G2Isogeny(&Q0.X, &Q0.Y) + hash_to_curve.G2Isogeny(&Q1.X, &Q1.Y) -// g2MulByZ multiplies x by [-2, -1] and stores the result in z -func g2MulByZ(z *fptower.E2, x *fptower.E2) { + var _Q0, _Q1 G2Jac + _Q0.FromAffine(&Q0) + _Q1.FromAffine(&Q1).AddAssign(&_Q0) - z.Mul(x, &fptower.E2{ - A0: fp.Element{9794203289623549276, 7309342082925068282, 1139538881605221074, 15659550692327388916, 16008355200866287827, 582484205531694093}, - A1: fp.Element{4897101644811774638, 3654671041462534141, 569769440802610537, 17053147383018470266, 17227549637287919721, 291242102765847046}, - }) + _Q1.ClearCofactor(&_Q1) + Q1.FromJacobian(&_Q1) + return Q1, nil } -// https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-simplified-swu-method -// MapToCurve2 implements the SSWU map -// No cofactor clearing or isogeny +// MapToCurve2 implements the SSWU map. It does not perform cofactor clearing nor isogeny. For map to group, use [MapToG2]. +// +// See: https://www.rfc-editor.org/rfc/rfc9380.html#name-simplified-swu-method func MapToCurve2(u *fptower.E2) G2Affine { - - var sswuIsoCurveCoeffA = fptower.E2{ - A0: fp.Element{0}, - A1: fp.Element{16517514583386313282, 74322656156451461, 16683759486841714365, 815493829203396097, 204518332920448171, 1306242806803223655}, - } - var sswuIsoCurveCoeffB = fptower.E2{ - A0: fp.Element{2515823342057463218, 7982686274772798116, 7934098172177393262, 8484566552980779962, 4455086327883106868, 1323173589274087377}, - A1: fp.Element{2515823342057463218, 7982686274772798116, 7934098172177393262, 8484566552980779962, 4455086327883106868, 1323173589274087377}, - } + sswuIsoCurveCoeffA, sswuIsoCurveCoeffB := hash_to_curve.G2SSWUIsogenyCurveCoefficients() var tv1 fptower.E2 tv1.Square(u) // 1. tv1 = u² //mul tv1 by Z - g2MulByZ(&tv1, &tv1) // 2. tv1 = Z * tv1 + hash_to_curve.G2MulByZ(&tv1, &tv1) // 2. tv1 = Z * tv1 var tv2 fptower.E2 tv2.Square(&tv1) // 3. tv2 = tv1² @@ -242,13 +100,10 @@ func MapToCurve2(u *fptower.E2) G2Affine { tv3.Add(&tv2, &tv4) // 5. tv3 = tv2 + 1 tv3.Mul(&tv3, &sswuIsoCurveCoeffB) // 6. tv3 = B * tv3 - tv2NZero := g2NotZero(&tv2) + tv2NZero := hash_to_curve.G2NotZero(&tv2) // tv4 = Z - tv4 = fptower.E2{ - A0: fp.Element{9794203289623549276, 7309342082925068282, 1139538881605221074, 15659550692327388916, 16008355200866287827, 582484205531694093}, - A1: fp.Element{4897101644811774638, 3654671041462534141, 569769440802610537, 17053147383018470266, 17227549637287919721, 291242102765847046}, - } + tv4 = hash_to_curve.G2SSWUIsogenyZ() tv2.Neg(&tv2) tv4.Select(int(tv2NZero), &tv4, &tv2) // 7. tv4 = CMOV(Z, -tv2, tv2 != 0) @@ -273,7 +128,7 @@ func MapToCurve2(u *fptower.E2) G2Affine { x.Mul(&tv1, &tv3) // 17. x = tv1 * tv3 var y1 fptower.E2 - gx1NSquare := g2SqrtRatio(&y1, &tv2, &tv6) // 18. (is_gx1_square, y1) = sqrt_ratio(tv2, tv6) + gx1NSquare := hash_to_curve.G2SqrtRatio(&y1, &tv2, &tv6) // 18. (is_gx1_square, y1) = sqrt_ratio(tv2, tv6) var y fptower.E2 y.Mul(&tv1, u) // 19. y = tv1 * u @@ -284,7 +139,7 @@ func MapToCurve2(u *fptower.E2) G2Affine { y.Select(int(gx1NSquare), &y1, &y) // 22. y = CMOV(y, y1, is_gx1_square) y1.Neg(&y) - y.Select(int(g2Sgn0(u)^g2Sgn0(&y)), &y, &y1) + y.Select(int(hash_to_curve.G2Sgn0(u)^hash_to_curve.G2Sgn0(&y)), &y, &y1) // 23. e1 = sgn0(u) == sgn0(y) // 24. y = CMOV(-y, y, e1) @@ -293,117 +148,3 @@ func MapToCurve2(u *fptower.E2) G2Affine { return G2Affine{x, y} } - -func g2EvalPolynomial(z *fptower.E2, monic bool, coefficients []fptower.E2, x *fptower.E2) { - dst := coefficients[len(coefficients)-1] - - if monic { - dst.Add(&dst, x) - } - - for i := len(coefficients) - 2; i >= 0; i-- { - dst.Mul(&dst, x) - dst.Add(&dst, &coefficients[i]) - } - - z.Set(&dst) -} - -// g2Sgn0 is an algebraic substitute for the notion of sign in ordered fields -// Namely, every non-zero quadratic residue in a finite field of characteristic =/= 2 has exactly two square roots, one of each sign -// https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-the-sgn0-function -// The sign of an element is not obviously related to that of its Montgomery form -func g2Sgn0(z *fptower.E2) uint64 { - - nonMont := z.Bits() - - sign := uint64(0) // 1. sign = 0 - zero := uint64(1) // 2. zero = 1 - var signI uint64 - var zeroI uint64 - - // 3. i = 1 - signI = nonMont.A0[0] % 2 // 4. sign_i = x_i mod 2 - zeroI = g1NotZero(&nonMont.A0) - zeroI = 1 ^ (zeroI|-zeroI)>>63 // 5. zero_i = x_i == 0 - sign = sign | (zero & signI) // 6. sign = sign OR (zero AND sign_i) # Avoid short-circuit logic ops - zero = zero & zeroI // 7. zero = zero AND zero_i - // 3. i = 2 - signI = nonMont.A1[0] % 2 // 4. sign_i = x_i mod 2 - // 5. zero_i = x_i == 0 - sign = sign | (zero & signI) // 6. sign = sign OR (zero AND sign_i) # Avoid short-circuit logic ops - // 7. zero = zero AND zero_i - return sign - -} - -// MapToG2 invokes the SSWU map, and guarantees that the result is in g2 -func MapToG2(u fptower.E2) G2Affine { - res := MapToCurve2(&u) - //this is in an isogenous curve - g2Isogeny(&res) - res.ClearCofactor(&res) - return res -} - -// EncodeToG2 hashes a message to a point on the G2 curve using the SSWU map. -// It is faster than HashToG2, but the result is not uniformly distributed. Unsuitable as a random oracle. -// dst stands for "domain separation tag", a string unique to the construction using the hash function -// https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#roadmap -func EncodeToG2(msg, dst []byte) (G2Affine, error) { - - var res G2Affine - u, err := fp.Hash(msg, dst, 2) - if err != nil { - return res, err - } - - res = MapToCurve2(&fptower.E2{ - A0: u[0], - A1: u[1], - }) - - //this is in an isogenous curve - g2Isogeny(&res) - res.ClearCofactor(&res) - return res, nil -} - -// HashToG2 hashes a message to a point on the G2 curve using the SSWU map. -// Slower than EncodeToG2, but usable as a random oracle. -// dst stands for "domain separation tag", a string unique to the construction using the hash function -// https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#roadmap -func HashToG2(msg, dst []byte) (G2Affine, error) { - u, err := fp.Hash(msg, dst, 2*2) - if err != nil { - return G2Affine{}, err - } - - Q0 := MapToCurve2(&fptower.E2{ - A0: u[0], - A1: u[1], - }) - Q1 := MapToCurve2(&fptower.E2{ - A0: u[2+0], - A1: u[2+1], - }) - - //TODO (perf): Add in E' first, then apply isogeny - g2Isogeny(&Q0) - g2Isogeny(&Q1) - - var _Q0, _Q1 G2Jac - _Q0.FromAffine(&Q0) - _Q1.FromAffine(&Q1).AddAssign(&_Q0) - - _Q1.ClearCofactor(&_Q1) - - Q1.FromJacobian(&_Q1) - return Q1, nil -} - -func g2NotZero(x *fptower.E2) uint64 { - //Assuming G1 is over Fp and that if hashing is available for G2, it also is for G1 - return g1NotZero(&x.A0) | g1NotZero(&x.A1) - -} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/asm.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/asm.go index 49751a93969..83956e0b4c0 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/asm.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/asm.go @@ -1,28 +1,16 @@ //go:build !noadx -// +build !noadx -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT package fptower -import "golang.org/x/sys/cpu" +import "github.com/consensys/gnark-crypto/utils/cpu" // supportAdx will be set only on amd64 that has MULX and ADDX instructions var ( - supportAdx = cpu.X86.HasADX && cpu.X86.HasBMI2 + supportAdx = cpu.SupportADX _ = supportAdx // used in asm ) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/asm_noadx.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/asm_noadx.go index c6a97081fca..1dc20b49918 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/asm_noadx.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/asm_noadx.go @@ -1,19 +1,7 @@ //go:build noadx -// +build noadx -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e12.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e12.go index 095a79a4c09..4a32bf25539 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e12.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e12.go @@ -1,16 +1,5 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -67,14 +56,14 @@ func (z *E12) SetOne() *E12 { return z } -// Add set z=x+y in E12 and return z +// Add sets z=x+y in E12 and returns z func (z *E12) Add(x, y *E12) *E12 { z.C0.Add(&x.C0, &y.C0) z.C1.Add(&x.C1, &y.C1) return z } -// Sub sets z to x sub y and return z +// Sub sets z to x-y and returns z func (z *E12) Sub(x, y *E12) *E12 { z.C0.Sub(&x.C0, &y.C0) z.C1.Sub(&x.C1, &y.C1) @@ -99,16 +88,25 @@ func (z *E12) SetRandom() (*E12, error) { return z, nil } -// IsZero returns true if the two elements are equal, false otherwise +// MustSetRandom sets a0 and a1 to random values. +// It panics if reading form crypto/rand fails +func (z *E12) MustSetRandom() { + if _, err := z.SetRandom(); err != nil { + panic(err) + } +} + +// IsZero returns true if z is zero, false otherwise func (z *E12) IsZero() bool { return z.C0.IsZero() && z.C1.IsZero() } +// IsOne returns true if z is one, false otherwise func (z *E12) IsOne() bool { return z.C0.IsOne() && z.C1.IsZero() } -// Mul set z=x*y in E12 and return z +// Mul sets z=x*y in E12 and returns z func (z *E12) Mul(x, y *E12) *E12 { var a, b, c E6 a.Add(&x.C0, &x.C1) @@ -121,7 +119,7 @@ func (z *E12) Mul(x, y *E12) *E12 { return z } -// Square set z=x*x in E12 and return z +// Square sets z=x*x in E12 and returns z func (z *E12) Square(x *E12) *E12 { //Algorithm 22 from https://eprint.iacr.org/2010/354.pdf @@ -406,7 +404,7 @@ func (z *E12) CyclotomicSquare(x *E12) *E12 { return z } -// Inverse set z to the inverse of x in E12 and return z +// Inverse sets z to the inverse of x in E12 and returns z // // if x == 0, sets and returns z = x func (z *E12) Inverse(x *E12) *E12 { @@ -424,8 +422,8 @@ func (z *E12) Inverse(x *E12) *E12 { return z } -// BatchInvertE12 returns a new slice with every element inverted. -// Uses Montgomery batch inversion trick +// BatchInvertE12 returns a new slice with every element in a inverted. +// It uses Montgomery batch inversion trick. // // if a[i] == 0, returns result[i] = a[i] func BatchInvertE12(a []E12) []E12 { @@ -635,12 +633,12 @@ func (z *E12) ExpGLV(x E12, k *big.Int) *E12 { return z } -// InverseUnitary inverse a unitary element +// InverseUnitary inverses a unitary element func (z *E12) InverseUnitary(x *E12) *E12 { return z.Conjugate(x) } -// Conjugate set z to x conjugated and return z +// Conjugate sets z to x conjugated and returns z func (z *E12) Conjugate(x *E12) *E12 { *z = *x z.C1.Neg(&z.C1) @@ -846,6 +844,8 @@ func BatchDecompressTorus(x []E6) ([]E12, error) { return res, nil } +// Select is conditional move. +// If cond = 0, it sets z to caseZ and returns it. otherwise caseNz. func (z *E12) Select(cond int, caseZ *E12, caseNz *E12) *E12 { //Might be able to save a nanosecond or two by an aggregate implementation @@ -855,6 +855,7 @@ func (z *E12) Select(cond int, caseZ *E12, caseNz *E12) *E12 { return z } +// Div divides an element in E12 by an element in E12 func (z *E12) Div(x *E12, y *E12) *E12 { var r E12 r.Inverse(y).Mul(x, &r) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e12_pairing.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e12_pairing.go index 880520f815f..035f26e73b2 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e12_pairing.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e12_pairing.go @@ -66,6 +66,28 @@ func (z *E12) MulBy014(c0, c1, c4 *E2) *E12 { return z } +// MulBy01 multiplication by sparse element (c0, c1, 0, 0, 1) +func (z *E12) MulBy01(c0, c1 *E2) *E12 { + + var a, b E6 + var d E2 + + a.Set(&z.C0) + a.MulBy01(c0, c1) + + b.MulByNonResidue(&z.C1) + d.SetOne().Add(c1, &d) + + z.C1.Add(&z.C1, &z.C0) + z.C1.MulBy01(c0, &d) + z.C1.Sub(&z.C1, &a) + z.C1.Sub(&z.C1, &b) + z.C0.MulByNonResidue(&b) + z.C0.Add(&z.C0, &a) + + return z +} + // Mul014By014 multiplication of sparse element (c0,c1,0,0,c4,0) by sparse element (d0,d1,0,0,d4,0) func Mul014By014(d0, d1, d4, c0, c1, c4 *E2) [5]E2 { var z00, tmp, x0, x1, x4, x04, x01, x14 E2 @@ -94,6 +116,26 @@ func Mul014By014(d0, d1, d4, c0, c1, c4 *E2) [5]E2 { return [5]E2{z00, x01, x1, x04, x14} } +// Mul01By01 multiplication of sparse element (c0,c1,0,0,1,0) by sparse element (d0,d1,0,0,1,0) +func Mul01By01(d0, d1, c0, c1 *E2) [5]E2 { + var z00, tmp, x0, x1, x4, x04, x01, x14 E2 + x0.Mul(c0, d0) + x1.Mul(c1, d1) + x4.SetOne() + x04.Add(d0, c0) + tmp.Add(c0, c1) + x01.Add(d0, d1). + Mul(&x01, &tmp). + Sub(&x01, &x0). + Sub(&x01, &x1) + x14.Add(d1, c1) + + z00.MulByNonResidue(&x4). + Add(&z00, &x0) + + return [5]E2{z00, x01, x1, x04, x14} +} + // MulBy01245 multiplies z by an E12 sparse element of the form (x0, x1, x2, 0, x4, x5) func (z *E12) MulBy01245(x *[5]E2) *E12 { var c1, a, b, c, z0, z1 E6 diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e2.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e2.go index 0390e7e4b34..3e50a6380e1 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e2.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e2.go @@ -1,16 +1,5 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -101,11 +90,20 @@ func (z *E2) SetRandom() (*E2, error) { return z, nil } -// IsZero returns true if the two elements are equal, false otherwise +// MustSetRandom sets a0 and a1 to random values. +// It panics if reading form crypto/rand fails +func (z *E2) MustSetRandom() { + if _, err := z.SetRandom(); err != nil { + panic(err) + } +} + +// IsZero returns true if z is zero, false otherwise func (z *E2) IsZero() bool { return z.A0.IsZero() && z.A1.IsZero() } +// IsOne returns true if z is one, false otherwise func (z *E2) IsOne() bool { return z.A0.IsOne() && z.A1.IsZero() } @@ -116,7 +114,7 @@ func (z *E2) Add(x, y *E2) *E2 { return z } -// Sub two elements of E2 +// Sub subtracts two elements of E2 func (z *E2) Sub(x, y *E2) *E2 { subE2(z, x, y) return z @@ -155,7 +153,7 @@ func (z *E2) Conjugate(x *E2) *E2 { return z } -// Halve sets z = z / 2 +// Halve sets z to z / 2 func (z *E2) Halve() { z.A0.Halve() z.A1.Halve() @@ -213,7 +211,7 @@ func init() { var sqrtExp1, sqrtExp2 big.Int -// Sqrt sets z to the square root of and returns z +// Sqrt sets z to the square root of x and returns z // The function does not test whether the square root // exists or not, it's up to the caller to call // Legendre beforehand. @@ -243,8 +241,8 @@ func (z *E2) Sqrt(x *E2) *E2 { return z } -// BatchInvertE2 returns a new slice with every element inverted. -// Uses Montgomery batch inversion trick +// BatchInvertE2 returns a new slice with every element in a inverted. +// It uses Montgomery batch inversion trick. // // if a[i] == 0, returns result[i] = a[i] func BatchInvertE2(a []E2) []E2 { @@ -279,6 +277,8 @@ func BatchInvertE2(a []E2) []E2 { return res } +// Select is conditional move. +// If cond = 0, it sets z to caseZ and returns it. otherwise caseNz. func (z *E2) Select(cond int, caseZ *E2, caseNz *E2) *E2 { //Might be able to save a nanosecond or two by an aggregate implementation @@ -288,6 +288,7 @@ func (z *E2) Select(cond int, caseZ *E2, caseNz *E2) *E2 { return z } +// Div divides an element in E2 by an element in E2 func (z *E2) Div(x *E2, y *E2) *E2 { var r E2 r.Inverse(y).Mul(x, &r) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e2_amd64.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e2_amd64.go index 5121f7cca2b..f0acaeab06c 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e2_amd64.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e2_amd64.go @@ -1,21 +1,37 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT package fptower +import ( + "github.com/consensys/gnark-crypto/ecc/bls12-381/fp" +) + +// q + r'.r = 1, i.e., qInvNeg = - q⁻¹ mod r +// used for Montgomery reduction +const qInvNeg uint64 = 9940570264628428797 + +// Field modulus q (Fp) +const ( + q0 uint64 = 13402431016077863595 + q1 uint64 = 2210141511517208575 + q2 uint64 = 7435674573564081700 + q3 uint64 = 7239337960414712511 + q4 uint64 = 5412103778470702295 + q5 uint64 = 1873798617647539866 +) + +var qElement = fp.Element{ + q0, + q1, + q2, + q3, + q4, + q5, +} + //go:noescape func addE2(res, x, y *E2) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e2_amd64.s b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e2_amd64.s index 7fc53f46338..d38ef3b2198 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e2_amd64.s +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e2_amd64.s @@ -1,52 +1,29 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. #include "textflag.h" #include "funcdata.h" - -// modulus q -DATA q<>+0(SB)/8, $0xb9feffffffffaaab -DATA q<>+8(SB)/8, $0x1eabfffeb153ffff -DATA q<>+16(SB)/8, $0x6730d2a0f6b0f624 -DATA q<>+24(SB)/8, $0x64774b84f38512bf -DATA q<>+32(SB)/8, $0x4b1ba7b6434bacd7 -DATA q<>+40(SB)/8, $0x1a0111ea397fe69a -GLOBL q<>(SB), (RODATA+NOPTR), $48 - -// qInv0 q'[0] -DATA qInv0<>(SB)/8, $0x89f3fffcfffcfffd -GLOBL qInv0<>(SB), (RODATA+NOPTR), $8 +#include "go_asm.h" #define REDUCE(ra0, ra1, ra2, ra3, ra4, ra5, rb0, rb1, rb2, rb3, rb4, rb5) \ - MOVQ ra0, rb0; \ - SUBQ q<>(SB), ra0; \ - MOVQ ra1, rb1; \ - SBBQ q<>+8(SB), ra1; \ - MOVQ ra2, rb2; \ - SBBQ q<>+16(SB), ra2; \ - MOVQ ra3, rb3; \ - SBBQ q<>+24(SB), ra3; \ - MOVQ ra4, rb4; \ - SBBQ q<>+32(SB), ra4; \ - MOVQ ra5, rb5; \ - SBBQ q<>+40(SB), ra5; \ - CMOVQCS rb0, ra0; \ - CMOVQCS rb1, ra1; \ - CMOVQCS rb2, ra2; \ - CMOVQCS rb3, ra3; \ - CMOVQCS rb4, ra4; \ - CMOVQCS rb5, ra5; \ + MOVQ ra0, rb0; \ + SUBQ ·qElement(SB), ra0; \ + MOVQ ra1, rb1; \ + SBBQ ·qElement+8(SB), ra1; \ + MOVQ ra2, rb2; \ + SBBQ ·qElement+16(SB), ra2; \ + MOVQ ra3, rb3; \ + SBBQ ·qElement+24(SB), ra3; \ + MOVQ ra4, rb4; \ + SBBQ ·qElement+32(SB), ra4; \ + MOVQ ra5, rb5; \ + SBBQ ·qElement+40(SB), ra5; \ + CMOVQCS rb0, ra0; \ + CMOVQCS rb1, ra1; \ + CMOVQCS rb2, ra2; \ + CMOVQCS rb3, ra3; \ + CMOVQCS rb4, ra4; \ + CMOVQCS rb5, ra5; \ TEXT ·addE2(SB), NOSPLIT, $0-24 MOVQ x+8(FP), AX @@ -421,496 +398,79 @@ TEXT ·squareAdxE2(SB), $48-16 // t[3] -> R11 // t[4] -> R12 // t[5] -> R13 - // clear the flags - XORQ AX, AX +#define MACC(in0, in1, in2) \ + ADCXQ in0, in1 \ + MULXQ in2, AX, in0 \ + ADOXQ AX, in1 \ + +#define DIV_SHIFT() \ + PUSHQ BP \ + MOVQ $const_qInvNeg, DX \ + IMULQ R8, DX \ + XORQ AX, AX \ + MULXQ ·qElement+0(SB), AX, BP \ + ADCXQ R8, AX \ + MOVQ BP, R8 \ + POPQ BP \ + MACC(R9, R8, ·qElement+8(SB)) \ + MACC(R10, R9, ·qElement+16(SB)) \ + MACC(R11, R10, ·qElement+24(SB)) \ + MACC(R12, R11, ·qElement+32(SB)) \ + MACC(R13, R12, ·qElement+40(SB)) \ + MOVQ $0, AX \ + ADCXQ AX, R13 \ + ADOXQ BP, R13 \ + +#define MUL_WORD_0() \ + XORQ AX, AX \ + MULXQ R14, R8, R9 \ + MULXQ R15, AX, R10 \ + ADOXQ AX, R9 \ + MULXQ CX, AX, R11 \ + ADOXQ AX, R10 \ + MULXQ BX, AX, R12 \ + ADOXQ AX, R11 \ + MULXQ SI, AX, R13 \ + ADOXQ AX, R12 \ + MULXQ DI, AX, BP \ + ADOXQ AX, R13 \ + MOVQ $0, AX \ + ADOXQ AX, BP \ + DIV_SHIFT() \ + +#define MUL_WORD_N() \ + XORQ AX, AX \ + MULXQ R14, AX, BP \ + ADOXQ AX, R8 \ + MACC(BP, R9, R15) \ + MACC(BP, R10, CX) \ + MACC(BP, R11, BX) \ + MACC(BP, R12, SI) \ + MACC(BP, R13, DI) \ + MOVQ $0, AX \ + ADCXQ AX, BP \ + ADOXQ AX, BP \ + DIV_SHIFT() \ + + // mul body MOVQ x+8(FP), DX MOVQ 0(DX), DX - - // (A,t[0]) := x[0]*y[0] + A - MULXQ R14, R8, R9 - - // (A,t[1]) := x[1]*y[0] + A - MULXQ R15, AX, R10 - ADOXQ AX, R9 - - // (A,t[2]) := x[2]*y[0] + A - MULXQ CX, AX, R11 - ADOXQ AX, R10 - - // (A,t[3]) := x[3]*y[0] + A - MULXQ BX, AX, R12 - ADOXQ AX, R11 - - // (A,t[4]) := x[4]*y[0] + A - MULXQ SI, AX, R13 - ADOXQ AX, R12 - - // (A,t[5]) := x[5]*y[0] + A - MULXQ DI, AX, BP - ADOXQ AX, R13 - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADOXQ AX, BP - PUSHQ BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R8, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R8, AX - MOVQ BP, R8 - POPQ BP - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R9, R8 - MULXQ q<>+8(SB), AX, R9 - ADOXQ AX, R8 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ R10, R9 - MULXQ q<>+16(SB), AX, R10 - ADOXQ AX, R9 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ R11, R10 - MULXQ q<>+24(SB), AX, R11 - ADOXQ AX, R10 - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ R12, R11 - MULXQ q<>+32(SB), AX, R12 - ADOXQ AX, R11 - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ R13, R12 - MULXQ q<>+40(SB), AX, R13 - ADOXQ AX, R12 - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, R13 - ADOXQ BP, R13 - - // clear the flags - XORQ AX, AX + MUL_WORD_0() MOVQ x+8(FP), DX MOVQ 8(DX), DX - - // (A,t[0]) := t[0] + x[0]*y[1] + A - MULXQ R14, AX, BP - ADOXQ AX, R8 - - // (A,t[1]) := t[1] + x[1]*y[1] + A - ADCXQ BP, R9 - MULXQ R15, AX, BP - ADOXQ AX, R9 - - // (A,t[2]) := t[2] + x[2]*y[1] + A - ADCXQ BP, R10 - MULXQ CX, AX, BP - ADOXQ AX, R10 - - // (A,t[3]) := t[3] + x[3]*y[1] + A - ADCXQ BP, R11 - MULXQ BX, AX, BP - ADOXQ AX, R11 - - // (A,t[4]) := t[4] + x[4]*y[1] + A - ADCXQ BP, R12 - MULXQ SI, AX, BP - ADOXQ AX, R12 - - // (A,t[5]) := t[5] + x[5]*y[1] + A - ADCXQ BP, R13 - MULXQ DI, AX, BP - ADOXQ AX, R13 - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - PUSHQ BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R8, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R8, AX - MOVQ BP, R8 - POPQ BP - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R9, R8 - MULXQ q<>+8(SB), AX, R9 - ADOXQ AX, R8 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ R10, R9 - MULXQ q<>+16(SB), AX, R10 - ADOXQ AX, R9 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ R11, R10 - MULXQ q<>+24(SB), AX, R11 - ADOXQ AX, R10 - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ R12, R11 - MULXQ q<>+32(SB), AX, R12 - ADOXQ AX, R11 - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ R13, R12 - MULXQ q<>+40(SB), AX, R13 - ADOXQ AX, R12 - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, R13 - ADOXQ BP, R13 - - // clear the flags - XORQ AX, AX + MUL_WORD_N() MOVQ x+8(FP), DX MOVQ 16(DX), DX - - // (A,t[0]) := t[0] + x[0]*y[2] + A - MULXQ R14, AX, BP - ADOXQ AX, R8 - - // (A,t[1]) := t[1] + x[1]*y[2] + A - ADCXQ BP, R9 - MULXQ R15, AX, BP - ADOXQ AX, R9 - - // (A,t[2]) := t[2] + x[2]*y[2] + A - ADCXQ BP, R10 - MULXQ CX, AX, BP - ADOXQ AX, R10 - - // (A,t[3]) := t[3] + x[3]*y[2] + A - ADCXQ BP, R11 - MULXQ BX, AX, BP - ADOXQ AX, R11 - - // (A,t[4]) := t[4] + x[4]*y[2] + A - ADCXQ BP, R12 - MULXQ SI, AX, BP - ADOXQ AX, R12 - - // (A,t[5]) := t[5] + x[5]*y[2] + A - ADCXQ BP, R13 - MULXQ DI, AX, BP - ADOXQ AX, R13 - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - PUSHQ BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R8, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R8, AX - MOVQ BP, R8 - POPQ BP - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R9, R8 - MULXQ q<>+8(SB), AX, R9 - ADOXQ AX, R8 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ R10, R9 - MULXQ q<>+16(SB), AX, R10 - ADOXQ AX, R9 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ R11, R10 - MULXQ q<>+24(SB), AX, R11 - ADOXQ AX, R10 - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ R12, R11 - MULXQ q<>+32(SB), AX, R12 - ADOXQ AX, R11 - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ R13, R12 - MULXQ q<>+40(SB), AX, R13 - ADOXQ AX, R12 - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, R13 - ADOXQ BP, R13 - - // clear the flags - XORQ AX, AX + MUL_WORD_N() MOVQ x+8(FP), DX MOVQ 24(DX), DX - - // (A,t[0]) := t[0] + x[0]*y[3] + A - MULXQ R14, AX, BP - ADOXQ AX, R8 - - // (A,t[1]) := t[1] + x[1]*y[3] + A - ADCXQ BP, R9 - MULXQ R15, AX, BP - ADOXQ AX, R9 - - // (A,t[2]) := t[2] + x[2]*y[3] + A - ADCXQ BP, R10 - MULXQ CX, AX, BP - ADOXQ AX, R10 - - // (A,t[3]) := t[3] + x[3]*y[3] + A - ADCXQ BP, R11 - MULXQ BX, AX, BP - ADOXQ AX, R11 - - // (A,t[4]) := t[4] + x[4]*y[3] + A - ADCXQ BP, R12 - MULXQ SI, AX, BP - ADOXQ AX, R12 - - // (A,t[5]) := t[5] + x[5]*y[3] + A - ADCXQ BP, R13 - MULXQ DI, AX, BP - ADOXQ AX, R13 - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - PUSHQ BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R8, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R8, AX - MOVQ BP, R8 - POPQ BP - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R9, R8 - MULXQ q<>+8(SB), AX, R9 - ADOXQ AX, R8 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ R10, R9 - MULXQ q<>+16(SB), AX, R10 - ADOXQ AX, R9 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ R11, R10 - MULXQ q<>+24(SB), AX, R11 - ADOXQ AX, R10 - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ R12, R11 - MULXQ q<>+32(SB), AX, R12 - ADOXQ AX, R11 - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ R13, R12 - MULXQ q<>+40(SB), AX, R13 - ADOXQ AX, R12 - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, R13 - ADOXQ BP, R13 - - // clear the flags - XORQ AX, AX + MUL_WORD_N() MOVQ x+8(FP), DX MOVQ 32(DX), DX - - // (A,t[0]) := t[0] + x[0]*y[4] + A - MULXQ R14, AX, BP - ADOXQ AX, R8 - - // (A,t[1]) := t[1] + x[1]*y[4] + A - ADCXQ BP, R9 - MULXQ R15, AX, BP - ADOXQ AX, R9 - - // (A,t[2]) := t[2] + x[2]*y[4] + A - ADCXQ BP, R10 - MULXQ CX, AX, BP - ADOXQ AX, R10 - - // (A,t[3]) := t[3] + x[3]*y[4] + A - ADCXQ BP, R11 - MULXQ BX, AX, BP - ADOXQ AX, R11 - - // (A,t[4]) := t[4] + x[4]*y[4] + A - ADCXQ BP, R12 - MULXQ SI, AX, BP - ADOXQ AX, R12 - - // (A,t[5]) := t[5] + x[5]*y[4] + A - ADCXQ BP, R13 - MULXQ DI, AX, BP - ADOXQ AX, R13 - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - PUSHQ BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R8, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R8, AX - MOVQ BP, R8 - POPQ BP - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R9, R8 - MULXQ q<>+8(SB), AX, R9 - ADOXQ AX, R8 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ R10, R9 - MULXQ q<>+16(SB), AX, R10 - ADOXQ AX, R9 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ R11, R10 - MULXQ q<>+24(SB), AX, R11 - ADOXQ AX, R10 - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ R12, R11 - MULXQ q<>+32(SB), AX, R12 - ADOXQ AX, R11 - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ R13, R12 - MULXQ q<>+40(SB), AX, R13 - ADOXQ AX, R12 - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, R13 - ADOXQ BP, R13 - - // clear the flags - XORQ AX, AX + MUL_WORD_N() MOVQ x+8(FP), DX MOVQ 40(DX), DX - - // (A,t[0]) := t[0] + x[0]*y[5] + A - MULXQ R14, AX, BP - ADOXQ AX, R8 - - // (A,t[1]) := t[1] + x[1]*y[5] + A - ADCXQ BP, R9 - MULXQ R15, AX, BP - ADOXQ AX, R9 - - // (A,t[2]) := t[2] + x[2]*y[5] + A - ADCXQ BP, R10 - MULXQ CX, AX, BP - ADOXQ AX, R10 - - // (A,t[3]) := t[3] + x[3]*y[5] + A - ADCXQ BP, R11 - MULXQ BX, AX, BP - ADOXQ AX, R11 - - // (A,t[4]) := t[4] + x[4]*y[5] + A - ADCXQ BP, R12 - MULXQ SI, AX, BP - ADOXQ AX, R12 - - // (A,t[5]) := t[5] + x[5]*y[5] + A - ADCXQ BP, R13 - MULXQ DI, AX, BP - ADOXQ AX, R13 - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - PUSHQ BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R8, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R8, AX - MOVQ BP, R8 - POPQ BP - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R9, R8 - MULXQ q<>+8(SB), AX, R9 - ADOXQ AX, R8 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ R10, R9 - MULXQ q<>+16(SB), AX, R10 - ADOXQ AX, R9 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ R11, R10 - MULXQ q<>+24(SB), AX, R11 - ADOXQ AX, R10 - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ R12, R11 - MULXQ q<>+32(SB), AX, R12 - ADOXQ AX, R11 - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ R13, R12 - MULXQ q<>+40(SB), AX, R13 - ADOXQ AX, R12 - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, R13 - ADOXQ BP, R13 + MUL_WORD_N() // reduce element(R8,R9,R10,R11,R12,R13) using temp registers (R14,R15,CX,BX,SI,DI) REDUCE(R8,R9,R10,R11,R12,R13,R14,R15,CX,BX,SI,DI) @@ -997,490 +557,19 @@ TEXT ·squareAdxE2(SB), $48-16 // t[3] -> R11 // t[4] -> R12 // t[5] -> R13 - // clear the flags - XORQ AX, AX + // mul body MOVQ s0-8(SP), DX - - // (A,t[0]) := x[0]*y[0] + A - MULXQ R14, R8, R9 - - // (A,t[1]) := x[1]*y[0] + A - MULXQ R15, AX, R10 - ADOXQ AX, R9 - - // (A,t[2]) := x[2]*y[0] + A - MULXQ CX, AX, R11 - ADOXQ AX, R10 - - // (A,t[3]) := x[3]*y[0] + A - MULXQ BX, AX, R12 - ADOXQ AX, R11 - - // (A,t[4]) := x[4]*y[0] + A - MULXQ SI, AX, R13 - ADOXQ AX, R12 - - // (A,t[5]) := x[5]*y[0] + A - MULXQ DI, AX, BP - ADOXQ AX, R13 - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADOXQ AX, BP - PUSHQ BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R8, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R8, AX - MOVQ BP, R8 - POPQ BP - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R9, R8 - MULXQ q<>+8(SB), AX, R9 - ADOXQ AX, R8 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ R10, R9 - MULXQ q<>+16(SB), AX, R10 - ADOXQ AX, R9 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ R11, R10 - MULXQ q<>+24(SB), AX, R11 - ADOXQ AX, R10 - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ R12, R11 - MULXQ q<>+32(SB), AX, R12 - ADOXQ AX, R11 - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ R13, R12 - MULXQ q<>+40(SB), AX, R13 - ADOXQ AX, R12 - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, R13 - ADOXQ BP, R13 - - // clear the flags - XORQ AX, AX + MUL_WORD_0() MOVQ s1-16(SP), DX - - // (A,t[0]) := t[0] + x[0]*y[1] + A - MULXQ R14, AX, BP - ADOXQ AX, R8 - - // (A,t[1]) := t[1] + x[1]*y[1] + A - ADCXQ BP, R9 - MULXQ R15, AX, BP - ADOXQ AX, R9 - - // (A,t[2]) := t[2] + x[2]*y[1] + A - ADCXQ BP, R10 - MULXQ CX, AX, BP - ADOXQ AX, R10 - - // (A,t[3]) := t[3] + x[3]*y[1] + A - ADCXQ BP, R11 - MULXQ BX, AX, BP - ADOXQ AX, R11 - - // (A,t[4]) := t[4] + x[4]*y[1] + A - ADCXQ BP, R12 - MULXQ SI, AX, BP - ADOXQ AX, R12 - - // (A,t[5]) := t[5] + x[5]*y[1] + A - ADCXQ BP, R13 - MULXQ DI, AX, BP - ADOXQ AX, R13 - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - PUSHQ BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R8, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R8, AX - MOVQ BP, R8 - POPQ BP - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R9, R8 - MULXQ q<>+8(SB), AX, R9 - ADOXQ AX, R8 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ R10, R9 - MULXQ q<>+16(SB), AX, R10 - ADOXQ AX, R9 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ R11, R10 - MULXQ q<>+24(SB), AX, R11 - ADOXQ AX, R10 - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ R12, R11 - MULXQ q<>+32(SB), AX, R12 - ADOXQ AX, R11 - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ R13, R12 - MULXQ q<>+40(SB), AX, R13 - ADOXQ AX, R12 - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, R13 - ADOXQ BP, R13 - - // clear the flags - XORQ AX, AX + MUL_WORD_N() MOVQ s2-24(SP), DX - - // (A,t[0]) := t[0] + x[0]*y[2] + A - MULXQ R14, AX, BP - ADOXQ AX, R8 - - // (A,t[1]) := t[1] + x[1]*y[2] + A - ADCXQ BP, R9 - MULXQ R15, AX, BP - ADOXQ AX, R9 - - // (A,t[2]) := t[2] + x[2]*y[2] + A - ADCXQ BP, R10 - MULXQ CX, AX, BP - ADOXQ AX, R10 - - // (A,t[3]) := t[3] + x[3]*y[2] + A - ADCXQ BP, R11 - MULXQ BX, AX, BP - ADOXQ AX, R11 - - // (A,t[4]) := t[4] + x[4]*y[2] + A - ADCXQ BP, R12 - MULXQ SI, AX, BP - ADOXQ AX, R12 - - // (A,t[5]) := t[5] + x[5]*y[2] + A - ADCXQ BP, R13 - MULXQ DI, AX, BP - ADOXQ AX, R13 - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - PUSHQ BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R8, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R8, AX - MOVQ BP, R8 - POPQ BP - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R9, R8 - MULXQ q<>+8(SB), AX, R9 - ADOXQ AX, R8 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ R10, R9 - MULXQ q<>+16(SB), AX, R10 - ADOXQ AX, R9 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ R11, R10 - MULXQ q<>+24(SB), AX, R11 - ADOXQ AX, R10 - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ R12, R11 - MULXQ q<>+32(SB), AX, R12 - ADOXQ AX, R11 - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ R13, R12 - MULXQ q<>+40(SB), AX, R13 - ADOXQ AX, R12 - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, R13 - ADOXQ BP, R13 - - // clear the flags - XORQ AX, AX + MUL_WORD_N() MOVQ s3-32(SP), DX - - // (A,t[0]) := t[0] + x[0]*y[3] + A - MULXQ R14, AX, BP - ADOXQ AX, R8 - - // (A,t[1]) := t[1] + x[1]*y[3] + A - ADCXQ BP, R9 - MULXQ R15, AX, BP - ADOXQ AX, R9 - - // (A,t[2]) := t[2] + x[2]*y[3] + A - ADCXQ BP, R10 - MULXQ CX, AX, BP - ADOXQ AX, R10 - - // (A,t[3]) := t[3] + x[3]*y[3] + A - ADCXQ BP, R11 - MULXQ BX, AX, BP - ADOXQ AX, R11 - - // (A,t[4]) := t[4] + x[4]*y[3] + A - ADCXQ BP, R12 - MULXQ SI, AX, BP - ADOXQ AX, R12 - - // (A,t[5]) := t[5] + x[5]*y[3] + A - ADCXQ BP, R13 - MULXQ DI, AX, BP - ADOXQ AX, R13 - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - PUSHQ BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R8, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R8, AX - MOVQ BP, R8 - POPQ BP - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R9, R8 - MULXQ q<>+8(SB), AX, R9 - ADOXQ AX, R8 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ R10, R9 - MULXQ q<>+16(SB), AX, R10 - ADOXQ AX, R9 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ R11, R10 - MULXQ q<>+24(SB), AX, R11 - ADOXQ AX, R10 - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ R12, R11 - MULXQ q<>+32(SB), AX, R12 - ADOXQ AX, R11 - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ R13, R12 - MULXQ q<>+40(SB), AX, R13 - ADOXQ AX, R12 - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, R13 - ADOXQ BP, R13 - - // clear the flags - XORQ AX, AX + MUL_WORD_N() MOVQ s4-40(SP), DX - - // (A,t[0]) := t[0] + x[0]*y[4] + A - MULXQ R14, AX, BP - ADOXQ AX, R8 - - // (A,t[1]) := t[1] + x[1]*y[4] + A - ADCXQ BP, R9 - MULXQ R15, AX, BP - ADOXQ AX, R9 - - // (A,t[2]) := t[2] + x[2]*y[4] + A - ADCXQ BP, R10 - MULXQ CX, AX, BP - ADOXQ AX, R10 - - // (A,t[3]) := t[3] + x[3]*y[4] + A - ADCXQ BP, R11 - MULXQ BX, AX, BP - ADOXQ AX, R11 - - // (A,t[4]) := t[4] + x[4]*y[4] + A - ADCXQ BP, R12 - MULXQ SI, AX, BP - ADOXQ AX, R12 - - // (A,t[5]) := t[5] + x[5]*y[4] + A - ADCXQ BP, R13 - MULXQ DI, AX, BP - ADOXQ AX, R13 - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - PUSHQ BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R8, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R8, AX - MOVQ BP, R8 - POPQ BP - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R9, R8 - MULXQ q<>+8(SB), AX, R9 - ADOXQ AX, R8 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ R10, R9 - MULXQ q<>+16(SB), AX, R10 - ADOXQ AX, R9 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ R11, R10 - MULXQ q<>+24(SB), AX, R11 - ADOXQ AX, R10 - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ R12, R11 - MULXQ q<>+32(SB), AX, R12 - ADOXQ AX, R11 - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ R13, R12 - MULXQ q<>+40(SB), AX, R13 - ADOXQ AX, R12 - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, R13 - ADOXQ BP, R13 - - // clear the flags - XORQ AX, AX + MUL_WORD_N() MOVQ s5-48(SP), DX - - // (A,t[0]) := t[0] + x[0]*y[5] + A - MULXQ R14, AX, BP - ADOXQ AX, R8 - - // (A,t[1]) := t[1] + x[1]*y[5] + A - ADCXQ BP, R9 - MULXQ R15, AX, BP - ADOXQ AX, R9 - - // (A,t[2]) := t[2] + x[2]*y[5] + A - ADCXQ BP, R10 - MULXQ CX, AX, BP - ADOXQ AX, R10 - - // (A,t[3]) := t[3] + x[3]*y[5] + A - ADCXQ BP, R11 - MULXQ BX, AX, BP - ADOXQ AX, R11 - - // (A,t[4]) := t[4] + x[4]*y[5] + A - ADCXQ BP, R12 - MULXQ SI, AX, BP - ADOXQ AX, R12 - - // (A,t[5]) := t[5] + x[5]*y[5] + A - ADCXQ BP, R13 - MULXQ DI, AX, BP - ADOXQ AX, R13 - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - PUSHQ BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R8, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R8, AX - MOVQ BP, R8 - POPQ BP - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R9, R8 - MULXQ q<>+8(SB), AX, R9 - ADOXQ AX, R8 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ R10, R9 - MULXQ q<>+16(SB), AX, R10 - ADOXQ AX, R9 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ R11, R10 - MULXQ q<>+24(SB), AX, R11 - ADOXQ AX, R10 - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ R12, R11 - MULXQ q<>+32(SB), AX, R12 - ADOXQ AX, R11 - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ R13, R12 - MULXQ q<>+40(SB), AX, R13 - ADOXQ AX, R12 - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, R13 - ADOXQ BP, R13 + MUL_WORD_N() // reduce element(R8,R9,R10,R11,R12,R13) using temp registers (R14,R15,CX,BX,SI,DI) REDUCE(R8,R9,R10,R11,R12,R13,R14,R15,CX,BX,SI,DI) @@ -1531,496 +620,25 @@ TEXT ·mulAdxE2(SB), $96-24 // t[3] -> R11 // t[4] -> R12 // t[5] -> R13 - // clear the flags - XORQ AX, AX + // mul body MOVQ y+16(FP), DX MOVQ 48(DX), DX - - // (A,t[0]) := x[0]*y[0] + A - MULXQ R14, R8, R9 - - // (A,t[1]) := x[1]*y[0] + A - MULXQ R15, AX, R10 - ADOXQ AX, R9 - - // (A,t[2]) := x[2]*y[0] + A - MULXQ CX, AX, R11 - ADOXQ AX, R10 - - // (A,t[3]) := x[3]*y[0] + A - MULXQ BX, AX, R12 - ADOXQ AX, R11 - - // (A,t[4]) := x[4]*y[0] + A - MULXQ SI, AX, R13 - ADOXQ AX, R12 - - // (A,t[5]) := x[5]*y[0] + A - MULXQ DI, AX, BP - ADOXQ AX, R13 - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADOXQ AX, BP - PUSHQ BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R8, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R8, AX - MOVQ BP, R8 - POPQ BP - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R9, R8 - MULXQ q<>+8(SB), AX, R9 - ADOXQ AX, R8 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ R10, R9 - MULXQ q<>+16(SB), AX, R10 - ADOXQ AX, R9 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ R11, R10 - MULXQ q<>+24(SB), AX, R11 - ADOXQ AX, R10 - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ R12, R11 - MULXQ q<>+32(SB), AX, R12 - ADOXQ AX, R11 - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ R13, R12 - MULXQ q<>+40(SB), AX, R13 - ADOXQ AX, R12 - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, R13 - ADOXQ BP, R13 - - // clear the flags - XORQ AX, AX + MUL_WORD_0() MOVQ y+16(FP), DX MOVQ 56(DX), DX - - // (A,t[0]) := t[0] + x[0]*y[1] + A - MULXQ R14, AX, BP - ADOXQ AX, R8 - - // (A,t[1]) := t[1] + x[1]*y[1] + A - ADCXQ BP, R9 - MULXQ R15, AX, BP - ADOXQ AX, R9 - - // (A,t[2]) := t[2] + x[2]*y[1] + A - ADCXQ BP, R10 - MULXQ CX, AX, BP - ADOXQ AX, R10 - - // (A,t[3]) := t[3] + x[3]*y[1] + A - ADCXQ BP, R11 - MULXQ BX, AX, BP - ADOXQ AX, R11 - - // (A,t[4]) := t[4] + x[4]*y[1] + A - ADCXQ BP, R12 - MULXQ SI, AX, BP - ADOXQ AX, R12 - - // (A,t[5]) := t[5] + x[5]*y[1] + A - ADCXQ BP, R13 - MULXQ DI, AX, BP - ADOXQ AX, R13 - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - PUSHQ BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R8, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R8, AX - MOVQ BP, R8 - POPQ BP - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R9, R8 - MULXQ q<>+8(SB), AX, R9 - ADOXQ AX, R8 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ R10, R9 - MULXQ q<>+16(SB), AX, R10 - ADOXQ AX, R9 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ R11, R10 - MULXQ q<>+24(SB), AX, R11 - ADOXQ AX, R10 - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ R12, R11 - MULXQ q<>+32(SB), AX, R12 - ADOXQ AX, R11 - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ R13, R12 - MULXQ q<>+40(SB), AX, R13 - ADOXQ AX, R12 - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, R13 - ADOXQ BP, R13 - - // clear the flags - XORQ AX, AX + MUL_WORD_N() MOVQ y+16(FP), DX MOVQ 64(DX), DX - - // (A,t[0]) := t[0] + x[0]*y[2] + A - MULXQ R14, AX, BP - ADOXQ AX, R8 - - // (A,t[1]) := t[1] + x[1]*y[2] + A - ADCXQ BP, R9 - MULXQ R15, AX, BP - ADOXQ AX, R9 - - // (A,t[2]) := t[2] + x[2]*y[2] + A - ADCXQ BP, R10 - MULXQ CX, AX, BP - ADOXQ AX, R10 - - // (A,t[3]) := t[3] + x[3]*y[2] + A - ADCXQ BP, R11 - MULXQ BX, AX, BP - ADOXQ AX, R11 - - // (A,t[4]) := t[4] + x[4]*y[2] + A - ADCXQ BP, R12 - MULXQ SI, AX, BP - ADOXQ AX, R12 - - // (A,t[5]) := t[5] + x[5]*y[2] + A - ADCXQ BP, R13 - MULXQ DI, AX, BP - ADOXQ AX, R13 - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - PUSHQ BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R8, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R8, AX - MOVQ BP, R8 - POPQ BP - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R9, R8 - MULXQ q<>+8(SB), AX, R9 - ADOXQ AX, R8 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ R10, R9 - MULXQ q<>+16(SB), AX, R10 - ADOXQ AX, R9 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ R11, R10 - MULXQ q<>+24(SB), AX, R11 - ADOXQ AX, R10 - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ R12, R11 - MULXQ q<>+32(SB), AX, R12 - ADOXQ AX, R11 - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ R13, R12 - MULXQ q<>+40(SB), AX, R13 - ADOXQ AX, R12 - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, R13 - ADOXQ BP, R13 - - // clear the flags - XORQ AX, AX + MUL_WORD_N() MOVQ y+16(FP), DX MOVQ 72(DX), DX - - // (A,t[0]) := t[0] + x[0]*y[3] + A - MULXQ R14, AX, BP - ADOXQ AX, R8 - - // (A,t[1]) := t[1] + x[1]*y[3] + A - ADCXQ BP, R9 - MULXQ R15, AX, BP - ADOXQ AX, R9 - - // (A,t[2]) := t[2] + x[2]*y[3] + A - ADCXQ BP, R10 - MULXQ CX, AX, BP - ADOXQ AX, R10 - - // (A,t[3]) := t[3] + x[3]*y[3] + A - ADCXQ BP, R11 - MULXQ BX, AX, BP - ADOXQ AX, R11 - - // (A,t[4]) := t[4] + x[4]*y[3] + A - ADCXQ BP, R12 - MULXQ SI, AX, BP - ADOXQ AX, R12 - - // (A,t[5]) := t[5] + x[5]*y[3] + A - ADCXQ BP, R13 - MULXQ DI, AX, BP - ADOXQ AX, R13 - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - PUSHQ BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R8, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R8, AX - MOVQ BP, R8 - POPQ BP - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R9, R8 - MULXQ q<>+8(SB), AX, R9 - ADOXQ AX, R8 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ R10, R9 - MULXQ q<>+16(SB), AX, R10 - ADOXQ AX, R9 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ R11, R10 - MULXQ q<>+24(SB), AX, R11 - ADOXQ AX, R10 - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ R12, R11 - MULXQ q<>+32(SB), AX, R12 - ADOXQ AX, R11 - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ R13, R12 - MULXQ q<>+40(SB), AX, R13 - ADOXQ AX, R12 - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, R13 - ADOXQ BP, R13 - - // clear the flags - XORQ AX, AX + MUL_WORD_N() MOVQ y+16(FP), DX MOVQ 80(DX), DX - - // (A,t[0]) := t[0] + x[0]*y[4] + A - MULXQ R14, AX, BP - ADOXQ AX, R8 - - // (A,t[1]) := t[1] + x[1]*y[4] + A - ADCXQ BP, R9 - MULXQ R15, AX, BP - ADOXQ AX, R9 - - // (A,t[2]) := t[2] + x[2]*y[4] + A - ADCXQ BP, R10 - MULXQ CX, AX, BP - ADOXQ AX, R10 - - // (A,t[3]) := t[3] + x[3]*y[4] + A - ADCXQ BP, R11 - MULXQ BX, AX, BP - ADOXQ AX, R11 - - // (A,t[4]) := t[4] + x[4]*y[4] + A - ADCXQ BP, R12 - MULXQ SI, AX, BP - ADOXQ AX, R12 - - // (A,t[5]) := t[5] + x[5]*y[4] + A - ADCXQ BP, R13 - MULXQ DI, AX, BP - ADOXQ AX, R13 - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - PUSHQ BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R8, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R8, AX - MOVQ BP, R8 - POPQ BP - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R9, R8 - MULXQ q<>+8(SB), AX, R9 - ADOXQ AX, R8 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ R10, R9 - MULXQ q<>+16(SB), AX, R10 - ADOXQ AX, R9 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ R11, R10 - MULXQ q<>+24(SB), AX, R11 - ADOXQ AX, R10 - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ R12, R11 - MULXQ q<>+32(SB), AX, R12 - ADOXQ AX, R11 - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ R13, R12 - MULXQ q<>+40(SB), AX, R13 - ADOXQ AX, R12 - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, R13 - ADOXQ BP, R13 - - // clear the flags - XORQ AX, AX + MUL_WORD_N() MOVQ y+16(FP), DX MOVQ 88(DX), DX - - // (A,t[0]) := t[0] + x[0]*y[5] + A - MULXQ R14, AX, BP - ADOXQ AX, R8 - - // (A,t[1]) := t[1] + x[1]*y[5] + A - ADCXQ BP, R9 - MULXQ R15, AX, BP - ADOXQ AX, R9 - - // (A,t[2]) := t[2] + x[2]*y[5] + A - ADCXQ BP, R10 - MULXQ CX, AX, BP - ADOXQ AX, R10 - - // (A,t[3]) := t[3] + x[3]*y[5] + A - ADCXQ BP, R11 - MULXQ BX, AX, BP - ADOXQ AX, R11 - - // (A,t[4]) := t[4] + x[4]*y[5] + A - ADCXQ BP, R12 - MULXQ SI, AX, BP - ADOXQ AX, R12 - - // (A,t[5]) := t[5] + x[5]*y[5] + A - ADCXQ BP, R13 - MULXQ DI, AX, BP - ADOXQ AX, R13 - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - PUSHQ BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R8, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R8, AX - MOVQ BP, R8 - POPQ BP - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R9, R8 - MULXQ q<>+8(SB), AX, R9 - ADOXQ AX, R8 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ R10, R9 - MULXQ q<>+16(SB), AX, R10 - ADOXQ AX, R9 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ R11, R10 - MULXQ q<>+24(SB), AX, R11 - ADOXQ AX, R10 - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ R12, R11 - MULXQ q<>+32(SB), AX, R12 - ADOXQ AX, R11 - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ R13, R12 - MULXQ q<>+40(SB), AX, R13 - ADOXQ AX, R12 - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, R13 - ADOXQ BP, R13 + MUL_WORD_N() // reduce element(R8,R9,R10,R11,R12,R13) using temp registers (R14,R15,CX,BX,SI,DI) REDUCE(R8,R9,R10,R11,R12,R13,R14,R15,CX,BX,SI,DI) @@ -2071,490 +689,19 @@ TEXT ·mulAdxE2(SB), $96-24 // t[3] -> R11 // t[4] -> R12 // t[5] -> R13 - // clear the flags - XORQ AX, AX + // mul body MOVQ s0-8(SP), DX - - // (A,t[0]) := x[0]*y[0] + A - MULXQ R14, R8, R9 - - // (A,t[1]) := x[1]*y[0] + A - MULXQ R15, AX, R10 - ADOXQ AX, R9 - - // (A,t[2]) := x[2]*y[0] + A - MULXQ CX, AX, R11 - ADOXQ AX, R10 - - // (A,t[3]) := x[3]*y[0] + A - MULXQ BX, AX, R12 - ADOXQ AX, R11 - - // (A,t[4]) := x[4]*y[0] + A - MULXQ SI, AX, R13 - ADOXQ AX, R12 - - // (A,t[5]) := x[5]*y[0] + A - MULXQ DI, AX, BP - ADOXQ AX, R13 - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADOXQ AX, BP - PUSHQ BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R8, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R8, AX - MOVQ BP, R8 - POPQ BP - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R9, R8 - MULXQ q<>+8(SB), AX, R9 - ADOXQ AX, R8 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ R10, R9 - MULXQ q<>+16(SB), AX, R10 - ADOXQ AX, R9 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ R11, R10 - MULXQ q<>+24(SB), AX, R11 - ADOXQ AX, R10 - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ R12, R11 - MULXQ q<>+32(SB), AX, R12 - ADOXQ AX, R11 - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ R13, R12 - MULXQ q<>+40(SB), AX, R13 - ADOXQ AX, R12 - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, R13 - ADOXQ BP, R13 - - // clear the flags - XORQ AX, AX + MUL_WORD_0() MOVQ s1-16(SP), DX - - // (A,t[0]) := t[0] + x[0]*y[1] + A - MULXQ R14, AX, BP - ADOXQ AX, R8 - - // (A,t[1]) := t[1] + x[1]*y[1] + A - ADCXQ BP, R9 - MULXQ R15, AX, BP - ADOXQ AX, R9 - - // (A,t[2]) := t[2] + x[2]*y[1] + A - ADCXQ BP, R10 - MULXQ CX, AX, BP - ADOXQ AX, R10 - - // (A,t[3]) := t[3] + x[3]*y[1] + A - ADCXQ BP, R11 - MULXQ BX, AX, BP - ADOXQ AX, R11 - - // (A,t[4]) := t[4] + x[4]*y[1] + A - ADCXQ BP, R12 - MULXQ SI, AX, BP - ADOXQ AX, R12 - - // (A,t[5]) := t[5] + x[5]*y[1] + A - ADCXQ BP, R13 - MULXQ DI, AX, BP - ADOXQ AX, R13 - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - PUSHQ BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R8, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R8, AX - MOVQ BP, R8 - POPQ BP - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R9, R8 - MULXQ q<>+8(SB), AX, R9 - ADOXQ AX, R8 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ R10, R9 - MULXQ q<>+16(SB), AX, R10 - ADOXQ AX, R9 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ R11, R10 - MULXQ q<>+24(SB), AX, R11 - ADOXQ AX, R10 - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ R12, R11 - MULXQ q<>+32(SB), AX, R12 - ADOXQ AX, R11 - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ R13, R12 - MULXQ q<>+40(SB), AX, R13 - ADOXQ AX, R12 - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, R13 - ADOXQ BP, R13 - - // clear the flags - XORQ AX, AX + MUL_WORD_N() MOVQ s2-24(SP), DX - - // (A,t[0]) := t[0] + x[0]*y[2] + A - MULXQ R14, AX, BP - ADOXQ AX, R8 - - // (A,t[1]) := t[1] + x[1]*y[2] + A - ADCXQ BP, R9 - MULXQ R15, AX, BP - ADOXQ AX, R9 - - // (A,t[2]) := t[2] + x[2]*y[2] + A - ADCXQ BP, R10 - MULXQ CX, AX, BP - ADOXQ AX, R10 - - // (A,t[3]) := t[3] + x[3]*y[2] + A - ADCXQ BP, R11 - MULXQ BX, AX, BP - ADOXQ AX, R11 - - // (A,t[4]) := t[4] + x[4]*y[2] + A - ADCXQ BP, R12 - MULXQ SI, AX, BP - ADOXQ AX, R12 - - // (A,t[5]) := t[5] + x[5]*y[2] + A - ADCXQ BP, R13 - MULXQ DI, AX, BP - ADOXQ AX, R13 - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - PUSHQ BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R8, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R8, AX - MOVQ BP, R8 - POPQ BP - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R9, R8 - MULXQ q<>+8(SB), AX, R9 - ADOXQ AX, R8 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ R10, R9 - MULXQ q<>+16(SB), AX, R10 - ADOXQ AX, R9 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ R11, R10 - MULXQ q<>+24(SB), AX, R11 - ADOXQ AX, R10 - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ R12, R11 - MULXQ q<>+32(SB), AX, R12 - ADOXQ AX, R11 - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ R13, R12 - MULXQ q<>+40(SB), AX, R13 - ADOXQ AX, R12 - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, R13 - ADOXQ BP, R13 - - // clear the flags - XORQ AX, AX + MUL_WORD_N() MOVQ s3-32(SP), DX - - // (A,t[0]) := t[0] + x[0]*y[3] + A - MULXQ R14, AX, BP - ADOXQ AX, R8 - - // (A,t[1]) := t[1] + x[1]*y[3] + A - ADCXQ BP, R9 - MULXQ R15, AX, BP - ADOXQ AX, R9 - - // (A,t[2]) := t[2] + x[2]*y[3] + A - ADCXQ BP, R10 - MULXQ CX, AX, BP - ADOXQ AX, R10 - - // (A,t[3]) := t[3] + x[3]*y[3] + A - ADCXQ BP, R11 - MULXQ BX, AX, BP - ADOXQ AX, R11 - - // (A,t[4]) := t[4] + x[4]*y[3] + A - ADCXQ BP, R12 - MULXQ SI, AX, BP - ADOXQ AX, R12 - - // (A,t[5]) := t[5] + x[5]*y[3] + A - ADCXQ BP, R13 - MULXQ DI, AX, BP - ADOXQ AX, R13 - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - PUSHQ BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R8, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R8, AX - MOVQ BP, R8 - POPQ BP - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R9, R8 - MULXQ q<>+8(SB), AX, R9 - ADOXQ AX, R8 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ R10, R9 - MULXQ q<>+16(SB), AX, R10 - ADOXQ AX, R9 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ R11, R10 - MULXQ q<>+24(SB), AX, R11 - ADOXQ AX, R10 - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ R12, R11 - MULXQ q<>+32(SB), AX, R12 - ADOXQ AX, R11 - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ R13, R12 - MULXQ q<>+40(SB), AX, R13 - ADOXQ AX, R12 - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, R13 - ADOXQ BP, R13 - - // clear the flags - XORQ AX, AX + MUL_WORD_N() MOVQ s4-40(SP), DX - - // (A,t[0]) := t[0] + x[0]*y[4] + A - MULXQ R14, AX, BP - ADOXQ AX, R8 - - // (A,t[1]) := t[1] + x[1]*y[4] + A - ADCXQ BP, R9 - MULXQ R15, AX, BP - ADOXQ AX, R9 - - // (A,t[2]) := t[2] + x[2]*y[4] + A - ADCXQ BP, R10 - MULXQ CX, AX, BP - ADOXQ AX, R10 - - // (A,t[3]) := t[3] + x[3]*y[4] + A - ADCXQ BP, R11 - MULXQ BX, AX, BP - ADOXQ AX, R11 - - // (A,t[4]) := t[4] + x[4]*y[4] + A - ADCXQ BP, R12 - MULXQ SI, AX, BP - ADOXQ AX, R12 - - // (A,t[5]) := t[5] + x[5]*y[4] + A - ADCXQ BP, R13 - MULXQ DI, AX, BP - ADOXQ AX, R13 - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - PUSHQ BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R8, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R8, AX - MOVQ BP, R8 - POPQ BP - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R9, R8 - MULXQ q<>+8(SB), AX, R9 - ADOXQ AX, R8 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ R10, R9 - MULXQ q<>+16(SB), AX, R10 - ADOXQ AX, R9 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ R11, R10 - MULXQ q<>+24(SB), AX, R11 - ADOXQ AX, R10 - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ R12, R11 - MULXQ q<>+32(SB), AX, R12 - ADOXQ AX, R11 - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ R13, R12 - MULXQ q<>+40(SB), AX, R13 - ADOXQ AX, R12 - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, R13 - ADOXQ BP, R13 - - // clear the flags - XORQ AX, AX + MUL_WORD_N() MOVQ s5-48(SP), DX - - // (A,t[0]) := t[0] + x[0]*y[5] + A - MULXQ R14, AX, BP - ADOXQ AX, R8 - - // (A,t[1]) := t[1] + x[1]*y[5] + A - ADCXQ BP, R9 - MULXQ R15, AX, BP - ADOXQ AX, R9 - - // (A,t[2]) := t[2] + x[2]*y[5] + A - ADCXQ BP, R10 - MULXQ CX, AX, BP - ADOXQ AX, R10 - - // (A,t[3]) := t[3] + x[3]*y[5] + A - ADCXQ BP, R11 - MULXQ BX, AX, BP - ADOXQ AX, R11 - - // (A,t[4]) := t[4] + x[4]*y[5] + A - ADCXQ BP, R12 - MULXQ SI, AX, BP - ADOXQ AX, R12 - - // (A,t[5]) := t[5] + x[5]*y[5] + A - ADCXQ BP, R13 - MULXQ DI, AX, BP - ADOXQ AX, R13 - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - PUSHQ BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R8, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R8, AX - MOVQ BP, R8 - POPQ BP - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R9, R8 - MULXQ q<>+8(SB), AX, R9 - ADOXQ AX, R8 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ R10, R9 - MULXQ q<>+16(SB), AX, R10 - ADOXQ AX, R9 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ R11, R10 - MULXQ q<>+24(SB), AX, R11 - ADOXQ AX, R10 - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ R12, R11 - MULXQ q<>+32(SB), AX, R12 - ADOXQ AX, R11 - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ R13, R12 - MULXQ q<>+40(SB), AX, R13 - ADOXQ AX, R12 - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, R13 - ADOXQ BP, R13 + MUL_WORD_N() // reduce element(R8,R9,R10,R11,R12,R13) using temp registers (R14,R15,CX,BX,SI,DI) REDUCE(R8,R9,R10,R11,R12,R13,R14,R15,CX,BX,SI,DI) @@ -2580,496 +727,25 @@ TEXT ·mulAdxE2(SB), $96-24 // t[3] -> R11 // t[4] -> R12 // t[5] -> R13 - // clear the flags - XORQ AX, AX + // mul body MOVQ y+16(FP), DX MOVQ 0(DX), DX - - // (A,t[0]) := x[0]*y[0] + A - MULXQ R14, R8, R9 - - // (A,t[1]) := x[1]*y[0] + A - MULXQ R15, AX, R10 - ADOXQ AX, R9 - - // (A,t[2]) := x[2]*y[0] + A - MULXQ CX, AX, R11 - ADOXQ AX, R10 - - // (A,t[3]) := x[3]*y[0] + A - MULXQ BX, AX, R12 - ADOXQ AX, R11 - - // (A,t[4]) := x[4]*y[0] + A - MULXQ SI, AX, R13 - ADOXQ AX, R12 - - // (A,t[5]) := x[5]*y[0] + A - MULXQ DI, AX, BP - ADOXQ AX, R13 - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADOXQ AX, BP - PUSHQ BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R8, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R8, AX - MOVQ BP, R8 - POPQ BP - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R9, R8 - MULXQ q<>+8(SB), AX, R9 - ADOXQ AX, R8 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ R10, R9 - MULXQ q<>+16(SB), AX, R10 - ADOXQ AX, R9 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ R11, R10 - MULXQ q<>+24(SB), AX, R11 - ADOXQ AX, R10 - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ R12, R11 - MULXQ q<>+32(SB), AX, R12 - ADOXQ AX, R11 - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ R13, R12 - MULXQ q<>+40(SB), AX, R13 - ADOXQ AX, R12 - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, R13 - ADOXQ BP, R13 - - // clear the flags - XORQ AX, AX + MUL_WORD_0() MOVQ y+16(FP), DX MOVQ 8(DX), DX - - // (A,t[0]) := t[0] + x[0]*y[1] + A - MULXQ R14, AX, BP - ADOXQ AX, R8 - - // (A,t[1]) := t[1] + x[1]*y[1] + A - ADCXQ BP, R9 - MULXQ R15, AX, BP - ADOXQ AX, R9 - - // (A,t[2]) := t[2] + x[2]*y[1] + A - ADCXQ BP, R10 - MULXQ CX, AX, BP - ADOXQ AX, R10 - - // (A,t[3]) := t[3] + x[3]*y[1] + A - ADCXQ BP, R11 - MULXQ BX, AX, BP - ADOXQ AX, R11 - - // (A,t[4]) := t[4] + x[4]*y[1] + A - ADCXQ BP, R12 - MULXQ SI, AX, BP - ADOXQ AX, R12 - - // (A,t[5]) := t[5] + x[5]*y[1] + A - ADCXQ BP, R13 - MULXQ DI, AX, BP - ADOXQ AX, R13 - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - PUSHQ BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R8, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R8, AX - MOVQ BP, R8 - POPQ BP - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R9, R8 - MULXQ q<>+8(SB), AX, R9 - ADOXQ AX, R8 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ R10, R9 - MULXQ q<>+16(SB), AX, R10 - ADOXQ AX, R9 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ R11, R10 - MULXQ q<>+24(SB), AX, R11 - ADOXQ AX, R10 - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ R12, R11 - MULXQ q<>+32(SB), AX, R12 - ADOXQ AX, R11 - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ R13, R12 - MULXQ q<>+40(SB), AX, R13 - ADOXQ AX, R12 - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, R13 - ADOXQ BP, R13 - - // clear the flags - XORQ AX, AX + MUL_WORD_N() MOVQ y+16(FP), DX MOVQ 16(DX), DX - - // (A,t[0]) := t[0] + x[0]*y[2] + A - MULXQ R14, AX, BP - ADOXQ AX, R8 - - // (A,t[1]) := t[1] + x[1]*y[2] + A - ADCXQ BP, R9 - MULXQ R15, AX, BP - ADOXQ AX, R9 - - // (A,t[2]) := t[2] + x[2]*y[2] + A - ADCXQ BP, R10 - MULXQ CX, AX, BP - ADOXQ AX, R10 - - // (A,t[3]) := t[3] + x[3]*y[2] + A - ADCXQ BP, R11 - MULXQ BX, AX, BP - ADOXQ AX, R11 - - // (A,t[4]) := t[4] + x[4]*y[2] + A - ADCXQ BP, R12 - MULXQ SI, AX, BP - ADOXQ AX, R12 - - // (A,t[5]) := t[5] + x[5]*y[2] + A - ADCXQ BP, R13 - MULXQ DI, AX, BP - ADOXQ AX, R13 - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - PUSHQ BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R8, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R8, AX - MOVQ BP, R8 - POPQ BP - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R9, R8 - MULXQ q<>+8(SB), AX, R9 - ADOXQ AX, R8 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ R10, R9 - MULXQ q<>+16(SB), AX, R10 - ADOXQ AX, R9 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ R11, R10 - MULXQ q<>+24(SB), AX, R11 - ADOXQ AX, R10 - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ R12, R11 - MULXQ q<>+32(SB), AX, R12 - ADOXQ AX, R11 - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ R13, R12 - MULXQ q<>+40(SB), AX, R13 - ADOXQ AX, R12 - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, R13 - ADOXQ BP, R13 - - // clear the flags - XORQ AX, AX + MUL_WORD_N() MOVQ y+16(FP), DX MOVQ 24(DX), DX - - // (A,t[0]) := t[0] + x[0]*y[3] + A - MULXQ R14, AX, BP - ADOXQ AX, R8 - - // (A,t[1]) := t[1] + x[1]*y[3] + A - ADCXQ BP, R9 - MULXQ R15, AX, BP - ADOXQ AX, R9 - - // (A,t[2]) := t[2] + x[2]*y[3] + A - ADCXQ BP, R10 - MULXQ CX, AX, BP - ADOXQ AX, R10 - - // (A,t[3]) := t[3] + x[3]*y[3] + A - ADCXQ BP, R11 - MULXQ BX, AX, BP - ADOXQ AX, R11 - - // (A,t[4]) := t[4] + x[4]*y[3] + A - ADCXQ BP, R12 - MULXQ SI, AX, BP - ADOXQ AX, R12 - - // (A,t[5]) := t[5] + x[5]*y[3] + A - ADCXQ BP, R13 - MULXQ DI, AX, BP - ADOXQ AX, R13 - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - PUSHQ BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R8, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R8, AX - MOVQ BP, R8 - POPQ BP - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R9, R8 - MULXQ q<>+8(SB), AX, R9 - ADOXQ AX, R8 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ R10, R9 - MULXQ q<>+16(SB), AX, R10 - ADOXQ AX, R9 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ R11, R10 - MULXQ q<>+24(SB), AX, R11 - ADOXQ AX, R10 - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ R12, R11 - MULXQ q<>+32(SB), AX, R12 - ADOXQ AX, R11 - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ R13, R12 - MULXQ q<>+40(SB), AX, R13 - ADOXQ AX, R12 - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, R13 - ADOXQ BP, R13 - - // clear the flags - XORQ AX, AX + MUL_WORD_N() MOVQ y+16(FP), DX MOVQ 32(DX), DX - - // (A,t[0]) := t[0] + x[0]*y[4] + A - MULXQ R14, AX, BP - ADOXQ AX, R8 - - // (A,t[1]) := t[1] + x[1]*y[4] + A - ADCXQ BP, R9 - MULXQ R15, AX, BP - ADOXQ AX, R9 - - // (A,t[2]) := t[2] + x[2]*y[4] + A - ADCXQ BP, R10 - MULXQ CX, AX, BP - ADOXQ AX, R10 - - // (A,t[3]) := t[3] + x[3]*y[4] + A - ADCXQ BP, R11 - MULXQ BX, AX, BP - ADOXQ AX, R11 - - // (A,t[4]) := t[4] + x[4]*y[4] + A - ADCXQ BP, R12 - MULXQ SI, AX, BP - ADOXQ AX, R12 - - // (A,t[5]) := t[5] + x[5]*y[4] + A - ADCXQ BP, R13 - MULXQ DI, AX, BP - ADOXQ AX, R13 - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - PUSHQ BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R8, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R8, AX - MOVQ BP, R8 - POPQ BP - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R9, R8 - MULXQ q<>+8(SB), AX, R9 - ADOXQ AX, R8 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ R10, R9 - MULXQ q<>+16(SB), AX, R10 - ADOXQ AX, R9 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ R11, R10 - MULXQ q<>+24(SB), AX, R11 - ADOXQ AX, R10 - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ R12, R11 - MULXQ q<>+32(SB), AX, R12 - ADOXQ AX, R11 - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ R13, R12 - MULXQ q<>+40(SB), AX, R13 - ADOXQ AX, R12 - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, R13 - ADOXQ BP, R13 - - // clear the flags - XORQ AX, AX + MUL_WORD_N() MOVQ y+16(FP), DX MOVQ 40(DX), DX - - // (A,t[0]) := t[0] + x[0]*y[5] + A - MULXQ R14, AX, BP - ADOXQ AX, R8 - - // (A,t[1]) := t[1] + x[1]*y[5] + A - ADCXQ BP, R9 - MULXQ R15, AX, BP - ADOXQ AX, R9 - - // (A,t[2]) := t[2] + x[2]*y[5] + A - ADCXQ BP, R10 - MULXQ CX, AX, BP - ADOXQ AX, R10 - - // (A,t[3]) := t[3] + x[3]*y[5] + A - ADCXQ BP, R11 - MULXQ BX, AX, BP - ADOXQ AX, R11 - - // (A,t[4]) := t[4] + x[4]*y[5] + A - ADCXQ BP, R12 - MULXQ SI, AX, BP - ADOXQ AX, R12 - - // (A,t[5]) := t[5] + x[5]*y[5] + A - ADCXQ BP, R13 - MULXQ DI, AX, BP - ADOXQ AX, R13 - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - PUSHQ BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R8, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R8, AX - MOVQ BP, R8 - POPQ BP - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R9, R8 - MULXQ q<>+8(SB), AX, R9 - ADOXQ AX, R8 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ R10, R9 - MULXQ q<>+16(SB), AX, R10 - ADOXQ AX, R9 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ R11, R10 - MULXQ q<>+24(SB), AX, R11 - ADOXQ AX, R10 - - // (C,t[3]) := t[4] + m*q[4] + C - ADCXQ R12, R11 - MULXQ q<>+32(SB), AX, R12 - ADOXQ AX, R11 - - // (C,t[4]) := t[5] + m*q[5] + C - ADCXQ R13, R12 - MULXQ q<>+40(SB), AX, R13 - ADOXQ AX, R12 - - // t[5] = C + A - MOVQ $0, AX - ADCXQ AX, R13 - ADOXQ BP, R13 + MUL_WORD_N() // reduce element(R8,R9,R10,R11,R12,R13) using temp registers (R14,R15,CX,BX,SI,DI) REDUCE(R8,R9,R10,R11,R12,R13,R14,R15,CX,BX,SI,DI) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e2_bls381.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e2_bls381.go index 32fb644b69c..41a36ab3553 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e2_bls381.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e2_bls381.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys AG -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. package fptower diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e2_bls381_fallback.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e2_bls381_fallback.go index 0ae39042dca..3e81e3ee1bb 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e2_bls381_fallback.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e2_bls381_fallback.go @@ -1,19 +1,8 @@ //go:build !amd64 // +build !amd64 -// Copyright 2020 ConsenSys AG -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. package fptower diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e2_fallback.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e2_fallback.go index 6fe47c4111b..7a2461ec533 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e2_fallback.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e2_fallback.go @@ -1,19 +1,7 @@ //go:build !amd64 -// +build !amd64 -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e6.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e6.go index 128007df278..4c932208b41 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e6.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/e6.go @@ -1,16 +1,5 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -63,11 +52,20 @@ func (z *E6) SetRandom() (*E6, error) { return z, nil } -// IsZero returns true if the two elements are equal, false otherwise +// MustSetRandom sets a0 and a1 to random values. +// It panics if reading form crypto/rand fails +func (z *E6) MustSetRandom() { + if _, err := z.SetRandom(); err != nil { + panic(err) + } +} + +// IsZero returns true if z is zero, false otherwise func (z *E6) IsZero() bool { return z.B0.IsZero() && z.B1.IsZero() && z.B2.IsZero() } +// IsOne returns true if z is one, false otherwise func (z *E6) IsOne() bool { return z.B0.IsOne() && z.B1.IsZero() && z.B2.IsZero() } @@ -88,7 +86,7 @@ func (z *E6) Neg(x *E6) *E6 { return z } -// Sub two elements of E6 +// Sub subtracts two elements of E6 func (z *E6) Sub(x, y *E6) *E6 { z.B0.Sub(&x.B0, &y.B0) z.B1.Sub(&x.B1, &y.B1) @@ -286,8 +284,8 @@ func (z *E6) Inverse(x *E6) *E6 { return z } -// BatchInvertE6 returns a new slice with every element inverted. -// Uses Montgomery batch inversion trick +// BatchInvertE6 returns a new slice with every element in a inverted. +// It uses Montgomery batch inversion trick. // // if a[i] == 0, returns result[i] = a[i] func BatchInvertE6(a []E6) []E6 { @@ -322,6 +320,8 @@ func BatchInvertE6(a []E6) []E6 { return res } +// Select is conditional move. +// If cond = 0, it sets z to caseZ and returns it. otherwise caseNz. func (z *E6) Select(cond int, caseZ *E6, caseNz *E6) *E6 { //Might be able to save a nanosecond or two by an aggregate implementation @@ -332,6 +332,7 @@ func (z *E6) Select(cond int, caseZ *E6, caseNz *E6) *E6 { return z } +// Div divides an element in E6 by an element in E6 func (z *E6) Div(x *E6, y *E6) *E6 { var r E6 r.Inverse(y).Mul(x, &r) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/frobenius.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/frobenius.go index 94b38f42822..5a3bbc08809 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/frobenius.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/frobenius.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys AG -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. package fptower diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/parameters.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/parameters.go index 9f97e117510..798b3a80268 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/parameters.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower/parameters.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys AG -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. package fptower diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/marshal.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/marshal.go index 8779479b249..dd36f429b12 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/marshal.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/marshal.go @@ -1,16 +1,5 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -171,6 +160,26 @@ func (dec *Decoder) Decode(v interface{}) (err error) { dec.n += read64 } return + case *[][][]fr.Element: + if sliceLen, err = dec.readUint32(); err != nil { + return + } + if len(*t) != int(sliceLen) { + *t = make([][][]fr.Element, sliceLen) + } + for i := range *t { + if sliceLen, err = dec.readUint32(); err != nil { + return + } + if len((*t)[i]) != int(sliceLen) { + (*t)[i] = make([][]fr.Element, sliceLen) + } + for j := range (*t)[i] { + read64, err = (*fr.Vector)(&(*t)[i][j]).ReadFrom(dec.r) + dec.n += read64 + } + } + return case *G1Affine: // we start by reading compressed point size, if metadata tells us it is uncompressed, we read more. read, err = io.ReadFull(dec.r, buf[:SizeOfG1AffineCompressed]) @@ -426,7 +435,7 @@ func NewEncoder(w io.Writer, options ...func(*Encoder)) *Encoder { } // Encode writes the binary encoding of v to the stream -// type must be uint64, *fr.Element, *fp.Element, *G1Affine, *G2Affine, []G1Affine or []G2Affine +// type must be uint64, *fr.Element, *fp.Element, *G1Affine, *G2Affine, []G1Affine, []G2Affine, *[]G1Affine or *[]G2Affine func (enc *Encoder) Encode(v interface{}) (err error) { if enc.raw { return enc.encodeRaw(v) @@ -537,6 +546,27 @@ func (enc *Encoder) encode(v interface{}) (err error) { enc.n += written64 } return + case [][][]fr.Element: + // number of collections + if err = binary.Write(enc.w, binary.BigEndian, uint32(len(t))); err != nil { + return + } + enc.n += 4 + for i := range t { + // size of current collection + if err = binary.Write(enc.w, binary.BigEndian, uint32(len(t[i]))); err != nil { + return + } + enc.n += 4 + // write each vector of the current collection + for j := range t[i] { + written64, err = (*fr.Vector)(&t[i][j]).WriteTo(enc.w) + enc.n += written64 + } + } + return + case *[]G1Affine: + return enc.encode(*t) case []G1Affine: // write slice length err = binary.Write(enc.w, binary.BigEndian, uint32(len(t))) @@ -556,6 +586,8 @@ func (enc *Encoder) encode(v interface{}) (err error) { } } return nil + case *[]G2Affine: + return enc.encode(*t) case []G2Affine: // write slice length err = binary.Write(enc.w, binary.BigEndian, uint32(len(t))) @@ -655,6 +687,27 @@ func (enc *Encoder) encodeRaw(v interface{}) (err error) { enc.n += written64 } return + case [][][]fr.Element: + // number of collections + if err = binary.Write(enc.w, binary.BigEndian, uint32(len(t))); err != nil { + return + } + enc.n += 4 + for i := range t { + // size of current collection + if err = binary.Write(enc.w, binary.BigEndian, uint32(len(t[i]))); err != nil { + return + } + enc.n += 4 + // write each vector of the current collection + for j := range t[i] { + written64, err = (*fr.Vector)(&t[i][j]).WriteTo(enc.w) + enc.n += written64 + } + } + return + case *[]G1Affine: + return enc.encodeRaw(*t) case []G1Affine: // write slice length err = binary.Write(enc.w, binary.BigEndian, uint32(len(t))) @@ -674,6 +727,8 @@ func (enc *Encoder) encodeRaw(v interface{}) (err error) { } } return nil + case *[]G2Affine: + return enc.encodeRaw(*t) case []G2Affine: // write slice length err = binary.Write(enc.w, binary.BigEndian, uint32(len(t))) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/multiexp.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/multiexp.go index 19350818ff0..bd0427c04ab 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/multiexp.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/multiexp.go @@ -1,16 +1,5 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -323,6 +312,31 @@ func msmReduceChunkG1Affine(p *G1Jac, c int, chChunks []chan g1JacExtended) *G1J return p.unsafeFromJacExtended(&_p) } +// Fold computes the multi-exponentiation \sum_{i=0}^{len(points)-1} points[i] * +// combinationCoeff^i and stores the result in p. It returns error in case +// configuration is invalid. +func (p *G1Affine) Fold(points []G1Affine, combinationCoeff fr.Element, config ecc.MultiExpConfig) (*G1Affine, error) { + var _p G1Jac + if _, err := _p.Fold(points, combinationCoeff, config); err != nil { + return nil, err + } + p.FromJacobian(&_p) + return p, nil +} + +// Fold computes the multi-exponentiation \sum_{i=0}^{len(points)-1} points[i] * +// combinationCoeff^i and stores the result in p. It returns error in case +// configuration is invalid. +func (p *G1Jac) Fold(points []G1Affine, combinationCoeff fr.Element, config ecc.MultiExpConfig) (*G1Jac, error) { + scalars := make([]fr.Element, len(points)) + scalar := fr.NewElement(1) + for i := 0; i < len(points); i++ { + scalars[i].Set(&scalar) + scalar.Mul(&scalar, &combinationCoeff) + } + return p.MultiExp(points, scalars, config) +} + // MultiExp implements section 4 of https://eprint.iacr.org/2012/549.pdf // // This call return an error if len(scalars) != len(points) or if provided config is invalid. @@ -621,6 +635,31 @@ func msmReduceChunkG2Affine(p *G2Jac, c int, chChunks []chan g2JacExtended) *G2J return p.unsafeFromJacExtended(&_p) } +// Fold computes the multi-exponentiation \sum_{i=0}^{len(points)-1} points[i] * +// combinationCoeff^i and stores the result in p. It returns error in case +// configuration is invalid. +func (p *G2Affine) Fold(points []G2Affine, combinationCoeff fr.Element, config ecc.MultiExpConfig) (*G2Affine, error) { + var _p G2Jac + if _, err := _p.Fold(points, combinationCoeff, config); err != nil { + return nil, err + } + p.FromJacobian(&_p) + return p, nil +} + +// Fold computes the multi-exponentiation \sum_{i=0}^{len(points)-1} points[i] * +// combinationCoeff^i and stores the result in p. It returns error in case +// configuration is invalid. +func (p *G2Jac) Fold(points []G2Affine, combinationCoeff fr.Element, config ecc.MultiExpConfig) (*G2Jac, error) { + scalars := make([]fr.Element, len(points)) + scalar := fr.NewElement(1) + for i := 0; i < len(points); i++ { + scalars[i].Set(&scalar) + scalar.Mul(&scalar, &combinationCoeff) + } + return p.MultiExp(points, scalars, config) +} + // selector stores the index, mask and shifts needed to select bits from a scalar // it is used during the multiExp algorithm or the batch scalar multiplication type selector struct { diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/multiexp_affine.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/multiexp_affine.go index 937a43c9d17..a7005c76b51 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/multiexp_affine.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/multiexp_affine.go @@ -1,16 +1,5 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -30,7 +19,7 @@ type batchOpG1Affine struct { // using affine coordinates for the buckets. To amortize the cost of the inverse in the affine addition // we use a batch affine addition. // -// this is derived from a PR by 0x0ece : https://github.com/ConsenSys/gnark-crypto/pull/249 +// this is derived from a PR by 0x0ece : https://github.com/Consensys/gnark-crypto/pull/249 // See Section 5.3: ia.cr/2022/1396 func processChunkG1BatchAffine[BJE ibg1JacExtended, B ibG1Affine, BS bitSet, TP pG1Affine, TPP ppG1Affine, TQ qOpsG1Affine, TC cG1Affine]( chunk uint64, @@ -60,11 +49,10 @@ func processChunkG1BatchAffine[BJE ibg1JacExtended, B ibG1Affine, BS bitSet, TP // note that we have 2 sets of buckets // 1 in G1Affine used with the batch affine additions // 1 in g1JacExtended used in case the queue of conflicting points - var buckets B + var buckets B // in G1Affine coordinates, infinity point is represented as (0,0), no need to init var bucketsJE BJE for i := 0; i < len(buckets); i++ { - buckets[i].setInfinity() - bucketsJE[i].setInfinity() + bucketsJE[i].SetInfinity() } // setup for the batch affine; @@ -107,7 +95,7 @@ func processChunkG1BatchAffine[BJE ibg1JacExtended, B ibG1Affine, BS bitSet, TP bucketsJE[op.bucketID].addMixed(&op.point) return } - BK.setInfinity() + BK.SetInfinity() return } @@ -135,12 +123,12 @@ func processChunkG1BatchAffine[BJE ibg1JacExtended, B ibG1Affine, BS bitSet, TP if isAdd { bucketsJE[bucketID].addMixed(PP) } else { - BK.setInfinity() + BK.SetInfinity() } return } if isAdd { - BK.setInfinity() + BK.SetInfinity() } else { bucketsJE[bucketID].subMixed(PP) } @@ -222,11 +210,11 @@ func processChunkG1BatchAffine[BJE ibg1JacExtended, B ibG1Affine, BS bitSet, TP // reduce buckets into total // total = bucket[0] + 2*bucket[1] + 3*bucket[2] ... + n*bucket[n-1] var runningSum, total g1JacExtended - runningSum.setInfinity() - total.setInfinity() + runningSum.SetInfinity() + total.SetInfinity() for k := len(buckets) - 1; k >= 0; k-- { runningSum.addMixed(&buckets[k]) - if !bucketsJE[k].IsZero() { + if !bucketsJE[k].IsInfinity() { runningSum.add(&bucketsJE[k]) } total.add(&runningSum) @@ -358,7 +346,7 @@ type batchOpG2Affine struct { // using affine coordinates for the buckets. To amortize the cost of the inverse in the affine addition // we use a batch affine addition. // -// this is derived from a PR by 0x0ece : https://github.com/ConsenSys/gnark-crypto/pull/249 +// this is derived from a PR by 0x0ece : https://github.com/Consensys/gnark-crypto/pull/249 // See Section 5.3: ia.cr/2022/1396 func processChunkG2BatchAffine[BJE ibg2JacExtended, B ibG2Affine, BS bitSet, TP pG2Affine, TPP ppG2Affine, TQ qOpsG2Affine, TC cG2Affine]( chunk uint64, @@ -388,11 +376,10 @@ func processChunkG2BatchAffine[BJE ibg2JacExtended, B ibG2Affine, BS bitSet, TP // note that we have 2 sets of buckets // 1 in G2Affine used with the batch affine additions // 1 in g2JacExtended used in case the queue of conflicting points - var buckets B + var buckets B // in G2Affine coordinates, infinity point is represented as (0,0), no need to init var bucketsJE BJE for i := 0; i < len(buckets); i++ { - buckets[i].setInfinity() - bucketsJE[i].setInfinity() + bucketsJE[i].SetInfinity() } // setup for the batch affine; @@ -435,7 +422,7 @@ func processChunkG2BatchAffine[BJE ibg2JacExtended, B ibG2Affine, BS bitSet, TP bucketsJE[op.bucketID].addMixed(&op.point) return } - BK.setInfinity() + BK.SetInfinity() return } @@ -463,12 +450,12 @@ func processChunkG2BatchAffine[BJE ibg2JacExtended, B ibG2Affine, BS bitSet, TP if isAdd { bucketsJE[bucketID].addMixed(PP) } else { - BK.setInfinity() + BK.SetInfinity() } return } if isAdd { - BK.setInfinity() + BK.SetInfinity() } else { bucketsJE[bucketID].subMixed(PP) } @@ -550,11 +537,11 @@ func processChunkG2BatchAffine[BJE ibg2JacExtended, B ibG2Affine, BS bitSet, TP // reduce buckets into total // total = bucket[0] + 2*bucket[1] + 3*bucket[2] ... + n*bucket[n-1] var runningSum, total g2JacExtended - runningSum.setInfinity() - total.setInfinity() + runningSum.SetInfinity() + total.SetInfinity() for k := len(buckets) - 1; k >= 0; k-- { runningSum.addMixed(&buckets[k]) - if !bucketsJE[k].IsZero() { + if !bucketsJE[k].IsInfinity() { runningSum.add(&bucketsJE[k]) } total.add(&runningSum) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/multiexp_jacobian.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/multiexp_jacobian.go index 1b8c0e79aa4..b2a94f7937f 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/multiexp_jacobian.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/multiexp_jacobian.go @@ -1,16 +1,5 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -30,7 +19,7 @@ func processChunkG1Jacobian[B ibg1JacExtended](chunk uint64, var buckets B for i := 0; i < len(buckets); i++ { - buckets[i].setInfinity() + buckets[i].SetInfinity() } // for each scalars, get the digit corresponding to the chunk we're processing. @@ -53,10 +42,10 @@ func processChunkG1Jacobian[B ibg1JacExtended](chunk uint64, // total = bucket[0] + 2*bucket[1] + 3*bucket[2] ... + n*bucket[n-1] var runningSum, total g1JacExtended - runningSum.setInfinity() - total.setInfinity() + runningSum.SetInfinity() + total.SetInfinity() for k := len(buckets) - 1; k >= 0; k-- { - if !buckets[k].IsZero() { + if !buckets[k].IsInfinity() { runningSum.add(&buckets[k]) } total.add(&runningSum) @@ -119,7 +108,7 @@ func processChunkG2Jacobian[B ibg2JacExtended](chunk uint64, var buckets B for i := 0; i < len(buckets); i++ { - buckets[i].setInfinity() + buckets[i].SetInfinity() } // for each scalars, get the digit corresponding to the chunk we're processing. @@ -142,10 +131,10 @@ func processChunkG2Jacobian[B ibg2JacExtended](chunk uint64, // total = bucket[0] + 2*bucket[1] + 3*bucket[2] ... + n*bucket[n-1] var runningSum, total g2JacExtended - runningSum.setInfinity() - total.setInfinity() + runningSum.SetInfinity() + total.SetInfinity() for k := len(buckets) - 1; k >= 0; k-- { - if !buckets[k].IsZero() { + if !buckets[k].IsInfinity() { runningSum.add(&buckets[k]) } total.add(&runningSum) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/pairing.go b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/pairing.go index e2c362f9b51..3379bd25b18 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/pairing.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bls12-381/pairing.go @@ -1,22 +1,12 @@ -// Copyright 2020 ConsenSys AG -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. package bls12381 import ( "errors" + "github.com/consensys/gnark-crypto/ecc/bls12-381/fp" "github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower" ) @@ -146,7 +136,7 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) { if n >= 1 { // i = 62, separately to avoid an E12 Square // (Square(res) = 1² = 1) - // loopCounter[62] = 1 + // LoopCounter[62] = 1 // k = 0, separately to avoid MulBy014 (res × ℓ) // (assign line to res) @@ -193,7 +183,7 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) { } // i <= 61 - for i := len(loopCounter) - 3; i >= 1; i-- { + for i := len(LoopCounter) - 3; i >= 1; i-- { // mutualize the square among n Miller loops // (∏ᵢfᵢ)² result.Square(&result) @@ -205,7 +195,7 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) { l1.r1.MulByElement(&l1.r1, &p[k].X) l1.r2.MulByElement(&l1.r2, &p[k].Y) - if loopCounter[i] == 0 { + if LoopCounter[i] == 0 { // ℓ × res result.MulBy014(&l1.r0, &l1.r1, &l1.r2) } else { @@ -224,7 +214,7 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) { } // i = 0, separately to avoid a point doubling - // loopCounter[0] = 0 + // LoopCounter[0] = 0 result.Square(&result) for k := 0; k < n; k++ { // l1 the tangent ℓ passing 2qProj[k] @@ -345,3 +335,245 @@ func (p *g2Proj) tangentLine(l *lineEvaluation) { Add(&l.r1, &J) l.r2.Neg(&H) } + +// ---------------------- +// Fixed-argument pairing +// ---------------------- + +type LineEvaluationAff struct { + R0 fptower.E2 + R1 fptower.E2 +} + +// PairFixedQ calculates the reduced pairing for a set of points +// ∏ᵢ e(Pᵢ, Qᵢ) where Q are fixed points in G2. +// +// This function doesn't check that the inputs are in the correct subgroup. See IsInSubGroup. +func PairFixedQ(P []G1Affine, lines [][2][len(LoopCounter) - 1]LineEvaluationAff) (GT, error) { + f, err := MillerLoopFixedQ(P, lines) + if err != nil { + return GT{}, err + } + return FinalExponentiation(&f), nil +} + +// PairingCheckFixedQ calculates the reduced pairing for a set of points and returns True if the result is One +// ∏ᵢ e(Pᵢ, Qᵢ) =? 1 where Q are fixed points in G2. +// +// This function doesn't check that the inputs are in the correct subgroup. See IsInSubGroup. +func PairingCheckFixedQ(P []G1Affine, lines [][2][len(LoopCounter) - 1]LineEvaluationAff) (bool, error) { + f, err := PairFixedQ(P, lines) + if err != nil { + return false, err + } + var one GT + one.SetOne() + return f.Equal(&one), nil +} + +// PrecomputeLines precomputes the lines for the fixed-argument Miller loop +func PrecomputeLines(Q G2Affine) (PrecomputedLines [2][len(LoopCounter) - 1]LineEvaluationAff) { + var accQ G2Affine + accQ.Set(&Q) + n := len(LoopCounter) + // i = n - 2 + accQ.doubleStep(&PrecomputedLines[0][n-2]) + accQ.addStep(&PrecomputedLines[1][n-2], &Q) + for i := n - 3; i >= 0; i-- { + if LoopCounter[i] == 0 { + accQ.doubleStep(&PrecomputedLines[0][i]) + } else { + accQ.doubleAndAddStep(&PrecomputedLines[0][i], &PrecomputedLines[1][i], &Q) + } + } + return PrecomputedLines +} + +// MillerLoopFixedQ computes the multi-Miller loop as in MillerLoop +// but Qᵢ are fixed points in G2 known in advance. +func MillerLoopFixedQ(P []G1Affine, lines [][2][len(LoopCounter) - 1]LineEvaluationAff) (GT, error) { + n := len(P) + if n == 0 || n != len(lines) { + return GT{}, errors.New("invalid inputs sizes") + } + + // no need to filter infinity points: + // 1. if Pᵢ=(0,0) then -x/y=1/y=0 by gnark-crypto convention and so + // lines R0 and R1 are 0. It happens that result will stay, through + // the Miller loop, in 𝔽p⁶ because MulBy01(0,0,1), + // Mul01By01(0,0,1,0,0,1) and MulBy01245 set result.C0 to 0. At the + // end result will be in a proper subgroup of Fp¹² so it be reduced to + // 1 in FinalExponentiation. + // + // and/or + // + // 2. if Qᵢ=(0,0) then PrecomputeLines(Qᵢ) will return lines R0 and R1 + // that are 0 because of gnark-convention (*/0==0) in doubleStep and + // addStep. Similarly to Pᵢ=(0,0) it happens that result be 1 + // after the FinalExponentiation. + + // precomputations + yInv := make([]fp.Element, n) + xNegOverY := make([]fp.Element, n) + for k := 0; k < n; k++ { + yInv[k].Set(&P[k].Y) + } + yInv = fp.BatchInvert(yInv) + for k := 0; k < n; k++ { + xNegOverY[k].Mul(&P[k].X, &yInv[k]). + Neg(&xNegOverY[k]) + } + + var result GT + result.SetOne() + var prodLines [5]E2 + + // Compute ∏ᵢ { fᵢ_{x₀,Q}(P) } + for i := len(LoopCounter) - 2; i >= 0; i-- { + // mutualize the square among n Miller loops + // (∏ᵢfᵢ)² + result.Square(&result) + + for k := 0; k < n; k++ { + // line evaluation at P[k] + lines[k][0][i].R1. + MulByElement( + &lines[k][0][i].R1, + &yInv[k], + ) + lines[k][0][i].R0. + MulByElement(&lines[k][0][i].R0, + &xNegOverY[k], + ) + if LoopCounter[i] == 0 { + // ℓ × res + result.MulBy01( + &lines[k][0][i].R1, + &lines[k][0][i].R0, + ) + + } else { + lines[k][1][i].R1. + MulByElement( + &lines[k][1][i].R1, + &yInv[k], + ) + lines[k][1][i].R0. + MulByElement( + &lines[k][1][i].R0, + &xNegOverY[k], + ) + prodLines = fptower.Mul01By01( + &lines[k][0][i].R1, &lines[k][0][i].R0, + &lines[k][1][i].R1, &lines[k][1][i].R0, + ) + result.MulBy01245(&prodLines) + } + } + } + + // negative x₀ + result.Conjugate(&result) + + return result, nil +} + +func (p *G2Affine) doubleStep(evaluations *LineEvaluationAff) { + + var n, d, λ, xr, yr fptower.E2 + // λ = 3x²/2y + n.Square(&p.X) + λ.Double(&n). + Add(&λ, &n) + d.Double(&p.Y) + λ.Div(&λ, &d) + + // xr = λ²-2x + xr.Square(&λ). + Sub(&xr, &p.X). + Sub(&xr, &p.X) + + // yr = λ(x-xr)-y + yr.Sub(&p.X, &xr). + Mul(&yr, &λ). + Sub(&yr, &p.Y) + + evaluations.R0.Set(&λ) + evaluations.R1.Mul(&λ, &p.X). + Sub(&evaluations.R1, &p.Y) + + p.X.Set(&xr) + p.Y.Set(&yr) +} + +func (p *G2Affine) addStep(evaluations *LineEvaluationAff, a *G2Affine) { + var n, d, λ, λλ, xr, yr fptower.E2 + + // compute λ = (y2-y1)/(x2-x1) + n.Sub(&a.Y, &p.Y) + d.Sub(&a.X, &p.X) + λ.Div(&n, &d) + + // xr = λ²-x1-x2 + λλ.Square(&λ) + n.Add(&p.X, &a.X) + xr.Sub(&λλ, &n) + + // yr = λ(x1-xr) - y1 + yr.Sub(&p.X, &xr). + Mul(&yr, &λ). + Sub(&yr, &p.Y) + + evaluations.R0.Set(&λ) + evaluations.R1.Mul(&λ, &p.X). + Sub(&evaluations.R1, &p.Y) + + p.X.Set(&xr) + p.Y.Set(&yr) +} + +func (p *G2Affine) doubleAndAddStep(evaluations1, evaluations2 *LineEvaluationAff, a *G2Affine) { + var n, d, l1, x3, l2, x4, y4 fptower.E2 + + // compute λ1 = (y2-y1)/(x2-x1) + n.Sub(&p.Y, &a.Y) + d.Sub(&p.X, &a.X) + l1.Div(&n, &d) + + // compute x3 =λ1²-x1-x2 + x3.Square(&l1) + x3.Sub(&x3, &p.X) + x3.Sub(&x3, &a.X) + + // omit y3 computation + + // compute line1 + evaluations1.R0.Set(&l1) + evaluations1.R1.Mul(&l1, &p.X) + evaluations1.R1.Sub(&evaluations1.R1, &p.Y) + + // compute λ2 = -λ1-2y1/(x3-x1) + n.Double(&p.Y) + d.Sub(&x3, &p.X) + l2.Div(&n, &d) + l2.Add(&l2, &l1) + l2.Neg(&l2) + + // compute x4 = λ2²-x1-x3 + x4.Square(&l2) + x4.Sub(&x4, &p.X) + x4.Sub(&x4, &x3) + + // compute y4 = λ2(x1 - x4)-y1 + y4.Sub(&p.X, &x4) + y4.Mul(&l2, &y4) + y4.Sub(&y4, &p.Y) + + // compute line2 + evaluations2.R0.Set(&l2) + evaluations2.R1.Mul(&l2, &p.X) + evaluations2.R1.Sub(&evaluations2.R1, &p.Y) + + p.X.Set(&x4) + p.Y.Set(&y4) +} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/bn254.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/bn254.go index f6f2990ca39..a0fa54df7e9 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/bn254.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/bn254.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Package bn254 efficient elliptic curve, pairing and hash to curve implementation for bn254. This curve appears in // Ethereum pre-compiles as altbn128. @@ -76,7 +65,7 @@ var g1Infinity G1Jac var g2Infinity G2Jac // optimal Ate loop counter -var loopCounter [66]int8 +var LoopCounter [66]int8 // Parameters useful for the GLV scalar multiplication. The third roots define the // endomorphisms ϕ₁ and ϕ₂ for and . lambda is such that lies above @@ -152,7 +141,7 @@ func init() { // 2-NAF decomposition of 6x₀+2 little endian optimaAteLoop, _ := new(big.Int).SetString("29793968203157093288", 10) - ecc.NafDecomposition(optimaAteLoop, loopCounter[:]) + ecc.NafDecomposition(optimaAteLoop, LoopCounter[:]) xGen.SetString("4965661367192848881", 10) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/arith.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/arith.go index 6f281563b3d..5c9905de801 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/arith.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/arith.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -58,16 +47,3 @@ func madd3(a, b, c, d, e uint64) (hi uint64, lo uint64) { hi, _ = bits.Add64(hi, e, carry) return } -func max(a int, b int) int { - if a > b { - return a - } - return b -} - -func min(a int, b int) int { - if a < b { - return a - } - return b -} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/asm.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/asm.go deleted file mode 100644 index 0481989ec6a..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/asm.go +++ /dev/null @@ -1,27 +0,0 @@ -//go:build !noadx -// +build !noadx - -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by consensys/gnark-crypto DO NOT EDIT - -package fp - -import "golang.org/x/sys/cpu" - -var ( - supportAdx = cpu.X86.HasADX && cpu.X86.HasBMI2 - _ = supportAdx -) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/asm_noadx.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/asm_noadx.go deleted file mode 100644 index 92f8cc0f424..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/asm_noadx.go +++ /dev/null @@ -1,28 +0,0 @@ -//go:build noadx -// +build noadx - -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by consensys/gnark-crypto DO NOT EDIT - -package fp - -// note: this is needed for test purposes, as dynamically changing supportAdx doesn't flag -// certain errors (like fatal error: missing stackmap) -// this ensures we test all asm path. -var ( - supportAdx = false - _ = supportAdx -) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/doc.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/doc.go index ac24d2e0de5..0a37ea68ecf 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/doc.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/doc.go @@ -1,22 +1,13 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT // Package fp contains field arithmetic operations for modulus = 0x30644e...7cfd47. // -// The API is similar to math/big (big.Int), but the operations are significantly faster (up to 20x for the modular multiplication on amd64, see also https://hackmd.io/@gnark/modular_multiplication) +// The API is similar to math/big (big.Int), but the operations are significantly faster (up to 20x). +// +// Additionally fp.Vector offers an API to manipulate []Element using AVX512 instructions if available. // // The modulus is hardcoded in all the operations. // @@ -49,5 +40,7 @@ // // # Warning // -// This code has not been audited and is provided as-is. In particular, there is no security guarantees such as constant time implementation or side-channel attack resistance. +// There is no security guarantees such as constant time implementation or side-channel attack resistance. +// This code is provided as-is. Partially audited, see https://github.com/Consensys/gnark/tree/master/audits +// for more details. package fp diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element.go index 5ba388e7376..315cb1103b8 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -54,10 +43,10 @@ const ( // Field modulus q const ( - q0 uint64 = 4332616871279656263 - q1 uint64 = 10917124144477883021 - q2 uint64 = 13281191951274694749 - q3 uint64 = 3486998266802970665 + q0 = 4332616871279656263 + q1 = 10917124144477883021 + q2 = 13281191951274694749 + q3 = 3486998266802970665 ) var qElement = Element{ @@ -79,7 +68,10 @@ func Modulus() *big.Int { // q + r'.r = 1, i.e., qInvNeg = - q⁻¹ mod r // used for Montgomery reduction -const qInvNeg uint64 = 9786893198990664585 +const qInvNeg = 9786893198990664585 + +// mu = 2^288 / q needed for partial Barrett reduction +const mu uint64 = 22721021478 func init() { _modulus.SetString("30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47", 16) @@ -350,6 +342,16 @@ func (z *Element) SetRandom() (*Element, error) { } } +// MustSetRandom sets z to a uniform random value in [0, q). +// +// It panics if reading from crypto/rand.Reader errors. +func (z *Element) MustSetRandom() *Element { + if _, err := z.SetRandom(); err != nil { + panic(err) + } + return z +} + // smallerThanModulus returns true if z < q // This is not constant time func (z *Element) smallerThanModulus() bool { @@ -477,32 +479,8 @@ func (z *Element) Select(c int, x0 *Element, x1 *Element) *Element { // and is used for testing purposes. func _mulGeneric(z, x, y *Element) { - // Implements CIOS multiplication -- section 2.3.2 of Tolga Acar's thesis - // https://www.microsoft.com/en-us/research/wp-content/uploads/1998/06/97Acar.pdf - // - // The algorithm: - // - // for i=0 to N-1 - // C := 0 - // for j=0 to N-1 - // (C,t[j]) := t[j] + x[j]*y[i] + C - // (t[N+1],t[N]) := t[N] + C - // - // C := 0 - // m := t[0]*q'[0] mod D - // (C,_) := t[0] + m*q[0] - // for j=1 to N-1 - // (C,t[j-1]) := t[j] + m*q[j] + C - // - // (C,t[N-1]) := t[N] + C - // t[N] := t[N+1] + C - // - // → N is the number of machine words needed to store the modulus q - // → D is the word size. For example, on a 64-bit architecture D is 2 64 - // → x[i], y[i], q[i] is the ith word of the numbers x,y,q - // → q'[0] is the lowest word of the number -q⁻¹ mod r. This quantity is pre-computed, as it does not depend on the inputs. - // → t is a temporary array of size N+2 - // → C, S are machine words. A pair (C,S) refers to (hi-bits, lo-bits) of a two-word number + // Algorithm 2 of "Faster Montgomery Multiplication and Multi-Scalar-Multiplication for SNARKS" + // by Y. El Housni and G. Botrel https://doi.org/10.46586/tches.v2023.i3.504-521 var t [5]uint64 var D uint64 @@ -960,7 +938,7 @@ func (z *Element) SetBigInt(v *big.Int) *Element { // v == 0 return z } else if c != 1 && v.Cmp(&zero) != -1 { - // 0 < v < q + // 0 <= v < q return z.setBigInt(v) } @@ -1087,6 +1065,8 @@ type ByteOrder interface { String() string } +var errInvalidEncoding = errors.New("invalid fp.Element encoding") + // BigEndian is the big-endian implementation of ByteOrder and AppendByteOrder. var BigEndian bigEndian @@ -1102,7 +1082,7 @@ func (bigEndian) Element(b *[Bytes]byte) (Element, error) { z[3] = binary.BigEndian.Uint64((*b)[0:8]) if !z.smallerThanModulus() { - return Element{}, errors.New("invalid fp.Element encoding") + return Element{}, errInvalidEncoding } z.toMont() @@ -1132,7 +1112,7 @@ func (littleEndian) Element(b *[Bytes]byte) (Element, error) { z[3] = binary.LittleEndian.Uint64((*b)[24:32]) if !z.smallerThanModulus() { - return Element{}, errors.New("invalid fp.Element encoding") + return Element{}, errInvalidEncoding } z.toMont() diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element_amd64.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element_amd64.go new file mode 100644 index 00000000000..e02a9d04c2b --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element_amd64.go @@ -0,0 +1,62 @@ +//go:build !purego + +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fp + +import ( + _ "github.com/consensys/gnark-crypto/field/asm/element_4w" + "github.com/consensys/gnark-crypto/utils/cpu" +) + +var supportAdx = cpu.SupportADX + +//go:noescape +func MulBy3(x *Element) + +//go:noescape +func MulBy5(x *Element) + +//go:noescape +func MulBy13(x *Element) + +//go:noescape +func mul(res, x, y *Element) + +//go:noescape +func fromMont(res *Element) + +//go:noescape +func reduce(res *Element) + +// Butterfly sets +// +// a = a + b (mod q) +// b = a - b (mod q) +// +//go:noescape +func Butterfly(a, b *Element) + +// Mul z = x * y (mod q) +// +// x and y must be less than q +func (z *Element) Mul(x, y *Element) *Element { + + // Algorithm 2 of "Faster Montgomery Multiplication and Multi-Scalar-Multiplication for SNARKS" + // by Y. El Housni and G. Botrel https://doi.org/10.46586/tches.v2023.i3.504-521 + + mul(z, x, y) + return z +} + +// Square z = x * x (mod q) +// +// x must be less than q +func (z *Element) Square(x *Element) *Element { + // see Mul for doc. + mul(z, x, x) + return z +} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element_amd64.s b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element_amd64.s new file mode 100644 index 00000000000..b45615aa361 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element_amd64.s @@ -0,0 +1,10 @@ +//go:build !purego + +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +// We include the hash to force the Go compiler to recompile: 14652627197992229521 +#include "../../../field/asm/element_4w/element_4w_amd64.s" + diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element_arm64.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element_arm64.go new file mode 100644 index 00000000000..4d030715d62 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element_arm64.go @@ -0,0 +1,70 @@ +//go:build !purego + +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fp + +import ( + _ "github.com/consensys/gnark-crypto/field/asm/element_4w" +) + +// Butterfly sets +// +// a = a + b (mod q) +// b = a - b (mod q) +// +//go:noescape +func Butterfly(a, b *Element) + +//go:noescape +func mul(res, x, y *Element) + +// Mul z = x * y (mod q) +// +// x and y must be less than q +func (z *Element) Mul(x, y *Element) *Element { + mul(z, x, y) + return z +} + +// Square z = x * x (mod q) +// +// x must be less than q +func (z *Element) Square(x *Element) *Element { + // see Mul for doc. + mul(z, x, x) + return z +} + +// MulBy3 x *= 3 (mod q) +func MulBy3(x *Element) { + _x := *x + x.Double(x).Add(x, &_x) +} + +// MulBy5 x *= 5 (mod q) +func MulBy5(x *Element) { + _x := *x + x.Double(x).Double(x).Add(x, &_x) +} + +// MulBy13 x *= 13 (mod q) +func MulBy13(x *Element) { + var y = Element{ + 529957932336199972, + 13952065197595570812, + 769406925088786211, + 2691790815622165739, + } + x.Mul(x, &y) +} + +func fromMont(z *Element) { + _fromMontGeneric(z) +} + +//go:noescape +func reduce(res *Element) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element_arm64.s b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element_arm64.s new file mode 100644 index 00000000000..c8df07e3454 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element_arm64.s @@ -0,0 +1,10 @@ +//go:build !purego + +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +// We include the hash to force the Go compiler to recompile: 1501560133179981797 +#include "../../../field/asm/element_4w/element_4w_arm64.s" + diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element_exp.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element_exp.go index 315a40b9fb9..a1f9c2a4927 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element_exp.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element_exp.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element_mul_amd64.s b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element_mul_amd64.s deleted file mode 100644 index e58b316819c..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element_mul_amd64.s +++ /dev/null @@ -1,487 +0,0 @@ -// +build !purego - -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "textflag.h" -#include "funcdata.h" - -// modulus q -DATA q<>+0(SB)/8, $0x3c208c16d87cfd47 -DATA q<>+8(SB)/8, $0x97816a916871ca8d -DATA q<>+16(SB)/8, $0xb85045b68181585d -DATA q<>+24(SB)/8, $0x30644e72e131a029 -GLOBL q<>(SB), (RODATA+NOPTR), $32 - -// qInv0 q'[0] -DATA qInv0<>(SB)/8, $0x87d20782e4866389 -GLOBL qInv0<>(SB), (RODATA+NOPTR), $8 - -#define REDUCE(ra0, ra1, ra2, ra3, rb0, rb1, rb2, rb3) \ - MOVQ ra0, rb0; \ - SUBQ q<>(SB), ra0; \ - MOVQ ra1, rb1; \ - SBBQ q<>+8(SB), ra1; \ - MOVQ ra2, rb2; \ - SBBQ q<>+16(SB), ra2; \ - MOVQ ra3, rb3; \ - SBBQ q<>+24(SB), ra3; \ - CMOVQCS rb0, ra0; \ - CMOVQCS rb1, ra1; \ - CMOVQCS rb2, ra2; \ - CMOVQCS rb3, ra3; \ - -// mul(res, x, y *Element) -TEXT ·mul(SB), $24-24 - - // the algorithm is described in the Element.Mul declaration (.go) - // however, to benefit from the ADCX and ADOX carry chains - // we split the inner loops in 2: - // for i=0 to N-1 - // for j=0 to N-1 - // (A,t[j]) := t[j] + x[j]*y[i] + A - // m := t[0]*q'[0] mod W - // C,_ := t[0] + m*q[0] - // for j=1 to N-1 - // (C,t[j-1]) := t[j] + m*q[j] + C - // t[N-1] = C + A - - NO_LOCAL_POINTERS - CMPB ·supportAdx(SB), $1 - JNE l1 - MOVQ x+8(FP), SI - - // x[0] -> DI - // x[1] -> R8 - // x[2] -> R9 - // x[3] -> R10 - MOVQ 0(SI), DI - MOVQ 8(SI), R8 - MOVQ 16(SI), R9 - MOVQ 24(SI), R10 - MOVQ y+16(FP), R11 - - // A -> BP - // t[0] -> R14 - // t[1] -> R13 - // t[2] -> CX - // t[3] -> BX - // clear the flags - XORQ AX, AX - MOVQ 0(R11), DX - - // (A,t[0]) := x[0]*y[0] + A - MULXQ DI, R14, R13 - - // (A,t[1]) := x[1]*y[0] + A - MULXQ R8, AX, CX - ADOXQ AX, R13 - - // (A,t[2]) := x[2]*y[0] + A - MULXQ R9, AX, BX - ADOXQ AX, CX - - // (A,t[3]) := x[3]*y[0] + A - MULXQ R10, AX, BP - ADOXQ AX, BX - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADOXQ AX, BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, R12 - ADCXQ R14, AX - MOVQ R12, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R13, R14 - MULXQ q<>+8(SB), AX, R13 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R13 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R13 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // t[3] = C + A - MOVQ $0, AX - ADCXQ AX, BX - ADOXQ BP, BX - - // clear the flags - XORQ AX, AX - MOVQ 8(R11), DX - - // (A,t[0]) := t[0] + x[0]*y[1] + A - MULXQ DI, AX, BP - ADOXQ AX, R14 - - // (A,t[1]) := t[1] + x[1]*y[1] + A - ADCXQ BP, R13 - MULXQ R8, AX, BP - ADOXQ AX, R13 - - // (A,t[2]) := t[2] + x[2]*y[1] + A - ADCXQ BP, CX - MULXQ R9, AX, BP - ADOXQ AX, CX - - // (A,t[3]) := t[3] + x[3]*y[1] + A - ADCXQ BP, BX - MULXQ R10, AX, BP - ADOXQ AX, BX - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, R12 - ADCXQ R14, AX - MOVQ R12, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R13, R14 - MULXQ q<>+8(SB), AX, R13 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R13 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R13 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // t[3] = C + A - MOVQ $0, AX - ADCXQ AX, BX - ADOXQ BP, BX - - // clear the flags - XORQ AX, AX - MOVQ 16(R11), DX - - // (A,t[0]) := t[0] + x[0]*y[2] + A - MULXQ DI, AX, BP - ADOXQ AX, R14 - - // (A,t[1]) := t[1] + x[1]*y[2] + A - ADCXQ BP, R13 - MULXQ R8, AX, BP - ADOXQ AX, R13 - - // (A,t[2]) := t[2] + x[2]*y[2] + A - ADCXQ BP, CX - MULXQ R9, AX, BP - ADOXQ AX, CX - - // (A,t[3]) := t[3] + x[3]*y[2] + A - ADCXQ BP, BX - MULXQ R10, AX, BP - ADOXQ AX, BX - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, R12 - ADCXQ R14, AX - MOVQ R12, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R13, R14 - MULXQ q<>+8(SB), AX, R13 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R13 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R13 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // t[3] = C + A - MOVQ $0, AX - ADCXQ AX, BX - ADOXQ BP, BX - - // clear the flags - XORQ AX, AX - MOVQ 24(R11), DX - - // (A,t[0]) := t[0] + x[0]*y[3] + A - MULXQ DI, AX, BP - ADOXQ AX, R14 - - // (A,t[1]) := t[1] + x[1]*y[3] + A - ADCXQ BP, R13 - MULXQ R8, AX, BP - ADOXQ AX, R13 - - // (A,t[2]) := t[2] + x[2]*y[3] + A - ADCXQ BP, CX - MULXQ R9, AX, BP - ADOXQ AX, CX - - // (A,t[3]) := t[3] + x[3]*y[3] + A - ADCXQ BP, BX - MULXQ R10, AX, BP - ADOXQ AX, BX - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, R12 - ADCXQ R14, AX - MOVQ R12, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R13, R14 - MULXQ q<>+8(SB), AX, R13 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R13 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R13 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // t[3] = C + A - MOVQ $0, AX - ADCXQ AX, BX - ADOXQ BP, BX - - // reduce element(R14,R13,CX,BX) using temp registers (SI,R12,R11,DI) - REDUCE(R14,R13,CX,BX,SI,R12,R11,DI) - - MOVQ res+0(FP), AX - MOVQ R14, 0(AX) - MOVQ R13, 8(AX) - MOVQ CX, 16(AX) - MOVQ BX, 24(AX) - RET - -l1: - MOVQ res+0(FP), AX - MOVQ AX, (SP) - MOVQ x+8(FP), AX - MOVQ AX, 8(SP) - MOVQ y+16(FP), AX - MOVQ AX, 16(SP) - CALL ·_mulGeneric(SB) - RET - -TEXT ·fromMont(SB), $8-8 - NO_LOCAL_POINTERS - - // the algorithm is described here - // https://hackmd.io/@gnark/modular_multiplication - // when y = 1 we have: - // for i=0 to N-1 - // t[i] = x[i] - // for i=0 to N-1 - // m := t[0]*q'[0] mod W - // C,_ := t[0] + m*q[0] - // for j=1 to N-1 - // (C,t[j-1]) := t[j] + m*q[j] + C - // t[N-1] = C - CMPB ·supportAdx(SB), $1 - JNE l2 - MOVQ res+0(FP), DX - MOVQ 0(DX), R14 - MOVQ 8(DX), R13 - MOVQ 16(DX), CX - MOVQ 24(DX), BX - XORQ DX, DX - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R14, AX - MOVQ BP, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R13, R14 - MULXQ q<>+8(SB), AX, R13 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R13 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R13 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - MOVQ $0, AX - ADCXQ AX, BX - ADOXQ AX, BX - XORQ DX, DX - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R14, AX - MOVQ BP, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R13, R14 - MULXQ q<>+8(SB), AX, R13 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R13 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R13 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - MOVQ $0, AX - ADCXQ AX, BX - ADOXQ AX, BX - XORQ DX, DX - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R14, AX - MOVQ BP, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R13, R14 - MULXQ q<>+8(SB), AX, R13 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R13 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R13 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - MOVQ $0, AX - ADCXQ AX, BX - ADOXQ AX, BX - XORQ DX, DX - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R14, AX - MOVQ BP, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R13, R14 - MULXQ q<>+8(SB), AX, R13 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R13 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R13 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - MOVQ $0, AX - ADCXQ AX, BX - ADOXQ AX, BX - - // reduce element(R14,R13,CX,BX) using temp registers (SI,DI,R8,R9) - REDUCE(R14,R13,CX,BX,SI,DI,R8,R9) - - MOVQ res+0(FP), AX - MOVQ R14, 0(AX) - MOVQ R13, 8(AX) - MOVQ CX, 16(AX) - MOVQ BX, 24(AX) - RET - -l2: - MOVQ res+0(FP), AX - MOVQ AX, (SP) - CALL ·_fromMontGeneric(SB) - RET diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element_ops_amd64.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element_ops_amd64.go deleted file mode 100644 index 83bba45aedf..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element_ops_amd64.go +++ /dev/null @@ -1,107 +0,0 @@ -//go:build !purego -// +build !purego - -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by consensys/gnark-crypto DO NOT EDIT - -package fp - -//go:noescape -func MulBy3(x *Element) - -//go:noescape -func MulBy5(x *Element) - -//go:noescape -func MulBy13(x *Element) - -//go:noescape -func mul(res, x, y *Element) - -//go:noescape -func fromMont(res *Element) - -//go:noescape -func reduce(res *Element) - -// Butterfly sets -// -// a = a + b (mod q) -// b = a - b (mod q) -// -//go:noescape -func Butterfly(a, b *Element) - -// Mul z = x * y (mod q) -// -// x and y must be less than q -func (z *Element) Mul(x, y *Element) *Element { - - // Implements CIOS multiplication -- section 2.3.2 of Tolga Acar's thesis - // https://www.microsoft.com/en-us/research/wp-content/uploads/1998/06/97Acar.pdf - // - // The algorithm: - // - // for i=0 to N-1 - // C := 0 - // for j=0 to N-1 - // (C,t[j]) := t[j] + x[j]*y[i] + C - // (t[N+1],t[N]) := t[N] + C - // - // C := 0 - // m := t[0]*q'[0] mod D - // (C,_) := t[0] + m*q[0] - // for j=1 to N-1 - // (C,t[j-1]) := t[j] + m*q[j] + C - // - // (C,t[N-1]) := t[N] + C - // t[N] := t[N+1] + C - // - // → N is the number of machine words needed to store the modulus q - // → D is the word size. For example, on a 64-bit architecture D is 2 64 - // → x[i], y[i], q[i] is the ith word of the numbers x,y,q - // → q'[0] is the lowest word of the number -q⁻¹ mod r. This quantity is pre-computed, as it does not depend on the inputs. - // → t is a temporary array of size N+2 - // → C, S are machine words. A pair (C,S) refers to (hi-bits, lo-bits) of a two-word number - // - // As described here https://hackmd.io/@gnark/modular_multiplication we can get rid of one carry chain and simplify: - // (also described in https://eprint.iacr.org/2022/1400.pdf annex) - // - // for i=0 to N-1 - // (A,t[0]) := t[0] + x[0]*y[i] - // m := t[0]*q'[0] mod W - // C,_ := t[0] + m*q[0] - // for j=1 to N-1 - // (A,t[j]) := t[j] + x[j]*y[i] + A - // (C,t[j-1]) := t[j] + m*q[j] + C - // - // t[N-1] = C + A - // - // This optimization saves 5N + 2 additions in the algorithm, and can be used whenever the highest bit - // of the modulus is zero (and not all of the remaining bits are set). - - mul(z, x, y) - return z -} - -// Square z = x * x (mod q) -// -// x must be less than q -func (z *Element) Square(x *Element) *Element { - // see Mul for doc. - mul(z, x, x) - return z -} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element_ops_amd64.s b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element_ops_amd64.s deleted file mode 100644 index 48f34db8fe5..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element_ops_amd64.s +++ /dev/null @@ -1,230 +0,0 @@ -// +build !purego - -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "textflag.h" -#include "funcdata.h" - -// modulus q -DATA q<>+0(SB)/8, $0x3c208c16d87cfd47 -DATA q<>+8(SB)/8, $0x97816a916871ca8d -DATA q<>+16(SB)/8, $0xb85045b68181585d -DATA q<>+24(SB)/8, $0x30644e72e131a029 -GLOBL q<>(SB), (RODATA+NOPTR), $32 - -// qInv0 q'[0] -DATA qInv0<>(SB)/8, $0x87d20782e4866389 -GLOBL qInv0<>(SB), (RODATA+NOPTR), $8 - -#define REDUCE(ra0, ra1, ra2, ra3, rb0, rb1, rb2, rb3) \ - MOVQ ra0, rb0; \ - SUBQ q<>(SB), ra0; \ - MOVQ ra1, rb1; \ - SBBQ q<>+8(SB), ra1; \ - MOVQ ra2, rb2; \ - SBBQ q<>+16(SB), ra2; \ - MOVQ ra3, rb3; \ - SBBQ q<>+24(SB), ra3; \ - CMOVQCS rb0, ra0; \ - CMOVQCS rb1, ra1; \ - CMOVQCS rb2, ra2; \ - CMOVQCS rb3, ra3; \ - -TEXT ·reduce(SB), NOSPLIT, $0-8 - MOVQ res+0(FP), AX - MOVQ 0(AX), DX - MOVQ 8(AX), CX - MOVQ 16(AX), BX - MOVQ 24(AX), SI - - // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) - - MOVQ DX, 0(AX) - MOVQ CX, 8(AX) - MOVQ BX, 16(AX) - MOVQ SI, 24(AX) - RET - -// MulBy3(x *Element) -TEXT ·MulBy3(SB), NOSPLIT, $0-8 - MOVQ x+0(FP), AX - MOVQ 0(AX), DX - MOVQ 8(AX), CX - MOVQ 16(AX), BX - MOVQ 24(AX), SI - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - - // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) - - ADDQ 0(AX), DX - ADCQ 8(AX), CX - ADCQ 16(AX), BX - ADCQ 24(AX), SI - - // reduce element(DX,CX,BX,SI) using temp registers (R11,R12,R13,R14) - REDUCE(DX,CX,BX,SI,R11,R12,R13,R14) - - MOVQ DX, 0(AX) - MOVQ CX, 8(AX) - MOVQ BX, 16(AX) - MOVQ SI, 24(AX) - RET - -// MulBy5(x *Element) -TEXT ·MulBy5(SB), NOSPLIT, $0-8 - MOVQ x+0(FP), AX - MOVQ 0(AX), DX - MOVQ 8(AX), CX - MOVQ 16(AX), BX - MOVQ 24(AX), SI - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - - // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) - - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - - // reduce element(DX,CX,BX,SI) using temp registers (R11,R12,R13,R14) - REDUCE(DX,CX,BX,SI,R11,R12,R13,R14) - - ADDQ 0(AX), DX - ADCQ 8(AX), CX - ADCQ 16(AX), BX - ADCQ 24(AX), SI - - // reduce element(DX,CX,BX,SI) using temp registers (R15,DI,R8,R9) - REDUCE(DX,CX,BX,SI,R15,DI,R8,R9) - - MOVQ DX, 0(AX) - MOVQ CX, 8(AX) - MOVQ BX, 16(AX) - MOVQ SI, 24(AX) - RET - -// MulBy13(x *Element) -TEXT ·MulBy13(SB), NOSPLIT, $0-8 - MOVQ x+0(FP), AX - MOVQ 0(AX), DX - MOVQ 8(AX), CX - MOVQ 16(AX), BX - MOVQ 24(AX), SI - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - - // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) - - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - - // reduce element(DX,CX,BX,SI) using temp registers (R11,R12,R13,R14) - REDUCE(DX,CX,BX,SI,R11,R12,R13,R14) - - MOVQ DX, R11 - MOVQ CX, R12 - MOVQ BX, R13 - MOVQ SI, R14 - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - - // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) - - ADDQ R11, DX - ADCQ R12, CX - ADCQ R13, BX - ADCQ R14, SI - - // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) - - ADDQ 0(AX), DX - ADCQ 8(AX), CX - ADCQ 16(AX), BX - ADCQ 24(AX), SI - - // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) - - MOVQ DX, 0(AX) - MOVQ CX, 8(AX) - MOVQ BX, 16(AX) - MOVQ SI, 24(AX) - RET - -// Butterfly(a, b *Element) sets a = a + b; b = a - b -TEXT ·Butterfly(SB), NOSPLIT, $0-16 - MOVQ a+0(FP), AX - MOVQ 0(AX), CX - MOVQ 8(AX), BX - MOVQ 16(AX), SI - MOVQ 24(AX), DI - MOVQ CX, R8 - MOVQ BX, R9 - MOVQ SI, R10 - MOVQ DI, R11 - XORQ AX, AX - MOVQ b+8(FP), DX - ADDQ 0(DX), CX - ADCQ 8(DX), BX - ADCQ 16(DX), SI - ADCQ 24(DX), DI - SUBQ 0(DX), R8 - SBBQ 8(DX), R9 - SBBQ 16(DX), R10 - SBBQ 24(DX), R11 - MOVQ $0x3c208c16d87cfd47, R12 - MOVQ $0x97816a916871ca8d, R13 - MOVQ $0xb85045b68181585d, R14 - MOVQ $0x30644e72e131a029, R15 - CMOVQCC AX, R12 - CMOVQCC AX, R13 - CMOVQCC AX, R14 - CMOVQCC AX, R15 - ADDQ R12, R8 - ADCQ R13, R9 - ADCQ R14, R10 - ADCQ R15, R11 - MOVQ R8, 0(DX) - MOVQ R9, 8(DX) - MOVQ R10, 16(DX) - MOVQ R11, 24(DX) - - // reduce element(CX,BX,SI,DI) using temp registers (R8,R9,R10,R11) - REDUCE(CX,BX,SI,DI,R8,R9,R10,R11) - - MOVQ a+0(FP), AX - MOVQ CX, 0(AX) - MOVQ BX, 8(AX) - MOVQ SI, 16(AX) - MOVQ DI, 24(AX) - RET diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element_ops_purego.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element_purego.go similarity index 80% rename from vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element_ops_purego.go rename to vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element_purego.go index 93aca54ddb4..69565d890bb 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element_ops_purego.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/element_purego.go @@ -1,19 +1,7 @@ -//go:build !amd64 || purego -// +build !amd64 purego +//go:build purego || (!amd64 && !arm64) -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -44,14 +32,6 @@ func MulBy13(x *Element) { x.Mul(x, &y) } -// Butterfly sets -// -// a = a + b (mod q) -// b = a - b (mod q) -func Butterfly(a, b *Element) { - _butterflyGeneric(a, b) -} - func fromMont(z *Element) { _fromMontGeneric(z) } @@ -65,48 +45,8 @@ func reduce(z *Element) { // x and y must be less than q func (z *Element) Mul(x, y *Element) *Element { - // Implements CIOS multiplication -- section 2.3.2 of Tolga Acar's thesis - // https://www.microsoft.com/en-us/research/wp-content/uploads/1998/06/97Acar.pdf - // - // The algorithm: - // - // for i=0 to N-1 - // C := 0 - // for j=0 to N-1 - // (C,t[j]) := t[j] + x[j]*y[i] + C - // (t[N+1],t[N]) := t[N] + C - // - // C := 0 - // m := t[0]*q'[0] mod D - // (C,_) := t[0] + m*q[0] - // for j=1 to N-1 - // (C,t[j-1]) := t[j] + m*q[j] + C - // - // (C,t[N-1]) := t[N] + C - // t[N] := t[N+1] + C - // - // → N is the number of machine words needed to store the modulus q - // → D is the word size. For example, on a 64-bit architecture D is 2 64 - // → x[i], y[i], q[i] is the ith word of the numbers x,y,q - // → q'[0] is the lowest word of the number -q⁻¹ mod r. This quantity is pre-computed, as it does not depend on the inputs. - // → t is a temporary array of size N+2 - // → C, S are machine words. A pair (C,S) refers to (hi-bits, lo-bits) of a two-word number - // - // As described here https://hackmd.io/@gnark/modular_multiplication we can get rid of one carry chain and simplify: - // (also described in https://eprint.iacr.org/2022/1400.pdf annex) - // - // for i=0 to N-1 - // (A,t[0]) := t[0] + x[0]*y[i] - // m := t[0]*q'[0] mod W - // C,_ := t[0] + m*q[0] - // for j=1 to N-1 - // (A,t[j]) := t[j] + x[j]*y[i] + A - // (C,t[j-1]) := t[j] + m*q[j] + C - // - // t[N-1] = C + A - // - // This optimization saves 5N + 2 additions in the algorithm, and can be used whenever the highest bit - // of the modulus is zero (and not all of the remaining bits are set). + // Algorithm 2 of "Faster Montgomery Multiplication and Multi-Scalar-Multiplication for SNARKS" + // by Y. El Housni and G. Botrel https://doi.org/10.46586/tches.v2023.i3.504-521 var t0, t1, t2, t3 uint64 var u0, u1, u2, u3 uint64 @@ -441,3 +381,11 @@ func (z *Element) Square(x *Element) *Element { } return z } + +// Butterfly sets +// +// a = a + b (mod q) +// b = a - b (mod q) +func Butterfly(a, b *Element) { + _butterflyGeneric(a, b) +} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/vector.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/vector.go index acf1e44ea92..46e630879bd 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/vector.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/vector.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -19,9 +8,12 @@ package fp import ( "bytes" "encoding/binary" + "errors" "fmt" "io" + "math/bits" "runtime" + "slices" "strings" "sync" "sync/atomic" @@ -78,40 +70,84 @@ func (vector *Vector) WriteTo(w io.Writer) (int64, error) { return n, nil } -// AsyncReadFrom reads a vector of big endian encoded Element. -// Length of the vector must be encoded as a uint32 on the first 4 bytes. -// It consumes the needed bytes from the reader and returns the number of bytes read and an error if any. -// It also returns a channel that will be closed when the validation is done. -// The validation consist of checking that the elements are smaller than the modulus, and -// converting them to montgomery form. -func (vector *Vector) AsyncReadFrom(r io.Reader) (int64, error, chan error) { +// AsyncReadFrom implements an asynchronous version of [Vector.ReadFrom]. It +// reads the reader r in full and then performs the validation and conversion to +// Montgomery form separately in a goroutine. Any error encountered during +// reading is returned directly, while errors encountered during +// validation/conversion are sent on the returned channel. Thus the caller must +// wait on the channel to ensure the vector is ready to use. The method +// additionally returns the number of bytes read from r. +// +// The errors during reading can be: +// - an error while reading from r; +// - not enough bytes in r to read the full vector indicated by header. +// +// The reader can contain more bytes than needed to decode the vector, in which +// case the extra bytes are ignored. In that case the reader is not seeked nor +// read further. +// +// The method allocates sufficiently large slice to store the vector. If the +// current slice fits the vector, it is reused, otherwise the slice is grown to +// fit the vector. +// +// The serialized encoding is as follows: +// - first 4 bytes: length of the vector as a big-endian uint32 +// - for each element of the vector, [Bytes] bytes representing the element in +// big-endian encoding. +func (vector *Vector) AsyncReadFrom(r io.Reader) (int64, error, chan error) { // nolint ST1008 chErr := make(chan error, 1) var buf [Bytes]byte if read, err := io.ReadFull(r, buf[:4]); err != nil { close(chErr) return int64(read), err, chErr } - sliceLen := binary.BigEndian.Uint32(buf[:4]) - - n := int64(4) - (*vector) = make(Vector, sliceLen) - if sliceLen == 0 { + headerSliceLen := uint64(binary.BigEndian.Uint32(buf[:4])) + + // to avoid allocating too large slice when the header is tampered, we limit + // the maximum allocation. We set the target to 4GB. This incurs a performance + // hit when reading very large slices, but protects against OOM. + targetSize := uint64(1 << 32) // 4GB + if bits.UintSize == 32 { + // reduce target size to 1GB on 32 bits architectures + targetSize = uint64(1 << 30) // 1GB + } + maxAllocateSliceLength := targetSize / uint64(Bytes) + + totalRead := int64(4) + *vector = (*vector)[:0] + if headerSliceLen == 0 { + // if the vector was nil previously even by reslicing we have a nil vector. + // but we want to have an empty slice to indicate that the vector has zero length. + if *vector == nil { + *vector = []Element{} + } + // we return already here to avoid launching a goroutine doing nothing below close(chErr) - return n, nil, chErr + return totalRead, nil, chErr } - bSlice := unsafe.Slice((*byte)(unsafe.Pointer(&(*vector)[0])), sliceLen*Bytes) - read, err := io.ReadFull(r, bSlice) - n += int64(read) - if err != nil { - close(chErr) - return n, err, chErr + for i := uint64(0); i < headerSliceLen; i += maxAllocateSliceLength { + if len(*vector) <= int(i) { + (*vector) = append(*vector, make([]Element, int(min(headerSliceLen-i, maxAllocateSliceLength)))...) + } + bSlice := unsafe.Slice((*byte)(unsafe.Pointer(&(*vector)[i])), int(min(headerSliceLen-i, maxAllocateSliceLength))*Bytes) + read, err := io.ReadFull(r, bSlice) + totalRead += int64(read) + if errors.Is(err, io.ErrUnexpectedEOF) { + close(chErr) + return totalRead, fmt.Errorf("less data than expected: read %d elements, expected %d", i+uint64(read)/Bytes, headerSliceLen), chErr + } + if err != nil { + close(chErr) + return totalRead, err, chErr + } } + bSlice := unsafe.Slice((*byte)(unsafe.Pointer(&(*vector)[0])), int(headerSliceLen)*Bytes) go func() { var cptErrors uint64 // process the elements in parallel - execute(int(sliceLen), func(start, end int) { + execute(int(headerSliceLen), func(start, end int) { var z Element for i := start; i < end; i++ { @@ -138,35 +174,72 @@ func (vector *Vector) AsyncReadFrom(r io.Reader) (int64, error, chan error) { } close(chErr) }() - return n, nil, chErr + return totalRead, nil, chErr } -// ReadFrom implements io.ReaderFrom and reads a vector of big endian encoded Element. -// Length of the vector must be encoded as a uint32 on the first 4 bytes. +// ReadFrom reads the vector from the reader r. It returns the number of bytes +// read and an error, if any. The errors can be: +// - an error while reading from r; +// - not enough bytes in r to read the full vector indicated by header; +// - when decoding the bytes into elements. +// +// The reader can contain more bytes than needed to decode the vector, in which case +// the extra bytes are ignored. In that case the reader is not seeked nor read further. +// +// The method allocates sufficiently large slice to store the vector. If the current slice fits +// the vector, it is reused, otherwise the slice is grown to fit the vector. +// +// The serialized encoding is as follows: +// - first 4 bytes: length of the vector as a big-endian uint32 +// - for each element of the vector, [Bytes] bytes representing the element in big-endian encoding. +// +// The method implements [io.ReaderFrom] interface. func (vector *Vector) ReadFrom(r io.Reader) (int64, error) { - var buf [Bytes]byte if read, err := io.ReadFull(r, buf[:4]); err != nil { return int64(read), err } - sliceLen := binary.BigEndian.Uint32(buf[:4]) - - n := int64(4) - (*vector) = make(Vector, sliceLen) + headerSliceLen := uint64(binary.BigEndian.Uint32(buf[:4])) + + // to avoid allocating too large slice when the header is tampered, we limit + // the maximum allocation. We set the target to 4GB. This incurs a performance + // hit when reading very large slices, but protects against OOM. + targetSize := uint64(1 << 32) // 4GB + if bits.UintSize == 32 { + // reduce target size to 1GB on 32 bits architectures + targetSize = uint64(1 << 30) // 1GB + } + maxAllocateSliceLength := targetSize / uint64(Bytes) + + totalRead := int64(4) // include already the header length + *vector = (*vector)[:0] + // if the vector was nil previously even by reslicing we have a nil vector. But we want + // to have an empty slice to indicate that the vector has zero length. When headerSliceLen == 0 + // we handle this edge case after reading the header as the loop body below is skipped. + if headerSliceLen == 0 && *vector == nil { + *vector = []Element{} + } - for i := 0; i < int(sliceLen); i++ { + for i := uint64(0); i < headerSliceLen; i++ { read, err := io.ReadFull(r, buf[:]) - n += int64(read) + totalRead += int64(read) + if errors.Is(err, io.ErrUnexpectedEOF) { + return totalRead, fmt.Errorf("less data than expected: read %d elements, expected %d", i, headerSliceLen) + } if err != nil { - return n, err + return totalRead, fmt.Errorf("error reading element %d: %w", i, err) } - (*vector)[i], err = BigEndian.Element(&buf) + if uint64(cap(*vector)) <= i { + (*vector) = slices.Grow(*vector, int(min(headerSliceLen-i, maxAllocateSliceLength))) + } + el, err := BigEndian.Element(&buf) if err != nil { - return n, err + return totalRead, fmt.Errorf("error decoding element %d: %w", i, err) } + *vector = append(*vector, el) } - return n, nil + return totalRead, nil } // String implements fmt.Stringer interface @@ -199,6 +272,88 @@ func (vector Vector) Swap(i, j int) { vector[i], vector[j] = vector[j], vector[i] } +// SetRandom sets the elements in vector to independent uniform random values in [0, q). +// +// This might error only if reading from crypto/rand.Reader errors, +// in which case the values in vector are undefined. +func (vector Vector) SetRandom() error { + for i := range vector { + if _, err := vector[i].SetRandom(); err != nil { + return err + } + } + return nil +} + +// MustSetRandom sets the elements in vector to independent uniform random values in [0, q). +// +// It panics if reading from crypto/rand.Reader errors. +func (vector Vector) MustSetRandom() { + for i := range vector { + if _, err := vector[i].SetRandom(); err != nil { + panic(err) + } + } +} + +// Equal returns true if vector and other have the same length and same elements. +func (vector Vector) Equal(other Vector) bool { + return slices.Equal(vector, other) +} + +func addVecGeneric(res, a, b Vector) { + if len(a) != len(b) || len(a) != len(res) { + panic("vector.Add: vectors don't have the same length") + } + for i := 0; i < len(a); i++ { + res[i].Add(&a[i], &b[i]) + } +} + +func subVecGeneric(res, a, b Vector) { + if len(a) != len(b) || len(a) != len(res) { + panic("vector.Sub: vectors don't have the same length") + } + for i := 0; i < len(a); i++ { + res[i].Sub(&a[i], &b[i]) + } +} + +func scalarMulVecGeneric(res, a Vector, b *Element) { + if len(a) != len(res) { + panic("vector.ScalarMul: vectors don't have the same length") + } + for i := 0; i < len(a); i++ { + res[i].Mul(&a[i], b) + } +} + +func sumVecGeneric(res *Element, a Vector) { + for i := 0; i < len(a); i++ { + res.Add(res, &a[i]) + } +} + +func innerProductVecGeneric(res *Element, a, b Vector) { + if len(a) != len(b) { + panic("vector.InnerProduct: vectors don't have the same length") + } + var tmp Element + for i := 0; i < len(a); i++ { + tmp.Mul(&a[i], &b[i]) + res.Add(res, &tmp) + } +} + +func mulVecGeneric(res, a, b Vector) { + if len(a) != len(b) || len(a) != len(res) { + panic("vector.Mul: vectors don't have the same length") + } + for i := 0; i < len(a); i++ { + res[i].Mul(&a[i], &b[i]) + } +} + // TODO @gbotrel make a public package out of that. // execute executes the work function in parallel. // this is copy paste from internal/parallel/parallel.go diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/vector_amd64.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/vector_amd64.go new file mode 100644 index 00000000000..d843c6a0e36 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/vector_amd64.go @@ -0,0 +1,154 @@ +//go:build !purego + +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fp + +import ( + _ "github.com/consensys/gnark-crypto/field/asm/element_4w" + "github.com/consensys/gnark-crypto/utils/cpu" +) + +// Add adds two vectors element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) Add(a, b Vector) { + if len(a) != len(b) || len(a) != len(*vector) { + panic("vector.Add: vectors don't have the same length") + } + n := uint64(len(a)) + addVec(&(*vector)[0], &a[0], &b[0], n) +} + +//go:noescape +func addVec(res, a, b *Element, n uint64) + +// Sub subtracts two vectors element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) Sub(a, b Vector) { + if len(a) != len(b) || len(a) != len(*vector) { + panic("vector.Sub: vectors don't have the same length") + } + subVec(&(*vector)[0], &a[0], &b[0], uint64(len(a))) +} + +//go:noescape +func subVec(res, a, b *Element, n uint64) + +// ScalarMul multiplies a vector by a scalar element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) ScalarMul(a Vector, b *Element) { + if len(a) != len(*vector) { + panic("vector.ScalarMul: vectors don't have the same length") + } + const maxN = (1 << 32) - 1 + if !cpu.SupportAVX512 || uint64(len(a)) >= maxN { + // call scalarMulVecGeneric + scalarMulVecGeneric(*vector, a, b) + return + } + n := uint64(len(a)) + if n == 0 { + return + } + // the code for scalarMul is identical to mulVec; and it expects at least + // 2 elements in the vector to fill the Z registers + var bb [2]Element + bb[0] = *b + bb[1] = *b + const blockSize = 16 + scalarMulVec(&(*vector)[0], &a[0], &bb[0], n/blockSize, qInvNeg) + if n%blockSize != 0 { + // call scalarMulVecGeneric on the rest + start := n - n%blockSize + scalarMulVecGeneric((*vector)[start:], a[start:], b) + } +} + +//go:noescape +func scalarMulVec(res, a, b *Element, n uint64, qInvNeg uint64) + +// Sum computes the sum of all elements in the vector. +func (vector *Vector) Sum() (res Element) { + n := uint64(len(*vector)) + if n == 0 { + return + } + const minN = 16 * 7 // AVX512 slower than generic for small n + const maxN = (1 << 32) - 1 + if !cpu.SupportAVX512 || n <= minN || n >= maxN { + // call sumVecGeneric + sumVecGeneric(&res, *vector) + return + } + sumVec(&res, &(*vector)[0], uint64(len(*vector))) + return +} + +//go:noescape +func sumVec(res *Element, a *Element, n uint64) + +// InnerProduct computes the inner product of two vectors. +// It panics if the vectors don't have the same length. +func (vector *Vector) InnerProduct(other Vector) (res Element) { + n := uint64(len(*vector)) + if n == 0 { + return + } + if n != uint64(len(other)) { + panic("vector.InnerProduct: vectors don't have the same length") + } + const maxN = (1 << 32) - 1 + if !cpu.SupportAVX512 || n >= maxN { + // call innerProductVecGeneric + // note; we could split the vector into smaller chunks and call innerProductVec + innerProductVecGeneric(&res, *vector, other) + return + } + innerProdVec(&res[0], &(*vector)[0], &other[0], uint64(len(*vector))) + + return +} + +//go:noescape +func innerProdVec(res *uint64, a, b *Element, n uint64) + +// Mul multiplies two vectors element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) Mul(a, b Vector) { + if len(a) != len(b) || len(a) != len(*vector) { + panic("vector.Mul: vectors don't have the same length") + } + n := uint64(len(a)) + if n == 0 { + return + } + const maxN = (1 << 32) - 1 + if !cpu.SupportAVX512 || n >= maxN { + // call mulVecGeneric + mulVecGeneric(*vector, a, b) + return + } + + const blockSize = 16 + mulVec(&(*vector)[0], &a[0], &b[0], n/blockSize, qInvNeg) + if n%blockSize != 0 { + // call mulVecGeneric on the rest + start := n - n%blockSize + mulVecGeneric((*vector)[start:], a[start:], b[start:]) + } + +} + +// Patterns use for transposing the vectors in mulVec +var ( + pattern1 = [8]uint64{0, 8, 1, 9, 2, 10, 3, 11} + pattern2 = [8]uint64{12, 4, 13, 5, 14, 6, 15, 7} + pattern3 = [8]uint64{0, 1, 8, 9, 2, 3, 10, 11} + pattern4 = [8]uint64{12, 13, 4, 5, 14, 15, 6, 7} +) + +//go:noescape +func mulVec(res, a, b *Element, n uint64, qInvNeg uint64) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/vector_purego.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/vector_purego.go new file mode 100644 index 00000000000..98343052a26 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fp/vector_purego.go @@ -0,0 +1,45 @@ +//go:build purego || !amd64 + +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fp + +// Add adds two vectors element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) Add(a, b Vector) { + addVecGeneric(*vector, a, b) +} + +// Sub subtracts two vectors element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) Sub(a, b Vector) { + subVecGeneric(*vector, a, b) +} + +// ScalarMul multiplies a vector by a scalar element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) ScalarMul(a Vector, b *Element) { + scalarMulVecGeneric(*vector, a, b) +} + +// Sum computes the sum of all elements in the vector. +func (vector *Vector) Sum() (res Element) { + sumVecGeneric(&res, *vector) + return +} + +// InnerProduct computes the inner product of two vectors. +// It panics if the vectors don't have the same length. +func (vector *Vector) InnerProduct(other Vector) (res Element) { + innerProductVecGeneric(&res, *vector, other) + return +} + +// Mul multiplies two vectors element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) Mul(a, b Vector) { + mulVecGeneric(*vector, a, b) +} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/arith.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/arith.go index 7cfd55da199..8dbae56e320 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/arith.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/arith.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -58,16 +47,3 @@ func madd3(a, b, c, d, e uint64) (hi uint64, lo uint64) { hi, _ = bits.Add64(hi, e, carry) return } -func max(a int, b int) int { - if a > b { - return a - } - return b -} - -func min(a int, b int) int { - if a < b { - return a - } - return b -} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/asm.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/asm.go deleted file mode 100644 index da061913ba7..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/asm.go +++ /dev/null @@ -1,27 +0,0 @@ -//go:build !noadx -// +build !noadx - -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by consensys/gnark-crypto DO NOT EDIT - -package fr - -import "golang.org/x/sys/cpu" - -var ( - supportAdx = cpu.X86.HasADX && cpu.X86.HasBMI2 - _ = supportAdx -) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/asm_noadx.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/asm_noadx.go deleted file mode 100644 index 7f52ffa197b..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/asm_noadx.go +++ /dev/null @@ -1,28 +0,0 @@ -//go:build noadx -// +build noadx - -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by consensys/gnark-crypto DO NOT EDIT - -package fr - -// note: this is needed for test purposes, as dynamically changing supportAdx doesn't flag -// certain errors (like fatal error: missing stackmap) -// this ensures we test all asm path. -var ( - supportAdx = false - _ = supportAdx -) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/doc.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/doc.go index 35388f880f8..49b9df511a1 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/doc.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/doc.go @@ -1,22 +1,13 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT // Package fr contains field arithmetic operations for modulus = 0x30644e...000001. // -// The API is similar to math/big (big.Int), but the operations are significantly faster (up to 20x for the modular multiplication on amd64, see also https://hackmd.io/@gnark/modular_multiplication) +// The API is similar to math/big (big.Int), but the operations are significantly faster (up to 20x). +// +// Additionally fr.Vector offers an API to manipulate []Element using AVX512 instructions if available. // // The modulus is hardcoded in all the operations. // @@ -49,5 +40,7 @@ // // # Warning // -// This code has not been audited and is provided as-is. In particular, there is no security guarantees such as constant time implementation or side-channel attack resistance. +// There is no security guarantees such as constant time implementation or side-channel attack resistance. +// This code is provided as-is. Partially audited, see https://github.com/Consensys/gnark/tree/master/audits +// for more details. package fr diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element.go index cda0b2c2885..0bb356cbf77 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -54,10 +43,10 @@ const ( // Field modulus q const ( - q0 uint64 = 4891460686036598785 - q1 uint64 = 2896914383306846353 - q2 uint64 = 13281191951274694749 - q3 uint64 = 3486998266802970665 + q0 = 4891460686036598785 + q1 = 2896914383306846353 + q2 = 13281191951274694749 + q3 = 3486998266802970665 ) var qElement = Element{ @@ -79,7 +68,10 @@ func Modulus() *big.Int { // q + r'.r = 1, i.e., qInvNeg = - q⁻¹ mod r // used for Montgomery reduction -const qInvNeg uint64 = 14042775128853446655 +const qInvNeg = 14042775128853446655 + +// mu = 2^288 / q needed for partial Barrett reduction +const mu uint64 = 22721021478 func init() { _modulus.SetString("30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001", 16) @@ -350,6 +342,16 @@ func (z *Element) SetRandom() (*Element, error) { } } +// MustSetRandom sets z to a uniform random value in [0, q). +// +// It panics if reading from crypto/rand.Reader errors. +func (z *Element) MustSetRandom() *Element { + if _, err := z.SetRandom(); err != nil { + panic(err) + } + return z +} + // smallerThanModulus returns true if z < q // This is not constant time func (z *Element) smallerThanModulus() bool { @@ -477,32 +479,8 @@ func (z *Element) Select(c int, x0 *Element, x1 *Element) *Element { // and is used for testing purposes. func _mulGeneric(z, x, y *Element) { - // Implements CIOS multiplication -- section 2.3.2 of Tolga Acar's thesis - // https://www.microsoft.com/en-us/research/wp-content/uploads/1998/06/97Acar.pdf - // - // The algorithm: - // - // for i=0 to N-1 - // C := 0 - // for j=0 to N-1 - // (C,t[j]) := t[j] + x[j]*y[i] + C - // (t[N+1],t[N]) := t[N] + C - // - // C := 0 - // m := t[0]*q'[0] mod D - // (C,_) := t[0] + m*q[0] - // for j=1 to N-1 - // (C,t[j-1]) := t[j] + m*q[j] + C - // - // (C,t[N-1]) := t[N] + C - // t[N] := t[N+1] + C - // - // → N is the number of machine words needed to store the modulus q - // → D is the word size. For example, on a 64-bit architecture D is 2 64 - // → x[i], y[i], q[i] is the ith word of the numbers x,y,q - // → q'[0] is the lowest word of the number -q⁻¹ mod r. This quantity is pre-computed, as it does not depend on the inputs. - // → t is a temporary array of size N+2 - // → C, S are machine words. A pair (C,S) refers to (hi-bits, lo-bits) of a two-word number + // Algorithm 2 of "Faster Montgomery Multiplication and Multi-Scalar-Multiplication for SNARKS" + // by Y. El Housni and G. Botrel https://doi.org/10.46586/tches.v2023.i3.504-521 var t [5]uint64 var D uint64 @@ -960,7 +938,7 @@ func (z *Element) SetBigInt(v *big.Int) *Element { // v == 0 return z } else if c != 1 && v.Cmp(&zero) != -1 { - // 0 < v < q + // 0 <= v < q return z.setBigInt(v) } @@ -1087,6 +1065,8 @@ type ByteOrder interface { String() string } +var errInvalidEncoding = errors.New("invalid fr.Element encoding") + // BigEndian is the big-endian implementation of ByteOrder and AppendByteOrder. var BigEndian bigEndian @@ -1102,7 +1082,7 @@ func (bigEndian) Element(b *[Bytes]byte) (Element, error) { z[3] = binary.BigEndian.Uint64((*b)[0:8]) if !z.smallerThanModulus() { - return Element{}, errors.New("invalid fr.Element encoding") + return Element{}, errInvalidEncoding } z.toMont() @@ -1132,7 +1112,7 @@ func (littleEndian) Element(b *[Bytes]byte) (Element, error) { z[3] = binary.LittleEndian.Uint64((*b)[24:32]) if !z.smallerThanModulus() { - return Element{}, errors.New("invalid fr.Element encoding") + return Element{}, errInvalidEncoding } z.toMont() diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element_amd64.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element_amd64.go new file mode 100644 index 00000000000..c282ebc9fc8 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element_amd64.go @@ -0,0 +1,62 @@ +//go:build !purego + +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fr + +import ( + _ "github.com/consensys/gnark-crypto/field/asm/element_4w" + "github.com/consensys/gnark-crypto/utils/cpu" +) + +var supportAdx = cpu.SupportADX + +//go:noescape +func MulBy3(x *Element) + +//go:noescape +func MulBy5(x *Element) + +//go:noescape +func MulBy13(x *Element) + +//go:noescape +func mul(res, x, y *Element) + +//go:noescape +func fromMont(res *Element) + +//go:noescape +func reduce(res *Element) + +// Butterfly sets +// +// a = a + b (mod q) +// b = a - b (mod q) +// +//go:noescape +func Butterfly(a, b *Element) + +// Mul z = x * y (mod q) +// +// x and y must be less than q +func (z *Element) Mul(x, y *Element) *Element { + + // Algorithm 2 of "Faster Montgomery Multiplication and Multi-Scalar-Multiplication for SNARKS" + // by Y. El Housni and G. Botrel https://doi.org/10.46586/tches.v2023.i3.504-521 + + mul(z, x, y) + return z +} + +// Square z = x * x (mod q) +// +// x must be less than q +func (z *Element) Square(x *Element) *Element { + // see Mul for doc. + mul(z, x, x) + return z +} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element_amd64.s b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element_amd64.s new file mode 100644 index 00000000000..b45615aa361 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element_amd64.s @@ -0,0 +1,10 @@ +//go:build !purego + +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +// We include the hash to force the Go compiler to recompile: 14652627197992229521 +#include "../../../field/asm/element_4w/element_4w_amd64.s" + diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element_arm64.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element_arm64.go new file mode 100644 index 00000000000..b99b03a7e97 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element_arm64.go @@ -0,0 +1,70 @@ +//go:build !purego + +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fr + +import ( + _ "github.com/consensys/gnark-crypto/field/asm/element_4w" +) + +// Butterfly sets +// +// a = a + b (mod q) +// b = a - b (mod q) +// +//go:noescape +func Butterfly(a, b *Element) + +//go:noescape +func mul(res, x, y *Element) + +// Mul z = x * y (mod q) +// +// x and y must be less than q +func (z *Element) Mul(x, y *Element) *Element { + mul(z, x, y) + return z +} + +// Square z = x * x (mod q) +// +// x must be less than q +func (z *Element) Square(x *Element) *Element { + // see Mul for doc. + mul(z, x, x) + return z +} + +// MulBy3 x *= 3 (mod q) +func MulBy3(x *Element) { + _x := *x + x.Double(x).Add(x, &_x) +} + +// MulBy5 x *= 5 (mod q) +func MulBy5(x *Element) { + _x := *x + x.Double(x).Double(x).Add(x, &_x) +} + +// MulBy13 x *= 13 (mod q) +func MulBy13(x *Element) { + var y = Element{ + 17868810749992763324, + 5924006745939515753, + 769406925088786241, + 2691790815622165739, + } + x.Mul(x, &y) +} + +func fromMont(z *Element) { + _fromMontGeneric(z) +} + +//go:noescape +func reduce(res *Element) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element_arm64.s b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element_arm64.s new file mode 100644 index 00000000000..c8df07e3454 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element_arm64.s @@ -0,0 +1,10 @@ +//go:build !purego + +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +// We include the hash to force the Go compiler to recompile: 1501560133179981797 +#include "../../../field/asm/element_4w/element_4w_arm64.s" + diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element_exp.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element_exp.go index e8c4da79289..28b8506cf43 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element_exp.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element_exp.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element_mul_amd64.s b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element_mul_amd64.s deleted file mode 100644 index b51bc69986b..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element_mul_amd64.s +++ /dev/null @@ -1,487 +0,0 @@ -// +build !purego - -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "textflag.h" -#include "funcdata.h" - -// modulus q -DATA q<>+0(SB)/8, $0x43e1f593f0000001 -DATA q<>+8(SB)/8, $0x2833e84879b97091 -DATA q<>+16(SB)/8, $0xb85045b68181585d -DATA q<>+24(SB)/8, $0x30644e72e131a029 -GLOBL q<>(SB), (RODATA+NOPTR), $32 - -// qInv0 q'[0] -DATA qInv0<>(SB)/8, $0xc2e1f593efffffff -GLOBL qInv0<>(SB), (RODATA+NOPTR), $8 - -#define REDUCE(ra0, ra1, ra2, ra3, rb0, rb1, rb2, rb3) \ - MOVQ ra0, rb0; \ - SUBQ q<>(SB), ra0; \ - MOVQ ra1, rb1; \ - SBBQ q<>+8(SB), ra1; \ - MOVQ ra2, rb2; \ - SBBQ q<>+16(SB), ra2; \ - MOVQ ra3, rb3; \ - SBBQ q<>+24(SB), ra3; \ - CMOVQCS rb0, ra0; \ - CMOVQCS rb1, ra1; \ - CMOVQCS rb2, ra2; \ - CMOVQCS rb3, ra3; \ - -// mul(res, x, y *Element) -TEXT ·mul(SB), $24-24 - - // the algorithm is described in the Element.Mul declaration (.go) - // however, to benefit from the ADCX and ADOX carry chains - // we split the inner loops in 2: - // for i=0 to N-1 - // for j=0 to N-1 - // (A,t[j]) := t[j] + x[j]*y[i] + A - // m := t[0]*q'[0] mod W - // C,_ := t[0] + m*q[0] - // for j=1 to N-1 - // (C,t[j-1]) := t[j] + m*q[j] + C - // t[N-1] = C + A - - NO_LOCAL_POINTERS - CMPB ·supportAdx(SB), $1 - JNE l1 - MOVQ x+8(FP), SI - - // x[0] -> DI - // x[1] -> R8 - // x[2] -> R9 - // x[3] -> R10 - MOVQ 0(SI), DI - MOVQ 8(SI), R8 - MOVQ 16(SI), R9 - MOVQ 24(SI), R10 - MOVQ y+16(FP), R11 - - // A -> BP - // t[0] -> R14 - // t[1] -> R13 - // t[2] -> CX - // t[3] -> BX - // clear the flags - XORQ AX, AX - MOVQ 0(R11), DX - - // (A,t[0]) := x[0]*y[0] + A - MULXQ DI, R14, R13 - - // (A,t[1]) := x[1]*y[0] + A - MULXQ R8, AX, CX - ADOXQ AX, R13 - - // (A,t[2]) := x[2]*y[0] + A - MULXQ R9, AX, BX - ADOXQ AX, CX - - // (A,t[3]) := x[3]*y[0] + A - MULXQ R10, AX, BP - ADOXQ AX, BX - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADOXQ AX, BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, R12 - ADCXQ R14, AX - MOVQ R12, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R13, R14 - MULXQ q<>+8(SB), AX, R13 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R13 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R13 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // t[3] = C + A - MOVQ $0, AX - ADCXQ AX, BX - ADOXQ BP, BX - - // clear the flags - XORQ AX, AX - MOVQ 8(R11), DX - - // (A,t[0]) := t[0] + x[0]*y[1] + A - MULXQ DI, AX, BP - ADOXQ AX, R14 - - // (A,t[1]) := t[1] + x[1]*y[1] + A - ADCXQ BP, R13 - MULXQ R8, AX, BP - ADOXQ AX, R13 - - // (A,t[2]) := t[2] + x[2]*y[1] + A - ADCXQ BP, CX - MULXQ R9, AX, BP - ADOXQ AX, CX - - // (A,t[3]) := t[3] + x[3]*y[1] + A - ADCXQ BP, BX - MULXQ R10, AX, BP - ADOXQ AX, BX - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, R12 - ADCXQ R14, AX - MOVQ R12, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R13, R14 - MULXQ q<>+8(SB), AX, R13 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R13 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R13 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // t[3] = C + A - MOVQ $0, AX - ADCXQ AX, BX - ADOXQ BP, BX - - // clear the flags - XORQ AX, AX - MOVQ 16(R11), DX - - // (A,t[0]) := t[0] + x[0]*y[2] + A - MULXQ DI, AX, BP - ADOXQ AX, R14 - - // (A,t[1]) := t[1] + x[1]*y[2] + A - ADCXQ BP, R13 - MULXQ R8, AX, BP - ADOXQ AX, R13 - - // (A,t[2]) := t[2] + x[2]*y[2] + A - ADCXQ BP, CX - MULXQ R9, AX, BP - ADOXQ AX, CX - - // (A,t[3]) := t[3] + x[3]*y[2] + A - ADCXQ BP, BX - MULXQ R10, AX, BP - ADOXQ AX, BX - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, R12 - ADCXQ R14, AX - MOVQ R12, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R13, R14 - MULXQ q<>+8(SB), AX, R13 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R13 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R13 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // t[3] = C + A - MOVQ $0, AX - ADCXQ AX, BX - ADOXQ BP, BX - - // clear the flags - XORQ AX, AX - MOVQ 24(R11), DX - - // (A,t[0]) := t[0] + x[0]*y[3] + A - MULXQ DI, AX, BP - ADOXQ AX, R14 - - // (A,t[1]) := t[1] + x[1]*y[3] + A - ADCXQ BP, R13 - MULXQ R8, AX, BP - ADOXQ AX, R13 - - // (A,t[2]) := t[2] + x[2]*y[3] + A - ADCXQ BP, CX - MULXQ R9, AX, BP - ADOXQ AX, CX - - // (A,t[3]) := t[3] + x[3]*y[3] + A - ADCXQ BP, BX - MULXQ R10, AX, BP - ADOXQ AX, BX - - // A += carries from ADCXQ and ADOXQ - MOVQ $0, AX - ADCXQ AX, BP - ADOXQ AX, BP - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - - // clear the flags - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, R12 - ADCXQ R14, AX - MOVQ R12, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R13, R14 - MULXQ q<>+8(SB), AX, R13 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R13 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R13 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - - // t[3] = C + A - MOVQ $0, AX - ADCXQ AX, BX - ADOXQ BP, BX - - // reduce element(R14,R13,CX,BX) using temp registers (SI,R12,R11,DI) - REDUCE(R14,R13,CX,BX,SI,R12,R11,DI) - - MOVQ res+0(FP), AX - MOVQ R14, 0(AX) - MOVQ R13, 8(AX) - MOVQ CX, 16(AX) - MOVQ BX, 24(AX) - RET - -l1: - MOVQ res+0(FP), AX - MOVQ AX, (SP) - MOVQ x+8(FP), AX - MOVQ AX, 8(SP) - MOVQ y+16(FP), AX - MOVQ AX, 16(SP) - CALL ·_mulGeneric(SB) - RET - -TEXT ·fromMont(SB), $8-8 - NO_LOCAL_POINTERS - - // the algorithm is described here - // https://hackmd.io/@gnark/modular_multiplication - // when y = 1 we have: - // for i=0 to N-1 - // t[i] = x[i] - // for i=0 to N-1 - // m := t[0]*q'[0] mod W - // C,_ := t[0] + m*q[0] - // for j=1 to N-1 - // (C,t[j-1]) := t[j] + m*q[j] + C - // t[N-1] = C - CMPB ·supportAdx(SB), $1 - JNE l2 - MOVQ res+0(FP), DX - MOVQ 0(DX), R14 - MOVQ 8(DX), R13 - MOVQ 16(DX), CX - MOVQ 24(DX), BX - XORQ DX, DX - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R14, AX - MOVQ BP, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R13, R14 - MULXQ q<>+8(SB), AX, R13 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R13 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R13 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - MOVQ $0, AX - ADCXQ AX, BX - ADOXQ AX, BX - XORQ DX, DX - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R14, AX - MOVQ BP, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R13, R14 - MULXQ q<>+8(SB), AX, R13 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R13 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R13 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - MOVQ $0, AX - ADCXQ AX, BX - ADOXQ AX, BX - XORQ DX, DX - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R14, AX - MOVQ BP, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R13, R14 - MULXQ q<>+8(SB), AX, R13 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R13 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R13 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - MOVQ $0, AX - ADCXQ AX, BX - ADOXQ AX, BX - XORQ DX, DX - - // m := t[0]*q'[0] mod W - MOVQ qInv0<>(SB), DX - IMULQ R14, DX - XORQ AX, AX - - // C,_ := t[0] + m*q[0] - MULXQ q<>+0(SB), AX, BP - ADCXQ R14, AX - MOVQ BP, R14 - - // (C,t[0]) := t[1] + m*q[1] + C - ADCXQ R13, R14 - MULXQ q<>+8(SB), AX, R13 - ADOXQ AX, R14 - - // (C,t[1]) := t[2] + m*q[2] + C - ADCXQ CX, R13 - MULXQ q<>+16(SB), AX, CX - ADOXQ AX, R13 - - // (C,t[2]) := t[3] + m*q[3] + C - ADCXQ BX, CX - MULXQ q<>+24(SB), AX, BX - ADOXQ AX, CX - MOVQ $0, AX - ADCXQ AX, BX - ADOXQ AX, BX - - // reduce element(R14,R13,CX,BX) using temp registers (SI,DI,R8,R9) - REDUCE(R14,R13,CX,BX,SI,DI,R8,R9) - - MOVQ res+0(FP), AX - MOVQ R14, 0(AX) - MOVQ R13, 8(AX) - MOVQ CX, 16(AX) - MOVQ BX, 24(AX) - RET - -l2: - MOVQ res+0(FP), AX - MOVQ AX, (SP) - CALL ·_fromMontGeneric(SB) - RET diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element_ops_amd64.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element_ops_amd64.go deleted file mode 100644 index e40a9caed55..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element_ops_amd64.go +++ /dev/null @@ -1,107 +0,0 @@ -//go:build !purego -// +build !purego - -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by consensys/gnark-crypto DO NOT EDIT - -package fr - -//go:noescape -func MulBy3(x *Element) - -//go:noescape -func MulBy5(x *Element) - -//go:noescape -func MulBy13(x *Element) - -//go:noescape -func mul(res, x, y *Element) - -//go:noescape -func fromMont(res *Element) - -//go:noescape -func reduce(res *Element) - -// Butterfly sets -// -// a = a + b (mod q) -// b = a - b (mod q) -// -//go:noescape -func Butterfly(a, b *Element) - -// Mul z = x * y (mod q) -// -// x and y must be less than q -func (z *Element) Mul(x, y *Element) *Element { - - // Implements CIOS multiplication -- section 2.3.2 of Tolga Acar's thesis - // https://www.microsoft.com/en-us/research/wp-content/uploads/1998/06/97Acar.pdf - // - // The algorithm: - // - // for i=0 to N-1 - // C := 0 - // for j=0 to N-1 - // (C,t[j]) := t[j] + x[j]*y[i] + C - // (t[N+1],t[N]) := t[N] + C - // - // C := 0 - // m := t[0]*q'[0] mod D - // (C,_) := t[0] + m*q[0] - // for j=1 to N-1 - // (C,t[j-1]) := t[j] + m*q[j] + C - // - // (C,t[N-1]) := t[N] + C - // t[N] := t[N+1] + C - // - // → N is the number of machine words needed to store the modulus q - // → D is the word size. For example, on a 64-bit architecture D is 2 64 - // → x[i], y[i], q[i] is the ith word of the numbers x,y,q - // → q'[0] is the lowest word of the number -q⁻¹ mod r. This quantity is pre-computed, as it does not depend on the inputs. - // → t is a temporary array of size N+2 - // → C, S are machine words. A pair (C,S) refers to (hi-bits, lo-bits) of a two-word number - // - // As described here https://hackmd.io/@gnark/modular_multiplication we can get rid of one carry chain and simplify: - // (also described in https://eprint.iacr.org/2022/1400.pdf annex) - // - // for i=0 to N-1 - // (A,t[0]) := t[0] + x[0]*y[i] - // m := t[0]*q'[0] mod W - // C,_ := t[0] + m*q[0] - // for j=1 to N-1 - // (A,t[j]) := t[j] + x[j]*y[i] + A - // (C,t[j-1]) := t[j] + m*q[j] + C - // - // t[N-1] = C + A - // - // This optimization saves 5N + 2 additions in the algorithm, and can be used whenever the highest bit - // of the modulus is zero (and not all of the remaining bits are set). - - mul(z, x, y) - return z -} - -// Square z = x * x (mod q) -// -// x must be less than q -func (z *Element) Square(x *Element) *Element { - // see Mul for doc. - mul(z, x, x) - return z -} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element_ops_amd64.s b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element_ops_amd64.s deleted file mode 100644 index b9d8a5bfa22..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element_ops_amd64.s +++ /dev/null @@ -1,230 +0,0 @@ -// +build !purego - -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "textflag.h" -#include "funcdata.h" - -// modulus q -DATA q<>+0(SB)/8, $0x43e1f593f0000001 -DATA q<>+8(SB)/8, $0x2833e84879b97091 -DATA q<>+16(SB)/8, $0xb85045b68181585d -DATA q<>+24(SB)/8, $0x30644e72e131a029 -GLOBL q<>(SB), (RODATA+NOPTR), $32 - -// qInv0 q'[0] -DATA qInv0<>(SB)/8, $0xc2e1f593efffffff -GLOBL qInv0<>(SB), (RODATA+NOPTR), $8 - -#define REDUCE(ra0, ra1, ra2, ra3, rb0, rb1, rb2, rb3) \ - MOVQ ra0, rb0; \ - SUBQ q<>(SB), ra0; \ - MOVQ ra1, rb1; \ - SBBQ q<>+8(SB), ra1; \ - MOVQ ra2, rb2; \ - SBBQ q<>+16(SB), ra2; \ - MOVQ ra3, rb3; \ - SBBQ q<>+24(SB), ra3; \ - CMOVQCS rb0, ra0; \ - CMOVQCS rb1, ra1; \ - CMOVQCS rb2, ra2; \ - CMOVQCS rb3, ra3; \ - -TEXT ·reduce(SB), NOSPLIT, $0-8 - MOVQ res+0(FP), AX - MOVQ 0(AX), DX - MOVQ 8(AX), CX - MOVQ 16(AX), BX - MOVQ 24(AX), SI - - // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) - - MOVQ DX, 0(AX) - MOVQ CX, 8(AX) - MOVQ BX, 16(AX) - MOVQ SI, 24(AX) - RET - -// MulBy3(x *Element) -TEXT ·MulBy3(SB), NOSPLIT, $0-8 - MOVQ x+0(FP), AX - MOVQ 0(AX), DX - MOVQ 8(AX), CX - MOVQ 16(AX), BX - MOVQ 24(AX), SI - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - - // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) - - ADDQ 0(AX), DX - ADCQ 8(AX), CX - ADCQ 16(AX), BX - ADCQ 24(AX), SI - - // reduce element(DX,CX,BX,SI) using temp registers (R11,R12,R13,R14) - REDUCE(DX,CX,BX,SI,R11,R12,R13,R14) - - MOVQ DX, 0(AX) - MOVQ CX, 8(AX) - MOVQ BX, 16(AX) - MOVQ SI, 24(AX) - RET - -// MulBy5(x *Element) -TEXT ·MulBy5(SB), NOSPLIT, $0-8 - MOVQ x+0(FP), AX - MOVQ 0(AX), DX - MOVQ 8(AX), CX - MOVQ 16(AX), BX - MOVQ 24(AX), SI - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - - // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) - - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - - // reduce element(DX,CX,BX,SI) using temp registers (R11,R12,R13,R14) - REDUCE(DX,CX,BX,SI,R11,R12,R13,R14) - - ADDQ 0(AX), DX - ADCQ 8(AX), CX - ADCQ 16(AX), BX - ADCQ 24(AX), SI - - // reduce element(DX,CX,BX,SI) using temp registers (R15,DI,R8,R9) - REDUCE(DX,CX,BX,SI,R15,DI,R8,R9) - - MOVQ DX, 0(AX) - MOVQ CX, 8(AX) - MOVQ BX, 16(AX) - MOVQ SI, 24(AX) - RET - -// MulBy13(x *Element) -TEXT ·MulBy13(SB), NOSPLIT, $0-8 - MOVQ x+0(FP), AX - MOVQ 0(AX), DX - MOVQ 8(AX), CX - MOVQ 16(AX), BX - MOVQ 24(AX), SI - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - - // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) - - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - - // reduce element(DX,CX,BX,SI) using temp registers (R11,R12,R13,R14) - REDUCE(DX,CX,BX,SI,R11,R12,R13,R14) - - MOVQ DX, R11 - MOVQ CX, R12 - MOVQ BX, R13 - MOVQ SI, R14 - ADDQ DX, DX - ADCQ CX, CX - ADCQ BX, BX - ADCQ SI, SI - - // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) - - ADDQ R11, DX - ADCQ R12, CX - ADCQ R13, BX - ADCQ R14, SI - - // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) - - ADDQ 0(AX), DX - ADCQ 8(AX), CX - ADCQ 16(AX), BX - ADCQ 24(AX), SI - - // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) - REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) - - MOVQ DX, 0(AX) - MOVQ CX, 8(AX) - MOVQ BX, 16(AX) - MOVQ SI, 24(AX) - RET - -// Butterfly(a, b *Element) sets a = a + b; b = a - b -TEXT ·Butterfly(SB), NOSPLIT, $0-16 - MOVQ a+0(FP), AX - MOVQ 0(AX), CX - MOVQ 8(AX), BX - MOVQ 16(AX), SI - MOVQ 24(AX), DI - MOVQ CX, R8 - MOVQ BX, R9 - MOVQ SI, R10 - MOVQ DI, R11 - XORQ AX, AX - MOVQ b+8(FP), DX - ADDQ 0(DX), CX - ADCQ 8(DX), BX - ADCQ 16(DX), SI - ADCQ 24(DX), DI - SUBQ 0(DX), R8 - SBBQ 8(DX), R9 - SBBQ 16(DX), R10 - SBBQ 24(DX), R11 - MOVQ $0x43e1f593f0000001, R12 - MOVQ $0x2833e84879b97091, R13 - MOVQ $0xb85045b68181585d, R14 - MOVQ $0x30644e72e131a029, R15 - CMOVQCC AX, R12 - CMOVQCC AX, R13 - CMOVQCC AX, R14 - CMOVQCC AX, R15 - ADDQ R12, R8 - ADCQ R13, R9 - ADCQ R14, R10 - ADCQ R15, R11 - MOVQ R8, 0(DX) - MOVQ R9, 8(DX) - MOVQ R10, 16(DX) - MOVQ R11, 24(DX) - - // reduce element(CX,BX,SI,DI) using temp registers (R8,R9,R10,R11) - REDUCE(CX,BX,SI,DI,R8,R9,R10,R11) - - MOVQ a+0(FP), AX - MOVQ CX, 0(AX) - MOVQ BX, 8(AX) - MOVQ SI, 16(AX) - MOVQ DI, 24(AX) - RET diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element_ops_purego.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element_purego.go similarity index 80% rename from vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element_ops_purego.go rename to vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element_purego.go index be0f0858326..8b6bab2e094 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element_ops_purego.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/element_purego.go @@ -1,19 +1,7 @@ -//go:build !amd64 || purego -// +build !amd64 purego +//go:build purego || (!amd64 && !arm64) -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -44,14 +32,6 @@ func MulBy13(x *Element) { x.Mul(x, &y) } -// Butterfly sets -// -// a = a + b (mod q) -// b = a - b (mod q) -func Butterfly(a, b *Element) { - _butterflyGeneric(a, b) -} - func fromMont(z *Element) { _fromMontGeneric(z) } @@ -65,48 +45,8 @@ func reduce(z *Element) { // x and y must be less than q func (z *Element) Mul(x, y *Element) *Element { - // Implements CIOS multiplication -- section 2.3.2 of Tolga Acar's thesis - // https://www.microsoft.com/en-us/research/wp-content/uploads/1998/06/97Acar.pdf - // - // The algorithm: - // - // for i=0 to N-1 - // C := 0 - // for j=0 to N-1 - // (C,t[j]) := t[j] + x[j]*y[i] + C - // (t[N+1],t[N]) := t[N] + C - // - // C := 0 - // m := t[0]*q'[0] mod D - // (C,_) := t[0] + m*q[0] - // for j=1 to N-1 - // (C,t[j-1]) := t[j] + m*q[j] + C - // - // (C,t[N-1]) := t[N] + C - // t[N] := t[N+1] + C - // - // → N is the number of machine words needed to store the modulus q - // → D is the word size. For example, on a 64-bit architecture D is 2 64 - // → x[i], y[i], q[i] is the ith word of the numbers x,y,q - // → q'[0] is the lowest word of the number -q⁻¹ mod r. This quantity is pre-computed, as it does not depend on the inputs. - // → t is a temporary array of size N+2 - // → C, S are machine words. A pair (C,S) refers to (hi-bits, lo-bits) of a two-word number - // - // As described here https://hackmd.io/@gnark/modular_multiplication we can get rid of one carry chain and simplify: - // (also described in https://eprint.iacr.org/2022/1400.pdf annex) - // - // for i=0 to N-1 - // (A,t[0]) := t[0] + x[0]*y[i] - // m := t[0]*q'[0] mod W - // C,_ := t[0] + m*q[0] - // for j=1 to N-1 - // (A,t[j]) := t[j] + x[j]*y[i] + A - // (C,t[j-1]) := t[j] + m*q[j] + C - // - // t[N-1] = C + A - // - // This optimization saves 5N + 2 additions in the algorithm, and can be used whenever the highest bit - // of the modulus is zero (and not all of the remaining bits are set). + // Algorithm 2 of "Faster Montgomery Multiplication and Multi-Scalar-Multiplication for SNARKS" + // by Y. El Housni and G. Botrel https://doi.org/10.46586/tches.v2023.i3.504-521 var t0, t1, t2, t3 uint64 var u0, u1, u2, u3 uint64 @@ -441,3 +381,11 @@ func (z *Element) Square(x *Element) *Element { } return z } + +// Butterfly sets +// +// a = a + b (mod q) +// b = a - b (mod q) +func Butterfly(a, b *Element) { + _butterflyGeneric(a, b) +} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/generator.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/generator.go new file mode 100644 index 00000000000..085998e5c59 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/generator.go @@ -0,0 +1,36 @@ +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fr + +import ( + "fmt" + "math/big" + "math/bits" + + "github.com/consensys/gnark-crypto/ecc" +) + +// Generator returns a generator for Z/2^(log(m))Z +// or an error if m is too big (required root of unity doesn't exist) +func Generator(m uint64) (Element, error) { + x := ecc.NextPowerOfTwo(m) + + var rootOfUnity Element + + rootOfUnity.SetString("19103219067921713944291392827692070036145651957329286315305642004821462161904") + const maxOrderRoot uint64 = 28 + + // find generator for Z/2^(log(m))Z + logx := uint64(bits.TrailingZeros64(x)) + if logx > maxOrderRoot { + return Element{}, fmt.Errorf("m (%d) is too big: the required root of unity does not exist", m) + } + + expo := uint64(1 << (maxOrderRoot - logx)) + var generator Element + generator.Exp(rootOfUnity, big.NewInt(int64(expo))) // order x + return generator, nil +} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/vector.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/vector.go index 00ad8a8986b..eee2062de72 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/vector.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/vector.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -19,9 +8,12 @@ package fr import ( "bytes" "encoding/binary" + "errors" "fmt" "io" + "math/bits" "runtime" + "slices" "strings" "sync" "sync/atomic" @@ -78,40 +70,84 @@ func (vector *Vector) WriteTo(w io.Writer) (int64, error) { return n, nil } -// AsyncReadFrom reads a vector of big endian encoded Element. -// Length of the vector must be encoded as a uint32 on the first 4 bytes. -// It consumes the needed bytes from the reader and returns the number of bytes read and an error if any. -// It also returns a channel that will be closed when the validation is done. -// The validation consist of checking that the elements are smaller than the modulus, and -// converting them to montgomery form. -func (vector *Vector) AsyncReadFrom(r io.Reader) (int64, error, chan error) { +// AsyncReadFrom implements an asynchronous version of [Vector.ReadFrom]. It +// reads the reader r in full and then performs the validation and conversion to +// Montgomery form separately in a goroutine. Any error encountered during +// reading is returned directly, while errors encountered during +// validation/conversion are sent on the returned channel. Thus the caller must +// wait on the channel to ensure the vector is ready to use. The method +// additionally returns the number of bytes read from r. +// +// The errors during reading can be: +// - an error while reading from r; +// - not enough bytes in r to read the full vector indicated by header. +// +// The reader can contain more bytes than needed to decode the vector, in which +// case the extra bytes are ignored. In that case the reader is not seeked nor +// read further. +// +// The method allocates sufficiently large slice to store the vector. If the +// current slice fits the vector, it is reused, otherwise the slice is grown to +// fit the vector. +// +// The serialized encoding is as follows: +// - first 4 bytes: length of the vector as a big-endian uint32 +// - for each element of the vector, [Bytes] bytes representing the element in +// big-endian encoding. +func (vector *Vector) AsyncReadFrom(r io.Reader) (int64, error, chan error) { // nolint ST1008 chErr := make(chan error, 1) var buf [Bytes]byte if read, err := io.ReadFull(r, buf[:4]); err != nil { close(chErr) return int64(read), err, chErr } - sliceLen := binary.BigEndian.Uint32(buf[:4]) - - n := int64(4) - (*vector) = make(Vector, sliceLen) - if sliceLen == 0 { + headerSliceLen := uint64(binary.BigEndian.Uint32(buf[:4])) + + // to avoid allocating too large slice when the header is tampered, we limit + // the maximum allocation. We set the target to 4GB. This incurs a performance + // hit when reading very large slices, but protects against OOM. + targetSize := uint64(1 << 32) // 4GB + if bits.UintSize == 32 { + // reduce target size to 1GB on 32 bits architectures + targetSize = uint64(1 << 30) // 1GB + } + maxAllocateSliceLength := targetSize / uint64(Bytes) + + totalRead := int64(4) + *vector = (*vector)[:0] + if headerSliceLen == 0 { + // if the vector was nil previously even by reslicing we have a nil vector. + // but we want to have an empty slice to indicate that the vector has zero length. + if *vector == nil { + *vector = []Element{} + } + // we return already here to avoid launching a goroutine doing nothing below close(chErr) - return n, nil, chErr + return totalRead, nil, chErr } - bSlice := unsafe.Slice((*byte)(unsafe.Pointer(&(*vector)[0])), sliceLen*Bytes) - read, err := io.ReadFull(r, bSlice) - n += int64(read) - if err != nil { - close(chErr) - return n, err, chErr + for i := uint64(0); i < headerSliceLen; i += maxAllocateSliceLength { + if len(*vector) <= int(i) { + (*vector) = append(*vector, make([]Element, int(min(headerSliceLen-i, maxAllocateSliceLength)))...) + } + bSlice := unsafe.Slice((*byte)(unsafe.Pointer(&(*vector)[i])), int(min(headerSliceLen-i, maxAllocateSliceLength))*Bytes) + read, err := io.ReadFull(r, bSlice) + totalRead += int64(read) + if errors.Is(err, io.ErrUnexpectedEOF) { + close(chErr) + return totalRead, fmt.Errorf("less data than expected: read %d elements, expected %d", i+uint64(read)/Bytes, headerSliceLen), chErr + } + if err != nil { + close(chErr) + return totalRead, err, chErr + } } + bSlice := unsafe.Slice((*byte)(unsafe.Pointer(&(*vector)[0])), int(headerSliceLen)*Bytes) go func() { var cptErrors uint64 // process the elements in parallel - execute(int(sliceLen), func(start, end int) { + execute(int(headerSliceLen), func(start, end int) { var z Element for i := start; i < end; i++ { @@ -138,35 +174,72 @@ func (vector *Vector) AsyncReadFrom(r io.Reader) (int64, error, chan error) { } close(chErr) }() - return n, nil, chErr + return totalRead, nil, chErr } -// ReadFrom implements io.ReaderFrom and reads a vector of big endian encoded Element. -// Length of the vector must be encoded as a uint32 on the first 4 bytes. +// ReadFrom reads the vector from the reader r. It returns the number of bytes +// read and an error, if any. The errors can be: +// - an error while reading from r; +// - not enough bytes in r to read the full vector indicated by header; +// - when decoding the bytes into elements. +// +// The reader can contain more bytes than needed to decode the vector, in which case +// the extra bytes are ignored. In that case the reader is not seeked nor read further. +// +// The method allocates sufficiently large slice to store the vector. If the current slice fits +// the vector, it is reused, otherwise the slice is grown to fit the vector. +// +// The serialized encoding is as follows: +// - first 4 bytes: length of the vector as a big-endian uint32 +// - for each element of the vector, [Bytes] bytes representing the element in big-endian encoding. +// +// The method implements [io.ReaderFrom] interface. func (vector *Vector) ReadFrom(r io.Reader) (int64, error) { - var buf [Bytes]byte if read, err := io.ReadFull(r, buf[:4]); err != nil { return int64(read), err } - sliceLen := binary.BigEndian.Uint32(buf[:4]) - - n := int64(4) - (*vector) = make(Vector, sliceLen) + headerSliceLen := uint64(binary.BigEndian.Uint32(buf[:4])) + + // to avoid allocating too large slice when the header is tampered, we limit + // the maximum allocation. We set the target to 4GB. This incurs a performance + // hit when reading very large slices, but protects against OOM. + targetSize := uint64(1 << 32) // 4GB + if bits.UintSize == 32 { + // reduce target size to 1GB on 32 bits architectures + targetSize = uint64(1 << 30) // 1GB + } + maxAllocateSliceLength := targetSize / uint64(Bytes) + + totalRead := int64(4) // include already the header length + *vector = (*vector)[:0] + // if the vector was nil previously even by reslicing we have a nil vector. But we want + // to have an empty slice to indicate that the vector has zero length. When headerSliceLen == 0 + // we handle this edge case after reading the header as the loop body below is skipped. + if headerSliceLen == 0 && *vector == nil { + *vector = []Element{} + } - for i := 0; i < int(sliceLen); i++ { + for i := uint64(0); i < headerSliceLen; i++ { read, err := io.ReadFull(r, buf[:]) - n += int64(read) + totalRead += int64(read) + if errors.Is(err, io.ErrUnexpectedEOF) { + return totalRead, fmt.Errorf("less data than expected: read %d elements, expected %d", i, headerSliceLen) + } if err != nil { - return n, err + return totalRead, fmt.Errorf("error reading element %d: %w", i, err) } - (*vector)[i], err = BigEndian.Element(&buf) + if uint64(cap(*vector)) <= i { + (*vector) = slices.Grow(*vector, int(min(headerSliceLen-i, maxAllocateSliceLength))) + } + el, err := BigEndian.Element(&buf) if err != nil { - return n, err + return totalRead, fmt.Errorf("error decoding element %d: %w", i, err) } + *vector = append(*vector, el) } - return n, nil + return totalRead, nil } // String implements fmt.Stringer interface @@ -199,6 +272,88 @@ func (vector Vector) Swap(i, j int) { vector[i], vector[j] = vector[j], vector[i] } +// SetRandom sets the elements in vector to independent uniform random values in [0, q). +// +// This might error only if reading from crypto/rand.Reader errors, +// in which case the values in vector are undefined. +func (vector Vector) SetRandom() error { + for i := range vector { + if _, err := vector[i].SetRandom(); err != nil { + return err + } + } + return nil +} + +// MustSetRandom sets the elements in vector to independent uniform random values in [0, q). +// +// It panics if reading from crypto/rand.Reader errors. +func (vector Vector) MustSetRandom() { + for i := range vector { + if _, err := vector[i].SetRandom(); err != nil { + panic(err) + } + } +} + +// Equal returns true if vector and other have the same length and same elements. +func (vector Vector) Equal(other Vector) bool { + return slices.Equal(vector, other) +} + +func addVecGeneric(res, a, b Vector) { + if len(a) != len(b) || len(a) != len(res) { + panic("vector.Add: vectors don't have the same length") + } + for i := 0; i < len(a); i++ { + res[i].Add(&a[i], &b[i]) + } +} + +func subVecGeneric(res, a, b Vector) { + if len(a) != len(b) || len(a) != len(res) { + panic("vector.Sub: vectors don't have the same length") + } + for i := 0; i < len(a); i++ { + res[i].Sub(&a[i], &b[i]) + } +} + +func scalarMulVecGeneric(res, a Vector, b *Element) { + if len(a) != len(res) { + panic("vector.ScalarMul: vectors don't have the same length") + } + for i := 0; i < len(a); i++ { + res[i].Mul(&a[i], b) + } +} + +func sumVecGeneric(res *Element, a Vector) { + for i := 0; i < len(a); i++ { + res.Add(res, &a[i]) + } +} + +func innerProductVecGeneric(res *Element, a, b Vector) { + if len(a) != len(b) { + panic("vector.InnerProduct: vectors don't have the same length") + } + var tmp Element + for i := 0; i < len(a); i++ { + tmp.Mul(&a[i], &b[i]) + res.Add(res, &tmp) + } +} + +func mulVecGeneric(res, a, b Vector) { + if len(a) != len(b) || len(a) != len(res) { + panic("vector.Mul: vectors don't have the same length") + } + for i := 0; i < len(a); i++ { + res[i].Mul(&a[i], &b[i]) + } +} + // TODO @gbotrel make a public package out of that. // execute executes the work function in parallel. // this is copy paste from internal/parallel/parallel.go diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/vector_amd64.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/vector_amd64.go new file mode 100644 index 00000000000..8b6df0b4026 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/vector_amd64.go @@ -0,0 +1,154 @@ +//go:build !purego + +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fr + +import ( + _ "github.com/consensys/gnark-crypto/field/asm/element_4w" + "github.com/consensys/gnark-crypto/utils/cpu" +) + +// Add adds two vectors element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) Add(a, b Vector) { + if len(a) != len(b) || len(a) != len(*vector) { + panic("vector.Add: vectors don't have the same length") + } + n := uint64(len(a)) + addVec(&(*vector)[0], &a[0], &b[0], n) +} + +//go:noescape +func addVec(res, a, b *Element, n uint64) + +// Sub subtracts two vectors element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) Sub(a, b Vector) { + if len(a) != len(b) || len(a) != len(*vector) { + panic("vector.Sub: vectors don't have the same length") + } + subVec(&(*vector)[0], &a[0], &b[0], uint64(len(a))) +} + +//go:noescape +func subVec(res, a, b *Element, n uint64) + +// ScalarMul multiplies a vector by a scalar element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) ScalarMul(a Vector, b *Element) { + if len(a) != len(*vector) { + panic("vector.ScalarMul: vectors don't have the same length") + } + const maxN = (1 << 32) - 1 + if !cpu.SupportAVX512 || uint64(len(a)) >= maxN { + // call scalarMulVecGeneric + scalarMulVecGeneric(*vector, a, b) + return + } + n := uint64(len(a)) + if n == 0 { + return + } + // the code for scalarMul is identical to mulVec; and it expects at least + // 2 elements in the vector to fill the Z registers + var bb [2]Element + bb[0] = *b + bb[1] = *b + const blockSize = 16 + scalarMulVec(&(*vector)[0], &a[0], &bb[0], n/blockSize, qInvNeg) + if n%blockSize != 0 { + // call scalarMulVecGeneric on the rest + start := n - n%blockSize + scalarMulVecGeneric((*vector)[start:], a[start:], b) + } +} + +//go:noescape +func scalarMulVec(res, a, b *Element, n uint64, qInvNeg uint64) + +// Sum computes the sum of all elements in the vector. +func (vector *Vector) Sum() (res Element) { + n := uint64(len(*vector)) + if n == 0 { + return + } + const minN = 16 * 7 // AVX512 slower than generic for small n + const maxN = (1 << 32) - 1 + if !cpu.SupportAVX512 || n <= minN || n >= maxN { + // call sumVecGeneric + sumVecGeneric(&res, *vector) + return + } + sumVec(&res, &(*vector)[0], uint64(len(*vector))) + return +} + +//go:noescape +func sumVec(res *Element, a *Element, n uint64) + +// InnerProduct computes the inner product of two vectors. +// It panics if the vectors don't have the same length. +func (vector *Vector) InnerProduct(other Vector) (res Element) { + n := uint64(len(*vector)) + if n == 0 { + return + } + if n != uint64(len(other)) { + panic("vector.InnerProduct: vectors don't have the same length") + } + const maxN = (1 << 32) - 1 + if !cpu.SupportAVX512 || n >= maxN { + // call innerProductVecGeneric + // note; we could split the vector into smaller chunks and call innerProductVec + innerProductVecGeneric(&res, *vector, other) + return + } + innerProdVec(&res[0], &(*vector)[0], &other[0], uint64(len(*vector))) + + return +} + +//go:noescape +func innerProdVec(res *uint64, a, b *Element, n uint64) + +// Mul multiplies two vectors element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) Mul(a, b Vector) { + if len(a) != len(b) || len(a) != len(*vector) { + panic("vector.Mul: vectors don't have the same length") + } + n := uint64(len(a)) + if n == 0 { + return + } + const maxN = (1 << 32) - 1 + if !cpu.SupportAVX512 || n >= maxN { + // call mulVecGeneric + mulVecGeneric(*vector, a, b) + return + } + + const blockSize = 16 + mulVec(&(*vector)[0], &a[0], &b[0], n/blockSize, qInvNeg) + if n%blockSize != 0 { + // call mulVecGeneric on the rest + start := n - n%blockSize + mulVecGeneric((*vector)[start:], a[start:], b[start:]) + } + +} + +// Patterns use for transposing the vectors in mulVec +var ( + pattern1 = [8]uint64{0, 8, 1, 9, 2, 10, 3, 11} + pattern2 = [8]uint64{12, 4, 13, 5, 14, 6, 15, 7} + pattern3 = [8]uint64{0, 1, 8, 9, 2, 3, 10, 11} + pattern4 = [8]uint64{12, 13, 4, 5, 14, 15, 6, 7} +) + +//go:noescape +func mulVec(res, a, b *Element, n uint64, qInvNeg uint64) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/vector_purego.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/vector_purego.go new file mode 100644 index 00000000000..6608e394c79 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/fr/vector_purego.go @@ -0,0 +1,45 @@ +//go:build purego || !amd64 + +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fr + +// Add adds two vectors element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) Add(a, b Vector) { + addVecGeneric(*vector, a, b) +} + +// Sub subtracts two vectors element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) Sub(a, b Vector) { + subVecGeneric(*vector, a, b) +} + +// ScalarMul multiplies a vector by a scalar element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) ScalarMul(a Vector, b *Element) { + scalarMulVecGeneric(*vector, a, b) +} + +// Sum computes the sum of all elements in the vector. +func (vector *Vector) Sum() (res Element) { + sumVecGeneric(&res, *vector) + return +} + +// InnerProduct computes the inner product of two vectors. +// It panics if the vectors don't have the same length. +func (vector *Vector) InnerProduct(other Vector) (res Element) { + innerProductVecGeneric(&res, *vector, other) + return +} + +// Mul multiplies two vectors element-wise and stores the result in self. +// It panics if the vectors don't have the same length. +func (vector *Vector) Mul(a, b Vector) { + mulVecGeneric(*vector, a, b) +} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/g1.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/g1.go index e64b53ffa7a..6d10a8c0ca8 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/g1.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/g1.go @@ -1,16 +1,5 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -25,38 +14,40 @@ import ( "runtime" ) -// G1Affine point in affine coordinates +// G1Affine is a point in affine coordinates (x,y) type G1Affine struct { X, Y fp.Element } -// G1Jac is a point with fp.Element coordinates +// G1Jac is a point in Jacobian coordinates (x=X/Z², y=Y/Z³) type G1Jac struct { X, Y, Z fp.Element } -// g1JacExtended parameterized Jacobian coordinates (x=X/ZZ, y=Y/ZZZ, ZZ³=ZZZ²) +// g1JacExtended is a point in extended Jacobian coordinates (x=X/ZZ, y=Y/ZZZ, ZZ³=ZZZ²) type g1JacExtended struct { X, Y, ZZ, ZZZ fp.Element } // ------------------------------------------------------------------------------------------------- -// Affine +// Affine coordinates -// Set sets p to the provided point +// Set sets p to a in affine coordinates. func (p *G1Affine) Set(a *G1Affine) *G1Affine { p.X, p.Y = a.X, a.Y return p } -// setInfinity sets p to O -func (p *G1Affine) setInfinity() *G1Affine { +// SetInfinity sets p to the infinity point, which is encoded as (0,0). +// N.B.: (0,0) is never on the curve for j=0 curves (Y²=X³+B). +func (p *G1Affine) SetInfinity() *G1Affine { p.X.SetZero() p.Y.SetZero() return p } -// ScalarMultiplication computes and returns p = a ⋅ s +// ScalarMultiplication computes and returns p = [s]a +// where p and a are affine points. func (p *G1Affine) ScalarMultiplication(a *G1Affine, s *big.Int) *G1Affine { var _p G1Jac _p.FromAffine(a) @@ -65,15 +56,8 @@ func (p *G1Affine) ScalarMultiplication(a *G1Affine, s *big.Int) *G1Affine { return p } -// ScalarMultiplicationAffine computes and returns p = a ⋅ s -// Takes an affine point and returns a Jacobian point (useful for KZG) -func (p *G1Jac) ScalarMultiplicationAffine(a *G1Affine, s *big.Int) *G1Jac { - p.FromAffine(a) - p.mulGLV(p, s) - return p -} - -// ScalarMultiplicationBase computes and returns p = g ⋅ s where g is the prime subgroup generator +// ScalarMultiplicationBase computes and returns p = [s]g +// where g is the affine point generating the prime subgroup. func (p *G1Affine) ScalarMultiplicationBase(s *big.Int) *G1Affine { var _p G1Jac _p.mulGLV(&g1Gen, s) @@ -81,51 +65,88 @@ func (p *G1Affine) ScalarMultiplicationBase(s *big.Int) *G1Affine { return p } -// Add adds two point in affine coordinates. -// This should rarely be used as it is very inefficient compared to Jacobian +// Add adds two points in affine coordinates. +// It uses the Jacobian addition with a.Z=b.Z=1 and converts the result to affine coordinates. +// +// https://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-mmadd-2007-bl func (p *G1Affine) Add(a, b *G1Affine) *G1Affine { - var p1, p2 G1Jac - p1.FromAffine(a) - p2.FromAffine(b) - p1.AddAssign(&p2) - p.FromJacobian(&p1) - return p + var q G1Jac + // a is infinity, return b + if a.IsInfinity() { + p.Set(b) + return p + } + // b is infinity, return a + if b.IsInfinity() { + p.Set(a) + return p + } + if a.X.Equal(&b.X) { + // if b == a, we double instead + if a.Y.Equal(&b.Y) { + q.DoubleMixed(a) + return p.FromJacobian(&q) + } else { + // if b == -a, we return 0 + return p.SetInfinity() + } + } + var H, HH, I, J, r, V fp.Element + H.Sub(&b.X, &a.X) + HH.Square(&H) + I.Double(&HH).Double(&I) + J.Mul(&H, &I) + r.Sub(&b.Y, &a.Y) + r.Double(&r) + V.Mul(&a.X, &I) + q.X.Square(&r). + Sub(&q.X, &J). + Sub(&q.X, &V). + Sub(&q.X, &V) + q.Y.Sub(&V, &q.X). + Mul(&q.Y, &r) + J.Mul(&a.Y, &J).Double(&J) + q.Y.Sub(&q.Y, &J) + q.Z.Double(&H) + + return p.FromJacobian(&q) } // Double doubles a point in affine coordinates. -// This should rarely be used as it is very inefficient compared to Jacobian +// It converts the point to Jacobian coordinates, doubles it using Jacobian +// addition with a.Z=1, and converts it back to affine coordinates. +// +// http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-mdbl-2007-bl func (p *G1Affine) Double(a *G1Affine) *G1Affine { - var p1 G1Jac - p1.FromAffine(a) - p1.Double(&p1) - p.FromJacobian(&p1) + var q G1Jac + q.FromAffine(a) + q.DoubleMixed(a) + p.FromJacobian(&q) return p } -// Sub subs two point in affine coordinates. -// This should rarely be used as it is very inefficient compared to Jacobian +// Sub subtracts two points in affine coordinates. +// It uses a similar approach to Add, but negates the second point before adding. func (p *G1Affine) Sub(a, b *G1Affine) *G1Affine { - var p1, p2 G1Jac - p1.FromAffine(a) - p2.FromAffine(b) - p1.SubAssign(&p2) - p.FromJacobian(&p1) + var bneg G1Affine + bneg.Neg(b) + p.Add(a, &bneg) return p } -// Equal tests if two points (in Affine coordinates) are equal +// Equal tests if two points in affine coordinates are equal. func (p *G1Affine) Equal(a *G1Affine) bool { return p.X.Equal(&a.X) && p.Y.Equal(&a.Y) } -// Neg computes -G +// Neg sets p to the affine negative point -a = (a.X, -a.Y). func (p *G1Affine) Neg(a *G1Affine) *G1Affine { p.X = a.X p.Y.Neg(&a.Y) return p } -// FromJacobian rescales a point in Jacobian coord in z=1 plane +// FromJacobian converts a point p1 from Jacobian to affine coordinates. func (p *G1Affine) FromJacobian(p1 *G1Jac) *G1Affine { var a, b fp.Element @@ -144,7 +165,7 @@ func (p *G1Affine) FromJacobian(p1 *G1Jac) *G1Affine { return p } -// String returns the string representation of the point or "O" if it is infinity +// String returns the string representation E(x,y) of the affine point p or "O" if it is infinity. func (p *G1Affine) String() string { if p.IsInfinity() { return "O" @@ -152,106 +173,100 @@ func (p *G1Affine) String() string { return "E([" + p.X.String() + "," + p.Y.String() + "])" } -// IsInfinity checks if the point is infinity -// in affine, it's encoded as (0,0) -// (0,0) is never on the curve for j=0 curves +// IsInfinity checks if the affine point p is infinity, which is encoded as (0,0). +// N.B.: (0,0) is never on the curve for j=0 curves (Y²=X³+B). func (p *G1Affine) IsInfinity() bool { return p.X.IsZero() && p.Y.IsZero() } -// IsOnCurve returns true if p in on the curve +// IsOnCurve returns true if the affine point p in on the curve. func (p *G1Affine) IsOnCurve() bool { - var point G1Jac - point.FromAffine(p) - return point.IsOnCurve() // call this function to handle infinity point + if p.IsInfinity() { + return true + } + var left, right fp.Element + left.Square(&p.Y) + right.Square(&p.X).Mul(&right, &p.X) + right.Add(&right, &bCurveCoeff) + return left.Equal(&right) } -// IsInSubGroup returns true if p is in the correct subgroup, false otherwise +// IsInSubGroup returns true if the affine point p is in the correct subgroup, false otherwise. func (p *G1Affine) IsInSubGroup() bool { - var _p G1Jac - _p.FromAffine(p) - return _p.IsInSubGroup() + return p.IsOnCurve() } // ------------------------------------------------------------------------------------------------- -// Jacobian +// Jacobian coordinates -// Set sets p to the provided point -func (p *G1Jac) Set(a *G1Jac) *G1Jac { - p.X, p.Y, p.Z = a.X, a.Y, a.Z +// Set sets p to a in Jacobian coordinates. +func (p *G1Jac) Set(q *G1Jac) *G1Jac { + p.X, p.Y, p.Z = q.X, q.Y, q.Z return p } -// Equal tests if two points (in Jacobian coordinates) are equal -func (p *G1Jac) Equal(a *G1Jac) bool { +// Equal tests if two points in Jacobian coordinates are equal. +func (p *G1Jac) Equal(q *G1Jac) bool { // If one point is infinity, the other must also be infinity. if p.Z.IsZero() { - return a.Z.IsZero() + return q.Z.IsZero() } // If the other point is infinity, return false since we can't // the following checks would be incorrect. - if a.Z.IsZero() { + if q.Z.IsZero() { return false } var pZSquare, aZSquare fp.Element pZSquare.Square(&p.Z) - aZSquare.Square(&a.Z) + aZSquare.Square(&q.Z) var lhs, rhs fp.Element lhs.Mul(&p.X, &aZSquare) - rhs.Mul(&a.X, &pZSquare) + rhs.Mul(&q.X, &pZSquare) if !lhs.Equal(&rhs) { return false } - lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &a.Z) - rhs.Mul(&a.Y, &pZSquare).Mul(&rhs, &p.Z) + lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &q.Z) + rhs.Mul(&q.Y, &pZSquare).Mul(&rhs, &p.Z) return lhs.Equal(&rhs) } -// Neg computes -G -func (p *G1Jac) Neg(a *G1Jac) *G1Jac { - *p = *a - p.Y.Neg(&a.Y) +// Neg sets p to the Jacobian negative point -q = (q.X, -q.Y, q.Z). +func (p *G1Jac) Neg(q *G1Jac) *G1Jac { + *p = *q + p.Y.Neg(&q.Y) return p } -// SubAssign subtracts two points on the curve -func (p *G1Jac) SubAssign(a *G1Jac) *G1Jac { - var tmp G1Jac - tmp.Set(a) - tmp.Y.Neg(&tmp.Y) - p.AddAssign(&tmp) - return p -} - -// AddAssign point addition in montgomery form +// AddAssign sets p to p+a in Jacobian coordinates. +// // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl -func (p *G1Jac) AddAssign(a *G1Jac) *G1Jac { +func (p *G1Jac) AddAssign(q *G1Jac) *G1Jac { - // p is infinity, return a + // p is infinity, return q if p.Z.IsZero() { - p.Set(a) + p.Set(q) return p } - // a is infinity, return p - if a.Z.IsZero() { + // q is infinity, return p + if q.Z.IsZero() { return p } var Z1Z1, Z2Z2, U1, U2, S1, S2, H, I, J, r, V fp.Element - Z1Z1.Square(&a.Z) + Z1Z1.Square(&q.Z) Z2Z2.Square(&p.Z) - U1.Mul(&a.X, &Z2Z2) + U1.Mul(&q.X, &Z2Z2) U2.Mul(&p.X, &Z1Z1) - S1.Mul(&a.Y, &p.Z). + S1.Mul(&q.Y, &p.Z). Mul(&S1, &Z2Z2) - S2.Mul(&p.Y, &a.Z). + S2.Mul(&p.Y, &q.Z). Mul(&S2, &Z1Z1) - // if p == a, we double instead + // if p == q, we double instead if U1.Equal(&U2) && S1.Equal(&S2) { return p.DoubleAssign() } @@ -270,7 +285,7 @@ func (p *G1Jac) AddAssign(a *G1Jac) *G1Jac { Mul(&p.Y, &r) S1.Mul(&S1, &J).Double(&S1) p.Y.Sub(&p.Y, &S1) - p.Z.Add(&p.Z, &a.Z) + p.Z.Add(&p.Z, &q.Z) p.Z.Square(&p.Z). Sub(&p.Z, &Z1Z1). Sub(&p.Z, &Z2Z2). @@ -279,7 +294,48 @@ func (p *G1Jac) AddAssign(a *G1Jac) *G1Jac { return p } -// AddMixed point addition +// SubAssign sets p to p-a in Jacobian coordinates. +// It uses a similar approach to AddAssign, but negates the point a before adding. +func (p *G1Jac) SubAssign(q *G1Jac) *G1Jac { + var tmp G1Jac + tmp.Set(q) + tmp.Y.Neg(&tmp.Y) + p.AddAssign(&tmp) + return p +} + +// Double sets p to [2]q in Jacobian coordinates. +// +// https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl +func (p *G1Jac) DoubleMixed(a *G1Affine) *G1Jac { + var XX, YY, YYYY, S, M, T fp.Element + XX.Square(&a.X) + YY.Square(&a.Y) + YYYY.Square(&YY) + S.Add(&a.X, &YY). + Square(&S). + Sub(&S, &XX). + Sub(&S, &YYYY). + Double(&S) + M.Double(&XX). + Add(&M, &XX) // -> + A, but A=0 here + T.Square(&M). + Sub(&T, &S). + Sub(&T, &S) + p.X.Set(&T) + p.Y.Sub(&S, &T). + Mul(&p.Y, &M) + YYYY.Double(&YYYY). + Double(&YYYY). + Double(&YYYY) + p.Y.Sub(&p.Y, &YYYY) + p.Z.Double(&a.Y) + + return p +} + +// AddMixed sets p to p+a in Jacobian coordinates, where a.Z = 1. +// // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-madd-2007-bl func (p *G1Jac) AddMixed(a *G1Affine) *G1Jac { @@ -303,7 +359,7 @@ func (p *G1Jac) AddMixed(a *G1Affine) *G1Jac { // if p == a, we double instead if U2.Equal(&p.X) && S2.Equal(&p.Y) { - return p.DoubleAssign() + return p.DoubleMixed(a) } H.Sub(&U2, &p.X) @@ -328,7 +384,8 @@ func (p *G1Jac) AddMixed(a *G1Affine) *G1Jac { return p } -// Double doubles a point in Jacobian coordinates +// Double sets p to [2]q in Jacobian coordinates. +// // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl func (p *G1Jac) Double(q *G1Jac) *G1Jac { p.Set(q) @@ -336,7 +393,8 @@ func (p *G1Jac) Double(q *G1Jac) *G1Jac { return p } -// DoubleAssign doubles a point in Jacobian coordinates +// DoubleAssign doubles p in Jacobian coordinates. +// // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl func (p *G1Jac) DoubleAssign() *G1Jac { @@ -368,43 +426,51 @@ func (p *G1Jac) DoubleAssign() *G1Jac { return p } -// ScalarMultiplication computes and returns p = a ⋅ s +// ScalarMultiplication computes and returns p = [s]a +// where p and a are Jacobian points. +// using the GLV technique. // see https://www.iacr.org/archive/crypto2001/21390189.pdf -func (p *G1Jac) ScalarMultiplication(a *G1Jac, s *big.Int) *G1Jac { - return p.mulGLV(a, s) +func (p *G1Jac) ScalarMultiplication(q *G1Jac, s *big.Int) *G1Jac { + return p.mulGLV(q, s) } -// String returns canonical representation of the point in affine coordinates +// ScalarMultiplicationBase computes and returns p = [s]g +// where g is the prime subgroup generator. +func (p *G1Jac) ScalarMultiplicationBase(s *big.Int) *G1Jac { + return p.mulGLV(&g1Gen, s) + +} + +// String converts p to affine coordinates and returns its string representation E(x,y) or "O" if it is infinity. func (p *G1Jac) String() string { _p := G1Affine{} _p.FromJacobian(p) return _p.String() } -// FromAffine sets p = Q, p in Jacobian, Q in affine -func (p *G1Jac) FromAffine(Q *G1Affine) *G1Jac { - if Q.IsInfinity() { +// FromAffine converts a point a from affine to Jacobian coordinates. +func (p *G1Jac) FromAffine(a *G1Affine) *G1Jac { + if a.IsInfinity() { p.Z.SetZero() p.X.SetOne() p.Y.SetOne() return p } p.Z.SetOne() - p.X.Set(&Q.X) - p.Y.Set(&Q.Y) + p.X.Set(&a.X) + p.Y.Set(&a.Y) return p } -// IsOnCurve returns true if p in on the curve +// IsOnCurve returns true if the Jacobian point p in on the curve. func (p *G1Jac) IsOnCurve() bool { - var left, right, tmp fp.Element + var left, right, tmp, ZZ fp.Element left.Square(&p.Y) right.Square(&p.X).Mul(&right, &p.X) - tmp.Square(&p.Z). - Square(&tmp). - Mul(&tmp, &p.Z). - Mul(&tmp, &p.Z). - Mul(&tmp, &bCurveCoeff) + ZZ.Square(&p.Z) + tmp.Square(&ZZ).Mul(&tmp, &ZZ) + // Mul tmp by bCurveCoeff=3 + fp.MulBy3(&tmp) right.Add(&right, &tmp) return left.Equal(&right) } @@ -418,13 +484,14 @@ func (p *G1Jac) IsInSubGroup() bool { } -// mulWindowed computes a 2-bits windowed scalar multiplication -func (p *G1Jac) mulWindowed(a *G1Jac, s *big.Int) *G1Jac { +// mulWindowed computes the 2-bits windowed double-and-add scalar +// multiplication p=[s]q in Jacobian coordinates. +func (p *G1Jac) mulWindowed(q *G1Jac, s *big.Int) *G1Jac { var res G1Jac var ops [3]G1Jac - ops[0].Set(a) + ops[0].Set(q) if s.Sign() == -1 { ops[0].Neg(&ops[0]) } @@ -451,17 +518,74 @@ func (p *G1Jac) mulWindowed(a *G1Jac, s *big.Int) *G1Jac { } -// ϕ assigns p to ϕ(a) where ϕ: (x,y) → (w x,y), and returns p -// where w is a third root of unity in 𝔽p -func (p *G1Jac) phi(a *G1Jac) *G1Jac { - p.Set(a) +// mulBySeed multiplies the point q by the seed xGen in Jacobian coordinates +// using an optimized addition chain. +func (p *G1Jac) mulBySeed(q *G1Jac) *G1Jac { + // Generated by github.com/mmcloughlin/addchain v0.4.0. + // Operations: 62 squares 17 multiplies + + // Allocate Temporaries. + var res, t0, t1, t2, t3 G1Jac + + res.Double(q) + t0.Set(q).AddAssign(&res) + t2.Set(q).AddAssign(&t0) + t1.Set(&res).AddAssign(&t2) + res.Double(&t1) + res.AddAssign(&t0) + t0.AddAssign(&res) + t2.AddAssign(&t0) + t1.AddAssign(&t2) + t0.AddAssign(&t1) + t1.AddAssign(&t0) + t0.AddAssign(&t1) + t2.AddAssign(&t0) + t3.Double(&t2) + t1.AddAssign(&t3) + t2.AddAssign(&t1) + res.AddAssign(&t2) + t2.AddAssign(&res) + t3.Double(&t2) + res.AddAssign(&t3) + t0.AddAssign(&res) + t1.AddAssign(&t0) + t3.Double(&t1) + for s := 1; s < 2; s++ { + t3.Double(&t3) + } + t3.AddAssign(&t1) + t2.AddAssign(&t3) + t1.AddAssign(&t2) + t2.AddAssign(&t1) + for s := 0; s < 17; s++ { + t2.Double(&t2) + } + t1.AddAssign(&t2) + for s := 0; s < 14; s++ { + t1.Double(&t1) + } + t0.AddAssign(&t1) + for s := 0; s < 16; s++ { + t0.Double(&t0) + } + res.AddAssign(&t0) + + p.Set(&res) + return p +} + +// phi sets p to ϕ(a) where ϕ: (x,y) → (w x,y), +// where w is a third root of unity. +func (p *G1Jac) phi(q *G1Jac) *G1Jac { + p.Set(q) p.X.Mul(&p.X, &thirdRootOneG1) return p } // mulGLV computes the scalar multiplication using a windowed-GLV method +// // see https://www.iacr.org/archive/crypto2001/21390189.pdf -func (p *G1Jac) mulGLV(a *G1Jac, s *big.Int) *G1Jac { +func (p *G1Jac) mulGLV(q *G1Jac, s *big.Int) *G1Jac { var table [15]G1Jac var res G1Jac @@ -469,11 +593,11 @@ func (p *G1Jac) mulGLV(a *G1Jac, s *big.Int) *G1Jac { res.Set(&g1Infinity) - // table[b3b2b1b0-1] = b3b2 ⋅ ϕ(a) + b1b0*a - table[0].Set(a) - table[3].phi(a) + // table[b3b2b1b0-1] = b3b2 ⋅ ϕ(q) + b1b0*q + table[0].Set(q) + table[3].phi(q) - // split the scalar, modifies ±a, ϕ(a) accordingly + // split the scalar, modifies ±q, ϕ(q) accordingly k := ecc.SplitScalar(s, &glvBasis) if k[0].Sign() == -1 { @@ -486,7 +610,7 @@ func (p *G1Jac) mulGLV(a *G1Jac, s *big.Int) *G1Jac { } // precompute table (2 bits sliding window) - // table[b3b2b1b0-1] = b3b2 ⋅ ϕ(a) + b1b0 ⋅ a if b3b2b1b0 != 0 + // table[b3b2b1b0-1] = b3b2 ⋅ ϕ(q) + b1b0 ⋅ q if b3b2b1b0 != 0 table[1].Double(&table[0]) table[2].Set(&table[1]).AddAssign(&table[0]) table[4].Set(&table[3]).AddAssign(&table[0]) @@ -532,14 +656,14 @@ func (p *G1Jac) mulGLV(a *G1Jac, s *big.Int) *G1Jac { return p } -// JointScalarMultiplicationBase computes [s1]g+[s2]a using Straus-Shamir technique -// where g is the prime subgroup generator -func (p *G1Jac) JointScalarMultiplicationBase(a *G1Affine, s1, s2 *big.Int) *G1Jac { +// JointScalarMultiplication computes [s1]a1+[s2]a2 using Strauss-Shamir technique +// where a1 and a2 are affine points. +func (p *G1Jac) JointScalarMultiplication(a1, a2 *G1Affine, s1, s2 *big.Int) *G1Jac { var res, p1, p2 G1Jac res.Set(&g1Infinity) - p1.Set(&g1Gen) - p2.FromAffine(a) + p1.FromAffine(a1) + p2.FromAffine(a2) var table [15]G1Jac @@ -603,17 +727,24 @@ func (p *G1Jac) JointScalarMultiplicationBase(a *G1Affine, s1, s2 *big.Int) *G1J } +// JointScalarMultiplicationBase computes [s1]g+[s2]a using Straus-Shamir technique +// where g is the prime subgroup generator. +func (p *G1Jac) JointScalarMultiplicationBase(a *G1Affine, s1, s2 *big.Int) *G1Jac { + return p.JointScalarMultiplication(&g1GenAff, a, s1, s2) + +} + // ------------------------------------------------------------------------------------------------- -// Jacobian extended +// extended Jacobian coordinates -// Set sets p to the provided point -func (p *g1JacExtended) Set(a *g1JacExtended) *g1JacExtended { - p.X, p.Y, p.ZZ, p.ZZZ = a.X, a.Y, a.ZZ, a.ZZZ +// Set sets p to a in extended Jacobian coordinates. +func (p *g1JacExtended) Set(q *g1JacExtended) *g1JacExtended { + p.X, p.Y, p.ZZ, p.ZZZ = q.X, q.Y, q.ZZ, q.ZZZ return p } -// setInfinity sets p to O -func (p *g1JacExtended) setInfinity() *g1JacExtended { +// SetInfinity sets p to the infinity point (1,1,0,0). +func (p *g1JacExtended) SetInfinity() *g1JacExtended { p.X.SetOne() p.Y.SetOne() p.ZZ = fp.Element{} @@ -621,43 +752,45 @@ func (p *g1JacExtended) setInfinity() *g1JacExtended { return p } -func (p *g1JacExtended) IsZero() bool { +// IsInfinity checks if the p is infinity, i.e. p.ZZ=0. +func (p *g1JacExtended) IsInfinity() bool { return p.ZZ.IsZero() } -// fromJacExtended sets Q in affine coordinates -func (p *G1Affine) fromJacExtended(Q *g1JacExtended) *G1Affine { - if Q.ZZ.IsZero() { +// fromJacExtended converts an extended Jacobian point to an affine point. +func (p *G1Affine) fromJacExtended(q *g1JacExtended) *G1Affine { + if q.ZZ.IsZero() { p.X = fp.Element{} p.Y = fp.Element{} return p } - p.X.Inverse(&Q.ZZ).Mul(&p.X, &Q.X) - p.Y.Inverse(&Q.ZZZ).Mul(&p.Y, &Q.Y) + p.X.Inverse(&q.ZZ).Mul(&p.X, &q.X) + p.Y.Inverse(&q.ZZZ).Mul(&p.Y, &q.Y) return p } -// fromJacExtended sets Q in Jacobian coordinates -func (p *G1Jac) fromJacExtended(Q *g1JacExtended) *G1Jac { - if Q.ZZ.IsZero() { +// fromJacExtended converts an extended Jacobian point to a Jacobian point. +func (p *G1Jac) fromJacExtended(q *g1JacExtended) *G1Jac { + if q.ZZ.IsZero() { p.Set(&g1Infinity) return p } - p.X.Mul(&Q.ZZ, &Q.X).Mul(&p.X, &Q.ZZ) - p.Y.Mul(&Q.ZZZ, &Q.Y).Mul(&p.Y, &Q.ZZZ) - p.Z.Set(&Q.ZZZ) + p.X.Mul(&q.ZZ, &q.X).Mul(&p.X, &q.ZZ) + p.Y.Mul(&q.ZZZ, &q.Y).Mul(&p.Y, &q.ZZZ) + p.Z.Set(&q.ZZZ) return p } -// unsafeFromJacExtended sets p in Jacobian coordinates, but don't check for infinity -func (p *G1Jac) unsafeFromJacExtended(Q *g1JacExtended) *G1Jac { - p.X.Square(&Q.ZZ).Mul(&p.X, &Q.X) - p.Y.Square(&Q.ZZZ).Mul(&p.Y, &Q.Y) - p.Z = Q.ZZZ +// unsafeFromJacExtended converts an extended Jacobian point, distinct from Infinity, to a Jacobian point. +func (p *G1Jac) unsafeFromJacExtended(q *g1JacExtended) *G1Jac { + p.X.Square(&q.ZZ).Mul(&p.X, &q.X) + p.Y.Square(&q.ZZZ).Mul(&p.Y, &q.Y) + p.Z = q.ZZZ return p } -// add point in Jacobian extended coordinates +// add sets p to p+q in extended Jacobian coordinates. +// // https://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-add-2008-s func (p *g1JacExtended) add(q *g1JacExtended) *g1JacExtended { //if q is infinity return p @@ -713,10 +846,11 @@ func (p *g1JacExtended) add(q *g1JacExtended) *g1JacExtended { return p } -// double point in Jacobian extended coordinates +// double sets p to [2]q in Jacobian extended coordinates. +// // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#doubling-dbl-2008-s-1 -// since we consider any point on Z=0 as the point at infinity -// this doubling formula works for infinity points as well +// N.B.: since we consider any point on Z=0 as the point at infinity +// this doubling formula works for infinity points as well. func (p *g1JacExtended) double(q *g1JacExtended) *g1JacExtended { var U, V, W, S, XX, M fp.Element @@ -726,7 +860,7 @@ func (p *g1JacExtended) double(q *g1JacExtended) *g1JacExtended { S.Mul(&q.X, &V) XX.Square(&q.X) M.Double(&XX). - Add(&M, &XX) // -> + a, but a=0 here + Add(&M, &XX) // -> + A, but A=0 here U.Mul(&W, &q.Y) p.X.Square(&M). @@ -741,9 +875,10 @@ func (p *g1JacExtended) double(q *g1JacExtended) *g1JacExtended { return p } -// subMixed same as addMixed, but will negate a.Y +// addMixed sets p to p+q in extended Jacobian coordinates, where a.ZZ=1. +// // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-madd-2008-s -func (p *g1JacExtended) subMixed(a *G1Affine) *g1JacExtended { +func (p *g1JacExtended) addMixed(a *G1Affine) *g1JacExtended { //if a is infinity return p if a.IsInfinity() { @@ -752,7 +887,7 @@ func (p *g1JacExtended) subMixed(a *G1Affine) *g1JacExtended { // p is infinity, return a if p.ZZ.IsZero() { p.X = a.X - p.Y.Neg(&a.Y) + p.Y = a.Y p.ZZ.SetOne() p.ZZZ.SetOne() return p @@ -765,12 +900,11 @@ func (p *g1JacExtended) subMixed(a *G1Affine) *g1JacExtended { P.Sub(&P, &p.X) R.Mul(&a.Y, &p.ZZZ) - R.Neg(&R) R.Sub(&R, &p.Y) if P.IsZero() { if R.IsZero() { - return p.doubleNegMixed(a) + return p.doubleMixed(a) } p.ZZ = fp.Element{} @@ -797,9 +931,10 @@ func (p *g1JacExtended) subMixed(a *G1Affine) *g1JacExtended { } -// addMixed +// subMixed works the same as addMixed, but negates a.Y. +// // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-madd-2008-s -func (p *g1JacExtended) addMixed(a *G1Affine) *g1JacExtended { +func (p *g1JacExtended) subMixed(a *G1Affine) *g1JacExtended { //if a is infinity return p if a.IsInfinity() { @@ -808,7 +943,7 @@ func (p *g1JacExtended) addMixed(a *G1Affine) *g1JacExtended { // p is infinity, return a if p.ZZ.IsZero() { p.X = a.X - p.Y = a.Y + p.Y.Neg(&a.Y) p.ZZ.SetOne() p.ZZZ.SetOne() return p @@ -821,11 +956,12 @@ func (p *g1JacExtended) addMixed(a *G1Affine) *g1JacExtended { P.Sub(&P, &p.X) R.Mul(&a.Y, &p.ZZZ) + R.Neg(&R) R.Sub(&R, &p.Y) if P.IsZero() { if R.IsZero() { - return p.doubleMixed(a) + return p.doubleNegMixed(a) } p.ZZ = fp.Element{} @@ -852,21 +988,21 @@ func (p *g1JacExtended) addMixed(a *G1Affine) *g1JacExtended { } -// doubleNegMixed same as double, but will negate q.Y -func (p *g1JacExtended) doubleNegMixed(q *G1Affine) *g1JacExtended { +// doubleNegMixed works the same as double, but negates q.Y. +func (p *g1JacExtended) doubleNegMixed(a *G1Affine) *g1JacExtended { var U, V, W, S, XX, M, S2, L fp.Element - U.Double(&q.Y) + U.Double(&a.Y) U.Neg(&U) V.Square(&U) W.Mul(&U, &V) - S.Mul(&q.X, &V) - XX.Square(&q.X) + S.Mul(&a.X, &V) + XX.Square(&a.X) M.Double(&XX). - Add(&M, &XX) // -> + a, but a=0 here + Add(&M, &XX) // -> + A, but A=0 here S2.Double(&S) - L.Mul(&W, &q.Y) + L.Mul(&W, &a.Y) p.X.Square(&M). Sub(&p.X, &S2) @@ -879,21 +1015,22 @@ func (p *g1JacExtended) doubleNegMixed(q *G1Affine) *g1JacExtended { return p } -// doubleMixed point in Jacobian extended coordinates +// doubleMixed sets p to [2]a in Jacobian extended coordinates, where a.ZZ=1. +// // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#doubling-dbl-2008-s-1 -func (p *g1JacExtended) doubleMixed(q *G1Affine) *g1JacExtended { +func (p *g1JacExtended) doubleMixed(a *G1Affine) *g1JacExtended { var U, V, W, S, XX, M, S2, L fp.Element - U.Double(&q.Y) + U.Double(&a.Y) V.Square(&U) W.Mul(&U, &V) - S.Mul(&q.X, &V) - XX.Square(&q.X) + S.Mul(&a.X, &V) + XX.Square(&a.X) M.Double(&XX). - Add(&M, &XX) // -> + a, but a=0 here + Add(&M, &XX) // -> + A, but A=0 here S2.Double(&S) - L.Mul(&W, &q.Y) + L.Mul(&W, &a.Y) p.X.Square(&M). Sub(&p.X, &S2) @@ -907,7 +1044,7 @@ func (p *g1JacExtended) doubleMixed(q *G1Affine) *g1JacExtended { } // BatchJacobianToAffineG1 converts points in Jacobian coordinates to Affine coordinates -// performing a single field inversion (Montgomery batch inversion trick). +// performing a single field inversion using the Montgomery batch inversion trick. func BatchJacobianToAffineG1(points []G1Jac) []G1Affine { result := make([]G1Affine, len(points)) zeroes := make([]bool, len(points)) @@ -957,7 +1094,7 @@ func BatchJacobianToAffineG1(points []G1Jac) []G1Affine { // BatchScalarMultiplicationG1 multiplies the same base by all scalars // and return resulting points in affine coordinates -// uses a simple windowed-NAF like exponentiation algorithm +// uses a simple windowed-NAF-like multiplication algorithm. func BatchScalarMultiplicationG1(base *G1Affine, scalars []fr.Element) []G1Affine { // approximate cost in group ops is // cost = 2^{c-1} + n(scalar.nbBits+nbChunks) @@ -1039,18 +1176,29 @@ func BatchScalarMultiplicationG1(base *G1Affine, scalars []fr.Element) []G1Affin return toReturnAff } -// batch add affine coordinates -// using batch inversion -// special cases (doubling, infinity) must be filtered out before this call +// batchAddG1Affine adds affine points using the Montgomery batch inversion trick. +// Special cases (doubling, infinity) must be filtered out before this call. func batchAddG1Affine[TP pG1Affine, TPP ppG1Affine, TC cG1Affine](R *TPP, P *TP, batchSize int) { var lambda, lambdain TC - // add part + // from https://docs.zkproof.org/pages/standards/accepted-workshop3/proposal-turbo_plonk.pdf + // affine point addition formula + // R(X1, Y1) + P(X2, Y2) = Q(X3, Y3) + // λ = (Y2 - Y1) / (X2 - X1) + // X3 = λ² - (X1 + X2) + // Y3 = λ * (X1 - X3) - Y1 + + // first we compute the 1 / (X2 - X1) for all points using Montgomery batch inversion trick + + // X2 - X1 for j := 0; j < batchSize; j++ { lambdain[j].Sub(&(*P)[j].X, &(*R)[j].X) } - // invert denominator using montgomery batch invert technique + // montgomery batch inversion; + // lambda[0] = 1 / (P[0].X - R[0].X) + // lambda[1] = 1 / (P[1].X - R[1].X) + // ... { var accumulator fp.Element lambda[0].SetOne() @@ -1070,22 +1218,24 @@ func batchAddG1Affine[TP pG1Affine, TPP ppG1Affine, TC cG1Affine](R *TPP, P *TP, lambda[0].Set(&accumulator) } - var d fp.Element - var rr G1Affine + var t fp.Element + var Q G1Affine - // add part for j := 0; j < batchSize; j++ { - // computa lambda - d.Sub(&(*P)[j].Y, &(*R)[j].Y) - lambda[j].Mul(&lambda[j], &d) - - // compute X, Y - rr.X.Square(&lambda[j]) - rr.X.Sub(&rr.X, &(*R)[j].X) - rr.X.Sub(&rr.X, &(*P)[j].X) - d.Sub(&(*R)[j].X, &rr.X) - rr.Y.Mul(&lambda[j], &d) - rr.Y.Sub(&rr.Y, &(*R)[j].Y) - (*R)[j].Set(&rr) + // λ = (Y2 - Y1) / (X2 - X1) + t.Sub(&(*P)[j].Y, &(*R)[j].Y) + lambda[j].Mul(&lambda[j], &t) + + // X3 = λ² - (X1 + X2) + Q.X.Square(&lambda[j]) + Q.X.Sub(&Q.X, &(*R)[j].X) + Q.X.Sub(&Q.X, &(*P)[j].X) + + // Y3 = λ * (X1 - X3) - Y1 + t.Sub(&(*R)[j].X, &Q.X) + Q.Y.Mul(&lambda[j], &t) + Q.Y.Sub(&Q.Y, &(*R)[j].Y) + + (*R)[j].Set(&Q) } } diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/g2.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/g2.go index b4f279fc379..c8f31ad9248 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/g2.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/g2.go @@ -1,22 +1,12 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT package bn254 import ( + "crypto/rand" "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark-crypto/ecc/bn254/fr" "github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower" @@ -25,17 +15,17 @@ import ( "runtime" ) -// G2Affine point in affine coordinates +// G2Affine is a point in affine coordinates (x,y) type G2Affine struct { X, Y fptower.E2 } -// G2Jac is a point with fptower.E2 coordinates +// G2Jac is a point in Jacobian coordinates (x=X/Z², y=Y/Z³) type G2Jac struct { X, Y, Z fptower.E2 } -// g2JacExtended parameterized Jacobian coordinates (x=X/ZZ, y=Y/ZZZ, ZZ³=ZZZ²) +// g2JacExtended is a point in extended Jacobian coordinates (x=X/ZZ, y=Y/ZZZ, ZZ³=ZZZ²) type g2JacExtended struct { X, Y, ZZ, ZZZ fptower.E2 } @@ -46,22 +36,24 @@ type g2Proj struct { } // ------------------------------------------------------------------------------------------------- -// Affine +// Affine coordinates -// Set sets p to the provided point +// Set sets p to a in affine coordinates. func (p *G2Affine) Set(a *G2Affine) *G2Affine { p.X, p.Y = a.X, a.Y return p } -// setInfinity sets p to O -func (p *G2Affine) setInfinity() *G2Affine { +// SetInfinity sets p to the infinity point, which is encoded as (0,0). +// N.B.: (0,0) is never on the curve for j=0 curves (Y²=X³+B). +func (p *G2Affine) SetInfinity() *G2Affine { p.X.SetZero() p.Y.SetZero() return p } -// ScalarMultiplication computes and returns p = a ⋅ s +// ScalarMultiplication computes and returns p = [s]a +// where p and a are affine points. func (p *G2Affine) ScalarMultiplication(a *G2Affine, s *big.Int) *G2Affine { var _p G2Jac _p.FromAffine(a) @@ -70,51 +62,97 @@ func (p *G2Affine) ScalarMultiplication(a *G2Affine, s *big.Int) *G2Affine { return p } -// Add adds two point in affine coordinates. -// This should rarely be used as it is very inefficient compared to Jacobian -func (p *G2Affine) Add(a, b *G2Affine) *G2Affine { - var p1, p2 G2Jac - p1.FromAffine(a) - p2.FromAffine(b) - p1.AddAssign(&p2) - p.FromJacobian(&p1) +// ScalarMultiplicationBase computes and returns p = [s]g +// where g is the affine point generating the prime subgroup. +func (p *G2Affine) ScalarMultiplicationBase(s *big.Int) *G2Affine { + var _p G2Jac + _p.mulGLV(&g2Gen, s) + p.FromJacobian(&_p) return p } +// Add adds two points in affine coordinates. +// It uses the Jacobian addition with a.Z=b.Z=1 and converts the result to affine coordinates. +// +// https://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-mmadd-2007-bl +func (p *G2Affine) Add(a, b *G2Affine) *G2Affine { + var q G2Jac + // a is infinity, return b + if a.IsInfinity() { + p.Set(b) + return p + } + // b is infinity, return a + if b.IsInfinity() { + p.Set(a) + return p + } + if a.X.Equal(&b.X) { + // if b == a, we double instead + if a.Y.Equal(&b.Y) { + q.DoubleMixed(a) + return p.FromJacobian(&q) + } else { + // if b == -a, we return 0 + return p.SetInfinity() + } + } + var H, HH, I, J, r, V fptower.E2 + H.Sub(&b.X, &a.X) + HH.Square(&H) + I.Double(&HH).Double(&I) + J.Mul(&H, &I) + r.Sub(&b.Y, &a.Y) + r.Double(&r) + V.Mul(&a.X, &I) + q.X.Square(&r). + Sub(&q.X, &J). + Sub(&q.X, &V). + Sub(&q.X, &V) + q.Y.Sub(&V, &q.X). + Mul(&q.Y, &r) + J.Mul(&a.Y, &J).Double(&J) + q.Y.Sub(&q.Y, &J) + q.Z.Double(&H) + + return p.FromJacobian(&q) +} + // Double doubles a point in affine coordinates. -// This should rarely be used as it is very inefficient compared to Jacobian +// It converts the point to Jacobian coordinates, doubles it using Jacobian +// addition with a.Z=1, and converts it back to affine coordinates. +// +// http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-mdbl-2007-bl func (p *G2Affine) Double(a *G2Affine) *G2Affine { - var p1 G2Jac - p1.FromAffine(a) - p1.Double(&p1) - p.FromJacobian(&p1) + var q G2Jac + q.FromAffine(a) + q.DoubleMixed(a) + p.FromJacobian(&q) return p } -// Sub subs two point in affine coordinates. -// This should rarely be used as it is very inefficient compared to Jacobian +// Sub subtracts two points in affine coordinates. +// It uses a similar approach to Add, but negates the second point before adding. func (p *G2Affine) Sub(a, b *G2Affine) *G2Affine { - var p1, p2 G2Jac - p1.FromAffine(a) - p2.FromAffine(b) - p1.SubAssign(&p2) - p.FromJacobian(&p1) + var bneg G2Affine + bneg.Neg(b) + p.Add(a, &bneg) return p } -// Equal tests if two points (in Affine coordinates) are equal +// Equal tests if two points in affine coordinates are equal. func (p *G2Affine) Equal(a *G2Affine) bool { return p.X.Equal(&a.X) && p.Y.Equal(&a.Y) } -// Neg computes -G +// Neg sets p to the affine negative point -a = (a.X, -a.Y). func (p *G2Affine) Neg(a *G2Affine) *G2Affine { p.X = a.X p.Y.Neg(&a.Y) return p } -// FromJacobian rescales a point in Jacobian coord in z=1 plane +// FromJacobian converts a point p1 from Jacobian to affine coordinates. func (p *G2Affine) FromJacobian(p1 *G2Jac) *G2Affine { var a, b fptower.E2 @@ -133,7 +171,7 @@ func (p *G2Affine) FromJacobian(p1 *G2Jac) *G2Affine { return p } -// String returns the string representation of the point or "O" if it is infinity +// String returns the string representation E(x,y) of the affine point p or "O" if it is infinity. func (p *G2Affine) String() string { if p.IsInfinity() { return "O" @@ -141,106 +179,115 @@ func (p *G2Affine) String() string { return "E([" + p.X.String() + "," + p.Y.String() + "])" } -// IsInfinity checks if the point is infinity -// in affine, it's encoded as (0,0) -// (0,0) is never on the curve for j=0 curves +// IsInfinity checks if the affine point p is infinity, which is encoded as (0,0). +// N.B.: (0,0) is never on the curve for j=0 curves (Y²=X³+B). func (p *G2Affine) IsInfinity() bool { return p.X.IsZero() && p.Y.IsZero() } -// IsOnCurve returns true if p in on the curve +// IsOnCurve returns true if the affine point p in on the curve. func (p *G2Affine) IsOnCurve() bool { - var point G2Jac - point.FromAffine(p) - return point.IsOnCurve() // call this function to handle infinity point + if p.IsInfinity() { + return true + } + var left, right fptower.E2 + left.Square(&p.Y) + right.Square(&p.X).Mul(&right, &p.X) + right.Add(&right, &bTwistCurveCoeff) + return left.Equal(&right) } -// IsInSubGroup returns true if p is in the correct subgroup, false otherwise +// IsInSubGroup returns true if the affine point p is in the correct subgroup, false otherwise. func (p *G2Affine) IsInSubGroup() bool { - var _p G2Jac + if !p.IsOnCurve() { + return false + } + var a, b, c, res, _p G2Jac _p.FromAffine(p) - return _p.IsInSubGroup() + a.mulBySeed(&_p) + b.psi(&a) + a.AddAssign(&_p) + res.psi(&b) + c.Set(&res). + AddAssign(&b). + AddAssign(&a) + res.psi(&res). + Double(&res) + + return res.Equal(&c) } // ------------------------------------------------------------------------------------------------- -// Jacobian +// Jacobian coordinates -// Set sets p to the provided point -func (p *G2Jac) Set(a *G2Jac) *G2Jac { - p.X, p.Y, p.Z = a.X, a.Y, a.Z +// Set sets p to a in Jacobian coordinates. +func (p *G2Jac) Set(q *G2Jac) *G2Jac { + p.X, p.Y, p.Z = q.X, q.Y, q.Z return p } -// Equal tests if two points (in Jacobian coordinates) are equal -func (p *G2Jac) Equal(a *G2Jac) bool { +// Equal tests if two points in Jacobian coordinates are equal. +func (p *G2Jac) Equal(q *G2Jac) bool { // If one point is infinity, the other must also be infinity. if p.Z.IsZero() { - return a.Z.IsZero() + return q.Z.IsZero() } // If the other point is infinity, return false since we can't // the following checks would be incorrect. - if a.Z.IsZero() { + if q.Z.IsZero() { return false } var pZSquare, aZSquare fptower.E2 pZSquare.Square(&p.Z) - aZSquare.Square(&a.Z) + aZSquare.Square(&q.Z) var lhs, rhs fptower.E2 lhs.Mul(&p.X, &aZSquare) - rhs.Mul(&a.X, &pZSquare) + rhs.Mul(&q.X, &pZSquare) if !lhs.Equal(&rhs) { return false } - lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &a.Z) - rhs.Mul(&a.Y, &pZSquare).Mul(&rhs, &p.Z) + lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &q.Z) + rhs.Mul(&q.Y, &pZSquare).Mul(&rhs, &p.Z) return lhs.Equal(&rhs) } -// Neg computes -G -func (p *G2Jac) Neg(a *G2Jac) *G2Jac { - *p = *a - p.Y.Neg(&a.Y) - return p -} - -// SubAssign subtracts two points on the curve -func (p *G2Jac) SubAssign(a *G2Jac) *G2Jac { - var tmp G2Jac - tmp.Set(a) - tmp.Y.Neg(&tmp.Y) - p.AddAssign(&tmp) +// Neg sets p to the Jacobian negative point -q = (q.X, -q.Y, q.Z). +func (p *G2Jac) Neg(q *G2Jac) *G2Jac { + *p = *q + p.Y.Neg(&q.Y) return p } -// AddAssign point addition in montgomery form +// AddAssign sets p to p+a in Jacobian coordinates. +// // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl -func (p *G2Jac) AddAssign(a *G2Jac) *G2Jac { +func (p *G2Jac) AddAssign(q *G2Jac) *G2Jac { - // p is infinity, return a + // p is infinity, return q if p.Z.IsZero() { - p.Set(a) + p.Set(q) return p } - // a is infinity, return p - if a.Z.IsZero() { + // q is infinity, return p + if q.Z.IsZero() { return p } var Z1Z1, Z2Z2, U1, U2, S1, S2, H, I, J, r, V fptower.E2 - Z1Z1.Square(&a.Z) + Z1Z1.Square(&q.Z) Z2Z2.Square(&p.Z) - U1.Mul(&a.X, &Z2Z2) + U1.Mul(&q.X, &Z2Z2) U2.Mul(&p.X, &Z1Z1) - S1.Mul(&a.Y, &p.Z). + S1.Mul(&q.Y, &p.Z). Mul(&S1, &Z2Z2) - S2.Mul(&p.Y, &a.Z). + S2.Mul(&p.Y, &q.Z). Mul(&S2, &Z1Z1) - // if p == a, we double instead + // if p == q, we double instead if U1.Equal(&U2) && S1.Equal(&S2) { return p.DoubleAssign() } @@ -259,7 +306,7 @@ func (p *G2Jac) AddAssign(a *G2Jac) *G2Jac { Mul(&p.Y, &r) S1.Mul(&S1, &J).Double(&S1) p.Y.Sub(&p.Y, &S1) - p.Z.Add(&p.Z, &a.Z) + p.Z.Add(&p.Z, &q.Z) p.Z.Square(&p.Z). Sub(&p.Z, &Z1Z1). Sub(&p.Z, &Z2Z2). @@ -268,7 +315,48 @@ func (p *G2Jac) AddAssign(a *G2Jac) *G2Jac { return p } -// AddMixed point addition +// SubAssign sets p to p-a in Jacobian coordinates. +// It uses a similar approach to AddAssign, but negates the point a before adding. +func (p *G2Jac) SubAssign(q *G2Jac) *G2Jac { + var tmp G2Jac + tmp.Set(q) + tmp.Y.Neg(&tmp.Y) + p.AddAssign(&tmp) + return p +} + +// Double sets p to [2]q in Jacobian coordinates. +// +// https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl +func (p *G2Jac) DoubleMixed(a *G2Affine) *G2Jac { + var XX, YY, YYYY, S, M, T fptower.E2 + XX.Square(&a.X) + YY.Square(&a.Y) + YYYY.Square(&YY) + S.Add(&a.X, &YY). + Square(&S). + Sub(&S, &XX). + Sub(&S, &YYYY). + Double(&S) + M.Double(&XX). + Add(&M, &XX) // -> + A, but A=0 here + T.Square(&M). + Sub(&T, &S). + Sub(&T, &S) + p.X.Set(&T) + p.Y.Sub(&S, &T). + Mul(&p.Y, &M) + YYYY.Double(&YYYY). + Double(&YYYY). + Double(&YYYY) + p.Y.Sub(&p.Y, &YYYY) + p.Z.Double(&a.Y) + + return p +} + +// AddMixed sets p to p+a in Jacobian coordinates, where a.Z = 1. +// // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-madd-2007-bl func (p *G2Jac) AddMixed(a *G2Affine) *G2Jac { @@ -292,7 +380,7 @@ func (p *G2Jac) AddMixed(a *G2Affine) *G2Jac { // if p == a, we double instead if U2.Equal(&p.X) && S2.Equal(&p.Y) { - return p.DoubleAssign() + return p.DoubleMixed(a) } H.Sub(&U2, &p.X) @@ -317,7 +405,8 @@ func (p *G2Jac) AddMixed(a *G2Affine) *G2Jac { return p } -// Double doubles a point in Jacobian coordinates +// Double sets p to [2]q in Jacobian coordinates. +// // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl func (p *G2Jac) Double(q *G2Jac) *G2Jac { p.Set(q) @@ -325,7 +414,8 @@ func (p *G2Jac) Double(q *G2Jac) *G2Jac { return p } -// DoubleAssign doubles a point in Jacobian coordinates +// DoubleAssign doubles p in Jacobian coordinates. +// // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl func (p *G2Jac) DoubleAssign() *G2Jac { @@ -357,43 +447,50 @@ func (p *G2Jac) DoubleAssign() *G2Jac { return p } -// ScalarMultiplication computes and returns p = a ⋅ s +// ScalarMultiplication computes and returns p = [s]a +// where p and a are Jacobian points. +// using the GLV technique. // see https://www.iacr.org/archive/crypto2001/21390189.pdf -func (p *G2Jac) ScalarMultiplication(a *G2Jac, s *big.Int) *G2Jac { - return p.mulGLV(a, s) +func (p *G2Jac) ScalarMultiplication(q *G2Jac, s *big.Int) *G2Jac { + return p.mulGLV(q, s) } -// String returns canonical representation of the point in affine coordinates +// ScalarMultiplicationBase computes and returns p = [s]g +// where g is the prime subgroup generator. +func (p *G2Jac) ScalarMultiplicationBase(s *big.Int) *G2Jac { + return p.mulGLV(&g2Gen, s) + +} + +// String converts p to affine coordinates and returns its string representation E(x,y) or "O" if it is infinity. func (p *G2Jac) String() string { _p := G2Affine{} _p.FromJacobian(p) return _p.String() } -// FromAffine sets p = Q, p in Jacobian, Q in affine -func (p *G2Jac) FromAffine(Q *G2Affine) *G2Jac { - if Q.IsInfinity() { +// FromAffine converts a point a from affine to Jacobian coordinates. +func (p *G2Jac) FromAffine(a *G2Affine) *G2Jac { + if a.IsInfinity() { p.Z.SetZero() p.X.SetOne() p.Y.SetOne() return p } p.Z.SetOne() - p.X.Set(&Q.X) - p.Y.Set(&Q.Y) + p.X.Set(&a.X) + p.Y.Set(&a.Y) return p } -// IsOnCurve returns true if p in on the curve +// IsOnCurve returns true if the Jacobian point p in on the curve. func (p *G2Jac) IsOnCurve() bool { - var left, right, tmp fptower.E2 + var left, right, tmp, ZZ fptower.E2 left.Square(&p.Y) right.Square(&p.X).Mul(&right, &p.X) - tmp.Square(&p.Z). - Square(&tmp). - Mul(&tmp, &p.Z). - Mul(&tmp, &p.Z). - Mul(&tmp, &bTwistCurveCoeff) + ZZ.Square(&p.Z) + tmp.Square(&ZZ).Mul(&tmp, &ZZ) + tmp.MulBybTwistCurveCoeff(&tmp) right.Add(&right, &tmp) return left.Equal(&right) } @@ -402,28 +499,49 @@ func (p *G2Jac) IsOnCurve() bool { // https://eprint.iacr.org/2022/348.pdf, sec. 3 and 5.1 // [r]P == 0 <==> [x₀+1]P + ψ([x₀]P) + ψ²([x₀]P) = ψ³([2x₀]P) func (p *G2Jac) IsInSubGroup() bool { + if !p.IsOnCurve() { + return false + } var a, b, c, res G2Jac - a.ScalarMultiplication(p, &xGen) + a.mulBySeed(p) b.psi(&a) a.AddAssign(p) res.psi(&b) + c.Set(&res). + AddAssign(&b). + AddAssign(&a) + res.psi(&res). + Double(&res) + + return res.Equal(&c) +} + +func GeneratePointNotInG2(f E2) G2Jac { + var res, jac, a, b, c G2Jac + aff := MapToCurve2(&f) + jac.FromAffine(&aff) + // [x₀+1]P + ψ([x₀]P) + ψ²([x₀]P) - ψ³([2x₀]P) = [r]P + a.mulBySeed(&jac) + b.psi(&a) + a.AddAssign(&jac) + res.psi(&b) c.Set(&res). AddAssign(&b). AddAssign(&a) res.psi(&res). Double(&res). SubAssign(&c) - - return res.IsOnCurve() && res.Z.IsZero() + return res } -// mulWindowed computes a 2-bits windowed scalar multiplication -func (p *G2Jac) mulWindowed(a *G2Jac, s *big.Int) *G2Jac { +// mulWindowed computes the 2-bits windowed double-and-add scalar +// multiplication p=[s]q in Jacobian coordinates. +func (p *G2Jac) mulWindowed(q *G2Jac, s *big.Int) *G2Jac { var res G2Jac var ops [3]G2Jac - ops[0].Set(a) + ops[0].Set(q) if s.Sign() == -1 { ops[0].Neg(&ops[0]) } @@ -450,26 +568,83 @@ func (p *G2Jac) mulWindowed(a *G2Jac, s *big.Int) *G2Jac { } -// ψ(p) = u o π o u⁻¹ where u:E'→E iso from the twist to E -func (p *G2Jac) psi(a *G2Jac) *G2Jac { - p.Set(a) +// mulBySeed multiplies the point q by the seed xGen in Jacobian coordinates +// using an optimized addition chain. +func (p *G2Jac) mulBySeed(q *G2Jac) *G2Jac { + // Generated by github.com/mmcloughlin/addchain v0.4.0. + // Operations: 62 squares 17 multiplies + + // Allocate Temporaries. + var res, t0, t1, t2, t3 G2Jac + + res.Double(q) + t0.Set(q).AddAssign(&res) + t2.Set(q).AddAssign(&t0) + t1.Set(&res).AddAssign(&t2) + res.Double(&t1) + res.AddAssign(&t0) + t0.AddAssign(&res) + t2.AddAssign(&t0) + t1.AddAssign(&t2) + t0.AddAssign(&t1) + t1.AddAssign(&t0) + t0.AddAssign(&t1) + t2.AddAssign(&t0) + t3.Double(&t2) + t1.AddAssign(&t3) + t2.AddAssign(&t1) + res.AddAssign(&t2) + t2.AddAssign(&res) + t3.Double(&t2) + res.AddAssign(&t3) + t0.AddAssign(&res) + t1.AddAssign(&t0) + t3.Double(&t1) + for s := 1; s < 2; s++ { + t3.Double(&t3) + } + t3.AddAssign(&t1) + t2.AddAssign(&t3) + t1.AddAssign(&t2) + t2.AddAssign(&t1) + for s := 0; s < 17; s++ { + t2.Double(&t2) + } + t1.AddAssign(&t2) + for s := 0; s < 14; s++ { + t1.Double(&t1) + } + t0.AddAssign(&t1) + for s := 0; s < 16; s++ { + t0.Double(&t0) + } + res.AddAssign(&t0) + + p.Set(&res) + return p +} + +// psi sets p to ψ(q) = u o π o u⁻¹ where u:E'→E is the isomorphism from the twist to the curve E and π is the Frobenius map. +func (p *G2Jac) psi(q *G2Jac) *G2Jac { + p.Set(q) p.X.Conjugate(&p.X).Mul(&p.X, &endo.u) p.Y.Conjugate(&p.Y).Mul(&p.Y, &endo.v) p.Z.Conjugate(&p.Z) return p } -// ϕ assigns p to ϕ(a) where ϕ: (x,y) → (w x,y), and returns p -// where w is a third root of unity in 𝔽p -func (p *G2Jac) phi(a *G2Jac) *G2Jac { - p.Set(a) +// phi sets p to ϕ(a) where ϕ: (x,y) → (w x,y), +// where w is a third root of unity. +func (p *G2Jac) phi(q *G2Jac) *G2Jac { + p.Set(q) p.X.MulByElement(&p.X, &thirdRootOneG2) return p } // mulGLV computes the scalar multiplication using a windowed-GLV method +// // see https://www.iacr.org/archive/crypto2001/21390189.pdf -func (p *G2Jac) mulGLV(a *G2Jac, s *big.Int) *G2Jac { +func (p *G2Jac) mulGLV(q *G2Jac, s *big.Int) *G2Jac { var table [15]G2Jac var res G2Jac @@ -477,11 +652,11 @@ func (p *G2Jac) mulGLV(a *G2Jac, s *big.Int) *G2Jac { res.Set(&g2Infinity) - // table[b3b2b1b0-1] = b3b2 ⋅ ϕ(a) + b1b0*a - table[0].Set(a) - table[3].phi(a) + // table[b3b2b1b0-1] = b3b2 ⋅ ϕ(q) + b1b0*q + table[0].Set(q) + table[3].phi(q) - // split the scalar, modifies ±a, ϕ(a) accordingly + // split the scalar, modifies ±q, ϕ(q) accordingly k := ecc.SplitScalar(s, &glvBasis) if k[0].Sign() == -1 { @@ -494,7 +669,7 @@ func (p *G2Jac) mulGLV(a *G2Jac, s *big.Int) *G2Jac { } // precompute table (2 bits sliding window) - // table[b3b2b1b0-1] = b3b2 ⋅ ϕ(a) + b1b0 ⋅ a if b3b2b1b0 != 0 + // table[b3b2b1b0-1] = b3b2 ⋅ ϕ(q) + b1b0 ⋅ q if b3b2b1b0 != 0 table[1].Double(&table[0]) table[2].Set(&table[1]).AddAssign(&table[0]) table[4].Set(&table[3]).AddAssign(&table[0]) @@ -550,11 +725,11 @@ func (p *G2Affine) ClearCofactor(a *G2Affine) *G2Affine { } // ClearCofactor maps a point in curve to r-torsion -func (p *G2Jac) ClearCofactor(a *G2Jac) *G2Jac { +func (p *G2Jac) ClearCofactor(q *G2Jac) *G2Jac { // cf http://cacr.uwaterloo.ca/techreports/2011/cacr2011-26.pdf, 6.1 var points [4]G2Jac - points[0].ScalarMultiplication(a, &xGen) + points[0].mulBySeed(q) points[1].Double(&points[0]). AddAssign(&points[0]). @@ -563,7 +738,7 @@ func (p *G2Jac) ClearCofactor(a *G2Jac) *G2Jac { points[2].psi(&points[0]). psi(&points[2]) - points[3].psi(a).psi(&points[3]).psi(&points[3]) + points[3].psi(q).psi(&points[3]).psi(&points[3]) var res G2Jac res.Set(&g2Infinity) @@ -576,16 +751,16 @@ func (p *G2Jac) ClearCofactor(a *G2Jac) *G2Jac { } // ------------------------------------------------------------------------------------------------- -// Jacobian extended +// extended Jacobian coordinates -// Set sets p to the provided point -func (p *g2JacExtended) Set(a *g2JacExtended) *g2JacExtended { - p.X, p.Y, p.ZZ, p.ZZZ = a.X, a.Y, a.ZZ, a.ZZZ +// Set sets p to a in extended Jacobian coordinates. +func (p *g2JacExtended) Set(q *g2JacExtended) *g2JacExtended { + p.X, p.Y, p.ZZ, p.ZZZ = q.X, q.Y, q.ZZ, q.ZZZ return p } -// setInfinity sets p to O -func (p *g2JacExtended) setInfinity() *g2JacExtended { +// SetInfinity sets p to the infinity point (1,1,0,0). +func (p *g2JacExtended) SetInfinity() *g2JacExtended { p.X.SetOne() p.Y.SetOne() p.ZZ = fptower.E2{} @@ -593,43 +768,45 @@ func (p *g2JacExtended) setInfinity() *g2JacExtended { return p } -func (p *g2JacExtended) IsZero() bool { +// IsInfinity checks if the p is infinity, i.e. p.ZZ=0. +func (p *g2JacExtended) IsInfinity() bool { return p.ZZ.IsZero() } -// fromJacExtended sets Q in affine coordinates -func (p *G2Affine) fromJacExtended(Q *g2JacExtended) *G2Affine { - if Q.ZZ.IsZero() { +// fromJacExtended converts an extended Jacobian point to an affine point. +func (p *G2Affine) fromJacExtended(q *g2JacExtended) *G2Affine { + if q.ZZ.IsZero() { p.X = fptower.E2{} p.Y = fptower.E2{} return p } - p.X.Inverse(&Q.ZZ).Mul(&p.X, &Q.X) - p.Y.Inverse(&Q.ZZZ).Mul(&p.Y, &Q.Y) + p.X.Inverse(&q.ZZ).Mul(&p.X, &q.X) + p.Y.Inverse(&q.ZZZ).Mul(&p.Y, &q.Y) return p } -// fromJacExtended sets Q in Jacobian coordinates -func (p *G2Jac) fromJacExtended(Q *g2JacExtended) *G2Jac { - if Q.ZZ.IsZero() { +// fromJacExtended converts an extended Jacobian point to a Jacobian point. +func (p *G2Jac) fromJacExtended(q *g2JacExtended) *G2Jac { + if q.ZZ.IsZero() { p.Set(&g2Infinity) return p } - p.X.Mul(&Q.ZZ, &Q.X).Mul(&p.X, &Q.ZZ) - p.Y.Mul(&Q.ZZZ, &Q.Y).Mul(&p.Y, &Q.ZZZ) - p.Z.Set(&Q.ZZZ) + p.X.Mul(&q.ZZ, &q.X).Mul(&p.X, &q.ZZ) + p.Y.Mul(&q.ZZZ, &q.Y).Mul(&p.Y, &q.ZZZ) + p.Z.Set(&q.ZZZ) return p } -// unsafeFromJacExtended sets p in Jacobian coordinates, but don't check for infinity -func (p *G2Jac) unsafeFromJacExtended(Q *g2JacExtended) *G2Jac { - p.X.Square(&Q.ZZ).Mul(&p.X, &Q.X) - p.Y.Square(&Q.ZZZ).Mul(&p.Y, &Q.Y) - p.Z = Q.ZZZ +// unsafeFromJacExtended converts an extended Jacobian point, distinct from Infinity, to a Jacobian point. +func (p *G2Jac) unsafeFromJacExtended(q *g2JacExtended) *G2Jac { + p.X.Square(&q.ZZ).Mul(&p.X, &q.X) + p.Y.Square(&q.ZZZ).Mul(&p.Y, &q.Y) + p.Z = q.ZZZ return p } -// add point in Jacobian extended coordinates +// add sets p to p+q in extended Jacobian coordinates. +// // https://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-add-2008-s func (p *g2JacExtended) add(q *g2JacExtended) *g2JacExtended { //if q is infinity return p @@ -685,10 +862,11 @@ func (p *g2JacExtended) add(q *g2JacExtended) *g2JacExtended { return p } -// double point in Jacobian extended coordinates +// double sets p to [2]q in Jacobian extended coordinates. +// // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#doubling-dbl-2008-s-1 -// since we consider any point on Z=0 as the point at infinity -// this doubling formula works for infinity points as well +// N.B.: since we consider any point on Z=0 as the point at infinity +// this doubling formula works for infinity points as well. func (p *g2JacExtended) double(q *g2JacExtended) *g2JacExtended { var U, V, W, S, XX, M fptower.E2 @@ -698,7 +876,7 @@ func (p *g2JacExtended) double(q *g2JacExtended) *g2JacExtended { S.Mul(&q.X, &V) XX.Square(&q.X) M.Double(&XX). - Add(&M, &XX) // -> + a, but a=0 here + Add(&M, &XX) // -> + A, but A=0 here U.Mul(&W, &q.Y) p.X.Square(&M). @@ -713,9 +891,10 @@ func (p *g2JacExtended) double(q *g2JacExtended) *g2JacExtended { return p } -// subMixed same as addMixed, but will negate a.Y +// addMixed sets p to p+q in extended Jacobian coordinates, where a.ZZ=1. +// // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-madd-2008-s -func (p *g2JacExtended) subMixed(a *G2Affine) *g2JacExtended { +func (p *g2JacExtended) addMixed(a *G2Affine) *g2JacExtended { //if a is infinity return p if a.IsInfinity() { @@ -724,7 +903,7 @@ func (p *g2JacExtended) subMixed(a *G2Affine) *g2JacExtended { // p is infinity, return a if p.ZZ.IsZero() { p.X = a.X - p.Y.Neg(&a.Y) + p.Y = a.Y p.ZZ.SetOne() p.ZZZ.SetOne() return p @@ -737,12 +916,11 @@ func (p *g2JacExtended) subMixed(a *G2Affine) *g2JacExtended { P.Sub(&P, &p.X) R.Mul(&a.Y, &p.ZZZ) - R.Neg(&R) R.Sub(&R, &p.Y) if P.IsZero() { if R.IsZero() { - return p.doubleNegMixed(a) + return p.doubleMixed(a) } p.ZZ = fptower.E2{} @@ -769,9 +947,10 @@ func (p *g2JacExtended) subMixed(a *G2Affine) *g2JacExtended { } -// addMixed +// subMixed works the same as addMixed, but negates a.Y. +// // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-madd-2008-s -func (p *g2JacExtended) addMixed(a *G2Affine) *g2JacExtended { +func (p *g2JacExtended) subMixed(a *G2Affine) *g2JacExtended { //if a is infinity return p if a.IsInfinity() { @@ -780,7 +959,7 @@ func (p *g2JacExtended) addMixed(a *G2Affine) *g2JacExtended { // p is infinity, return a if p.ZZ.IsZero() { p.X = a.X - p.Y = a.Y + p.Y.Neg(&a.Y) p.ZZ.SetOne() p.ZZZ.SetOne() return p @@ -793,11 +972,12 @@ func (p *g2JacExtended) addMixed(a *G2Affine) *g2JacExtended { P.Sub(&P, &p.X) R.Mul(&a.Y, &p.ZZZ) + R.Neg(&R) R.Sub(&R, &p.Y) if P.IsZero() { if R.IsZero() { - return p.doubleMixed(a) + return p.doubleNegMixed(a) } p.ZZ = fptower.E2{} @@ -824,21 +1004,21 @@ func (p *g2JacExtended) addMixed(a *G2Affine) *g2JacExtended { } -// doubleNegMixed same as double, but will negate q.Y -func (p *g2JacExtended) doubleNegMixed(q *G2Affine) *g2JacExtended { +// doubleNegMixed works the same as double, but negates q.Y. +func (p *g2JacExtended) doubleNegMixed(a *G2Affine) *g2JacExtended { var U, V, W, S, XX, M, S2, L fptower.E2 - U.Double(&q.Y) + U.Double(&a.Y) U.Neg(&U) V.Square(&U) W.Mul(&U, &V) - S.Mul(&q.X, &V) - XX.Square(&q.X) + S.Mul(&a.X, &V) + XX.Square(&a.X) M.Double(&XX). - Add(&M, &XX) // -> + a, but a=0 here + Add(&M, &XX) // -> + A, but A=0 here S2.Double(&S) - L.Mul(&W, &q.Y) + L.Mul(&W, &a.Y) p.X.Square(&M). Sub(&p.X, &S2) @@ -851,21 +1031,22 @@ func (p *g2JacExtended) doubleNegMixed(q *G2Affine) *g2JacExtended { return p } -// doubleMixed point in Jacobian extended coordinates +// doubleMixed sets p to [2]a in Jacobian extended coordinates, where a.ZZ=1. +// // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#doubling-dbl-2008-s-1 -func (p *g2JacExtended) doubleMixed(q *G2Affine) *g2JacExtended { +func (p *g2JacExtended) doubleMixed(a *G2Affine) *g2JacExtended { var U, V, W, S, XX, M, S2, L fptower.E2 - U.Double(&q.Y) + U.Double(&a.Y) V.Square(&U) W.Mul(&U, &V) - S.Mul(&q.X, &V) - XX.Square(&q.X) + S.Mul(&a.X, &V) + XX.Square(&a.X) M.Double(&XX). - Add(&M, &XX) // -> + a, but a=0 here + Add(&M, &XX) // -> + A, but A=0 here S2.Double(&S) - L.Mul(&W, &q.Y) + L.Mul(&W, &a.Y) p.X.Square(&M). Sub(&p.X, &S2) @@ -879,38 +1060,38 @@ func (p *g2JacExtended) doubleMixed(q *G2Affine) *g2JacExtended { } // ------------------------------------------------------------------------------------------------- -// Homogenous projective +// Homogenous projective coordinates -// Set sets p to the provided point -func (p *g2Proj) Set(a *g2Proj) *g2Proj { - p.x, p.y, p.z = a.x, a.y, a.z +// Set sets p to a in projective coordinates. +func (p *g2Proj) Set(q *g2Proj) *g2Proj { + p.x, p.y, p.z = q.x, q.y, q.z return p } -// Neg computes -G -func (p *g2Proj) Neg(a *g2Proj) *g2Proj { - *p = *a - p.y.Neg(&a.y) +// Neg sets p to the projective negative point -q = (q.X, -q.Y). +func (p *g2Proj) Neg(q *g2Proj) *g2Proj { + *p = *q + p.y.Neg(&q.y) return p } -// FromAffine sets p = Q, p in homogenous projective, Q in affine -func (p *g2Proj) FromAffine(Q *G2Affine) *g2Proj { - if Q.X.IsZero() && Q.Y.IsZero() { +// FromAffine converts q in affine to p in projective coordinates. +func (p *g2Proj) FromAffine(a *G2Affine) *g2Proj { + if a.X.IsZero() && a.Y.IsZero() { p.z.SetZero() p.x.SetOne() p.y.SetOne() return p } p.z.SetOne() - p.x.Set(&Q.X) - p.y.Set(&Q.Y) + p.x.Set(&a.X) + p.y.Set(&a.Y) return p } // BatchScalarMultiplicationG2 multiplies the same base by all scalars // and return resulting points in affine coordinates -// uses a simple windowed-NAF like exponentiation algorithm +// uses a simple windowed-NAF-like multiplication algorithm. func BatchScalarMultiplicationG2(base *G2Affine, scalars []fr.Element) []G2Affine { // approximate cost in group ops is // cost = 2^{c-1} + n(scalar.nbBits+nbChunks) @@ -989,18 +1170,29 @@ func BatchScalarMultiplicationG2(base *G2Affine, scalars []fr.Element) []G2Affin return toReturn } -// batch add affine coordinates -// using batch inversion -// special cases (doubling, infinity) must be filtered out before this call +// batchAddG2Affine adds affine points using the Montgomery batch inversion trick. +// Special cases (doubling, infinity) must be filtered out before this call. func batchAddG2Affine[TP pG2Affine, TPP ppG2Affine, TC cG2Affine](R *TPP, P *TP, batchSize int) { var lambda, lambdain TC - // add part + // from https://docs.zkproof.org/pages/standards/accepted-workshop3/proposal-turbo_plonk.pdf + // affine point addition formula + // R(X1, Y1) + P(X2, Y2) = Q(X3, Y3) + // λ = (Y2 - Y1) / (X2 - X1) + // X3 = λ² - (X1 + X2) + // Y3 = λ * (X1 - X3) - Y1 + + // first we compute the 1 / (X2 - X1) for all points using Montgomery batch inversion trick + + // X2 - X1 for j := 0; j < batchSize; j++ { lambdain[j].Sub(&(*P)[j].X, &(*R)[j].X) } - // invert denominator using montgomery batch invert technique + // montgomery batch inversion; + // lambda[0] = 1 / (P[0].X - R[0].X) + // lambda[1] = 1 / (P[1].X - R[1].X) + // ... { var accumulator fptower.E2 lambda[0].SetOne() @@ -1020,22 +1212,41 @@ func batchAddG2Affine[TP pG2Affine, TPP ppG2Affine, TC cG2Affine](R *TPP, P *TP, lambda[0].Set(&accumulator) } - var d fptower.E2 - var rr G2Affine + var t fptower.E2 + var Q G2Affine - // add part for j := 0; j < batchSize; j++ { - // computa lambda - d.Sub(&(*P)[j].Y, &(*R)[j].Y) - lambda[j].Mul(&lambda[j], &d) - - // compute X, Y - rr.X.Square(&lambda[j]) - rr.X.Sub(&rr.X, &(*R)[j].X) - rr.X.Sub(&rr.X, &(*P)[j].X) - d.Sub(&(*R)[j].X, &rr.X) - rr.Y.Mul(&lambda[j], &d) - rr.Y.Sub(&rr.Y, &(*R)[j].Y) - (*R)[j].Set(&rr) + // λ = (Y2 - Y1) / (X2 - X1) + t.Sub(&(*P)[j].Y, &(*R)[j].Y) + lambda[j].Mul(&lambda[j], &t) + + // X3 = λ² - (X1 + X2) + Q.X.Square(&lambda[j]) + Q.X.Sub(&Q.X, &(*R)[j].X) + Q.X.Sub(&Q.X, &(*P)[j].X) + + // Y3 = λ * (X1 - X3) - Y1 + t.Sub(&(*R)[j].X, &Q.X) + Q.Y.Mul(&lambda[j], &t) + Q.Y.Sub(&Q.Y, &(*R)[j].Y) + + (*R)[j].Set(&Q) + } +} + +// RandomOnG2 produces a random point in G2 +// using standard map-to-curve methods, which means the relative discrete log +// of the generated point with respect to the canonical generator is not known. +func RandomOnG2() (G2Affine, error) { + if gBytes, err := randomFrSizedBytes(); err != nil { + return G2Affine{}, err + } else { + return HashToG2(gBytes, []byte("random on g2")) } } + +func randomFrSizedBytes() ([]byte, error) { + res := make([]byte, fr.Bytes) + _, err := rand.Read(res) + return res, err +} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/hash_to_curve/g1.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/hash_to_curve/g1.go new file mode 100644 index 00000000000..9f8daab1602 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/hash_to_curve/g1.go @@ -0,0 +1,31 @@ +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package hash_to_curve + +import ( + "github.com/consensys/gnark-crypto/ecc/bn254/fp" +) + +// G1Sgn0 is an algebraic substitute for the notion of sign in ordered fields. +// Namely, every non-zero quadratic residue in a finite field of characteristic =/= 2 has exactly two square roots, one of each sign. +// +// See: https://www.rfc-editor.org/rfc/rfc9380.html#name-the-sgn0-function +// +// The sign of an element is not obviously related to that of its Montgomery form +func G1Sgn0(z *fp.Element) uint64 { + + nonMont := z.Bits() + + // m == 1 + return nonMont[0] % 2 + +} + +func G1NotZero(x *fp.Element) uint64 { + + return x[0] | x[1] | x[2] | x[3] + +} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/hash_to_curve/g2.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/hash_to_curve/g2.go new file mode 100644 index 00000000000..4b259f7c5c1 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/hash_to_curve/g2.go @@ -0,0 +1,46 @@ +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package hash_to_curve + +import ( + "github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower" +) + +// G2Sgn0 is an algebraic substitute for the notion of sign in ordered fields. +// Namely, every non-zero quadratic residue in a finite field of characteristic =/= 2 has exactly two square roots, one of each sign. +// +// See: https://www.rfc-editor.org/rfc/rfc9380.html#name-the-sgn0-function +// +// The sign of an element is not obviously related to that of its Montgomery form +func G2Sgn0(z *fptower.E2) uint64 { + + nonMont := z.Bits() + + sign := uint64(0) // 1. sign = 0 + zero := uint64(1) // 2. zero = 1 + var signI uint64 + var zeroI uint64 + + // 3. i = 1 + signI = nonMont.A0[0] % 2 // 4. sign_i = x_i mod 2 + zeroI = G1NotZero(&nonMont.A0) + zeroI = 1 ^ (zeroI|-zeroI)>>63 // 5. zero_i = x_i == 0 + sign = sign | (zero & signI) // 6. sign = sign OR (zero AND sign_i) # Avoid short-circuit logic ops + zero = zero & zeroI // 7. zero = zero AND zero_i + // 3. i = 2 + signI = nonMont.A1[0] % 2 // 4. sign_i = x_i mod 2 + // 5. zero_i = x_i == 0 + sign = sign | (zero & signI) // 6. sign = sign OR (zero AND sign_i) # Avoid short-circuit logic ops + // 7. zero = zero AND zero_i + return sign + +} + +func G2NotZero(x *fptower.E2) uint64 { + //Assuming G1 is over Fp and that if hashing is available for G2, it also is for G1 + return G1NotZero(&x.A0) | G1NotZero(&x.A1) + +} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/hash_to_g1.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/hash_to_g1.go index 6be3be8e103..95364555596 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/hash_to_g1.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/hash_to_g1.go @@ -1,16 +1,5 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -18,11 +7,59 @@ package bn254 import ( "github.com/consensys/gnark-crypto/ecc/bn254/fp" + "github.com/consensys/gnark-crypto/ecc/bn254/hash_to_curve" ) -// MapToCurve1 implements the Shallue and van de Woestijne method, applicable to any elliptic curve in Weierstrass form -// No cofactor clearing or isogeny -// https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#straightline-svdw +// MapToG1 invokes the SVDW map, and guarantees that the result is in G1. +func MapToG1(u fp.Element) G1Affine { + res := MapToCurve1(&u) + return res +} + +// EncodeToG1 hashes a message to a point on the G1 curve using the SVDW map. +// It is faster than [HashToG1], but the result is not uniformly distributed. Unsuitable as a random oracle. +// dst stands for "domain separation tag", a string unique to the construction using the hash function +// +// See: https://www.rfc-editor.org/rfc/rfc9380.html#roadmap +func EncodeToG1(msg, dst []byte) (G1Affine, error) { + + var res G1Affine + u, err := fp.Hash(msg, dst, 1) + if err != nil { + return res, err + } + + res = MapToCurve1(&u[0]) + + return res, nil +} + +// HashToG1 hashes a message to a point on the G1 curve using the SVDW map. +// Slower than [EncodeToG1], but usable as a random oracle. +// dst stands for "domain separation tag", a string unique to the construction using the hash function. +// +// See https://www.rfc-editor.org/rfc/rfc9380.html#roadmap +func HashToG1(msg, dst []byte) (G1Affine, error) { + u, err := fp.Hash(msg, dst, 2*1) + if err != nil { + return G1Affine{}, err + } + + Q0 := MapToCurve1(&u[0]) + Q1 := MapToCurve1(&u[1]) + + var _Q0, _Q1 G1Jac + _Q0.FromAffine(&Q0) + _Q1.FromAffine(&Q1).AddAssign(&_Q0) + + Q1.FromJacobian(&_Q1) + return Q1, nil +} + +// MapToCurve1 implements the Shallue and van de Woestijne method, applicable to any elliptic curve in Weierstrass form. +// It does not perform cofactor clearing nor isogeny. Use [MapToG1] for mapping to group. +// +// See: https://www.rfc-editor.org/rfc/rfc9380.html#straightline-svdw func MapToCurve1(u *fp.Element) G1Affine { var tv1, tv2, tv3, tv4 fp.Element var x1, x2, x3, gx1, gx2, gx, x, y fp.Element @@ -89,73 +126,10 @@ func MapToCurve1(u *fp.Element) G1Affine { gx.Mul(&gx, &x) // 31. gx = gx * x gx.Add(&gx, &bCurveCoeff) // 32. gx = gx + B - y.Sqrt(&gx) // 33. y = sqrt(gx) - signsNotEqual := g1Sgn0(u) ^ g1Sgn0(&y) // 34. e3 = sgn0(u) == sgn0(y) + y.Sqrt(&gx) // 33. y = sqrt(gx) + signsNotEqual := hash_to_curve.G1Sgn0(u) ^ hash_to_curve.G1Sgn0(&y) // 34. e3 = sgn0(u) == sgn0(y) tv1.Neg(&y) y.Select(int(signsNotEqual), &y, &tv1) // 35. y = CMOV(-y, y, e3) # Select correct sign of y return G1Affine{x, y} } - -// g1Sgn0 is an algebraic substitute for the notion of sign in ordered fields -// Namely, every non-zero quadratic residue in a finite field of characteristic =/= 2 has exactly two square roots, one of each sign -// https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-the-sgn0-function -// The sign of an element is not obviously related to that of its Montgomery form -func g1Sgn0(z *fp.Element) uint64 { - - nonMont := z.Bits() - - // m == 1 - return nonMont[0] % 2 - -} - -// MapToG1 invokes the SVDW map, and guarantees that the result is in g1 -func MapToG1(u fp.Element) G1Affine { - res := MapToCurve1(&u) - return res -} - -// EncodeToG1 hashes a message to a point on the G1 curve using the SVDW map. -// It is faster than HashToG1, but the result is not uniformly distributed. Unsuitable as a random oracle. -// dst stands for "domain separation tag", a string unique to the construction using the hash function -// https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#roadmap -func EncodeToG1(msg, dst []byte) (G1Affine, error) { - - var res G1Affine - u, err := fp.Hash(msg, dst, 1) - if err != nil { - return res, err - } - - res = MapToCurve1(&u[0]) - - return res, nil -} - -// HashToG1 hashes a message to a point on the G1 curve using the SVDW map. -// Slower than EncodeToG1, but usable as a random oracle. -// dst stands for "domain separation tag", a string unique to the construction using the hash function -// https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#roadmap -func HashToG1(msg, dst []byte) (G1Affine, error) { - u, err := fp.Hash(msg, dst, 2*1) - if err != nil { - return G1Affine{}, err - } - - Q0 := MapToCurve1(&u[0]) - Q1 := MapToCurve1(&u[1]) - - var _Q0, _Q1 G1Jac - _Q0.FromAffine(&Q0) - _Q1.FromAffine(&Q1).AddAssign(&_Q0) - - Q1.FromJacobian(&_Q1) - return Q1, nil -} - -func g1NotZero(x *fp.Element) uint64 { - - return x[0] | x[1] | x[2] | x[3] - -} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/hash_to_g2.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/hash_to_g2.go index fa81853d03a..f09de46b675 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/hash_to_g2.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/hash_to_g2.go @@ -1,16 +1,5 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -18,12 +7,73 @@ package bn254 import ( "github.com/consensys/gnark-crypto/ecc/bn254/fp" + "github.com/consensys/gnark-crypto/ecc/bn254/hash_to_curve" "github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower" ) -// MapToCurve2 implements the Shallue and van de Woestijne method, applicable to any elliptic curve in Weierstrass form -// No cofactor clearing or isogeny -// https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#straightline-svdw +// MapToG2 invokes the SVDW map, and guarantees that the result is in G2. +func MapToG2(u fptower.E2) G2Affine { + res := MapToCurve2(&u) + res.ClearCofactor(&res) + return res +} + +// EncodeToG2 hashes a message to a point on the G2 curve using the SVDW map. +// It is faster than [HashToG2], but the result is not uniformly distributed. Unsuitable as a random oracle. +// dst stands for "domain separation tag", a string unique to the construction using the hash function +// +// See: https://www.rfc-editor.org/rfc/rfc9380.html#roadmap +func EncodeToG2(msg, dst []byte) (G2Affine, error) { + + var res G2Affine + u, err := fp.Hash(msg, dst, 2) + if err != nil { + return res, err + } + + res = MapToCurve2(&fptower.E2{ + A0: u[0], + A1: u[1], + }) + + res.ClearCofactor(&res) + return res, nil +} + +// HashToG2 hashes a message to a point on the G2 curve using the SVDW map. +// Slower than [EncodeToG2], but usable as a random oracle. +// dst stands for "domain separation tag", a string unique to the construction using the hash function. +// +// See https://www.rfc-editor.org/rfc/rfc9380.html#roadmap +func HashToG2(msg, dst []byte) (G2Affine, error) { + u, err := fp.Hash(msg, dst, 2*2) + if err != nil { + return G2Affine{}, err + } + + Q0 := MapToCurve2(&fptower.E2{ + A0: u[0], + A1: u[1], + }) + Q1 := MapToCurve2(&fptower.E2{ + A0: u[2+0], + A1: u[2+1], + }) + + var _Q0, _Q1 G2Jac + _Q0.FromAffine(&Q0) + _Q1.FromAffine(&Q1).AddAssign(&_Q0) + + _Q1.ClearCofactor(&_Q1) + + Q1.FromJacobian(&_Q1) + return Q1, nil +} + +// MapToCurve2 implements the Shallue and van de Woestijne method, applicable to any elliptic curve in Weierstrass form. +// It does not perform cofactor clearing nor isogeny. Use [MapToG2] for mapping to group. +// +// See: https://www.rfc-editor.org/rfc/rfc9380.html#straightline-svdw func MapToCurve2(u *fptower.E2) G2Affine { var tv1, tv2, tv3, tv4 fptower.E2 var x1, x2, x3, gx1, gx2, gx, x, y fptower.E2 @@ -105,101 +155,10 @@ func MapToCurve2(u *fptower.E2) G2Affine { gx.Mul(&gx, &x) // 31. gx = gx * x gx.Add(&gx, &bTwistCurveCoeff) // 32. gx = gx + B - y.Sqrt(&gx) // 33. y = sqrt(gx) - signsNotEqual := g2Sgn0(u) ^ g2Sgn0(&y) // 34. e3 = sgn0(u) == sgn0(y) + y.Sqrt(&gx) // 33. y = sqrt(gx) + signsNotEqual := hash_to_curve.G2Sgn0(u) ^ hash_to_curve.G2Sgn0(&y) // 34. e3 = sgn0(u) == sgn0(y) tv1.Neg(&y) y.Select(int(signsNotEqual), &y, &tv1) // 35. y = CMOV(-y, y, e3) # Select correct sign of y return G2Affine{x, y} } - -// g2Sgn0 is an algebraic substitute for the notion of sign in ordered fields -// Namely, every non-zero quadratic residue in a finite field of characteristic =/= 2 has exactly two square roots, one of each sign -// https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-the-sgn0-function -// The sign of an element is not obviously related to that of its Montgomery form -func g2Sgn0(z *fptower.E2) uint64 { - - nonMont := z.Bits() - - sign := uint64(0) // 1. sign = 0 - zero := uint64(1) // 2. zero = 1 - var signI uint64 - var zeroI uint64 - - // 3. i = 1 - signI = nonMont.A0[0] % 2 // 4. sign_i = x_i mod 2 - zeroI = g1NotZero(&nonMont.A0) - zeroI = 1 ^ (zeroI|-zeroI)>>63 // 5. zero_i = x_i == 0 - sign = sign | (zero & signI) // 6. sign = sign OR (zero AND sign_i) # Avoid short-circuit logic ops - zero = zero & zeroI // 7. zero = zero AND zero_i - // 3. i = 2 - signI = nonMont.A1[0] % 2 // 4. sign_i = x_i mod 2 - // 5. zero_i = x_i == 0 - sign = sign | (zero & signI) // 6. sign = sign OR (zero AND sign_i) # Avoid short-circuit logic ops - // 7. zero = zero AND zero_i - return sign - -} - -// MapToG2 invokes the SVDW map, and guarantees that the result is in g2 -func MapToG2(u fptower.E2) G2Affine { - res := MapToCurve2(&u) - res.ClearCofactor(&res) - return res -} - -// EncodeToG2 hashes a message to a point on the G2 curve using the SVDW map. -// It is faster than HashToG2, but the result is not uniformly distributed. Unsuitable as a random oracle. -// dst stands for "domain separation tag", a string unique to the construction using the hash function -// https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#roadmap -func EncodeToG2(msg, dst []byte) (G2Affine, error) { - - var res G2Affine - u, err := fp.Hash(msg, dst, 2) - if err != nil { - return res, err - } - - res = MapToCurve2(&fptower.E2{ - A0: u[0], - A1: u[1], - }) - - res.ClearCofactor(&res) - return res, nil -} - -// HashToG2 hashes a message to a point on the G2 curve using the SVDW map. -// Slower than EncodeToG2, but usable as a random oracle. -// dst stands for "domain separation tag", a string unique to the construction using the hash function -// https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#roadmap -func HashToG2(msg, dst []byte) (G2Affine, error) { - u, err := fp.Hash(msg, dst, 2*2) - if err != nil { - return G2Affine{}, err - } - - Q0 := MapToCurve2(&fptower.E2{ - A0: u[0], - A1: u[1], - }) - Q1 := MapToCurve2(&fptower.E2{ - A0: u[2+0], - A1: u[2+1], - }) - - var _Q0, _Q1 G2Jac - _Q0.FromAffine(&Q0) - _Q1.FromAffine(&Q1).AddAssign(&_Q0) - - _Q1.ClearCofactor(&_Q1) - - Q1.FromJacobian(&_Q1) - return Q1, nil -} - -func g2NotZero(x *fptower.E2) uint64 { - //Assuming G1 is over Fp and that if hashing is available for G2, it also is for G1 - return g1NotZero(&x.A0) | g1NotZero(&x.A1) - -} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/asm.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/asm.go index 49751a93969..83956e0b4c0 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/asm.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/asm.go @@ -1,28 +1,16 @@ //go:build !noadx -// +build !noadx -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT package fptower -import "golang.org/x/sys/cpu" +import "github.com/consensys/gnark-crypto/utils/cpu" // supportAdx will be set only on amd64 that has MULX and ADDX instructions var ( - supportAdx = cpu.X86.HasADX && cpu.X86.HasBMI2 + supportAdx = cpu.SupportADX _ = supportAdx // used in asm ) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/asm_noadx.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/asm_noadx.go index c6a97081fca..1dc20b49918 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/asm_noadx.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/asm_noadx.go @@ -1,19 +1,7 @@ //go:build noadx -// +build noadx -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e12.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e12.go index a9f6d28e9b4..a0a74e3da35 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e12.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e12.go @@ -1,16 +1,5 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -67,14 +56,14 @@ func (z *E12) SetOne() *E12 { return z } -// Add set z=x+y in E12 and return z +// Add sets z=x+y in E12 and returns z func (z *E12) Add(x, y *E12) *E12 { z.C0.Add(&x.C0, &y.C0) z.C1.Add(&x.C1, &y.C1) return z } -// Sub sets z to x sub y and return z +// Sub sets z to x-y and returns z func (z *E12) Sub(x, y *E12) *E12 { z.C0.Sub(&x.C0, &y.C0) z.C1.Sub(&x.C1, &y.C1) @@ -99,16 +88,25 @@ func (z *E12) SetRandom() (*E12, error) { return z, nil } -// IsZero returns true if the two elements are equal, false otherwise +// MustSetRandom sets a0 and a1 to random values. +// It panics if reading form crypto/rand fails +func (z *E12) MustSetRandom() { + if _, err := z.SetRandom(); err != nil { + panic(err) + } +} + +// IsZero returns true if z is zero, false otherwise func (z *E12) IsZero() bool { return z.C0.IsZero() && z.C1.IsZero() } +// IsOne returns true if z is one, false otherwise func (z *E12) IsOne() bool { return z.C0.IsOne() && z.C1.IsZero() } -// Mul set z=x*y in E12 and return z +// Mul sets z=x*y in E12 and returns z func (z *E12) Mul(x, y *E12) *E12 { var a, b, c E6 a.Add(&x.C0, &x.C1) @@ -121,7 +119,7 @@ func (z *E12) Mul(x, y *E12) *E12 { return z } -// Square set z=x*x in E12 and return z +// Square sets z=x*x in E12 and returns z func (z *E12) Square(x *E12) *E12 { //Algorithm 22 from https://eprint.iacr.org/2010/354.pdf @@ -406,7 +404,7 @@ func (z *E12) CyclotomicSquare(x *E12) *E12 { return z } -// Inverse set z to the inverse of x in E12 and return z +// Inverse sets z to the inverse of x in E12 and returns z // // if x == 0, sets and returns z = x func (z *E12) Inverse(x *E12) *E12 { @@ -424,8 +422,8 @@ func (z *E12) Inverse(x *E12) *E12 { return z } -// BatchInvertE12 returns a new slice with every element inverted. -// Uses Montgomery batch inversion trick +// BatchInvertE12 returns a new slice with every element in a inverted. +// It uses Montgomery batch inversion trick. // // if a[i] == 0, returns result[i] = a[i] func BatchInvertE12(a []E12) []E12 { @@ -635,12 +633,12 @@ func (z *E12) ExpGLV(x E12, k *big.Int) *E12 { return z } -// InverseUnitary inverse a unitary element +// InverseUnitary inverses a unitary element func (z *E12) InverseUnitary(x *E12) *E12 { return z.Conjugate(x) } -// Conjugate set z to x conjugated and return z +// Conjugate sets z to x conjugated and returns z func (z *E12) Conjugate(x *E12) *E12 { *z = *x z.C1.Neg(&z.C1) @@ -841,6 +839,8 @@ func BatchDecompressTorus(x []E6) ([]E12, error) { return res, nil } +// Select is conditional move. +// If cond = 0, it sets z to caseZ and returns it. otherwise caseNz. func (z *E12) Select(cond int, caseZ *E12, caseNz *E12) *E12 { //Might be able to save a nanosecond or two by an aggregate implementation @@ -850,6 +850,7 @@ func (z *E12) Select(cond int, caseZ *E12, caseNz *E12) *E12 { return z } +// Div divides an element in E12 by an element in E12 func (z *E12) Div(x *E12, y *E12) *E12 { var r E12 r.Inverse(y).Mul(x, &r) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e12_pairing.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e12_pairing.go index 78c94d2f613..4a068d7a105 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e12_pairing.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e12_pairing.go @@ -142,9 +142,31 @@ func (z *E12) MulBy034(c0, c3, c4 *E2) *E12 { b.Set(&z.C1) b.MulBy01(c3, c4) - c0.Add(c0, c3) + var d0 E2 + d0.Add(c0, c3) d.Add(&z.C0, &z.C1) - d.MulBy01(c0, c4) + d.MulBy01(&d0, c4) + + z.C1.Add(&a, &b).Neg(&z.C1).Add(&z.C1, &d) + z.C0.MulByNonResidue(&b).Add(&z.C0, &a) + + return z +} + +// MulBy34 multiplication by sparse element (1,0,0,c3,c4,0) +func (z *E12) MulBy34(c3, c4 *E2) *E12 { + + var a, b, d E6 + + a.Set(&z.C0) + + b.Set(&z.C1) + b.MulBy01(c3, c4) + + var d0 E2 + d0.SetOne().Add(&d0, c3) + d.Add(&z.C0, &z.C1) + d.MulBy01(&d0, c4) z.C1.Add(&a, &b).Neg(&z.C1).Add(&z.C1, &d) z.C0.MulByNonResidue(&b).Add(&z.C0, &a) @@ -180,6 +202,26 @@ func Mul034By034(d0, d3, d4, c0, c3, c4 *E2) [5]E2 { return [5]E2{z00, x3, x34, x03, x04} } +// Mul34By34 multiplication of sparse element (1,0,0,c3,c4,0) by sparse element (1,0,0,d3,d4,0) +func Mul34By34(d3, d4, c3, c4 *E2) [5]E2 { + var z00, tmp, x0, x3, x4, x04, x03, x34 E2 + x3.Mul(c3, d3) + x4.Mul(c4, d4) + x04.Add(c4, d4) + x03.Add(c3, d3) + tmp.Add(c3, c4) + x34.Add(d3, d4). + Mul(&x34, &tmp). + Sub(&x34, &x3). + Sub(&x34, &x4) + + x0.SetOne() + z00.MulByNonResidue(&x4). + Add(&z00, &x0) + + return [5]E2{z00, x3, x34, x03, x04} +} + // MulBy01234 multiplies z by an E12 sparse element of the form (x0, x1, x2, x3, x4, 0) func (z *E12) MulBy01234(x *[5]E2) *E12 { var c1, a, b, c, z0, z1 E6 diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e2.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e2.go index 8c16efc9375..75c9de26438 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e2.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e2.go @@ -1,16 +1,5 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -101,11 +90,20 @@ func (z *E2) SetRandom() (*E2, error) { return z, nil } -// IsZero returns true if the two elements are equal, false otherwise +// MustSetRandom sets a0 and a1 to random values. +// It panics if reading form crypto/rand fails +func (z *E2) MustSetRandom() { + if _, err := z.SetRandom(); err != nil { + panic(err) + } +} + +// IsZero returns true if z is zero, false otherwise func (z *E2) IsZero() bool { return z.A0.IsZero() && z.A1.IsZero() } +// IsOne returns true if z is one, false otherwise func (z *E2) IsOne() bool { return z.A0.IsOne() && z.A1.IsZero() } @@ -116,7 +114,7 @@ func (z *E2) Add(x, y *E2) *E2 { return z } -// Sub two elements of E2 +// Sub subtracts two elements of E2 func (z *E2) Sub(x, y *E2) *E2 { subE2(z, x, y) return z @@ -155,7 +153,7 @@ func (z *E2) Conjugate(x *E2) *E2 { return z } -// Halve sets z = z / 2 +// Halve sets z to z / 2 func (z *E2) Halve() { z.A0.Halve() z.A1.Halve() @@ -213,7 +211,7 @@ func init() { var sqrtExp1, sqrtExp2 big.Int -// Sqrt sets z to the square root of and returns z +// Sqrt sets z to the square root of x and returns z // The function does not test whether the square root // exists or not, it's up to the caller to call // Legendre beforehand. @@ -243,8 +241,8 @@ func (z *E2) Sqrt(x *E2) *E2 { return z } -// BatchInvertE2 returns a new slice with every element inverted. -// Uses Montgomery batch inversion trick +// BatchInvertE2 returns a new slice with every element in a inverted. +// It uses Montgomery batch inversion trick. // // if a[i] == 0, returns result[i] = a[i] func BatchInvertE2(a []E2) []E2 { @@ -279,6 +277,8 @@ func BatchInvertE2(a []E2) []E2 { return res } +// Select is conditional move. +// If cond = 0, it sets z to caseZ and returns it. otherwise caseNz. func (z *E2) Select(cond int, caseZ *E2, caseNz *E2) *E2 { //Might be able to save a nanosecond or two by an aggregate implementation @@ -288,6 +288,7 @@ func (z *E2) Select(cond int, caseZ *E2, caseNz *E2) *E2 { return z } +// Div divides an element in E2 by an element in E2 func (z *E2) Div(x *E2, y *E2) *E2 { var r E2 r.Inverse(y).Mul(x, &r) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e2_amd64.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e2_amd64.go index 259609bd813..17873820c3c 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e2_amd64.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e2_amd64.go @@ -1,21 +1,33 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT package fptower +import ( + "github.com/consensys/gnark-crypto/ecc/bn254/fp" +) + +// q + r'.r = 1, i.e., qInvNeg = - q⁻¹ mod r +// used for Montgomery reduction +const qInvNeg uint64 = 9786893198990664585 + +// Field modulus q (Fp) +const ( + q0 uint64 = 4332616871279656263 + q1 uint64 = 10917124144477883021 + q2 uint64 = 13281191951274694749 + q3 uint64 = 3486998266802970665 +) + +var qElement = fp.Element{ + q0, + q1, + q2, + q3, +} + //go:noescape func addE2(res, x, y *E2) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e2_amd64.s b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e2_amd64.s index 43ffb7f16c8..6806565b52f 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e2_amd64.s +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e2_amd64.s @@ -1,186 +1,85 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. #include "textflag.h" #include "funcdata.h" - -// modulus q -DATA q<>+0(SB)/8, $0x3c208c16d87cfd47 -DATA q<>+8(SB)/8, $0x97816a916871ca8d -DATA q<>+16(SB)/8, $0xb85045b68181585d -DATA q<>+24(SB)/8, $0x30644e72e131a029 -GLOBL q<>(SB), (RODATA+NOPTR), $32 - -// qInv0 q'[0] -DATA qInv0<>(SB)/8, $0x87d20782e4866389 -GLOBL qInv0<>(SB), (RODATA+NOPTR), $8 +#include "go_asm.h" #define REDUCE(ra0, ra1, ra2, ra3, rb0, rb1, rb2, rb3) \ - MOVQ ra0, rb0; \ - SUBQ q<>(SB), ra0; \ - MOVQ ra1, rb1; \ - SBBQ q<>+8(SB), ra1; \ - MOVQ ra2, rb2; \ - SBBQ q<>+16(SB), ra2; \ - MOVQ ra3, rb3; \ - SBBQ q<>+24(SB), ra3; \ - CMOVQCS rb0, ra0; \ - CMOVQCS rb1, ra1; \ - CMOVQCS rb2, ra2; \ - CMOVQCS rb3, ra3; \ + MOVQ ra0, rb0; \ + SUBQ ·qElement(SB), ra0; \ + MOVQ ra1, rb1; \ + SBBQ ·qElement+8(SB), ra1; \ + MOVQ ra2, rb2; \ + SBBQ ·qElement+16(SB), ra2; \ + MOVQ ra3, rb3; \ + SBBQ ·qElement+24(SB), ra3; \ + CMOVQCS rb0, ra0; \ + CMOVQCS rb1, ra1; \ + CMOVQCS rb2, ra2; \ + CMOVQCS rb3, ra3; \ // this code is generated and identical to fp.Mul(...) +// A -> BP +// t[0] -> R10 +// t[1] -> R11 +// t[2] -> R12 +// t[3] -> R13 +#define MACC(in0, in1, in2) \ + ADCXQ in0, in1 \ + MULXQ in2, AX, in0 \ + ADOXQ AX, in1 \ + +#define DIV_SHIFT() \ + PUSHQ BP \ + MOVQ $const_qInvNeg, DX \ + IMULQ R10, DX \ + XORQ AX, AX \ + MULXQ ·qElement+0(SB), AX, BP \ + ADCXQ R10, AX \ + MOVQ BP, R10 \ + POPQ BP \ + MACC(R11, R10, ·qElement+8(SB)) \ + MACC(R12, R11, ·qElement+16(SB)) \ + MACC(R13, R12, ·qElement+24(SB)) \ + MOVQ $0, AX \ + ADCXQ AX, R13 \ + ADOXQ BP, R13 \ + +#define MUL_WORD_0() \ + XORQ AX, AX \ + MULXQ R14, R10, R11 \ + MULXQ R15, AX, R12 \ + ADOXQ AX, R11 \ + MULXQ CX, AX, R13 \ + ADOXQ AX, R12 \ + MULXQ BX, AX, BP \ + ADOXQ AX, R13 \ + MOVQ $0, AX \ + ADOXQ AX, BP \ + DIV_SHIFT() \ + +#define MUL_WORD_N() \ + XORQ AX, AX \ + MULXQ R14, AX, BP \ + ADOXQ AX, R10 \ + MACC(BP, R11, R15) \ + MACC(BP, R12, CX) \ + MACC(BP, R13, BX) \ + MOVQ $0, AX \ + ADCXQ AX, BP \ + ADOXQ AX, BP \ + DIV_SHIFT() \ + #define MUL() \ - XORQ AX, AX; \ - MOVQ SI, DX; \ - MULXQ R14, R10, R11; \ - MULXQ R15, AX, R12; \ - ADOXQ AX, R11; \ - MULXQ CX, AX, R13; \ - ADOXQ AX, R12; \ - MULXQ BX, AX, BP; \ - ADOXQ AX, R13; \ - MOVQ $0, AX; \ - ADOXQ AX, BP; \ - PUSHQ BP; \ - MOVQ qInv0<>(SB), DX; \ - IMULQ R10, DX; \ - XORQ AX, AX; \ - MULXQ q<>+0(SB), AX, BP; \ - ADCXQ R10, AX; \ - MOVQ BP, R10; \ - POPQ BP; \ - ADCXQ R11, R10; \ - MULXQ q<>+8(SB), AX, R11; \ - ADOXQ AX, R10; \ - ADCXQ R12, R11; \ - MULXQ q<>+16(SB), AX, R12; \ - ADOXQ AX, R11; \ - ADCXQ R13, R12; \ - MULXQ q<>+24(SB), AX, R13; \ - ADOXQ AX, R12; \ - MOVQ $0, AX; \ - ADCXQ AX, R13; \ - ADOXQ BP, R13; \ - XORQ AX, AX; \ - MOVQ DI, DX; \ - MULXQ R14, AX, BP; \ - ADOXQ AX, R10; \ - ADCXQ BP, R11; \ - MULXQ R15, AX, BP; \ - ADOXQ AX, R11; \ - ADCXQ BP, R12; \ - MULXQ CX, AX, BP; \ - ADOXQ AX, R12; \ - ADCXQ BP, R13; \ - MULXQ BX, AX, BP; \ - ADOXQ AX, R13; \ - MOVQ $0, AX; \ - ADCXQ AX, BP; \ - ADOXQ AX, BP; \ - PUSHQ BP; \ - MOVQ qInv0<>(SB), DX; \ - IMULQ R10, DX; \ - XORQ AX, AX; \ - MULXQ q<>+0(SB), AX, BP; \ - ADCXQ R10, AX; \ - MOVQ BP, R10; \ - POPQ BP; \ - ADCXQ R11, R10; \ - MULXQ q<>+8(SB), AX, R11; \ - ADOXQ AX, R10; \ - ADCXQ R12, R11; \ - MULXQ q<>+16(SB), AX, R12; \ - ADOXQ AX, R11; \ - ADCXQ R13, R12; \ - MULXQ q<>+24(SB), AX, R13; \ - ADOXQ AX, R12; \ - MOVQ $0, AX; \ - ADCXQ AX, R13; \ - ADOXQ BP, R13; \ - XORQ AX, AX; \ - MOVQ R8, DX; \ - MULXQ R14, AX, BP; \ - ADOXQ AX, R10; \ - ADCXQ BP, R11; \ - MULXQ R15, AX, BP; \ - ADOXQ AX, R11; \ - ADCXQ BP, R12; \ - MULXQ CX, AX, BP; \ - ADOXQ AX, R12; \ - ADCXQ BP, R13; \ - MULXQ BX, AX, BP; \ - ADOXQ AX, R13; \ - MOVQ $0, AX; \ - ADCXQ AX, BP; \ - ADOXQ AX, BP; \ - PUSHQ BP; \ - MOVQ qInv0<>(SB), DX; \ - IMULQ R10, DX; \ - XORQ AX, AX; \ - MULXQ q<>+0(SB), AX, BP; \ - ADCXQ R10, AX; \ - MOVQ BP, R10; \ - POPQ BP; \ - ADCXQ R11, R10; \ - MULXQ q<>+8(SB), AX, R11; \ - ADOXQ AX, R10; \ - ADCXQ R12, R11; \ - MULXQ q<>+16(SB), AX, R12; \ - ADOXQ AX, R11; \ - ADCXQ R13, R12; \ - MULXQ q<>+24(SB), AX, R13; \ - ADOXQ AX, R12; \ - MOVQ $0, AX; \ - ADCXQ AX, R13; \ - ADOXQ BP, R13; \ - XORQ AX, AX; \ - MOVQ R9, DX; \ - MULXQ R14, AX, BP; \ - ADOXQ AX, R10; \ - ADCXQ BP, R11; \ - MULXQ R15, AX, BP; \ - ADOXQ AX, R11; \ - ADCXQ BP, R12; \ - MULXQ CX, AX, BP; \ - ADOXQ AX, R12; \ - ADCXQ BP, R13; \ - MULXQ BX, AX, BP; \ - ADOXQ AX, R13; \ - MOVQ $0, AX; \ - ADCXQ AX, BP; \ - ADOXQ AX, BP; \ - PUSHQ BP; \ - MOVQ qInv0<>(SB), DX; \ - IMULQ R10, DX; \ - XORQ AX, AX; \ - MULXQ q<>+0(SB), AX, BP; \ - ADCXQ R10, AX; \ - MOVQ BP, R10; \ - POPQ BP; \ - ADCXQ R11, R10; \ - MULXQ q<>+8(SB), AX, R11; \ - ADOXQ AX, R10; \ - ADCXQ R12, R11; \ - MULXQ q<>+16(SB), AX, R12; \ - ADOXQ AX, R11; \ - ADCXQ R13, R12; \ - MULXQ q<>+24(SB), AX, R13; \ - ADOXQ AX, R12; \ - MOVQ $0, AX; \ - ADCXQ AX, R13; \ - ADOXQ BP, R13; \ + MOVQ SI, DX; \ + MUL_WORD_0(); \ + MOVQ DI, DX; \ + MUL_WORD_N(); \ + MOVQ R8, DX; \ + MUL_WORD_N(); \ + MOVQ R9, DX; \ + MUL_WORD_N(); \ TEXT ·addE2(SB), NOSPLIT, $0-24 MOVQ x+8(FP), AX diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e2_bn254.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e2_bn254.go index 87ab9d1caff..ea5152b6963 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e2_bn254.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e2_bn254.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys AG -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. package fptower diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e2_bn254_fallback.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e2_bn254_fallback.go index 467a96f77eb..3d58d737a26 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e2_bn254_fallback.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e2_bn254_fallback.go @@ -1,19 +1,8 @@ //go:build !amd64 // +build !amd64 -// Copyright 2020 ConsenSys AG -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. package fptower diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e2_fallback.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e2_fallback.go index 6fe47c4111b..7a2461ec533 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e2_fallback.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e2_fallback.go @@ -1,19 +1,7 @@ //go:build !amd64 -// +build !amd64 -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e6.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e6.go index 128007df278..4c932208b41 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e6.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/e6.go @@ -1,16 +1,5 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -63,11 +52,20 @@ func (z *E6) SetRandom() (*E6, error) { return z, nil } -// IsZero returns true if the two elements are equal, false otherwise +// MustSetRandom sets a0 and a1 to random values. +// It panics if reading form crypto/rand fails +func (z *E6) MustSetRandom() { + if _, err := z.SetRandom(); err != nil { + panic(err) + } +} + +// IsZero returns true if z is zero, false otherwise func (z *E6) IsZero() bool { return z.B0.IsZero() && z.B1.IsZero() && z.B2.IsZero() } +// IsOne returns true if z is one, false otherwise func (z *E6) IsOne() bool { return z.B0.IsOne() && z.B1.IsZero() && z.B2.IsZero() } @@ -88,7 +86,7 @@ func (z *E6) Neg(x *E6) *E6 { return z } -// Sub two elements of E6 +// Sub subtracts two elements of E6 func (z *E6) Sub(x, y *E6) *E6 { z.B0.Sub(&x.B0, &y.B0) z.B1.Sub(&x.B1, &y.B1) @@ -286,8 +284,8 @@ func (z *E6) Inverse(x *E6) *E6 { return z } -// BatchInvertE6 returns a new slice with every element inverted. -// Uses Montgomery batch inversion trick +// BatchInvertE6 returns a new slice with every element in a inverted. +// It uses Montgomery batch inversion trick. // // if a[i] == 0, returns result[i] = a[i] func BatchInvertE6(a []E6) []E6 { @@ -322,6 +320,8 @@ func BatchInvertE6(a []E6) []E6 { return res } +// Select is conditional move. +// If cond = 0, it sets z to caseZ and returns it. otherwise caseNz. func (z *E6) Select(cond int, caseZ *E6, caseNz *E6) *E6 { //Might be able to save a nanosecond or two by an aggregate implementation @@ -332,6 +332,7 @@ func (z *E6) Select(cond int, caseZ *E6, caseNz *E6) *E6 { return z } +// Div divides an element in E6 by an element in E6 func (z *E6) Div(x *E6, y *E6) *E6 { var r E6 r.Inverse(y).Mul(x, &r) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/frobenius.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/frobenius.go index 18d8fef960f..4aaf9b5d010 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/frobenius.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/frobenius.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys AG -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. package fptower diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/parameters.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/parameters.go index 3859aeac76f..2778dd9948a 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/parameters.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower/parameters.go @@ -1,16 +1,5 @@ -// Copyright 2020 ConsenSys AG -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. package fptower diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/marshal.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/marshal.go index d4a6f6eea99..1e8b554a987 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/marshal.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/marshal.go @@ -1,16 +1,5 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -166,6 +155,26 @@ func (dec *Decoder) Decode(v interface{}) (err error) { dec.n += read64 } return + case *[][][]fr.Element: + if sliceLen, err = dec.readUint32(); err != nil { + return + } + if len(*t) != int(sliceLen) { + *t = make([][][]fr.Element, sliceLen) + } + for i := range *t { + if sliceLen, err = dec.readUint32(); err != nil { + return + } + if len((*t)[i]) != int(sliceLen) { + (*t)[i] = make([][]fr.Element, sliceLen) + } + for j := range (*t)[i] { + read64, err = (*fr.Vector)(&(*t)[i][j]).ReadFrom(dec.r) + dec.n += read64 + } + } + return case *G1Affine: // we start by reading compressed point size, if metadata tells us it is uncompressed, we read more. read, err = io.ReadFull(dec.r, buf[:SizeOfG1AffineCompressed]) @@ -391,7 +400,7 @@ func NewEncoder(w io.Writer, options ...func(*Encoder)) *Encoder { } // Encode writes the binary encoding of v to the stream -// type must be uint64, *fr.Element, *fp.Element, *G1Affine, *G2Affine, []G1Affine or []G2Affine +// type must be uint64, *fr.Element, *fp.Element, *G1Affine, *G2Affine, []G1Affine, []G2Affine, *[]G1Affine or *[]G2Affine func (enc *Encoder) Encode(v interface{}) (err error) { if enc.raw { return enc.encodeRaw(v) @@ -502,6 +511,27 @@ func (enc *Encoder) encode(v interface{}) (err error) { enc.n += written64 } return + case [][][]fr.Element: + // number of collections + if err = binary.Write(enc.w, binary.BigEndian, uint32(len(t))); err != nil { + return + } + enc.n += 4 + for i := range t { + // size of current collection + if err = binary.Write(enc.w, binary.BigEndian, uint32(len(t[i]))); err != nil { + return + } + enc.n += 4 + // write each vector of the current collection + for j := range t[i] { + written64, err = (*fr.Vector)(&t[i][j]).WriteTo(enc.w) + enc.n += written64 + } + } + return + case *[]G1Affine: + return enc.encode(*t) case []G1Affine: // write slice length err = binary.Write(enc.w, binary.BigEndian, uint32(len(t))) @@ -521,6 +551,8 @@ func (enc *Encoder) encode(v interface{}) (err error) { } } return nil + case *[]G2Affine: + return enc.encode(*t) case []G2Affine: // write slice length err = binary.Write(enc.w, binary.BigEndian, uint32(len(t))) @@ -620,6 +652,27 @@ func (enc *Encoder) encodeRaw(v interface{}) (err error) { enc.n += written64 } return + case [][][]fr.Element: + // number of collections + if err = binary.Write(enc.w, binary.BigEndian, uint32(len(t))); err != nil { + return + } + enc.n += 4 + for i := range t { + // size of current collection + if err = binary.Write(enc.w, binary.BigEndian, uint32(len(t[i]))); err != nil { + return + } + enc.n += 4 + // write each vector of the current collection + for j := range t[i] { + written64, err = (*fr.Vector)(&t[i][j]).WriteTo(enc.w) + enc.n += written64 + } + } + return + case *[]G1Affine: + return enc.encodeRaw(*t) case []G1Affine: // write slice length err = binary.Write(enc.w, binary.BigEndian, uint32(len(t))) @@ -639,6 +692,8 @@ func (enc *Encoder) encodeRaw(v interface{}) (err error) { } } return nil + case *[]G2Affine: + return enc.encodeRaw(*t) case []G2Affine: // write slice length err = binary.Write(enc.w, binary.BigEndian, uint32(len(t))) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/multiexp.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/multiexp.go index 9d1b71278aa..9bb0a8d486e 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/multiexp.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/multiexp.go @@ -1,16 +1,5 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -325,6 +314,31 @@ func msmReduceChunkG1Affine(p *G1Jac, c int, chChunks []chan g1JacExtended) *G1J return p.unsafeFromJacExtended(&_p) } +// Fold computes the multi-exponentiation \sum_{i=0}^{len(points)-1} points[i] * +// combinationCoeff^i and stores the result in p. It returns error in case +// configuration is invalid. +func (p *G1Affine) Fold(points []G1Affine, combinationCoeff fr.Element, config ecc.MultiExpConfig) (*G1Affine, error) { + var _p G1Jac + if _, err := _p.Fold(points, combinationCoeff, config); err != nil { + return nil, err + } + p.FromJacobian(&_p) + return p, nil +} + +// Fold computes the multi-exponentiation \sum_{i=0}^{len(points)-1} points[i] * +// combinationCoeff^i and stores the result in p. It returns error in case +// configuration is invalid. +func (p *G1Jac) Fold(points []G1Affine, combinationCoeff fr.Element, config ecc.MultiExpConfig) (*G1Jac, error) { + scalars := make([]fr.Element, len(points)) + scalar := fr.NewElement(1) + for i := 0; i < len(points); i++ { + scalars[i].Set(&scalar) + scalar.Mul(&scalar, &combinationCoeff) + } + return p.MultiExp(points, scalars, config) +} + // MultiExp implements section 4 of https://eprint.iacr.org/2012/549.pdf // // This call return an error if len(scalars) != len(points) or if provided config is invalid. @@ -625,6 +639,31 @@ func msmReduceChunkG2Affine(p *G2Jac, c int, chChunks []chan g2JacExtended) *G2J return p.unsafeFromJacExtended(&_p) } +// Fold computes the multi-exponentiation \sum_{i=0}^{len(points)-1} points[i] * +// combinationCoeff^i and stores the result in p. It returns error in case +// configuration is invalid. +func (p *G2Affine) Fold(points []G2Affine, combinationCoeff fr.Element, config ecc.MultiExpConfig) (*G2Affine, error) { + var _p G2Jac + if _, err := _p.Fold(points, combinationCoeff, config); err != nil { + return nil, err + } + p.FromJacobian(&_p) + return p, nil +} + +// Fold computes the multi-exponentiation \sum_{i=0}^{len(points)-1} points[i] * +// combinationCoeff^i and stores the result in p. It returns error in case +// configuration is invalid. +func (p *G2Jac) Fold(points []G2Affine, combinationCoeff fr.Element, config ecc.MultiExpConfig) (*G2Jac, error) { + scalars := make([]fr.Element, len(points)) + scalar := fr.NewElement(1) + for i := 0; i < len(points); i++ { + scalars[i].Set(&scalar) + scalar.Mul(&scalar, &combinationCoeff) + } + return p.MultiExp(points, scalars, config) +} + // selector stores the index, mask and shifts needed to select bits from a scalar // it is used during the multiExp algorithm or the batch scalar multiplication type selector struct { diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/multiexp_affine.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/multiexp_affine.go index 0958526ea74..0e198cbe821 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/multiexp_affine.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/multiexp_affine.go @@ -1,16 +1,5 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -30,7 +19,7 @@ type batchOpG1Affine struct { // using affine coordinates for the buckets. To amortize the cost of the inverse in the affine addition // we use a batch affine addition. // -// this is derived from a PR by 0x0ece : https://github.com/ConsenSys/gnark-crypto/pull/249 +// this is derived from a PR by 0x0ece : https://github.com/Consensys/gnark-crypto/pull/249 // See Section 5.3: ia.cr/2022/1396 func processChunkG1BatchAffine[BJE ibg1JacExtended, B ibG1Affine, BS bitSet, TP pG1Affine, TPP ppG1Affine, TQ qOpsG1Affine, TC cG1Affine]( chunk uint64, @@ -60,11 +49,10 @@ func processChunkG1BatchAffine[BJE ibg1JacExtended, B ibG1Affine, BS bitSet, TP // note that we have 2 sets of buckets // 1 in G1Affine used with the batch affine additions // 1 in g1JacExtended used in case the queue of conflicting points - var buckets B + var buckets B // in G1Affine coordinates, infinity point is represented as (0,0), no need to init var bucketsJE BJE for i := 0; i < len(buckets); i++ { - buckets[i].setInfinity() - bucketsJE[i].setInfinity() + bucketsJE[i].SetInfinity() } // setup for the batch affine; @@ -107,7 +95,7 @@ func processChunkG1BatchAffine[BJE ibg1JacExtended, B ibG1Affine, BS bitSet, TP bucketsJE[op.bucketID].addMixed(&op.point) return } - BK.setInfinity() + BK.SetInfinity() return } @@ -135,12 +123,12 @@ func processChunkG1BatchAffine[BJE ibg1JacExtended, B ibG1Affine, BS bitSet, TP if isAdd { bucketsJE[bucketID].addMixed(PP) } else { - BK.setInfinity() + BK.SetInfinity() } return } if isAdd { - BK.setInfinity() + BK.SetInfinity() } else { bucketsJE[bucketID].subMixed(PP) } @@ -222,11 +210,11 @@ func processChunkG1BatchAffine[BJE ibg1JacExtended, B ibG1Affine, BS bitSet, TP // reduce buckets into total // total = bucket[0] + 2*bucket[1] + 3*bucket[2] ... + n*bucket[n-1] var runningSum, total g1JacExtended - runningSum.setInfinity() - total.setInfinity() + runningSum.SetInfinity() + total.SetInfinity() for k := len(buckets) - 1; k >= 0; k-- { runningSum.addMixed(&buckets[k]) - if !bucketsJE[k].IsZero() { + if !bucketsJE[k].IsInfinity() { runningSum.add(&bucketsJE[k]) } total.add(&runningSum) @@ -358,7 +346,7 @@ type batchOpG2Affine struct { // using affine coordinates for the buckets. To amortize the cost of the inverse in the affine addition // we use a batch affine addition. // -// this is derived from a PR by 0x0ece : https://github.com/ConsenSys/gnark-crypto/pull/249 +// this is derived from a PR by 0x0ece : https://github.com/Consensys/gnark-crypto/pull/249 // See Section 5.3: ia.cr/2022/1396 func processChunkG2BatchAffine[BJE ibg2JacExtended, B ibG2Affine, BS bitSet, TP pG2Affine, TPP ppG2Affine, TQ qOpsG2Affine, TC cG2Affine]( chunk uint64, @@ -388,11 +376,10 @@ func processChunkG2BatchAffine[BJE ibg2JacExtended, B ibG2Affine, BS bitSet, TP // note that we have 2 sets of buckets // 1 in G2Affine used with the batch affine additions // 1 in g2JacExtended used in case the queue of conflicting points - var buckets B + var buckets B // in G2Affine coordinates, infinity point is represented as (0,0), no need to init var bucketsJE BJE for i := 0; i < len(buckets); i++ { - buckets[i].setInfinity() - bucketsJE[i].setInfinity() + bucketsJE[i].SetInfinity() } // setup for the batch affine; @@ -435,7 +422,7 @@ func processChunkG2BatchAffine[BJE ibg2JacExtended, B ibG2Affine, BS bitSet, TP bucketsJE[op.bucketID].addMixed(&op.point) return } - BK.setInfinity() + BK.SetInfinity() return } @@ -463,12 +450,12 @@ func processChunkG2BatchAffine[BJE ibg2JacExtended, B ibG2Affine, BS bitSet, TP if isAdd { bucketsJE[bucketID].addMixed(PP) } else { - BK.setInfinity() + BK.SetInfinity() } return } if isAdd { - BK.setInfinity() + BK.SetInfinity() } else { bucketsJE[bucketID].subMixed(PP) } @@ -550,11 +537,11 @@ func processChunkG2BatchAffine[BJE ibg2JacExtended, B ibG2Affine, BS bitSet, TP // reduce buckets into total // total = bucket[0] + 2*bucket[1] + 3*bucket[2] ... + n*bucket[n-1] var runningSum, total g2JacExtended - runningSum.setInfinity() - total.setInfinity() + runningSum.SetInfinity() + total.SetInfinity() for k := len(buckets) - 1; k >= 0; k-- { runningSum.addMixed(&buckets[k]) - if !bucketsJE[k].IsZero() { + if !bucketsJE[k].IsInfinity() { runningSum.add(&bucketsJE[k]) } total.add(&runningSum) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/multiexp_jacobian.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/multiexp_jacobian.go index 32f728fc052..b13a9ddce0b 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/multiexp_jacobian.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/multiexp_jacobian.go @@ -1,16 +1,5 @@ -// Copyright 2020 Consensys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. // Code generated by consensys/gnark-crypto DO NOT EDIT @@ -30,7 +19,7 @@ func processChunkG1Jacobian[B ibg1JacExtended](chunk uint64, var buckets B for i := 0; i < len(buckets); i++ { - buckets[i].setInfinity() + buckets[i].SetInfinity() } // for each scalars, get the digit corresponding to the chunk we're processing. @@ -53,10 +42,10 @@ func processChunkG1Jacobian[B ibg1JacExtended](chunk uint64, // total = bucket[0] + 2*bucket[1] + 3*bucket[2] ... + n*bucket[n-1] var runningSum, total g1JacExtended - runningSum.setInfinity() - total.setInfinity() + runningSum.SetInfinity() + total.SetInfinity() for k := len(buckets) - 1; k >= 0; k-- { - if !buckets[k].IsZero() { + if !buckets[k].IsInfinity() { runningSum.add(&buckets[k]) } total.add(&runningSum) @@ -121,7 +110,7 @@ func processChunkG2Jacobian[B ibg2JacExtended](chunk uint64, var buckets B for i := 0; i < len(buckets); i++ { - buckets[i].setInfinity() + buckets[i].SetInfinity() } // for each scalars, get the digit corresponding to the chunk we're processing. @@ -144,10 +133,10 @@ func processChunkG2Jacobian[B ibg2JacExtended](chunk uint64, // total = bucket[0] + 2*bucket[1] + 3*bucket[2] ... + n*bucket[n-1] var runningSum, total g2JacExtended - runningSum.setInfinity() - total.setInfinity() + runningSum.SetInfinity() + total.SetInfinity() for k := len(buckets) - 1; k >= 0; k-- { - if !buckets[k].IsZero() { + if !buckets[k].IsInfinity() { runningSum.add(&buckets[k]) } total.add(&runningSum) diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/pairing.go b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/pairing.go index ec342fe80e2..0d9bbcc9f0c 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/bn254/pairing.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/bn254/pairing.go @@ -1,22 +1,12 @@ -// Copyright 2020 ConsenSys AG -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. package bn254 import ( "errors" + "github.com/consensys/gnark-crypto/ecc/bn254/fp" "github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower" ) @@ -154,7 +144,7 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) { if n >= 1 { // i = 64, separately to avoid an E12 Square // (Square(res) = 1² = 1) - // loopCounter[64] = 0 + // LoopCounter[64] = 0 // k = 0, separately to avoid MulBy034 (res × ℓ) // (assign line to res) @@ -195,7 +185,7 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) { result.MulBy034(&l1.r0, &l1.r1, &l1.r2) } - // i = 63, separately to avoid a doubleStep (loopCounter[63]=-1) + // i = 63, separately to avoid a doubleStep (LoopCounter[63]=-1) // (at this point qProj = 2Q, so 2qProj-Q=3Q is equivalent to qProj+Q=3Q // this means doubleStep followed by an addMixedStep is equivalent to an // addMixedStep here) @@ -221,7 +211,7 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) { } // i <= 62 - for i := len(loopCounter) - 4; i >= 0; i-- { + for i := len(LoopCounter) - 4; i >= 0; i-- { // mutualize the square among n Miller loops // (∏ᵢfᵢ)² result.Square(&result) @@ -233,7 +223,7 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) { l1.r0.MulByElement(&l1.r0, &p[k].Y) l1.r1.MulByElement(&l1.r1, &p[k].X) - if loopCounter[i] == 1 { + if LoopCounter[i] == 1 { // qProj[k] ← qProj[k]+Q[k] and // l2 the line ℓ passing qProj[k] and Q[k] qProj[k].addMixedStep(&l2, &q[k]) @@ -245,7 +235,7 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) { // (ℓ × ℓ) × res result.MulBy01234(&prodLines) - } else if loopCounter[i] == -1 { + } else if LoopCounter[i] == -1 { // qProj[k] ← qProj[k]-Q[k] and // l2 the line ℓ passing qProj[k] and -Q[k] qProj[k].addMixedStep(&l2, &qNeg[k]) @@ -394,3 +384,329 @@ func (p *g2Proj) lineCompute(evaluations *lineEvaluation, a *G2Affine) { evaluations.r1.Neg(&O) evaluations.r2.Set(&J) } + +// ---------------------- +// Fixed-argument pairing +// ---------------------- + +type LineEvaluationAff struct { + R0 fptower.E2 + R1 fptower.E2 +} + +// PairFixedQ calculates the reduced pairing for a set of points +// ∏ᵢ e(Pᵢ, Qᵢ) where Q are fixed points in G2. +// +// This function doesn't check that the inputs are in the correct subgroup. See IsInSubGroup. +func PairFixedQ(P []G1Affine, lines [][2][len(LoopCounter)]LineEvaluationAff) (GT, error) { + f, err := MillerLoopFixedQ(P, lines) + if err != nil { + return GT{}, err + } + return FinalExponentiation(&f), nil +} + +// PairingCheckFixedQ calculates the reduced pairing for a set of points and returns True if the result is One +// ∏ᵢ e(Pᵢ, Qᵢ) =? 1 where Q are fixed points in G2. +// +// This function doesn't check that the inputs are in the correct subgroup. See IsInSubGroup. +func PairingCheckFixedQ(P []G1Affine, lines [][2][len(LoopCounter)]LineEvaluationAff) (bool, error) { + f, err := PairFixedQ(P, lines) + if err != nil { + return false, err + } + var one GT + one.SetOne() + return f.Equal(&one), nil +} + +// PrecomputeLines precomputes the lines for the fixed-argument Miller loop +func PrecomputeLines(Q G2Affine) (PrecomputedLines [2][len(LoopCounter)]LineEvaluationAff) { + var accQ, negQ G2Affine + accQ.Set(&Q) + negQ.Neg(&Q) + + n := len(LoopCounter) + for i := n - 2; i >= 0; i-- { + switch LoopCounter[i] { + case 0: + accQ.doubleStep(&PrecomputedLines[0][i]) + case 1: + accQ.doubleAndAddStep(&PrecomputedLines[0][i], &PrecomputedLines[1][i], &Q) + case -1: + accQ.doubleAndAddStep(&PrecomputedLines[0][i], &PrecomputedLines[1][i], &negQ) + default: + return [2][len(LoopCounter)]LineEvaluationAff{} + } + } + + var psiQ, phiQ G2Affine + phiQ.X.Conjugate(&Q.X).MulByNonResidue1Power2(&phiQ.X) + phiQ.Y.Conjugate(&Q.Y).MulByNonResidue1Power3(&phiQ.Y) + psiQ.X.MulByNonResidue2Power2(&Q.X) + psiQ.Y.MulByNonResidue2Power3(&Q.Y).Neg(&psiQ.Y) + + accQ.addStep(&PrecomputedLines[1][n-1], &phiQ) + accQ.addStep(&PrecomputedLines[0][n-1], &psiQ) + + return PrecomputedLines +} + +// MillerLoopFixedQ computes the multi-Miller loop as in MillerLoop +// but Qᵢ are fixed points in G2 known in advance. +func MillerLoopFixedQ(P []G1Affine, lines [][2][len(LoopCounter)]LineEvaluationAff) (GT, error) { + n := len(P) + if n == 0 || n != len(lines) { + return GT{}, errors.New("invalid inputs sizes") + } + + // no need to filter infinity points: + // 1. if Pᵢ=(0,0) then -x/y=1/y=0 by gnark-crypto convention and so + // lines R0 and R1 are 0. At the end it happens that result will stay + // 1 through the Miller loop because MulBy34(1,0,0)==1 + // Mul34By34(1,0,0,1,0,0)==1 and MulBy01234(1,0,0,0,0)==1. + // + // 2. if Qᵢ=(0,0) then PrecomputeLines(Qᵢ) will return lines R0 and R1 + // that are 0 because of gnark-convention (*/0==0) in doubleStep and + // addStep. Similarly to Pᵢ=(0,0) it happens that result stays 1 + // throughout the MillerLoop. + + // precomputations + yInv := make([]fp.Element, n) + xNegOverY := make([]fp.Element, n) + for k := 0; k < n; k++ { + yInv[k].Set(&P[k].Y) + } + yInv = fp.BatchInvert(yInv) + for k := 0; k < n; k++ { + xNegOverY[k].Mul(&P[k].X, &yInv[k]). + Neg(&xNegOverY[k]) + } + + var result GT + result.SetOne() + var prodLines [5]E2 + + // Compute ∏ᵢ { fᵢ_{6x₀+2,Q}(P) } + if n >= 1 { + // i = 64, separately to avoid an E12 Square + // (Square(res) = 1² = 1) + // LoopCounter[64] = 0 + // k = 0, separately to avoid MulBy34 (res × ℓ) + // (assign line to res) + + // line evaluation at P[0] (assign) + result.C1.B0.MulByElement(&lines[0][0][64].R0, &xNegOverY[0]) + result.C1.B1.MulByElement(&lines[0][0][64].R1, &yInv[0]) + // the coefficient which MulBy34 sets to 1 happens to be already 1 (result = 1) + } + + if n >= 2 { + // k = 1, separately to avoid MulBy34 (res × ℓ) + // (res is also a line at this point, so we use Mul34By34 ℓ × ℓ) + // line evaluation at P[1] + lines[1][0][64].R0.MulByElement(&lines[1][0][64].R0, &xNegOverY[1]) + lines[1][0][64].R1.MulByElement(&lines[1][0][64].R1, &yInv[1]) + // ℓ × res + prodLines = fptower.Mul34By34(&lines[1][0][64].R0, &lines[1][0][64].R1, &result.C1.B0, &result.C1.B1) + result.C0.B0 = prodLines[0] + result.C0.B1 = prodLines[1] + result.C0.B2 = prodLines[2] + result.C1.B0 = prodLines[3] + result.C1.B1 = prodLines[4] + } + + // k >= 2 + for k := 2; k < n; k++ { + // line evaluation at P[k] + lines[k][0][64].R0.MulByElement(&lines[k][0][64].R0, &xNegOverY[k]) + lines[k][0][64].R1.MulByElement(&lines[k][0][64].R1, &yInv[k]) + // ℓ × res + result.MulBy34( + &lines[k][0][64].R0, + &lines[k][0][64].R1, + ) + } + + for i := len(LoopCounter) - 3; i >= 0; i-- { + // mutualize the square among n Miller loops + // (∏ᵢfᵢ)² + result.Square(&result) + + for k := 0; k < n; k++ { + // line evaluation at P[k] + lines[k][0][i].R0. + MulByElement( + &lines[k][0][i].R0, + &xNegOverY[k], + ) + lines[k][0][i].R1. + MulByElement( + &lines[k][0][i].R1, + &yInv[k], + ) + + if LoopCounter[i] == 0 { + // ℓ × res + result.MulBy34( + &lines[k][0][i].R0, + &lines[k][0][i].R1, + ) + } else { + // line evaluation at P[k] + lines[k][1][i].R0. + MulByElement( + &lines[k][1][i].R0, + &xNegOverY[k], + ) + lines[k][1][i].R1. + MulByElement( + &lines[k][1][i].R1, + &yInv[k], + ) + // ℓ × ℓ + prodLines = fptower.Mul34By34( + &lines[k][0][i].R0, &lines[k][0][i].R1, + &lines[k][1][i].R0, &lines[k][1][i].R1, + ) + // (ℓ × ℓ) × res + result.MulBy01234(&prodLines) + } + } + } + + // Compute ∏ᵢ { ℓᵢ_{[6x₀+2]Q,π(Q)}(P) · ℓᵢ_{[6x₀+2]Q+π(Q),-π²(Q)}(P) } + for k := 0; k < n; k++ { + // line evaluation at P[k] + lines[k][1][65].R0. + MulByElement( + &lines[k][1][65].R0, + &xNegOverY[k], + ) + lines[k][1][65].R1. + MulByElement( + &lines[k][1][65].R1, + &yInv[k], + ) + // line evaluation at P[k] + lines[k][0][65].R0. + MulByElement( + &lines[k][0][65].R0, + &xNegOverY[k], + ) + lines[k][0][65].R1. + MulByElement( + &lines[k][0][65].R1, + &yInv[k], + ) + // ℓ × ℓ + prodLines = fptower.Mul34By34( + &lines[k][1][65].R0, &lines[k][1][65].R1, + &lines[k][0][65].R0, &lines[k][0][65].R1, + ) + // (ℓ × ℓ) × res + result.MulBy01234(&prodLines) + } + + return result, nil +} + +func (p *G2Affine) doubleStep(evaluations *LineEvaluationAff) { + + var n, d, λ, xr, yr fptower.E2 + // λ = 3x²/2y + n.Square(&p.X) + λ.Double(&n). + Add(&λ, &n) + d.Double(&p.Y) + λ.Div(&λ, &d) + + // xr = λ²-2x + xr.Square(&λ). + Sub(&xr, &p.X). + Sub(&xr, &p.X) + + // yr = λ(x-xr)-y + yr.Sub(&p.X, &xr). + Mul(&yr, &λ). + Sub(&yr, &p.Y) + + evaluations.R0.Set(&λ) + evaluations.R1.Mul(&λ, &p.X). + Sub(&evaluations.R1, &p.Y) + + p.X.Set(&xr) + p.Y.Set(&yr) +} + +func (p *G2Affine) addStep(evaluations *LineEvaluationAff, a *G2Affine) { + var n, d, λ, λλ, xr, yr fptower.E2 + + // compute λ = (y2-y1)/(x2-x1) + n.Sub(&a.Y, &p.Y) + d.Sub(&a.X, &p.X) + λ.Div(&n, &d) + + // xr = λ²-x1-x2 + λλ.Square(&λ) + n.Add(&p.X, &a.X) + xr.Sub(&λλ, &n) + + // yr = λ(x1-xr) - y1 + yr.Sub(&p.X, &xr). + Mul(&yr, &λ). + Sub(&yr, &p.Y) + + evaluations.R0.Set(&λ) + evaluations.R1.Mul(&λ, &p.X). + Sub(&evaluations.R1, &p.Y) + + p.X.Set(&xr) + p.Y.Set(&yr) +} + +func (p *G2Affine) doubleAndAddStep(evaluations1, evaluations2 *LineEvaluationAff, a *G2Affine) { + var n, d, l1, x3, l2, x4, y4 fptower.E2 + + // compute λ1 = (y2-y1)/(x2-x1) + n.Sub(&p.Y, &a.Y) + d.Sub(&p.X, &a.X) + l1.Div(&n, &d) + + // compute x3 =λ1²-x1-x2 + x3.Square(&l1) + x3.Sub(&x3, &p.X) + x3.Sub(&x3, &a.X) + + // omit y3 computation + + // compute line1 + evaluations1.R0.Set(&l1) + evaluations1.R1.Mul(&l1, &p.X) + evaluations1.R1.Sub(&evaluations1.R1, &p.Y) + + // compute λ2 = -λ1-2y1/(x3-x1) + n.Double(&p.Y) + d.Sub(&x3, &p.X) + l2.Div(&n, &d) + l2.Add(&l2, &l1) + l2.Neg(&l2) + + // compute x4 = λ2²-x1-x3 + x4.Square(&l2) + x4.Sub(&x4, &p.X) + x4.Sub(&x4, &x3) + + // compute y4 = λ2(x1 - x4)-y1 + y4.Sub(&p.X, &x4) + y4.Mul(&l2, &y4) + y4.Sub(&y4, &p.Y) + + // compute line2 + evaluations2.R0.Set(&l2) + evaluations2.R1.Mul(&l2, &p.X) + evaluations2.R1.Sub(&evaluations2.R1, &p.Y) + + p.X.Set(&x4) + p.Y.Set(&y4) +} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/ecc.go b/vendor/github.com/consensys/gnark-crypto/ecc/ecc.go index 5fa1bd961bb..fb4dc091802 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/ecc.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/ecc.go @@ -1,20 +1,7 @@ -/* -Copyright © 2020 ConsenSys +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Package ecc provides bls12-381, bls12-377, bls12-378, bn254, bw6-761, bls24-315, bls24-317, bw6-633, bls12-378, bw6-756, secp256k1 and stark-curve elliptic curves implementation (+pairing). +// Package ecc provides bls12-381, bls12-377, bn254, bw6-761, bls24-315, bls24-317, bw6-633, secp256k1 and stark-curve elliptic curves implementation (+pairing). // // Also // @@ -26,13 +13,6 @@ limitations under the License. // - EdDSA (on the "companion" twisted edwards curves) package ecc -import ( - "math/big" - "strings" - - "github.com/consensys/gnark-crypto/internal/generator/config" -) - // ID represent a unique ID for a curve type ID uint16 @@ -41,78 +21,16 @@ const ( UNKNOWN ID = iota BN254 BLS12_377 - BLS12_378 BLS12_381 BLS24_315 BLS24_317 BW6_761 BW6_633 - BW6_756 STARK_CURVE SECP256K1 + GRUMPKIN ) -// Implemented return the list of curves fully implemented in gnark-crypto -func Implemented() []ID { - return []ID{BN254, BLS12_377, BLS12_381, BW6_761, BLS24_315, BW6_633, BLS12_378, BW6_756, BLS24_317, STARK_CURVE, SECP256K1} -} - -func (id ID) String() string { - cfg := id.config() - return strings.ToLower(cfg.EnumID) -} - -// ScalarField returns the scalar field of the curve -func (id ID) ScalarField() *big.Int { - cfg := id.config() - return modulus(cfg, true) -} - -// BaseField returns the base field of the curve -func (id ID) BaseField() *big.Int { - cfg := id.config() - return modulus(cfg, false) -} - -func (id ID) config() *config.Curve { - // note to avoid circular dependency these are hard coded - // values are checked for non regression in code generation - switch id { - case BLS12_377: - return &config.BLS12_377 - case BLS12_378: - return &config.BLS12_378 - case BLS12_381: - return &config.BLS12_381 - case BN254: - return &config.BN254 - case BW6_761: - return &config.BW6_761 - case BW6_633: - return &config.BW6_633 - case BLS24_315: - return &config.BLS24_315 - case BLS24_317: - return &config.BLS24_317 - case BW6_756: - return &config.BW6_756 - case STARK_CURVE: - return &config.STARK_CURVE - case SECP256K1: - return &config.SECP256K1 - default: - panic("unimplemented ecc ID") - } -} - -func modulus(c *config.Curve, scalarField bool) *big.Int { - if scalarField { - return new(big.Int).Set(c.FrInfo.Modulus()) - } - - return new(big.Int).Set(c.FpInfo.Modulus()) -} - // MultiExpConfig enables to set optional configuration attribute to a call to MultiExp type MultiExpConfig struct { NbTasks int // go routines to be used in the multiexp. can be larger than num cpus. diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/ecc.md b/vendor/github.com/consensys/gnark-crypto/ecc/ecc.md index f4508d76108..b0be48033a1 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/ecc.md +++ b/vendor/github.com/consensys/gnark-crypto/ecc/ecc.md @@ -2,16 +2,16 @@ * BLS12-381 (Zcash) * BN254 (Ethereum) +* GRUMPKIN (2-cycle with BN254) * BLS12-377 (ZEXE) -* BW6-761 (EC supporting pairing on BLS12-377 field of definition) +* BW6-761 (2-chain with BLS12-377) * BLS24-315 -* BW6-633 (EC supporting pairing on BLS24-315 field of definition) -* BLS12-378 (GT-strong SNARK-friendly) -* BW6-756 (EC supporting pairing on BLS12-378 field of definition) +* BW6-633 (2-chain with BLS24-315) +* BLS24-317 * STARK (STARK curve for ECDSA) ### Twisted edwards curves -Each of these curve has a `twistededwards` sub-package with its companion curve. In particular, BLS12-381 comapnion curve is known as [Jubjub](https://z.cash/technology/jubjub/) and BN254's [Baby-Jubjub](https://iden3-docs.readthedocs.io/en/latest/_downloads/33717d75ab84e11313cc0d8a090b636f/Baby-Jubjub.pdf). +Each of these curve has a `twistededwards` sub-package with its companion curve. In particular, BLS12-381 companion curve is known as [Jubjub](https://z.cash/technology/jubjub/) and BN254's [Baby-Jubjub](https://iden3-docs.readthedocs.io/en/latest/_downloads/33717d75ab84e11313cc0d8a090b636f/Baby-Jubjub.pdf). They are of particular interest as they allow efficient elliptic curve cryptography inside zkSNARK circuits. diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/ecc_field.go b/vendor/github.com/consensys/gnark-crypto/ecc/ecc_field.go new file mode 100644 index 00000000000..5f9179e31ca --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/ecc/ecc_field.go @@ -0,0 +1,123 @@ +// Copyright 2020-2025 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package ecc + +import ( + "errors" + "math/big" + "strings" +) + +var mID = map[string]ID{ + "bls12_377": BLS12_377, + "bls12_381": BLS12_381, + "bls24_315": BLS24_315, + "bls24_317": BLS24_317, + "bn254": BN254, + "bw6_633": BW6_633, + "bw6_761": BW6_761, + "grumpkin": GRUMPKIN, + "secp256k1": SECP256K1, + "stark_curve": STARK_CURVE, +} + +// ScalarField returns the scalar field of the curve +func (id ID) ScalarField() *big.Int { + f := new(big.Int) + switch id { + case BLS12_377: + f.SetString("8444461749428370424248824938781546531375899335154063827935233455917409239041", 10) + case BLS12_381: + f.SetString("52435875175126190479447740508185965837690552500527637822603658699938581184513", 10) + case BLS24_315: + f.SetString("11502027791375260645628074404575422495959608200132055716665986169834464870401", 10) + case BLS24_317: + f.SetString("30869589236456844204538189757527902584594726589286811523515204428962673459201", 10) + case BN254: + f.SetString("21888242871839275222246405745257275088548364400416034343698204186575808495617", 10) + case BW6_633: + f.SetString("39705142709513438335025689890408969744933502416914749335064285505637884093126342347073617133569", 10) + case BW6_761: + f.SetString("258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458177", 10) + case GRUMPKIN: + f.SetString("21888242871839275222246405745257275088696311157297823662689037894645226208583", 10) + case SECP256K1: + f.SetString("115792089237316195423570985008687907852837564279074904382605163141518161494337", 10) + case STARK_CURVE: + f.SetString("3618502788666131213697322783095070105526743751716087489154079457884512865583", 10) + default: + panic("unimplemented ecc ID") + } + return f +} + +// BaseField returns the base field of the curve +func (id ID) BaseField() *big.Int { + f := new(big.Int) + switch id { + case BLS12_377: + f.SetString("258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458177", 10) + case BLS12_381: + f.SetString("4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787", 10) + case BLS24_315: + f.SetString("39705142709513438335025689890408969744933502416914749335064285505637884093126342347073617133569", 10) + case BLS24_317: + f.SetString("136393071104295911515099765908274057061945112121419593977210139303905973197232025618026156731051", 10) + case BN254: + f.SetString("21888242871839275222246405745257275088696311157297823662689037894645226208583", 10) + case BW6_633: + f.SetString("20494478644167774678813387386538961497669590920908778075528754551012016751717791778743535050360001387419576570244406805463255765034468441182772056330021723098661967429339971741066259394985997", 10) + case BW6_761: + f.SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068299", 10) + case GRUMPKIN: + f.SetString("21888242871839275222246405745257275088548364400416034343698204186575808495617", 10) + case SECP256K1: + f.SetString("115792089237316195423570985008687907853269984665640564039457584007908834671663", 10) + case STARK_CURVE: + f.SetString("3618502788666131213697322783095070105623107215331596699973092056135872020481", 10) + default: + panic("unimplemented ecc ID") + } + return f +} + +// String returns the string representation of the ID +func (id ID) String() string { + switch id { + case BLS12_377: + return "bls12_377" + case BLS12_381: + return "bls12_381" + case BLS24_315: + return "bls24_315" + case BLS24_317: + return "bls24_317" + case BN254: + return "bn254" + case BW6_633: + return "bw6_633" + case BW6_761: + return "bw6_761" + case GRUMPKIN: + return "grumpkin" + case SECP256K1: + return "secp256k1" + case STARK_CURVE: + return "stark_curve" + default: + panic("unimplemented ecc ID") + } +} + +// IDFromString returns the ID corresponding to the string representation of the curve ID. +// It returns UNKNOWN if the string does not match any known curve ID. +func IDFromString(s string) (ID, error) { + s = strings.ToLower(s) + if id, ok := mID[s]; ok { + return id, nil + } + return UNKNOWN, errors.New("unknown curve ID") +} diff --git a/vendor/github.com/consensys/gnark-crypto/ecc/utils.go b/vendor/github.com/consensys/gnark-crypto/ecc/utils.go index 78126fc1cc9..c86c6295ebb 100644 --- a/vendor/github.com/consensys/gnark-crypto/ecc/utils.go +++ b/vendor/github.com/consensys/gnark-crypto/ecc/utils.go @@ -178,7 +178,8 @@ func getVector(l *Lattice, a, b *big.Int) [2]big.Int { return res } -// NextPowerOfTwo returns the next power of 2 of n +// NextPowerOfTwo(n) = 2^⌈log₂(n)⌉ +// or 2ᵏ where 2ᵏ⁻¹ < n ≤ 2ᵏ func NextPowerOfTwo(n uint64) uint64 { c := bits.OnesCount64(n) if c == 0 { diff --git a/vendor/github.com/consensys/gnark-crypto/field/asm/element_4w/asm.go b/vendor/github.com/consensys/gnark-crypto/field/asm/element_4w/asm.go new file mode 100644 index 00000000000..f912791eaa3 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/field/asm/element_4w/asm.go @@ -0,0 +1,12 @@ +// Package asm is a workaround to force go mod vendor to include the asm files +// see https://github.com/Consensys/gnark-crypto/issues/619 +package asm + +const DUMMY = 0 +const qInvNeg = 0 +const mu = 0 +const q = 0 +const q0 = 0 +const q1 = 0 +const q2 = 0 +const q3 = 0 diff --git a/vendor/github.com/consensys/gnark-crypto/field/asm/element_4w/element_4w_amd64.s b/vendor/github.com/consensys/gnark-crypto/field/asm/element_4w/element_4w_amd64.s new file mode 100644 index 00000000000..6d7a31b6a22 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/field/asm/element_4w/element_4w_amd64.s @@ -0,0 +1,2438 @@ +// Code generated by gnark-crypto/generator. DO NOT EDIT. +#include "textflag.h" +#include "funcdata.h" +#include "go_asm.h" + +#define REDUCE(ra0, ra1, ra2, ra3, rb0, rb1, rb2, rb3) \ + MOVQ ra0, rb0; \ + SUBQ ·qElement(SB), ra0; \ + MOVQ ra1, rb1; \ + SBBQ ·qElement+8(SB), ra1; \ + MOVQ ra2, rb2; \ + SBBQ ·qElement+16(SB), ra2; \ + MOVQ ra3, rb3; \ + SBBQ ·qElement+24(SB), ra3; \ + CMOVQCS rb0, ra0; \ + CMOVQCS rb1, ra1; \ + CMOVQCS rb2, ra2; \ + CMOVQCS rb3, ra3; \ + +TEXT ·reduce(SB), NOSPLIT, $0-8 + MOVQ res+0(FP), AX + MOVQ 0(AX), DX + MOVQ 8(AX), CX + MOVQ 16(AX), BX + MOVQ 24(AX), SI + + // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) + REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) + + MOVQ DX, 0(AX) + MOVQ CX, 8(AX) + MOVQ BX, 16(AX) + MOVQ SI, 24(AX) + RET + +// MulBy3(x *Element) +TEXT ·MulBy3(SB), NOSPLIT, $0-8 + MOVQ x+0(FP), AX + MOVQ 0(AX), DX + MOVQ 8(AX), CX + MOVQ 16(AX), BX + MOVQ 24(AX), SI + ADDQ DX, DX + ADCQ CX, CX + ADCQ BX, BX + ADCQ SI, SI + + // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) + REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) + + ADDQ 0(AX), DX + ADCQ 8(AX), CX + ADCQ 16(AX), BX + ADCQ 24(AX), SI + + // reduce element(DX,CX,BX,SI) using temp registers (R11,R12,R13,R14) + REDUCE(DX,CX,BX,SI,R11,R12,R13,R14) + + MOVQ DX, 0(AX) + MOVQ CX, 8(AX) + MOVQ BX, 16(AX) + MOVQ SI, 24(AX) + RET + +// MulBy5(x *Element) +TEXT ·MulBy5(SB), NOSPLIT, $0-8 + MOVQ x+0(FP), AX + MOVQ 0(AX), DX + MOVQ 8(AX), CX + MOVQ 16(AX), BX + MOVQ 24(AX), SI + ADDQ DX, DX + ADCQ CX, CX + ADCQ BX, BX + ADCQ SI, SI + + // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) + REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) + + ADDQ DX, DX + ADCQ CX, CX + ADCQ BX, BX + ADCQ SI, SI + + // reduce element(DX,CX,BX,SI) using temp registers (R11,R12,R13,R14) + REDUCE(DX,CX,BX,SI,R11,R12,R13,R14) + + ADDQ 0(AX), DX + ADCQ 8(AX), CX + ADCQ 16(AX), BX + ADCQ 24(AX), SI + + // reduce element(DX,CX,BX,SI) using temp registers (R15,DI,R8,R9) + REDUCE(DX,CX,BX,SI,R15,DI,R8,R9) + + MOVQ DX, 0(AX) + MOVQ CX, 8(AX) + MOVQ BX, 16(AX) + MOVQ SI, 24(AX) + RET + +// MulBy13(x *Element) +TEXT ·MulBy13(SB), NOSPLIT, $0-8 + MOVQ x+0(FP), AX + MOVQ 0(AX), DX + MOVQ 8(AX), CX + MOVQ 16(AX), BX + MOVQ 24(AX), SI + ADDQ DX, DX + ADCQ CX, CX + ADCQ BX, BX + ADCQ SI, SI + + // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) + REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) + + ADDQ DX, DX + ADCQ CX, CX + ADCQ BX, BX + ADCQ SI, SI + + // reduce element(DX,CX,BX,SI) using temp registers (R11,R12,R13,R14) + REDUCE(DX,CX,BX,SI,R11,R12,R13,R14) + + MOVQ DX, R11 + MOVQ CX, R12 + MOVQ BX, R13 + MOVQ SI, R14 + ADDQ DX, DX + ADCQ CX, CX + ADCQ BX, BX + ADCQ SI, SI + + // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) + REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) + + ADDQ R11, DX + ADCQ R12, CX + ADCQ R13, BX + ADCQ R14, SI + + // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) + REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) + + ADDQ 0(AX), DX + ADCQ 8(AX), CX + ADCQ 16(AX), BX + ADCQ 24(AX), SI + + // reduce element(DX,CX,BX,SI) using temp registers (DI,R8,R9,R10) + REDUCE(DX,CX,BX,SI,DI,R8,R9,R10) + + MOVQ DX, 0(AX) + MOVQ CX, 8(AX) + MOVQ BX, 16(AX) + MOVQ SI, 24(AX) + RET + +// Butterfly(a, b *Element) sets a = a + b; b = a - b +TEXT ·Butterfly(SB), NOSPLIT, $0-16 + MOVQ a+0(FP), AX + MOVQ 0(AX), CX + MOVQ 8(AX), BX + MOVQ 16(AX), SI + MOVQ 24(AX), DI + MOVQ CX, R8 + MOVQ BX, R9 + MOVQ SI, R10 + MOVQ DI, R11 + XORQ AX, AX + MOVQ b+8(FP), DX + ADDQ 0(DX), CX + ADCQ 8(DX), BX + ADCQ 16(DX), SI + ADCQ 24(DX), DI + SUBQ 0(DX), R8 + SBBQ 8(DX), R9 + SBBQ 16(DX), R10 + SBBQ 24(DX), R11 + MOVQ $const_q0, R12 + MOVQ $const_q1, R13 + MOVQ $const_q2, R14 + MOVQ $const_q3, R15 + CMOVQCC AX, R12 + CMOVQCC AX, R13 + CMOVQCC AX, R14 + CMOVQCC AX, R15 + ADDQ R12, R8 + ADCQ R13, R9 + ADCQ R14, R10 + ADCQ R15, R11 + MOVQ R8, 0(DX) + MOVQ R9, 8(DX) + MOVQ R10, 16(DX) + MOVQ R11, 24(DX) + + // reduce element(CX,BX,SI,DI) using temp registers (R8,R9,R10,R11) + REDUCE(CX,BX,SI,DI,R8,R9,R10,R11) + + MOVQ a+0(FP), AX + MOVQ CX, 0(AX) + MOVQ BX, 8(AX) + MOVQ SI, 16(AX) + MOVQ DI, 24(AX) + RET + +// mul(res, x, y *Element) +TEXT ·mul(SB), $24-24 + + // Algorithm 2 of "Faster Montgomery Multiplication and Multi-Scalar-Multiplication for SNARKS" + // by Y. El Housni and G. Botrel https://doi.org/10.46586/tches.v2023.i3.504-521 + // See github.com/Consensys/gnark-crypto/field/generator for more comments. + + NO_LOCAL_POINTERS + CMPB ·supportAdx(SB), $1 + JNE noAdx_1 + MOVQ x+8(FP), SI + + // x[0] -> DI + // x[1] -> R8 + // x[2] -> R9 + // x[3] -> R10 + MOVQ 0(SI), DI + MOVQ 8(SI), R8 + MOVQ 16(SI), R9 + MOVQ 24(SI), R10 + MOVQ y+16(FP), R11 + + // A -> BP + // t[0] -> R14 + // t[1] -> R13 + // t[2] -> CX + // t[3] -> BX +#define MACC(in0, in1, in2) \ + ADCXQ in0, in1 \ + MULXQ in2, AX, in0 \ + ADOXQ AX, in1 \ + +#define DIV_SHIFT() \ + MOVQ $const_qInvNeg, DX \ + IMULQ R14, DX \ + XORQ AX, AX \ + MULXQ ·qElement+0(SB), AX, R12 \ + ADCXQ R14, AX \ + MOVQ R12, R14 \ + MACC(R13, R14, ·qElement+8(SB)) \ + MACC(CX, R13, ·qElement+16(SB)) \ + MACC(BX, CX, ·qElement+24(SB)) \ + MOVQ $0, AX \ + ADCXQ AX, BX \ + ADOXQ BP, BX \ + +#define MUL_WORD_0() \ + XORQ AX, AX \ + MULXQ DI, R14, R13 \ + MULXQ R8, AX, CX \ + ADOXQ AX, R13 \ + MULXQ R9, AX, BX \ + ADOXQ AX, CX \ + MULXQ R10, AX, BP \ + ADOXQ AX, BX \ + MOVQ $0, AX \ + ADOXQ AX, BP \ + DIV_SHIFT() \ + +#define MUL_WORD_N() \ + XORQ AX, AX \ + MULXQ DI, AX, BP \ + ADOXQ AX, R14 \ + MACC(BP, R13, R8) \ + MACC(BP, CX, R9) \ + MACC(BP, BX, R10) \ + MOVQ $0, AX \ + ADCXQ AX, BP \ + ADOXQ AX, BP \ + DIV_SHIFT() \ + + // mul body + MOVQ 0(R11), DX + MUL_WORD_0() + MOVQ 8(R11), DX + MUL_WORD_N() + MOVQ 16(R11), DX + MUL_WORD_N() + MOVQ 24(R11), DX + MUL_WORD_N() + + // reduce element(R14,R13,CX,BX) using temp registers (SI,R12,R11,DI) + REDUCE(R14,R13,CX,BX,SI,R12,R11,DI) + + MOVQ res+0(FP), AX + MOVQ R14, 0(AX) + MOVQ R13, 8(AX) + MOVQ CX, 16(AX) + MOVQ BX, 24(AX) + RET + +noAdx_1: + MOVQ res+0(FP), AX + MOVQ AX, (SP) + MOVQ x+8(FP), AX + MOVQ AX, 8(SP) + MOVQ y+16(FP), AX + MOVQ AX, 16(SP) + CALL ·_mulGeneric(SB) + RET + +TEXT ·fromMont(SB), $8-8 + NO_LOCAL_POINTERS + + // Algorithm 2 of "Faster Montgomery Multiplication and Multi-Scalar-Multiplication for SNARKS" + // by Y. El Housni and G. Botrel https://doi.org/10.46586/tches.v2023.i3.504-521 + // when y = 1 we have: + // for i=0 to N-1 + // t[i] = x[i] + // for i=0 to N-1 + // m := t[0]*q'[0] mod W + // C,_ := t[0] + m*q[0] + // for j=1 to N-1 + // (C,t[j-1]) := t[j] + m*q[j] + C + // t[N-1] = C + CMPB ·supportAdx(SB), $1 + JNE noAdx_2 + MOVQ res+0(FP), DX + MOVQ 0(DX), R14 + MOVQ 8(DX), R13 + MOVQ 16(DX), CX + MOVQ 24(DX), BX + XORQ DX, DX + + // m := t[0]*q'[0] mod W + MOVQ $const_qInvNeg, DX + IMULQ R14, DX + XORQ AX, AX + + // C,_ := t[0] + m*q[0] + MULXQ ·qElement+0(SB), AX, BP + ADCXQ R14, AX + MOVQ BP, R14 + + // (C,t[0]) := t[1] + m*q[1] + C + ADCXQ R13, R14 + MULXQ ·qElement+8(SB), AX, R13 + ADOXQ AX, R14 + + // (C,t[1]) := t[2] + m*q[2] + C + ADCXQ CX, R13 + MULXQ ·qElement+16(SB), AX, CX + ADOXQ AX, R13 + + // (C,t[2]) := t[3] + m*q[3] + C + ADCXQ BX, CX + MULXQ ·qElement+24(SB), AX, BX + ADOXQ AX, CX + MOVQ $0, AX + ADCXQ AX, BX + ADOXQ AX, BX + XORQ DX, DX + + // m := t[0]*q'[0] mod W + MOVQ $const_qInvNeg, DX + IMULQ R14, DX + XORQ AX, AX + + // C,_ := t[0] + m*q[0] + MULXQ ·qElement+0(SB), AX, BP + ADCXQ R14, AX + MOVQ BP, R14 + + // (C,t[0]) := t[1] + m*q[1] + C + ADCXQ R13, R14 + MULXQ ·qElement+8(SB), AX, R13 + ADOXQ AX, R14 + + // (C,t[1]) := t[2] + m*q[2] + C + ADCXQ CX, R13 + MULXQ ·qElement+16(SB), AX, CX + ADOXQ AX, R13 + + // (C,t[2]) := t[3] + m*q[3] + C + ADCXQ BX, CX + MULXQ ·qElement+24(SB), AX, BX + ADOXQ AX, CX + MOVQ $0, AX + ADCXQ AX, BX + ADOXQ AX, BX + XORQ DX, DX + + // m := t[0]*q'[0] mod W + MOVQ $const_qInvNeg, DX + IMULQ R14, DX + XORQ AX, AX + + // C,_ := t[0] + m*q[0] + MULXQ ·qElement+0(SB), AX, BP + ADCXQ R14, AX + MOVQ BP, R14 + + // (C,t[0]) := t[1] + m*q[1] + C + ADCXQ R13, R14 + MULXQ ·qElement+8(SB), AX, R13 + ADOXQ AX, R14 + + // (C,t[1]) := t[2] + m*q[2] + C + ADCXQ CX, R13 + MULXQ ·qElement+16(SB), AX, CX + ADOXQ AX, R13 + + // (C,t[2]) := t[3] + m*q[3] + C + ADCXQ BX, CX + MULXQ ·qElement+24(SB), AX, BX + ADOXQ AX, CX + MOVQ $0, AX + ADCXQ AX, BX + ADOXQ AX, BX + XORQ DX, DX + + // m := t[0]*q'[0] mod W + MOVQ $const_qInvNeg, DX + IMULQ R14, DX + XORQ AX, AX + + // C,_ := t[0] + m*q[0] + MULXQ ·qElement+0(SB), AX, BP + ADCXQ R14, AX + MOVQ BP, R14 + + // (C,t[0]) := t[1] + m*q[1] + C + ADCXQ R13, R14 + MULXQ ·qElement+8(SB), AX, R13 + ADOXQ AX, R14 + + // (C,t[1]) := t[2] + m*q[2] + C + ADCXQ CX, R13 + MULXQ ·qElement+16(SB), AX, CX + ADOXQ AX, R13 + + // (C,t[2]) := t[3] + m*q[3] + C + ADCXQ BX, CX + MULXQ ·qElement+24(SB), AX, BX + ADOXQ AX, CX + MOVQ $0, AX + ADCXQ AX, BX + ADOXQ AX, BX + + // reduce element(R14,R13,CX,BX) using temp registers (SI,DI,R8,R9) + REDUCE(R14,R13,CX,BX,SI,DI,R8,R9) + + MOVQ res+0(FP), AX + MOVQ R14, 0(AX) + MOVQ R13, 8(AX) + MOVQ CX, 16(AX) + MOVQ BX, 24(AX) + RET + +noAdx_2: + MOVQ res+0(FP), AX + MOVQ AX, (SP) + CALL ·_fromMontGeneric(SB) + RET + +// Vector operations are partially derived from Dag Arne Osvik's work in github.com/a16z/vectorized-fields + +// addVec(res, a, b *Element, n uint64) res[0...n] = a[0...n] + b[0...n] +TEXT ·addVec(SB), NOSPLIT, $0-32 + MOVQ res+0(FP), CX + MOVQ a+8(FP), AX + MOVQ b+16(FP), DX + MOVQ n+24(FP), BX + +loop_3: + TESTQ BX, BX + JEQ done_4 // n == 0, we are done + + // a[0] -> SI + // a[1] -> DI + // a[2] -> R8 + // a[3] -> R9 + MOVQ 0(AX), SI + MOVQ 8(AX), DI + MOVQ 16(AX), R8 + MOVQ 24(AX), R9 + ADDQ 0(DX), SI + ADCQ 8(DX), DI + ADCQ 16(DX), R8 + ADCQ 24(DX), R9 + PREFETCHT0 2048(AX) + PREFETCHT0 2048(DX) + + // reduce element(SI,DI,R8,R9) using temp registers (R10,R11,R12,R13) + REDUCE(SI,DI,R8,R9,R10,R11,R12,R13) + + MOVQ SI, 0(CX) + MOVQ DI, 8(CX) + MOVQ R8, 16(CX) + MOVQ R9, 24(CX) + + // increment pointers to visit next element + ADDQ $32, AX + ADDQ $32, DX + ADDQ $32, CX + DECQ BX // decrement n + JMP loop_3 + +done_4: + RET + +// subVec(res, a, b *Element, n uint64) res[0...n] = a[0...n] - b[0...n] +TEXT ·subVec(SB), NOSPLIT, $0-32 + MOVQ res+0(FP), CX + MOVQ a+8(FP), AX + MOVQ b+16(FP), DX + MOVQ n+24(FP), BX + XORQ SI, SI + +loop_5: + TESTQ BX, BX + JEQ done_6 // n == 0, we are done + + // a[0] -> DI + // a[1] -> R8 + // a[2] -> R9 + // a[3] -> R10 + MOVQ 0(AX), DI + MOVQ 8(AX), R8 + MOVQ 16(AX), R9 + MOVQ 24(AX), R10 + SUBQ 0(DX), DI + SBBQ 8(DX), R8 + SBBQ 16(DX), R9 + SBBQ 24(DX), R10 + PREFETCHT0 2048(AX) + PREFETCHT0 2048(DX) + + // reduce (a-b) mod q + // q[0] -> R11 + // q[1] -> R12 + // q[2] -> R13 + // q[3] -> R14 + MOVQ $const_q0, R11 + MOVQ $const_q1, R12 + MOVQ $const_q2, R13 + MOVQ $const_q3, R14 + CMOVQCC SI, R11 + CMOVQCC SI, R12 + CMOVQCC SI, R13 + CMOVQCC SI, R14 + + // add registers (q or 0) to a, and set to result + ADDQ R11, DI + ADCQ R12, R8 + ADCQ R13, R9 + ADCQ R14, R10 + MOVQ DI, 0(CX) + MOVQ R8, 8(CX) + MOVQ R9, 16(CX) + MOVQ R10, 24(CX) + + // increment pointers to visit next element + ADDQ $32, AX + ADDQ $32, DX + ADDQ $32, CX + DECQ BX // decrement n + JMP loop_5 + +done_6: + RET + +// sumVec(res, a *Element, n uint64) res = sum(a[0...n]) +TEXT ·sumVec(SB), NOSPLIT, $0-24 + + // Derived from https://github.com/a16z/vectorized-fields + // The idea is to use Z registers to accumulate the sum of elements, 8 by 8 + // first, we handle the case where n % 8 != 0 + // then, we loop over the elements 8 by 8 and accumulate the sum in the Z registers + // finally, we reduce the sum and store it in res + // + // when we move an element of a into a Z register, we use VPMOVZXDQ + // let's note w0...w3 the 4 64bits words of ai: w0 = ai[0], w1 = ai[1], w2 = ai[2], w3 = ai[3] + // VPMOVZXDQ(ai, Z0) will result in + // Z0= [hi(w3), lo(w3), hi(w2), lo(w2), hi(w1), lo(w1), hi(w0), lo(w0)] + // with hi(wi) the high 32 bits of wi and lo(wi) the low 32 bits of wi + // we can safely add 2^32+1 times Z registers constructed this way without overflow + // since each of this lo/hi bits are moved into a "64bits" slot + // N = 2^64-1 / 2^32-1 = 2^32+1 + // + // we then propagate the carry using ADOXQ and ADCXQ + // r0 = w0l + lo(woh) + // r1 = carry + hi(woh) + w1l + lo(w1h) + // r2 = carry + hi(w1h) + w2l + lo(w2h) + // r3 = carry + hi(w2h) + w3l + lo(w3h) + // r4 = carry + hi(w3h) + // we then reduce the sum using a single-word Barrett reduction + // we pick mu = 2^288 / q; which correspond to 4.5 words max. + // meaning we must guarantee that r4 fits in 32bits. + // To do so, we reduce N to 2^32-1 (since r4 receives 2 carries max) + + MOVQ a+8(FP), R14 + MOVQ n+16(FP), R15 + + // initialize accumulators Z0, Z1, Z2, Z3, Z4, Z5, Z6, Z7 + VXORPS Z0, Z0, Z0 + VMOVDQA64 Z0, Z1 + VMOVDQA64 Z0, Z2 + VMOVDQA64 Z0, Z3 + VMOVDQA64 Z0, Z4 + VMOVDQA64 Z0, Z5 + VMOVDQA64 Z0, Z6 + VMOVDQA64 Z0, Z7 + + // n % 8 -> CX + // n / 8 -> R15 + MOVQ R15, CX + ANDQ $7, CX + SHRQ $3, R15 + +loop_single_9: + TESTQ CX, CX + JEQ loop8by8_7 // n % 8 == 0, we are going to loop over 8 by 8 + VPMOVZXDQ 0(R14), Z8 + VPADDQ Z8, Z0, Z0 + ADDQ $32, R14 + DECQ CX // decrement nMod8 + JMP loop_single_9 + +loop8by8_7: + TESTQ R15, R15 + JEQ accumulate_10 // n == 0, we are going to accumulate + VPMOVZXDQ 0*32(R14), Z8 + VPMOVZXDQ 1*32(R14), Z9 + VPMOVZXDQ 2*32(R14), Z10 + VPMOVZXDQ 3*32(R14), Z11 + VPMOVZXDQ 4*32(R14), Z12 + VPMOVZXDQ 5*32(R14), Z13 + VPMOVZXDQ 6*32(R14), Z14 + VPMOVZXDQ 7*32(R14), Z15 + PREFETCHT0 4096(R14) + VPADDQ Z8, Z0, Z0 + VPADDQ Z9, Z1, Z1 + VPADDQ Z10, Z2, Z2 + VPADDQ Z11, Z3, Z3 + VPADDQ Z12, Z4, Z4 + VPADDQ Z13, Z5, Z5 + VPADDQ Z14, Z6, Z6 + VPADDQ Z15, Z7, Z7 + + // increment pointers to visit next 8 elements + ADDQ $256, R14 + DECQ R15 // decrement n + JMP loop8by8_7 + +accumulate_10: + // accumulate the 8 Z registers into Z0 + VPADDQ Z7, Z6, Z6 + VPADDQ Z6, Z5, Z5 + VPADDQ Z5, Z4, Z4 + VPADDQ Z4, Z3, Z3 + VPADDQ Z3, Z2, Z2 + VPADDQ Z2, Z1, Z1 + VPADDQ Z1, Z0, Z0 + + // carry propagation + // lo(w0) -> BX + // hi(w0) -> SI + // lo(w1) -> DI + // hi(w1) -> R8 + // lo(w2) -> R9 + // hi(w2) -> R10 + // lo(w3) -> R11 + // hi(w3) -> R12 + VMOVQ X0, BX + VALIGNQ $1, Z0, Z0, Z0 + VMOVQ X0, SI + VALIGNQ $1, Z0, Z0, Z0 + VMOVQ X0, DI + VALIGNQ $1, Z0, Z0, Z0 + VMOVQ X0, R8 + VALIGNQ $1, Z0, Z0, Z0 + VMOVQ X0, R9 + VALIGNQ $1, Z0, Z0, Z0 + VMOVQ X0, R10 + VALIGNQ $1, Z0, Z0, Z0 + VMOVQ X0, R11 + VALIGNQ $1, Z0, Z0, Z0 + VMOVQ X0, R12 + + // lo(hi(wo)) -> R13 + // lo(hi(w1)) -> CX + // lo(hi(w2)) -> R15 + // lo(hi(w3)) -> R14 +#define SPLIT_LO_HI(in0, in1) \ + MOVQ in1, in0 \ + ANDQ $0xffffffff, in0 \ + SHLQ $32, in0 \ + SHRQ $32, in1 \ + + SPLIT_LO_HI(R13, SI) + SPLIT_LO_HI(CX, R8) + SPLIT_LO_HI(R15, R10) + SPLIT_LO_HI(R14, R12) + + // r0 = w0l + lo(woh) + // r1 = carry + hi(woh) + w1l + lo(w1h) + // r2 = carry + hi(w1h) + w2l + lo(w2h) + // r3 = carry + hi(w2h) + w3l + lo(w3h) + // r4 = carry + hi(w3h) + + XORQ AX, AX // clear the flags + ADOXQ R13, BX + ADOXQ CX, DI + ADCXQ SI, DI + ADOXQ R15, R9 + ADCXQ R8, R9 + ADOXQ R14, R11 + ADCXQ R10, R11 + ADOXQ AX, R12 + ADCXQ AX, R12 + + // r[0] -> BX + // r[1] -> DI + // r[2] -> R9 + // r[3] -> R11 + // r[4] -> R12 + // reduce using single-word Barrett + // see see Handbook of Applied Cryptography, Algorithm 14.42. + // mu=2^288 / q -> SI + MOVQ $const_mu, SI + MOVQ R11, AX + SHRQ $32, R12, AX + MULQ SI // high bits of res stored in DX + MULXQ ·qElement+0(SB), AX, SI + SUBQ AX, BX + SBBQ SI, DI + MULXQ ·qElement+16(SB), AX, SI + SBBQ AX, R9 + SBBQ SI, R11 + SBBQ $0, R12 + MULXQ ·qElement+8(SB), AX, SI + SUBQ AX, DI + SBBQ SI, R9 + MULXQ ·qElement+24(SB), AX, SI + SBBQ AX, R11 + SBBQ SI, R12 + MOVQ BX, R8 + MOVQ DI, R10 + MOVQ R9, R13 + MOVQ R11, CX + SUBQ ·qElement+0(SB), BX + SBBQ ·qElement+8(SB), DI + SBBQ ·qElement+16(SB), R9 + SBBQ ·qElement+24(SB), R11 + SBBQ $0, R12 + JCS modReduced_11 + MOVQ BX, R8 + MOVQ DI, R10 + MOVQ R9, R13 + MOVQ R11, CX + SUBQ ·qElement+0(SB), BX + SBBQ ·qElement+8(SB), DI + SBBQ ·qElement+16(SB), R9 + SBBQ ·qElement+24(SB), R11 + SBBQ $0, R12 + JCS modReduced_11 + MOVQ BX, R8 + MOVQ DI, R10 + MOVQ R9, R13 + MOVQ R11, CX + +modReduced_11: + MOVQ res+0(FP), SI + MOVQ R8, 0(SI) + MOVQ R10, 8(SI) + MOVQ R13, 16(SI) + MOVQ CX, 24(SI) + +done_8: + RET + +// innerProdVec(res, a,b *Element, n uint64) res = sum(a[0...n] * b[0...n]) +TEXT ·innerProdVec(SB), NOSPLIT, $0-32 + MOVQ a+8(FP), R14 + MOVQ b+16(FP), R15 + MOVQ n+24(FP), CX + + // Create mask for low dword in each qword + VPCMPEQB Y0, Y0, Y0 + VPMOVZXDQ Y0, Z5 + VPXORQ Z16, Z16, Z16 + VMOVDQA64 Z16, Z17 + VMOVDQA64 Z16, Z18 + VMOVDQA64 Z16, Z19 + VMOVDQA64 Z16, Z20 + VMOVDQA64 Z16, Z21 + VMOVDQA64 Z16, Z22 + VMOVDQA64 Z16, Z23 + VMOVDQA64 Z16, Z24 + VMOVDQA64 Z16, Z25 + VMOVDQA64 Z16, Z26 + VMOVDQA64 Z16, Z27 + VMOVDQA64 Z16, Z28 + VMOVDQA64 Z16, Z29 + VMOVDQA64 Z16, Z30 + VMOVDQA64 Z16, Z31 + TESTQ CX, CX + JEQ done_13 // n == 0, we are done + +loop_12: + TESTQ CX, CX + JEQ accumulate_14 // n == 0 we can accumulate + VPMOVZXDQ (R15), Z4 + ADDQ $32, R15 + + // we multiply and accumulate partial products of 4 bytes * 32 bytes +#define MAC(in0, in1, in2) \ + VPMULUDQ.BCST in0, Z4, Z2 \ + VPSRLQ $32, Z2, Z3 \ + VPANDQ Z5, Z2, Z2 \ + VPADDQ Z2, in1, in1 \ + VPADDQ Z3, in2, in2 \ + + MAC(0*4(R14), Z16, Z24) + MAC(1*4(R14), Z17, Z25) + MAC(2*4(R14), Z18, Z26) + MAC(3*4(R14), Z19, Z27) + MAC(4*4(R14), Z20, Z28) + MAC(5*4(R14), Z21, Z29) + MAC(6*4(R14), Z22, Z30) + MAC(7*4(R14), Z23, Z31) + ADDQ $32, R14 + DECQ CX // decrement n + JMP loop_12 + +accumulate_14: + // we accumulate the partial products into 544bits in Z1:Z0 + MOVQ $0x0000000000001555, AX + KMOVD AX, K1 + MOVQ $1, AX + KMOVD AX, K2 + + // store the least significant 32 bits of ACC (starts with A0L) in Z0 + VALIGND.Z $16, Z16, Z16, K2, Z0 + KSHIFTLW $1, K2, K2 + VPSRLQ $32, Z16, Z2 + VALIGND.Z $2, Z16, Z16, K1, Z16 + VPADDQ Z2, Z16, Z16 + VPANDQ Z5, Z24, Z2 + VPADDQ Z2, Z16, Z16 + VPANDQ Z5, Z17, Z2 + VPADDQ Z2, Z16, Z16 + VALIGND $15, Z16, Z16, K2, Z0 + KSHIFTLW $1, K2, K2 + + // macro to add partial products and store the result in Z0 +#define ADDPP(in0, in1, in2, in3, in4) \ + VPSRLQ $32, Z16, Z2 \ + VALIGND.Z $2, Z16, Z16, K1, Z16 \ + VPADDQ Z2, Z16, Z16 \ + VPSRLQ $32, in0, in0 \ + VPADDQ in0, Z16, Z16 \ + VPSRLQ $32, in1, in1 \ + VPADDQ in1, Z16, Z16 \ + VPANDQ Z5, in2, Z2 \ + VPADDQ Z2, Z16, Z16 \ + VPANDQ Z5, in3, Z2 \ + VPADDQ Z2, Z16, Z16 \ + VALIGND $16-in4, Z16, Z16, K2, Z0 \ + KADDW K2, K2, K2 \ + + ADDPP(Z24, Z17, Z25, Z18, 2) + ADDPP(Z25, Z18, Z26, Z19, 3) + ADDPP(Z26, Z19, Z27, Z20, 4) + ADDPP(Z27, Z20, Z28, Z21, 5) + ADDPP(Z28, Z21, Z29, Z22, 6) + ADDPP(Z29, Z22, Z30, Z23, 7) + VPSRLQ $32, Z16, Z2 + VALIGND.Z $2, Z16, Z16, K1, Z16 + VPADDQ Z2, Z16, Z16 + VPSRLQ $32, Z30, Z30 + VPADDQ Z30, Z16, Z16 + VPSRLQ $32, Z23, Z23 + VPADDQ Z23, Z16, Z16 + VPANDQ Z5, Z31, Z2 + VPADDQ Z2, Z16, Z16 + VALIGND $16-8, Z16, Z16, K2, Z0 + KSHIFTLW $1, K2, K2 + VPSRLQ $32, Z16, Z2 + VALIGND.Z $2, Z16, Z16, K1, Z16 + VPADDQ Z2, Z16, Z16 + VPSRLQ $32, Z31, Z31 + VPADDQ Z31, Z16, Z16 + VALIGND $16-9, Z16, Z16, K2, Z0 + KSHIFTLW $1, K2, K2 + +#define ADDPP2(in0) \ + VPSRLQ $32, Z16, Z2 \ + VALIGND.Z $2, Z16, Z16, K1, Z16 \ + VPADDQ Z2, Z16, Z16 \ + VALIGND $16-in0, Z16, Z16, K2, Z0 \ + KSHIFTLW $1, K2, K2 \ + + ADDPP2(10) + ADDPP2(11) + ADDPP2(12) + ADDPP2(13) + ADDPP2(14) + ADDPP2(15) + VPSRLQ $32, Z16, Z2 + VALIGND.Z $2, Z16, Z16, K1, Z16 + VPADDQ Z2, Z16, Z16 + VMOVDQA64.Z Z16, K1, Z1 + + // Extract the 4 least significant qwords of Z0 + VMOVQ X0, SI + VALIGNQ $1, Z0, Z1, Z0 + VMOVQ X0, DI + VALIGNQ $1, Z0, Z0, Z0 + VMOVQ X0, R8 + VALIGNQ $1, Z0, Z0, Z0 + VMOVQ X0, R9 + VALIGNQ $1, Z0, Z0, Z0 + XORQ BX, BX + MOVQ $const_qInvNeg, DX + MULXQ SI, DX, R10 + MULXQ ·qElement+0(SB), AX, R10 + ADDQ AX, SI + ADCQ R10, DI + MULXQ ·qElement+16(SB), AX, R10 + ADCQ AX, R8 + ADCQ R10, R9 + ADCQ $0, BX + MULXQ ·qElement+8(SB), AX, R10 + ADDQ AX, DI + ADCQ R10, R8 + MULXQ ·qElement+24(SB), AX, R10 + ADCQ AX, R9 + ADCQ R10, BX + ADCQ $0, SI + MOVQ $const_qInvNeg, DX + MULXQ DI, DX, R10 + MULXQ ·qElement+0(SB), AX, R10 + ADDQ AX, DI + ADCQ R10, R8 + MULXQ ·qElement+16(SB), AX, R10 + ADCQ AX, R9 + ADCQ R10, BX + ADCQ $0, SI + MULXQ ·qElement+8(SB), AX, R10 + ADDQ AX, R8 + ADCQ R10, R9 + MULXQ ·qElement+24(SB), AX, R10 + ADCQ AX, BX + ADCQ R10, SI + ADCQ $0, DI + MOVQ $const_qInvNeg, DX + MULXQ R8, DX, R10 + MULXQ ·qElement+0(SB), AX, R10 + ADDQ AX, R8 + ADCQ R10, R9 + MULXQ ·qElement+16(SB), AX, R10 + ADCQ AX, BX + ADCQ R10, SI + ADCQ $0, DI + MULXQ ·qElement+8(SB), AX, R10 + ADDQ AX, R9 + ADCQ R10, BX + MULXQ ·qElement+24(SB), AX, R10 + ADCQ AX, SI + ADCQ R10, DI + ADCQ $0, R8 + MOVQ $const_qInvNeg, DX + MULXQ R9, DX, R10 + MULXQ ·qElement+0(SB), AX, R10 + ADDQ AX, R9 + ADCQ R10, BX + MULXQ ·qElement+16(SB), AX, R10 + ADCQ AX, SI + ADCQ R10, DI + ADCQ $0, R8 + MULXQ ·qElement+8(SB), AX, R10 + ADDQ AX, BX + ADCQ R10, SI + MULXQ ·qElement+24(SB), AX, R10 + ADCQ AX, DI + ADCQ R10, R8 + ADCQ $0, R9 + VMOVQ X0, AX + ADDQ AX, BX + VALIGNQ $1, Z0, Z0, Z0 + VMOVQ X0, AX + ADCQ AX, SI + VALIGNQ $1, Z0, Z0, Z0 + VMOVQ X0, AX + ADCQ AX, DI + VALIGNQ $1, Z0, Z0, Z0 + VMOVQ X0, AX + ADCQ AX, R8 + VALIGNQ $1, Z0, Z0, Z0 + VMOVQ X0, AX + ADCQ AX, R9 + + // Barrett reduction; see Handbook of Applied Cryptography, Algorithm 14.42. + MOVQ R8, AX + SHRQ $32, R9, AX + MOVQ $const_mu, DX + MULQ DX + MULXQ ·qElement+0(SB), AX, R10 + SUBQ AX, BX + SBBQ R10, SI + MULXQ ·qElement+16(SB), AX, R10 + SBBQ AX, DI + SBBQ R10, R8 + SBBQ $0, R9 + MULXQ ·qElement+8(SB), AX, R10 + SUBQ AX, SI + SBBQ R10, DI + MULXQ ·qElement+24(SB), AX, R10 + SBBQ AX, R8 + SBBQ R10, R9 + + // we need up to 2 conditional substractions to be < q + MOVQ res+0(FP), R11 + MOVQ BX, 0(R11) + MOVQ SI, 8(R11) + MOVQ DI, 16(R11) + MOVQ R8, 24(R11) + SUBQ ·qElement+0(SB), BX + SBBQ ·qElement+8(SB), SI + SBBQ ·qElement+16(SB), DI + SBBQ ·qElement+24(SB), R8 + SBBQ $0, R9 + JCS done_13 + MOVQ BX, 0(R11) + MOVQ SI, 8(R11) + MOVQ DI, 16(R11) + MOVQ R8, 24(R11) + SUBQ ·qElement+0(SB), BX + SBBQ ·qElement+8(SB), SI + SBBQ ·qElement+16(SB), DI + SBBQ ·qElement+24(SB), R8 + SBBQ $0, R9 + JCS done_13 + MOVQ BX, 0(R11) + MOVQ SI, 8(R11) + MOVQ DI, 16(R11) + MOVQ R8, 24(R11) + +done_13: + RET + +TEXT ·scalarMulVec(SB), $8-40 +#define AVX_MUL_Q_LO() \ + VPMULUDQ.BCST ·qElement+0(SB), Z9, Z10 \ + VPADDQ Z10, Z0, Z0 \ + VPMULUDQ.BCST ·qElement+4(SB), Z9, Z11 \ + VPADDQ Z11, Z1, Z1 \ + VPMULUDQ.BCST ·qElement+8(SB), Z9, Z12 \ + VPADDQ Z12, Z2, Z2 \ + VPMULUDQ.BCST ·qElement+12(SB), Z9, Z13 \ + VPADDQ Z13, Z3, Z3 \ + +#define AVX_MUL_Q_HI() \ + VPMULUDQ.BCST ·qElement+16(SB), Z9, Z14 \ + VPADDQ Z14, Z4, Z4 \ + VPMULUDQ.BCST ·qElement+20(SB), Z9, Z15 \ + VPADDQ Z15, Z5, Z5 \ + VPMULUDQ.BCST ·qElement+24(SB), Z9, Z16 \ + VPADDQ Z16, Z6, Z6 \ + VPMULUDQ.BCST ·qElement+28(SB), Z9, Z17 \ + VPADDQ Z17, Z7, Z7 \ + +#define SHIFT_ADD_AND(in0, in1, in2, in3) \ + VPSRLQ $32, in0, in1 \ + VPADDQ in1, in2, in2 \ + VPANDQ in3, in2, in0 \ + +#define CARRY1() \ + SHIFT_ADD_AND(Z0, Z10, Z1, Z8) \ + SHIFT_ADD_AND(Z1, Z11, Z2, Z8) \ + SHIFT_ADD_AND(Z2, Z12, Z3, Z8) \ + SHIFT_ADD_AND(Z3, Z13, Z4, Z8) \ + +#define CARRY2() \ + SHIFT_ADD_AND(Z4, Z14, Z5, Z8) \ + SHIFT_ADD_AND(Z5, Z15, Z6, Z8) \ + SHIFT_ADD_AND(Z6, Z16, Z7, Z8) \ + VPSRLQ $32, Z7, Z7 \ + +#define CARRY3() \ + VPSRLQ $32, Z0, Z10 \ + VPANDQ Z8, Z0, Z0 \ + VPADDQ Z10, Z1, Z1 \ + VPSRLQ $32, Z1, Z11 \ + VPANDQ Z8, Z1, Z1 \ + VPADDQ Z11, Z2, Z2 \ + VPSRLQ $32, Z2, Z12 \ + VPANDQ Z8, Z2, Z2 \ + VPADDQ Z12, Z3, Z3 \ + VPSRLQ $32, Z3, Z13 \ + VPANDQ Z8, Z3, Z3 \ + VPADDQ Z13, Z4, Z4 \ + +#define CARRY4() \ + VPSRLQ $32, Z4, Z14 \ + VPANDQ Z8, Z4, Z4 \ + VPADDQ Z14, Z5, Z5 \ + VPSRLQ $32, Z5, Z15 \ + VPANDQ Z8, Z5, Z5 \ + VPADDQ Z15, Z6, Z6 \ + VPSRLQ $32, Z6, Z16 \ + VPANDQ Z8, Z6, Z6 \ + VPADDQ Z16, Z7, Z7 \ + + // t[0] -> R14 + // t[1] -> R13 + // t[2] -> CX + // t[3] -> BX + // y[0] -> DI + // y[1] -> R8 + // y[2] -> R9 + // y[3] -> R10 + MOVQ res+0(FP), SI + MOVQ a+8(FP), R11 + MOVQ b+16(FP), R15 + MOVQ n+24(FP), R12 + MOVQ 0(R15), DI + MOVQ 8(R15), R8 + MOVQ 16(R15), R9 + MOVQ 24(R15), R10 + MOVQ R12, s0-8(SP) + + // Create mask for low dword in each qword + VPCMPEQB Y8, Y8, Y8 + VPMOVZXDQ Y8, Z8 + MOVQ $0x5555, DX + KMOVD DX, K1 + +loop_16: + TESTQ R12, R12 + JEQ done_15 // n == 0, we are done + MOVQ 0(R11), DX + VMOVDQU64 256+0*64(R11), Z16 + VMOVDQU64 256+1*64(R11), Z17 + VMOVDQU64 256+2*64(R11), Z18 + VMOVDQU64 256+3*64(R11), Z19 + VMOVDQU64 0(R15), Z24 + VMOVDQU64 0(R15), Z25 + VMOVDQU64 0(R15), Z26 + VMOVDQU64 0(R15), Z27 + + // Transpose and expand x and y + VSHUFI64X2 $0x88, Z17, Z16, Z20 + VSHUFI64X2 $0xdd, Z17, Z16, Z22 + VSHUFI64X2 $0x88, Z19, Z18, Z21 + VSHUFI64X2 $0xdd, Z19, Z18, Z23 + VSHUFI64X2 $0x88, Z25, Z24, Z28 + VSHUFI64X2 $0xdd, Z25, Z24, Z30 + VSHUFI64X2 $0x88, Z27, Z26, Z29 + VSHUFI64X2 $0xdd, Z27, Z26, Z31 + VPERMQ $0xd8, Z20, Z20 + VPERMQ $0xd8, Z21, Z21 + VPERMQ $0xd8, Z22, Z22 + VPERMQ $0xd8, Z23, Z23 + + // z[0] -> y * x[0] + MUL_WORD_0() + VPERMQ $0xd8, Z28, Z28 + VPERMQ $0xd8, Z29, Z29 + VPERMQ $0xd8, Z30, Z30 + VPERMQ $0xd8, Z31, Z31 + VSHUFI64X2 $0xd8, Z20, Z20, Z20 + VSHUFI64X2 $0xd8, Z21, Z21, Z21 + VSHUFI64X2 $0xd8, Z22, Z22, Z22 + VSHUFI64X2 $0xd8, Z23, Z23, Z23 + + // z[0] -> y * x[1] + MOVQ 8(R11), DX + MUL_WORD_N() + VSHUFI64X2 $0xd8, Z28, Z28, Z28 + VSHUFI64X2 $0xd8, Z29, Z29, Z29 + VSHUFI64X2 $0xd8, Z30, Z30, Z30 + VSHUFI64X2 $0xd8, Z31, Z31, Z31 + VSHUFI64X2 $0x44, Z21, Z20, Z16 + VSHUFI64X2 $0xee, Z21, Z20, Z18 + VSHUFI64X2 $0x44, Z23, Z22, Z20 + VSHUFI64X2 $0xee, Z23, Z22, Z22 + + // z[0] -> y * x[2] + MOVQ 16(R11), DX + MUL_WORD_N() + VSHUFI64X2 $0x44, Z29, Z28, Z24 + VSHUFI64X2 $0xee, Z29, Z28, Z26 + VSHUFI64X2 $0x44, Z31, Z30, Z28 + VSHUFI64X2 $0xee, Z31, Z30, Z30 + PREFETCHT0 1024(R11) + VPSRLQ $32, Z16, Z17 + VPSRLQ $32, Z18, Z19 + VPSRLQ $32, Z20, Z21 + VPSRLQ $32, Z22, Z23 + VPSRLQ $32, Z24, Z25 + VPSRLQ $32, Z26, Z27 + VPSRLQ $32, Z28, Z29 + VPSRLQ $32, Z30, Z31 + + // z[0] -> y * x[3] + MOVQ 24(R11), DX + MUL_WORD_N() + VPANDQ Z8, Z16, Z16 + VPANDQ Z8, Z18, Z18 + VPANDQ Z8, Z20, Z20 + VPANDQ Z8, Z22, Z22 + VPANDQ Z8, Z24, Z24 + VPANDQ Z8, Z26, Z26 + VPANDQ Z8, Z28, Z28 + VPANDQ Z8, Z30, Z30 + + // reduce element(R14,R13,CX,BX) using temp registers (BP,R12,AX,DX) + REDUCE(R14,R13,CX,BX,BP,R12,AX,DX) + + // store output z[0] + MOVQ R14, 0(SI) + MOVQ R13, 8(SI) + MOVQ CX, 16(SI) + MOVQ BX, 24(SI) + ADDQ $32, R11 + MOVQ 0(R11), DX + + // For each 256-bit input value, each zmm register now represents a 32-bit input word zero-extended to 64 bits. + // Multiply y by doubleword 0 of x + VPMULUDQ Z16, Z24, Z0 + VPMULUDQ Z16, Z25, Z1 + VPMULUDQ Z16, Z26, Z2 + VPMULUDQ Z16, Z27, Z3 + VPMULUDQ Z16, Z28, Z4 + VPMULUDQ Z16, Z29, Z5 + VPMULUDQ Z16, Z30, Z6 + VPMULUDQ Z16, Z31, Z7 + VPMULUDQ.BCST qInvNeg+32(FP), Z0, Z9 + VPSRLQ $32, Z0, Z10 + VPANDQ Z8, Z0, Z0 + VPADDQ Z10, Z1, Z1 + VPSRLQ $32, Z1, Z11 + VPANDQ Z8, Z1, Z1 + VPADDQ Z11, Z2, Z2 + VPSRLQ $32, Z2, Z12 + VPANDQ Z8, Z2, Z2 + VPADDQ Z12, Z3, Z3 + VPSRLQ $32, Z3, Z13 + VPANDQ Z8, Z3, Z3 + VPADDQ Z13, Z4, Z4 + + // z[1] -> y * x[0] + MUL_WORD_0() + VPSRLQ $32, Z4, Z14 + VPANDQ Z8, Z4, Z4 + VPADDQ Z14, Z5, Z5 + VPSRLQ $32, Z5, Z15 + VPANDQ Z8, Z5, Z5 + VPADDQ Z15, Z6, Z6 + VPSRLQ $32, Z6, Z16 + VPANDQ Z8, Z6, Z6 + VPADDQ Z16, Z7, Z7 + VPMULUDQ.BCST ·qElement+0(SB), Z9, Z10 + VPADDQ Z10, Z0, Z0 + VPMULUDQ.BCST ·qElement+4(SB), Z9, Z11 + VPADDQ Z11, Z1, Z1 + VPMULUDQ.BCST ·qElement+8(SB), Z9, Z12 + VPADDQ Z12, Z2, Z2 + VPMULUDQ.BCST ·qElement+12(SB), Z9, Z13 + VPADDQ Z13, Z3, Z3 + + // z[1] -> y * x[1] + MOVQ 8(R11), DX + MUL_WORD_N() + VPMULUDQ.BCST ·qElement+16(SB), Z9, Z14 + VPADDQ Z14, Z4, Z4 + VPMULUDQ.BCST ·qElement+20(SB), Z9, Z15 + VPADDQ Z15, Z5, Z5 + VPMULUDQ.BCST ·qElement+24(SB), Z9, Z16 + VPADDQ Z16, Z6, Z6 + VPMULUDQ.BCST ·qElement+28(SB), Z9, Z10 + VPADDQ Z10, Z7, Z7 + CARRY1() + + // z[1] -> y * x[2] + MOVQ 16(R11), DX + MUL_WORD_N() + SHIFT_ADD_AND(Z4, Z14, Z5, Z8) + SHIFT_ADD_AND(Z5, Z15, Z6, Z8) + SHIFT_ADD_AND(Z6, Z16, Z7, Z8) + VPSRLQ $32, Z7, Z7 + + // Process doubleword 1 of x + VPMULUDQ Z17, Z24, Z10 + VPADDQ Z10, Z0, Z0 + VPMULUDQ Z17, Z25, Z11 + VPADDQ Z11, Z1, Z1 + VPMULUDQ Z17, Z26, Z12 + VPADDQ Z12, Z2, Z2 + VPMULUDQ Z17, Z27, Z13 + VPADDQ Z13, Z3, Z3 + + // z[1] -> y * x[3] + MOVQ 24(R11), DX + MUL_WORD_N() + VPMULUDQ Z17, Z28, Z14 + VPADDQ Z14, Z4, Z4 + VPMULUDQ Z17, Z29, Z15 + VPADDQ Z15, Z5, Z5 + VPMULUDQ Z17, Z30, Z16 + VPADDQ Z16, Z6, Z6 + VPMULUDQ Z17, Z31, Z17 + VPADDQ Z17, Z7, Z7 + VPMULUDQ.BCST qInvNeg+32(FP), Z0, Z9 + + // reduce element(R14,R13,CX,BX) using temp registers (BP,R12,AX,DX) + REDUCE(R14,R13,CX,BX,BP,R12,AX,DX) + + // store output z[1] + MOVQ R14, 32(SI) + MOVQ R13, 40(SI) + MOVQ CX, 48(SI) + MOVQ BX, 56(SI) + ADDQ $32, R11 + MOVQ 0(R11), DX + + // Move high dwords to zmm10-16, add each to the corresponding low dword (propagate 32-bit carries) + VPSRLQ $32, Z0, Z10 + VPANDQ Z8, Z0, Z0 + VPADDQ Z10, Z1, Z1 + VPSRLQ $32, Z1, Z11 + VPANDQ Z8, Z1, Z1 + VPADDQ Z11, Z2, Z2 + VPSRLQ $32, Z2, Z12 + VPANDQ Z8, Z2, Z2 + VPADDQ Z12, Z3, Z3 + VPSRLQ $32, Z3, Z13 + VPANDQ Z8, Z3, Z3 + VPADDQ Z13, Z4, Z4 + CARRY4() + + // z[2] -> y * x[0] + MUL_WORD_0() + AVX_MUL_Q_LO() + AVX_MUL_Q_HI() + + // z[2] -> y * x[1] + MOVQ 8(R11), DX + MUL_WORD_N() + CARRY1() + CARRY2() + + // z[2] -> y * x[2] + MOVQ 16(R11), DX + MUL_WORD_N() + + // Process doubleword 2 of x + VPMULUDQ Z18, Z24, Z10 + VPADDQ Z10, Z0, Z0 + VPMULUDQ Z18, Z25, Z11 + VPADDQ Z11, Z1, Z1 + VPMULUDQ Z18, Z26, Z12 + VPADDQ Z12, Z2, Z2 + VPMULUDQ Z18, Z27, Z13 + VPADDQ Z13, Z3, Z3 + VPMULUDQ Z18, Z28, Z14 + VPADDQ Z14, Z4, Z4 + VPMULUDQ Z18, Z29, Z15 + VPADDQ Z15, Z5, Z5 + VPMULUDQ Z18, Z30, Z16 + VPADDQ Z16, Z6, Z6 + VPMULUDQ Z18, Z31, Z17 + VPADDQ Z17, Z7, Z7 + VPMULUDQ.BCST qInvNeg+32(FP), Z0, Z9 + + // z[2] -> y * x[3] + MOVQ 24(R11), DX + MUL_WORD_N() + + // Move high dwords to zmm10-16, add each to the corresponding low dword (propagate 32-bit carries) + CARRY3() + + // reduce element(R14,R13,CX,BX) using temp registers (BP,R12,AX,DX) + REDUCE(R14,R13,CX,BX,BP,R12,AX,DX) + + // store output z[2] + MOVQ R14, 64(SI) + MOVQ R13, 72(SI) + MOVQ CX, 80(SI) + MOVQ BX, 88(SI) + ADDQ $32, R11 + MOVQ 0(R11), DX + CARRY4() + AVX_MUL_Q_LO() + + // z[3] -> y * x[0] + MUL_WORD_0() + AVX_MUL_Q_HI() + CARRY1() + CARRY2() + + // Process doubleword 3 of x + VPMULUDQ Z19, Z24, Z10 + VPADDQ Z10, Z0, Z0 + VPMULUDQ Z19, Z25, Z11 + VPADDQ Z11, Z1, Z1 + VPMULUDQ Z19, Z26, Z12 + VPADDQ Z12, Z2, Z2 + VPMULUDQ Z19, Z27, Z13 + VPADDQ Z13, Z3, Z3 + + // z[3] -> y * x[1] + MOVQ 8(R11), DX + MUL_WORD_N() + VPMULUDQ Z19, Z28, Z14 + VPADDQ Z14, Z4, Z4 + VPMULUDQ Z19, Z29, Z15 + VPADDQ Z15, Z5, Z5 + VPMULUDQ Z19, Z30, Z16 + VPADDQ Z16, Z6, Z6 + VPMULUDQ Z19, Z31, Z17 + VPADDQ Z17, Z7, Z7 + + // z[3] -> y * x[2] + MOVQ 16(R11), DX + MUL_WORD_N() + VPMULUDQ.BCST qInvNeg+32(FP), Z0, Z9 + CARRY3() + CARRY4() + + // z[3] -> y * x[3] + MOVQ 24(R11), DX + MUL_WORD_N() + AVX_MUL_Q_LO() + AVX_MUL_Q_HI() + + // reduce element(R14,R13,CX,BX) using temp registers (BP,R12,AX,DX) + REDUCE(R14,R13,CX,BX,BP,R12,AX,DX) + + // store output z[3] + MOVQ R14, 96(SI) + MOVQ R13, 104(SI) + MOVQ CX, 112(SI) + MOVQ BX, 120(SI) + ADDQ $32, R11 + MOVQ 0(R11), DX + + // Propagate carries and shift down by one dword + CARRY1() + CARRY2() + + // Process doubleword 4 of x + VPMULUDQ Z20, Z24, Z10 + VPADDQ Z10, Z0, Z0 + VPMULUDQ Z20, Z25, Z11 + VPADDQ Z11, Z1, Z1 + VPMULUDQ Z20, Z26, Z12 + VPADDQ Z12, Z2, Z2 + VPMULUDQ Z20, Z27, Z13 + VPADDQ Z13, Z3, Z3 + + // z[4] -> y * x[0] + MUL_WORD_0() + VPMULUDQ Z20, Z28, Z14 + VPADDQ Z14, Z4, Z4 + VPMULUDQ Z20, Z29, Z15 + VPADDQ Z15, Z5, Z5 + VPMULUDQ Z20, Z30, Z16 + VPADDQ Z16, Z6, Z6 + VPMULUDQ Z20, Z31, Z17 + VPADDQ Z17, Z7, Z7 + VPMULUDQ.BCST qInvNeg+32(FP), Z0, Z9 + + // z[4] -> y * x[1] + MOVQ 8(R11), DX + MUL_WORD_N() + + // Move high dwords to zmm10-16, add each to the corresponding low dword (propagate 32-bit carries) + CARRY3() + CARRY4() + + // z[4] -> y * x[2] + MOVQ 16(R11), DX + MUL_WORD_N() + + // zmm7 keeps all 64 bits + AVX_MUL_Q_LO() + AVX_MUL_Q_HI() + + // z[4] -> y * x[3] + MOVQ 24(R11), DX + MUL_WORD_N() + + // Propagate carries and shift down by one dword + CARRY1() + CARRY2() + + // reduce element(R14,R13,CX,BX) using temp registers (BP,R12,AX,DX) + REDUCE(R14,R13,CX,BX,BP,R12,AX,DX) + + // store output z[4] + MOVQ R14, 128(SI) + MOVQ R13, 136(SI) + MOVQ CX, 144(SI) + MOVQ BX, 152(SI) + ADDQ $32, R11 + MOVQ 0(R11), DX + + // Process doubleword 5 of x + VPMULUDQ Z21, Z24, Z10 + VPADDQ Z10, Z0, Z0 + VPMULUDQ Z21, Z25, Z11 + VPADDQ Z11, Z1, Z1 + VPMULUDQ Z21, Z26, Z12 + VPADDQ Z12, Z2, Z2 + VPMULUDQ Z21, Z27, Z13 + VPADDQ Z13, Z3, Z3 + VPMULUDQ Z21, Z28, Z14 + VPADDQ Z14, Z4, Z4 + VPMULUDQ Z21, Z29, Z15 + VPADDQ Z15, Z5, Z5 + VPMULUDQ Z21, Z30, Z16 + VPADDQ Z16, Z6, Z6 + VPMULUDQ Z21, Z31, Z17 + VPADDQ Z17, Z7, Z7 + + // z[5] -> y * x[0] + MUL_WORD_0() + VPMULUDQ.BCST qInvNeg+32(FP), Z0, Z9 + + // Move high dwords to zmm10-16, add each to the corresponding low dword (propagate 32-bit carries) + CARRY3() + CARRY4() + + // z[5] -> y * x[1] + MOVQ 8(R11), DX + MUL_WORD_N() + AVX_MUL_Q_LO() + AVX_MUL_Q_HI() + + // z[5] -> y * x[2] + MOVQ 16(R11), DX + MUL_WORD_N() + CARRY1() + CARRY2() + + // z[5] -> y * x[3] + MOVQ 24(R11), DX + MUL_WORD_N() + + // Process doubleword 6 of x + VPMULUDQ Z22, Z24, Z10 + VPADDQ Z10, Z0, Z0 + VPMULUDQ Z22, Z25, Z11 + VPADDQ Z11, Z1, Z1 + VPMULUDQ Z22, Z26, Z12 + VPADDQ Z12, Z2, Z2 + VPMULUDQ Z22, Z27, Z13 + VPADDQ Z13, Z3, Z3 + VPMULUDQ Z22, Z28, Z14 + VPADDQ Z14, Z4, Z4 + VPMULUDQ Z22, Z29, Z15 + VPADDQ Z15, Z5, Z5 + VPMULUDQ Z22, Z30, Z16 + VPADDQ Z16, Z6, Z6 + VPMULUDQ Z22, Z31, Z17 + VPADDQ Z17, Z7, Z7 + VPMULUDQ.BCST qInvNeg+32(FP), Z0, Z9 + + // reduce element(R14,R13,CX,BX) using temp registers (BP,R12,AX,DX) + REDUCE(R14,R13,CX,BX,BP,R12,AX,DX) + + // store output z[5] + MOVQ R14, 160(SI) + MOVQ R13, 168(SI) + MOVQ CX, 176(SI) + MOVQ BX, 184(SI) + ADDQ $32, R11 + MOVQ 0(R11), DX + + // Move high dwords to zmm10-16, add each to the corresponding low dword (propagate 32-bit carries) + CARRY3() + CARRY4() + + // z[6] -> y * x[0] + MUL_WORD_0() + AVX_MUL_Q_LO() + AVX_MUL_Q_HI() + + // z[6] -> y * x[1] + MOVQ 8(R11), DX + MUL_WORD_N() + CARRY1() + CARRY2() + + // z[6] -> y * x[2] + MOVQ 16(R11), DX + MUL_WORD_N() + + // Process doubleword 7 of x + VPMULUDQ Z23, Z24, Z10 + VPADDQ Z10, Z0, Z0 + VPMULUDQ Z23, Z25, Z11 + VPADDQ Z11, Z1, Z1 + VPMULUDQ Z23, Z26, Z12 + VPADDQ Z12, Z2, Z2 + VPMULUDQ Z23, Z27, Z13 + VPADDQ Z13, Z3, Z3 + VPMULUDQ Z23, Z28, Z14 + VPADDQ Z14, Z4, Z4 + VPMULUDQ Z23, Z29, Z15 + VPADDQ Z15, Z5, Z5 + VPMULUDQ Z23, Z30, Z16 + VPADDQ Z16, Z6, Z6 + VPMULUDQ Z23, Z31, Z17 + VPADDQ Z17, Z7, Z7 + VPMULUDQ.BCST qInvNeg+32(FP), Z0, Z9 + + // z[6] -> y * x[3] + MOVQ 24(R11), DX + MUL_WORD_N() + CARRY3() + + // reduce element(R14,R13,CX,BX) using temp registers (BP,R12,AX,DX) + REDUCE(R14,R13,CX,BX,BP,R12,AX,DX) + + // store output z[6] + MOVQ R14, 192(SI) + MOVQ R13, 200(SI) + MOVQ CX, 208(SI) + MOVQ BX, 216(SI) + ADDQ $32, R11 + MOVQ 0(R11), DX + CARRY4() + AVX_MUL_Q_LO() + AVX_MUL_Q_HI() + + // z[7] -> y * x[0] + MUL_WORD_0() + CARRY1() + CARRY2() + + // z[7] -> y * x[1] + MOVQ 8(R11), DX + MUL_WORD_N() + + // Conditional subtraction of the modulus + VPERMD.BCST.Z ·qElement+0(SB), Z8, K1, Z10 + VPERMD.BCST.Z ·qElement+4(SB), Z8, K1, Z11 + VPERMD.BCST.Z ·qElement+8(SB), Z8, K1, Z12 + VPERMD.BCST.Z ·qElement+12(SB), Z8, K1, Z13 + VPERMD.BCST.Z ·qElement+16(SB), Z8, K1, Z14 + VPERMD.BCST.Z ·qElement+20(SB), Z8, K1, Z15 + VPERMD.BCST.Z ·qElement+24(SB), Z8, K1, Z16 + VPERMD.BCST.Z ·qElement+28(SB), Z8, K1, Z17 + VPSUBQ Z10, Z0, Z10 + VPSRLQ $63, Z10, Z20 + VPANDQ Z8, Z10, Z10 + VPSUBQ Z11, Z1, Z11 + VPSUBQ Z20, Z11, Z11 + VPSRLQ $63, Z11, Z21 + VPANDQ Z8, Z11, Z11 + VPSUBQ Z12, Z2, Z12 + VPSUBQ Z21, Z12, Z12 + VPSRLQ $63, Z12, Z22 + VPANDQ Z8, Z12, Z12 + VPSUBQ Z13, Z3, Z13 + VPSUBQ Z22, Z13, Z13 + VPSRLQ $63, Z13, Z23 + VPANDQ Z8, Z13, Z13 + VPSUBQ Z14, Z4, Z14 + VPSUBQ Z23, Z14, Z14 + VPSRLQ $63, Z14, Z24 + VPANDQ Z8, Z14, Z14 + VPSUBQ Z15, Z5, Z15 + VPSUBQ Z24, Z15, Z15 + VPSRLQ $63, Z15, Z25 + VPANDQ Z8, Z15, Z15 + VPSUBQ Z16, Z6, Z16 + VPSUBQ Z25, Z16, Z16 + VPSRLQ $63, Z16, Z26 + VPANDQ Z8, Z16, Z16 + VPSUBQ Z17, Z7, Z17 + VPSUBQ Z26, Z17, Z17 + VPMOVQ2M Z17, K2 + KNOTB K2, K2 + VMOVDQU64 Z10, K2, Z0 + VMOVDQU64 Z11, K2, Z1 + VMOVDQU64 Z12, K2, Z2 + VMOVDQU64 Z13, K2, Z3 + VMOVDQU64 Z14, K2, Z4 + + // z[7] -> y * x[2] + MOVQ 16(R11), DX + MUL_WORD_N() + VMOVDQU64 Z15, K2, Z5 + VMOVDQU64 Z16, K2, Z6 + VMOVDQU64 Z17, K2, Z7 + + // Transpose results back + VALIGND $0, ·pattern1+0(SB), Z11, Z11 + VALIGND $0, ·pattern2+0(SB), Z12, Z12 + VALIGND $0, ·pattern3+0(SB), Z13, Z13 + VALIGND $0, ·pattern4+0(SB), Z14, Z14 + VPSLLQ $32, Z1, Z1 + VPORQ Z1, Z0, Z0 + VPSLLQ $32, Z3, Z3 + VPORQ Z3, Z2, Z1 + VPSLLQ $32, Z5, Z5 + VPORQ Z5, Z4, Z2 + VPSLLQ $32, Z7, Z7 + VPORQ Z7, Z6, Z3 + VMOVDQU64 Z0, Z4 + VMOVDQU64 Z2, Z6 + + // z[7] -> y * x[3] + MOVQ 24(R11), DX + MUL_WORD_N() + VPERMT2Q Z1, Z11, Z0 + VPERMT2Q Z4, Z12, Z1 + VPERMT2Q Z3, Z11, Z2 + VPERMT2Q Z6, Z12, Z3 + + // reduce element(R14,R13,CX,BX) using temp registers (BP,R12,AX,DX) + REDUCE(R14,R13,CX,BX,BP,R12,AX,DX) + + // store output z[7] + MOVQ R14, 224(SI) + MOVQ R13, 232(SI) + MOVQ CX, 240(SI) + MOVQ BX, 248(SI) + ADDQ $288, R11 + VMOVDQU64 Z0, Z4 + VMOVDQU64 Z1, Z5 + VPERMT2Q Z2, Z13, Z0 + VPERMT2Q Z4, Z14, Z2 + VPERMT2Q Z3, Z13, Z1 + VPERMT2Q Z5, Z14, Z3 + + // Save AVX-512 results + VMOVDQU64 Z0, 256+0*64(SI) + VMOVDQU64 Z2, 256+1*64(SI) + VMOVDQU64 Z1, 256+2*64(SI) + VMOVDQU64 Z3, 256+3*64(SI) + ADDQ $512, SI + MOVQ s0-8(SP), R12 + DECQ R12 // decrement n + MOVQ R12, s0-8(SP) + JMP loop_16 + +done_15: + RET + +TEXT ·mulVec(SB), $8-40 + // t[0] -> R14 + // t[1] -> R13 + // t[2] -> CX + // t[3] -> BX + // y[0] -> DI + // y[1] -> R8 + // y[2] -> R9 + // y[3] -> R10 + MOVQ res+0(FP), SI + MOVQ a+8(FP), R11 + MOVQ b+16(FP), R15 + MOVQ n+24(FP), R12 + MOVQ R12, s0-8(SP) + + // Create mask for low dword in each qword + VPCMPEQB Y8, Y8, Y8 + VPMOVZXDQ Y8, Z8 + MOVQ $0x5555, DX + KMOVD DX, K1 + +loop_18: + TESTQ R12, R12 + JEQ done_17 // n == 0, we are done + MOVQ 0(R11), DX + VMOVDQU64 256+0*64(R11), Z16 + VMOVDQU64 256+1*64(R11), Z17 + VMOVDQU64 256+2*64(R11), Z18 + VMOVDQU64 256+3*64(R11), Z19 + + // load input y[0] + MOVQ 0(R15), DI + MOVQ 8(R15), R8 + MOVQ 16(R15), R9 + MOVQ 24(R15), R10 + VMOVDQU64 256+0*64(R15), Z24 + VMOVDQU64 256+1*64(R15), Z25 + VMOVDQU64 256+2*64(R15), Z26 + VMOVDQU64 256+3*64(R15), Z27 + + // Transpose and expand x and y + VSHUFI64X2 $0x88, Z17, Z16, Z20 + VSHUFI64X2 $0xdd, Z17, Z16, Z22 + VSHUFI64X2 $0x88, Z19, Z18, Z21 + VSHUFI64X2 $0xdd, Z19, Z18, Z23 + VSHUFI64X2 $0x88, Z25, Z24, Z28 + VSHUFI64X2 $0xdd, Z25, Z24, Z30 + VSHUFI64X2 $0x88, Z27, Z26, Z29 + VSHUFI64X2 $0xdd, Z27, Z26, Z31 + VPERMQ $0xd8, Z20, Z20 + VPERMQ $0xd8, Z21, Z21 + VPERMQ $0xd8, Z22, Z22 + VPERMQ $0xd8, Z23, Z23 + + // z[0] -> y * x[0] + MUL_WORD_0() + VPERMQ $0xd8, Z28, Z28 + VPERMQ $0xd8, Z29, Z29 + VPERMQ $0xd8, Z30, Z30 + VPERMQ $0xd8, Z31, Z31 + VSHUFI64X2 $0xd8, Z20, Z20, Z20 + VSHUFI64X2 $0xd8, Z21, Z21, Z21 + VSHUFI64X2 $0xd8, Z22, Z22, Z22 + VSHUFI64X2 $0xd8, Z23, Z23, Z23 + + // z[0] -> y * x[1] + MOVQ 8(R11), DX + MUL_WORD_N() + VSHUFI64X2 $0xd8, Z28, Z28, Z28 + VSHUFI64X2 $0xd8, Z29, Z29, Z29 + VSHUFI64X2 $0xd8, Z30, Z30, Z30 + VSHUFI64X2 $0xd8, Z31, Z31, Z31 + VSHUFI64X2 $0x44, Z21, Z20, Z16 + VSHUFI64X2 $0xee, Z21, Z20, Z18 + VSHUFI64X2 $0x44, Z23, Z22, Z20 + VSHUFI64X2 $0xee, Z23, Z22, Z22 + + // z[0] -> y * x[2] + MOVQ 16(R11), DX + MUL_WORD_N() + VSHUFI64X2 $0x44, Z29, Z28, Z24 + VSHUFI64X2 $0xee, Z29, Z28, Z26 + VSHUFI64X2 $0x44, Z31, Z30, Z28 + VSHUFI64X2 $0xee, Z31, Z30, Z30 + PREFETCHT0 1024(R11) + VPSRLQ $32, Z16, Z17 + VPSRLQ $32, Z18, Z19 + VPSRLQ $32, Z20, Z21 + VPSRLQ $32, Z22, Z23 + VPSRLQ $32, Z24, Z25 + VPSRLQ $32, Z26, Z27 + VPSRLQ $32, Z28, Z29 + VPSRLQ $32, Z30, Z31 + + // z[0] -> y * x[3] + MOVQ 24(R11), DX + MUL_WORD_N() + VPANDQ Z8, Z16, Z16 + VPANDQ Z8, Z18, Z18 + VPANDQ Z8, Z20, Z20 + VPANDQ Z8, Z22, Z22 + VPANDQ Z8, Z24, Z24 + VPANDQ Z8, Z26, Z26 + VPANDQ Z8, Z28, Z28 + VPANDQ Z8, Z30, Z30 + + // reduce element(R14,R13,CX,BX) using temp registers (BP,R12,AX,DX) + REDUCE(R14,R13,CX,BX,BP,R12,AX,DX) + + // store output z[0] + MOVQ R14, 0(SI) + MOVQ R13, 8(SI) + MOVQ CX, 16(SI) + MOVQ BX, 24(SI) + ADDQ $32, R11 + MOVQ 0(R11), DX + + // For each 256-bit input value, each zmm register now represents a 32-bit input word zero-extended to 64 bits. + // Multiply y by doubleword 0 of x + VPMULUDQ Z16, Z24, Z0 + VPMULUDQ Z16, Z25, Z1 + VPMULUDQ Z16, Z26, Z2 + VPMULUDQ Z16, Z27, Z3 + VPMULUDQ Z16, Z28, Z4 + PREFETCHT0 1024(R15) + VPMULUDQ Z16, Z29, Z5 + VPMULUDQ Z16, Z30, Z6 + VPMULUDQ Z16, Z31, Z7 + + // load input y[1] + MOVQ 32(R15), DI + MOVQ 40(R15), R8 + MOVQ 48(R15), R9 + MOVQ 56(R15), R10 + VPMULUDQ.BCST qInvNeg+32(FP), Z0, Z9 + VPSRLQ $32, Z0, Z10 + VPANDQ Z8, Z0, Z0 + VPADDQ Z10, Z1, Z1 + VPSRLQ $32, Z1, Z11 + VPANDQ Z8, Z1, Z1 + VPADDQ Z11, Z2, Z2 + VPSRLQ $32, Z2, Z12 + VPANDQ Z8, Z2, Z2 + VPADDQ Z12, Z3, Z3 + VPSRLQ $32, Z3, Z13 + VPANDQ Z8, Z3, Z3 + VPADDQ Z13, Z4, Z4 + + // z[1] -> y * x[0] + MUL_WORD_0() + VPSRLQ $32, Z4, Z14 + VPANDQ Z8, Z4, Z4 + VPADDQ Z14, Z5, Z5 + VPSRLQ $32, Z5, Z15 + VPANDQ Z8, Z5, Z5 + VPADDQ Z15, Z6, Z6 + VPSRLQ $32, Z6, Z16 + VPANDQ Z8, Z6, Z6 + VPADDQ Z16, Z7, Z7 + VPMULUDQ.BCST ·qElement+0(SB), Z9, Z10 + VPADDQ Z10, Z0, Z0 + VPMULUDQ.BCST ·qElement+4(SB), Z9, Z11 + VPADDQ Z11, Z1, Z1 + VPMULUDQ.BCST ·qElement+8(SB), Z9, Z12 + VPADDQ Z12, Z2, Z2 + VPMULUDQ.BCST ·qElement+12(SB), Z9, Z13 + VPADDQ Z13, Z3, Z3 + + // z[1] -> y * x[1] + MOVQ 8(R11), DX + MUL_WORD_N() + VPMULUDQ.BCST ·qElement+16(SB), Z9, Z14 + VPADDQ Z14, Z4, Z4 + VPMULUDQ.BCST ·qElement+20(SB), Z9, Z15 + VPADDQ Z15, Z5, Z5 + VPMULUDQ.BCST ·qElement+24(SB), Z9, Z16 + VPADDQ Z16, Z6, Z6 + VPMULUDQ.BCST ·qElement+28(SB), Z9, Z10 + VPADDQ Z10, Z7, Z7 + CARRY1() + + // z[1] -> y * x[2] + MOVQ 16(R11), DX + MUL_WORD_N() + SHIFT_ADD_AND(Z4, Z14, Z5, Z8) + SHIFT_ADD_AND(Z5, Z15, Z6, Z8) + SHIFT_ADD_AND(Z6, Z16, Z7, Z8) + VPSRLQ $32, Z7, Z7 + + // Process doubleword 1 of x + VPMULUDQ Z17, Z24, Z10 + VPADDQ Z10, Z0, Z0 + VPMULUDQ Z17, Z25, Z11 + VPADDQ Z11, Z1, Z1 + VPMULUDQ Z17, Z26, Z12 + VPADDQ Z12, Z2, Z2 + VPMULUDQ Z17, Z27, Z13 + VPADDQ Z13, Z3, Z3 + + // z[1] -> y * x[3] + MOVQ 24(R11), DX + MUL_WORD_N() + VPMULUDQ Z17, Z28, Z14 + VPADDQ Z14, Z4, Z4 + VPMULUDQ Z17, Z29, Z15 + VPADDQ Z15, Z5, Z5 + VPMULUDQ Z17, Z30, Z16 + VPADDQ Z16, Z6, Z6 + VPMULUDQ Z17, Z31, Z17 + VPADDQ Z17, Z7, Z7 + VPMULUDQ.BCST qInvNeg+32(FP), Z0, Z9 + + // reduce element(R14,R13,CX,BX) using temp registers (BP,R12,AX,DX) + REDUCE(R14,R13,CX,BX,BP,R12,AX,DX) + + // store output z[1] + MOVQ R14, 32(SI) + MOVQ R13, 40(SI) + MOVQ CX, 48(SI) + MOVQ BX, 56(SI) + ADDQ $32, R11 + MOVQ 0(R11), DX + + // Move high dwords to zmm10-16, add each to the corresponding low dword (propagate 32-bit carries) + VPSRLQ $32, Z0, Z10 + VPANDQ Z8, Z0, Z0 + VPADDQ Z10, Z1, Z1 + VPSRLQ $32, Z1, Z11 + VPANDQ Z8, Z1, Z1 + VPADDQ Z11, Z2, Z2 + VPSRLQ $32, Z2, Z12 + VPANDQ Z8, Z2, Z2 + VPADDQ Z12, Z3, Z3 + + // load input y[2] + MOVQ 64(R15), DI + MOVQ 72(R15), R8 + MOVQ 80(R15), R9 + MOVQ 88(R15), R10 + VPSRLQ $32, Z3, Z13 + VPANDQ Z8, Z3, Z3 + VPADDQ Z13, Z4, Z4 + CARRY4() + + // z[2] -> y * x[0] + MUL_WORD_0() + AVX_MUL_Q_LO() + AVX_MUL_Q_HI() + + // z[2] -> y * x[1] + MOVQ 8(R11), DX + MUL_WORD_N() + CARRY1() + CARRY2() + + // z[2] -> y * x[2] + MOVQ 16(R11), DX + MUL_WORD_N() + + // Process doubleword 2 of x + VPMULUDQ Z18, Z24, Z10 + VPADDQ Z10, Z0, Z0 + VPMULUDQ Z18, Z25, Z11 + VPADDQ Z11, Z1, Z1 + VPMULUDQ Z18, Z26, Z12 + VPADDQ Z12, Z2, Z2 + VPMULUDQ Z18, Z27, Z13 + VPADDQ Z13, Z3, Z3 + VPMULUDQ Z18, Z28, Z14 + VPADDQ Z14, Z4, Z4 + VPMULUDQ Z18, Z29, Z15 + VPADDQ Z15, Z5, Z5 + VPMULUDQ Z18, Z30, Z16 + VPADDQ Z16, Z6, Z6 + VPMULUDQ Z18, Z31, Z17 + VPADDQ Z17, Z7, Z7 + VPMULUDQ.BCST qInvNeg+32(FP), Z0, Z9 + + // z[2] -> y * x[3] + MOVQ 24(R11), DX + MUL_WORD_N() + + // Move high dwords to zmm10-16, add each to the corresponding low dword (propagate 32-bit carries) + CARRY3() + + // reduce element(R14,R13,CX,BX) using temp registers (BP,R12,AX,DX) + REDUCE(R14,R13,CX,BX,BP,R12,AX,DX) + + // store output z[2] + MOVQ R14, 64(SI) + MOVQ R13, 72(SI) + MOVQ CX, 80(SI) + MOVQ BX, 88(SI) + ADDQ $32, R11 + MOVQ 0(R11), DX + + // load input y[3] + MOVQ 96(R15), DI + MOVQ 104(R15), R8 + MOVQ 112(R15), R9 + MOVQ 120(R15), R10 + CARRY4() + AVX_MUL_Q_LO() + + // z[3] -> y * x[0] + MUL_WORD_0() + AVX_MUL_Q_HI() + CARRY1() + CARRY2() + + // Process doubleword 3 of x + VPMULUDQ Z19, Z24, Z10 + VPADDQ Z10, Z0, Z0 + VPMULUDQ Z19, Z25, Z11 + VPADDQ Z11, Z1, Z1 + VPMULUDQ Z19, Z26, Z12 + VPADDQ Z12, Z2, Z2 + VPMULUDQ Z19, Z27, Z13 + VPADDQ Z13, Z3, Z3 + + // z[3] -> y * x[1] + MOVQ 8(R11), DX + MUL_WORD_N() + VPMULUDQ Z19, Z28, Z14 + VPADDQ Z14, Z4, Z4 + VPMULUDQ Z19, Z29, Z15 + VPADDQ Z15, Z5, Z5 + VPMULUDQ Z19, Z30, Z16 + VPADDQ Z16, Z6, Z6 + VPMULUDQ Z19, Z31, Z17 + VPADDQ Z17, Z7, Z7 + + // z[3] -> y * x[2] + MOVQ 16(R11), DX + MUL_WORD_N() + VPMULUDQ.BCST qInvNeg+32(FP), Z0, Z9 + CARRY3() + CARRY4() + + // z[3] -> y * x[3] + MOVQ 24(R11), DX + MUL_WORD_N() + AVX_MUL_Q_LO() + AVX_MUL_Q_HI() + + // reduce element(R14,R13,CX,BX) using temp registers (BP,R12,AX,DX) + REDUCE(R14,R13,CX,BX,BP,R12,AX,DX) + + // store output z[3] + MOVQ R14, 96(SI) + MOVQ R13, 104(SI) + MOVQ CX, 112(SI) + MOVQ BX, 120(SI) + ADDQ $32, R11 + MOVQ 0(R11), DX + + // Propagate carries and shift down by one dword + CARRY1() + CARRY2() + + // load input y[4] + MOVQ 128(R15), DI + MOVQ 136(R15), R8 + MOVQ 144(R15), R9 + MOVQ 152(R15), R10 + + // Process doubleword 4 of x + VPMULUDQ Z20, Z24, Z10 + VPADDQ Z10, Z0, Z0 + VPMULUDQ Z20, Z25, Z11 + VPADDQ Z11, Z1, Z1 + VPMULUDQ Z20, Z26, Z12 + VPADDQ Z12, Z2, Z2 + VPMULUDQ Z20, Z27, Z13 + VPADDQ Z13, Z3, Z3 + + // z[4] -> y * x[0] + MUL_WORD_0() + VPMULUDQ Z20, Z28, Z14 + VPADDQ Z14, Z4, Z4 + VPMULUDQ Z20, Z29, Z15 + VPADDQ Z15, Z5, Z5 + VPMULUDQ Z20, Z30, Z16 + VPADDQ Z16, Z6, Z6 + VPMULUDQ Z20, Z31, Z17 + VPADDQ Z17, Z7, Z7 + VPMULUDQ.BCST qInvNeg+32(FP), Z0, Z9 + + // z[4] -> y * x[1] + MOVQ 8(R11), DX + MUL_WORD_N() + + // Move high dwords to zmm10-16, add each to the corresponding low dword (propagate 32-bit carries) + CARRY3() + CARRY4() + + // z[4] -> y * x[2] + MOVQ 16(R11), DX + MUL_WORD_N() + + // zmm7 keeps all 64 bits + AVX_MUL_Q_LO() + AVX_MUL_Q_HI() + + // z[4] -> y * x[3] + MOVQ 24(R11), DX + MUL_WORD_N() + + // Propagate carries and shift down by one dword + CARRY1() + CARRY2() + + // reduce element(R14,R13,CX,BX) using temp registers (BP,R12,AX,DX) + REDUCE(R14,R13,CX,BX,BP,R12,AX,DX) + + // store output z[4] + MOVQ R14, 128(SI) + MOVQ R13, 136(SI) + MOVQ CX, 144(SI) + MOVQ BX, 152(SI) + ADDQ $32, R11 + MOVQ 0(R11), DX + + // Process doubleword 5 of x + VPMULUDQ Z21, Z24, Z10 + VPADDQ Z10, Z0, Z0 + VPMULUDQ Z21, Z25, Z11 + VPADDQ Z11, Z1, Z1 + VPMULUDQ Z21, Z26, Z12 + VPADDQ Z12, Z2, Z2 + VPMULUDQ Z21, Z27, Z13 + VPADDQ Z13, Z3, Z3 + + // load input y[5] + MOVQ 160(R15), DI + MOVQ 168(R15), R8 + MOVQ 176(R15), R9 + MOVQ 184(R15), R10 + VPMULUDQ Z21, Z28, Z14 + VPADDQ Z14, Z4, Z4 + VPMULUDQ Z21, Z29, Z15 + VPADDQ Z15, Z5, Z5 + VPMULUDQ Z21, Z30, Z16 + VPADDQ Z16, Z6, Z6 + VPMULUDQ Z21, Z31, Z17 + VPADDQ Z17, Z7, Z7 + + // z[5] -> y * x[0] + MUL_WORD_0() + VPMULUDQ.BCST qInvNeg+32(FP), Z0, Z9 + + // Move high dwords to zmm10-16, add each to the corresponding low dword (propagate 32-bit carries) + CARRY3() + CARRY4() + + // z[5] -> y * x[1] + MOVQ 8(R11), DX + MUL_WORD_N() + AVX_MUL_Q_LO() + AVX_MUL_Q_HI() + + // z[5] -> y * x[2] + MOVQ 16(R11), DX + MUL_WORD_N() + CARRY1() + CARRY2() + + // z[5] -> y * x[3] + MOVQ 24(R11), DX + MUL_WORD_N() + + // Process doubleword 6 of x + VPMULUDQ Z22, Z24, Z10 + VPADDQ Z10, Z0, Z0 + VPMULUDQ Z22, Z25, Z11 + VPADDQ Z11, Z1, Z1 + VPMULUDQ Z22, Z26, Z12 + VPADDQ Z12, Z2, Z2 + VPMULUDQ Z22, Z27, Z13 + VPADDQ Z13, Z3, Z3 + VPMULUDQ Z22, Z28, Z14 + VPADDQ Z14, Z4, Z4 + VPMULUDQ Z22, Z29, Z15 + VPADDQ Z15, Z5, Z5 + VPMULUDQ Z22, Z30, Z16 + VPADDQ Z16, Z6, Z6 + VPMULUDQ Z22, Z31, Z17 + VPADDQ Z17, Z7, Z7 + VPMULUDQ.BCST qInvNeg+32(FP), Z0, Z9 + + // reduce element(R14,R13,CX,BX) using temp registers (BP,R12,AX,DX) + REDUCE(R14,R13,CX,BX,BP,R12,AX,DX) + + // store output z[5] + MOVQ R14, 160(SI) + MOVQ R13, 168(SI) + MOVQ CX, 176(SI) + MOVQ BX, 184(SI) + ADDQ $32, R11 + MOVQ 0(R11), DX + + // Move high dwords to zmm10-16, add each to the corresponding low dword (propagate 32-bit carries) + CARRY3() + + // load input y[6] + MOVQ 192(R15), DI + MOVQ 200(R15), R8 + MOVQ 208(R15), R9 + MOVQ 216(R15), R10 + CARRY4() + + // z[6] -> y * x[0] + MUL_WORD_0() + AVX_MUL_Q_LO() + AVX_MUL_Q_HI() + + // z[6] -> y * x[1] + MOVQ 8(R11), DX + MUL_WORD_N() + CARRY1() + CARRY2() + + // z[6] -> y * x[2] + MOVQ 16(R11), DX + MUL_WORD_N() + + // Process doubleword 7 of x + VPMULUDQ Z23, Z24, Z10 + VPADDQ Z10, Z0, Z0 + VPMULUDQ Z23, Z25, Z11 + VPADDQ Z11, Z1, Z1 + VPMULUDQ Z23, Z26, Z12 + VPADDQ Z12, Z2, Z2 + VPMULUDQ Z23, Z27, Z13 + VPADDQ Z13, Z3, Z3 + VPMULUDQ Z23, Z28, Z14 + VPADDQ Z14, Z4, Z4 + VPMULUDQ Z23, Z29, Z15 + VPADDQ Z15, Z5, Z5 + VPMULUDQ Z23, Z30, Z16 + VPADDQ Z16, Z6, Z6 + VPMULUDQ Z23, Z31, Z17 + VPADDQ Z17, Z7, Z7 + VPMULUDQ.BCST qInvNeg+32(FP), Z0, Z9 + + // z[6] -> y * x[3] + MOVQ 24(R11), DX + MUL_WORD_N() + CARRY3() + + // reduce element(R14,R13,CX,BX) using temp registers (BP,R12,AX,DX) + REDUCE(R14,R13,CX,BX,BP,R12,AX,DX) + + // store output z[6] + MOVQ R14, 192(SI) + MOVQ R13, 200(SI) + MOVQ CX, 208(SI) + MOVQ BX, 216(SI) + ADDQ $32, R11 + MOVQ 0(R11), DX + CARRY4() + + // load input y[7] + MOVQ 224(R15), DI + MOVQ 232(R15), R8 + MOVQ 240(R15), R9 + MOVQ 248(R15), R10 + AVX_MUL_Q_LO() + AVX_MUL_Q_HI() + + // z[7] -> y * x[0] + MUL_WORD_0() + CARRY1() + CARRY2() + + // z[7] -> y * x[1] + MOVQ 8(R11), DX + MUL_WORD_N() + + // Conditional subtraction of the modulus + VPERMD.BCST.Z ·qElement+0(SB), Z8, K1, Z10 + VPERMD.BCST.Z ·qElement+4(SB), Z8, K1, Z11 + VPERMD.BCST.Z ·qElement+8(SB), Z8, K1, Z12 + VPERMD.BCST.Z ·qElement+12(SB), Z8, K1, Z13 + VPERMD.BCST.Z ·qElement+16(SB), Z8, K1, Z14 + VPERMD.BCST.Z ·qElement+20(SB), Z8, K1, Z15 + VPERMD.BCST.Z ·qElement+24(SB), Z8, K1, Z16 + VPERMD.BCST.Z ·qElement+28(SB), Z8, K1, Z17 + VPSUBQ Z10, Z0, Z10 + VPSRLQ $63, Z10, Z20 + VPANDQ Z8, Z10, Z10 + VPSUBQ Z11, Z1, Z11 + VPSUBQ Z20, Z11, Z11 + VPSRLQ $63, Z11, Z21 + VPANDQ Z8, Z11, Z11 + VPSUBQ Z12, Z2, Z12 + VPSUBQ Z21, Z12, Z12 + VPSRLQ $63, Z12, Z22 + VPANDQ Z8, Z12, Z12 + VPSUBQ Z13, Z3, Z13 + VPSUBQ Z22, Z13, Z13 + VPSRLQ $63, Z13, Z23 + VPANDQ Z8, Z13, Z13 + VPSUBQ Z14, Z4, Z14 + VPSUBQ Z23, Z14, Z14 + VPSRLQ $63, Z14, Z24 + VPANDQ Z8, Z14, Z14 + VPSUBQ Z15, Z5, Z15 + VPSUBQ Z24, Z15, Z15 + VPSRLQ $63, Z15, Z25 + VPANDQ Z8, Z15, Z15 + VPSUBQ Z16, Z6, Z16 + VPSUBQ Z25, Z16, Z16 + VPSRLQ $63, Z16, Z26 + VPANDQ Z8, Z16, Z16 + VPSUBQ Z17, Z7, Z17 + VPSUBQ Z26, Z17, Z17 + VPMOVQ2M Z17, K2 + KNOTB K2, K2 + VMOVDQU64 Z10, K2, Z0 + VMOVDQU64 Z11, K2, Z1 + VMOVDQU64 Z12, K2, Z2 + VMOVDQU64 Z13, K2, Z3 + VMOVDQU64 Z14, K2, Z4 + + // z[7] -> y * x[2] + MOVQ 16(R11), DX + MUL_WORD_N() + VMOVDQU64 Z15, K2, Z5 + VMOVDQU64 Z16, K2, Z6 + VMOVDQU64 Z17, K2, Z7 + + // Transpose results back + VALIGND $0, ·pattern1+0(SB), Z11, Z11 + VALIGND $0, ·pattern2+0(SB), Z12, Z12 + VALIGND $0, ·pattern3+0(SB), Z13, Z13 + VALIGND $0, ·pattern4+0(SB), Z14, Z14 + VPSLLQ $32, Z1, Z1 + VPORQ Z1, Z0, Z0 + VPSLLQ $32, Z3, Z3 + VPORQ Z3, Z2, Z1 + VPSLLQ $32, Z5, Z5 + VPORQ Z5, Z4, Z2 + VPSLLQ $32, Z7, Z7 + VPORQ Z7, Z6, Z3 + VMOVDQU64 Z0, Z4 + VMOVDQU64 Z2, Z6 + + // z[7] -> y * x[3] + MOVQ 24(R11), DX + MUL_WORD_N() + VPERMT2Q Z1, Z11, Z0 + VPERMT2Q Z4, Z12, Z1 + VPERMT2Q Z3, Z11, Z2 + VPERMT2Q Z6, Z12, Z3 + + // reduce element(R14,R13,CX,BX) using temp registers (BP,R12,AX,DX) + REDUCE(R14,R13,CX,BX,BP,R12,AX,DX) + + // store output z[7] + MOVQ R14, 224(SI) + MOVQ R13, 232(SI) + MOVQ CX, 240(SI) + MOVQ BX, 248(SI) + ADDQ $288, R11 + VMOVDQU64 Z0, Z4 + VMOVDQU64 Z1, Z5 + VPERMT2Q Z2, Z13, Z0 + VPERMT2Q Z4, Z14, Z2 + VPERMT2Q Z3, Z13, Z1 + VPERMT2Q Z5, Z14, Z3 + + // Save AVX-512 results + VMOVDQU64 Z0, 256+0*64(SI) + VMOVDQU64 Z2, 256+1*64(SI) + VMOVDQU64 Z1, 256+2*64(SI) + VMOVDQU64 Z3, 256+3*64(SI) + ADDQ $512, SI + ADDQ $512, R15 + MOVQ s0-8(SP), R12 + DECQ R12 // decrement n + MOVQ R12, s0-8(SP) + JMP loop_18 + +done_17: + RET diff --git a/vendor/github.com/consensys/gnark-crypto/field/asm/element_4w/element_4w_arm64.s b/vendor/github.com/consensys/gnark-crypto/field/asm/element_4w/element_4w_arm64.s new file mode 100644 index 00000000000..fce96e30006 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/field/asm/element_4w/element_4w_arm64.s @@ -0,0 +1,163 @@ +// Code generated by gnark-crypto/generator. DO NOT EDIT. +#include "textflag.h" +#include "funcdata.h" +#include "go_asm.h" + +// butterfly(a, b *Element) +// a, b = a+b, a-b +TEXT ·Butterfly(SB), NOFRAME|NOSPLIT, $0-16 + LDP x+0(FP), (R16, R17) + LDP 0(R16), (R0, R1) + LDP 16(R16), (R2, R3) + LDP 0(R17), (R4, R5) + LDP 16(R17), (R6, R7) + ADDS R0, R4, R8 + ADCS R1, R5, R9 + ADCS R2, R6, R10 + ADC R3, R7, R11 + SUBS R4, R0, R4 + SBCS R5, R1, R5 + SBCS R6, R2, R6 + SBCS R7, R3, R7 + LDP ·qElement+0(SB), (R0, R1) + CSEL CS, ZR, R0, R12 + CSEL CS, ZR, R1, R13 + LDP ·qElement+16(SB), (R2, R3) + CSEL CS, ZR, R2, R14 + CSEL CS, ZR, R3, R15 + + // add q if underflow, 0 if not + ADDS R4, R12, R4 + ADCS R5, R13, R5 + STP (R4, R5), 0(R17) + ADCS R6, R14, R6 + ADC R7, R15, R7 + STP (R6, R7), 16(R17) + + // q = t - q + SUBS R0, R8, R0 + SBCS R1, R9, R1 + SBCS R2, R10, R2 + SBCS R3, R11, R3 + + // if no borrow, return q, else return t + CSEL CS, R0, R8, R8 + CSEL CS, R1, R9, R9 + STP (R8, R9), 0(R16) + CSEL CS, R2, R10, R10 + CSEL CS, R3, R11, R11 + STP (R10, R11), 16(R16) + RET + +// mul(res, x, y *Element) +// Algorithm 2 of Faster Montgomery Multiplication and Multi-Scalar-Multiplication for SNARKS +// by Y. El Housni and G. Botrel https://doi.org/10.46586/tches.v2023.i3.504-521 +TEXT ·mul(SB), NOFRAME|NOSPLIT, $0-24 +#define DIVSHIFT() \ + MUL R13, R12, R0 \ + ADDS R0, R6, R6 \ + MUL R14, R12, R0 \ + ADCS R0, R7, R7 \ + MUL R15, R12, R0 \ + ADCS R0, R8, R8 \ + MUL R16, R12, R0 \ + ADCS R0, R9, R9 \ + ADC R10, ZR, R10 \ + UMULH R13, R12, R0 \ + ADDS R0, R7, R6 \ + UMULH R14, R12, R0 \ + ADCS R0, R8, R7 \ + UMULH R15, R12, R0 \ + ADCS R0, R9, R8 \ + UMULH R16, R12, R0 \ + ADCS R0, R10, R9 \ + +#define MUL_WORD_N() \ + MUL R2, R1, R0 \ + ADDS R0, R6, R6 \ + MUL R6, R11, R12 \ + MUL R3, R1, R0 \ + ADCS R0, R7, R7 \ + MUL R4, R1, R0 \ + ADCS R0, R8, R8 \ + MUL R5, R1, R0 \ + ADCS R0, R9, R9 \ + ADC ZR, ZR, R10 \ + UMULH R2, R1, R0 \ + ADDS R0, R7, R7 \ + UMULH R3, R1, R0 \ + ADCS R0, R8, R8 \ + UMULH R4, R1, R0 \ + ADCS R0, R9, R9 \ + UMULH R5, R1, R0 \ + ADC R0, R10, R10 \ + DIVSHIFT() \ + +#define MUL_WORD_0() \ + MUL R2, R1, R6 \ + MUL R3, R1, R7 \ + MUL R4, R1, R8 \ + MUL R5, R1, R9 \ + UMULH R2, R1, R0 \ + ADDS R0, R7, R7 \ + UMULH R3, R1, R0 \ + ADCS R0, R8, R8 \ + UMULH R4, R1, R0 \ + ADCS R0, R9, R9 \ + UMULH R5, R1, R0 \ + ADC R0, ZR, R10 \ + MUL R6, R11, R12 \ + DIVSHIFT() \ + + MOVD y+16(FP), R17 + MOVD x+8(FP), R0 + LDP 0(R0), (R2, R3) + LDP 16(R0), (R4, R5) + MOVD 0(R17), R1 + MOVD $const_qInvNeg, R11 + LDP ·qElement+0(SB), (R13, R14) + LDP ·qElement+16(SB), (R15, R16) + MUL_WORD_0() + MOVD 8(R17), R1 + MUL_WORD_N() + MOVD 16(R17), R1 + MUL_WORD_N() + MOVD 24(R17), R1 + MUL_WORD_N() + + // reduce if necessary + SUBS R13, R6, R13 + SBCS R14, R7, R14 + SBCS R15, R8, R15 + SBCS R16, R9, R16 + MOVD res+0(FP), R0 + CSEL CS, R13, R6, R6 + CSEL CS, R14, R7, R7 + STP (R6, R7), 0(R0) + CSEL CS, R15, R8, R8 + CSEL CS, R16, R9, R9 + STP (R8, R9), 16(R0) + RET + +// reduce(res *Element) +TEXT ·reduce(SB), NOFRAME|NOSPLIT, $0-8 + LDP ·qElement+0(SB), (R4, R5) + LDP ·qElement+16(SB), (R6, R7) + MOVD res+0(FP), R8 + LDP 0(R8), (R0, R1) + LDP 16(R8), (R2, R3) + + // q = t - q + SUBS R4, R0, R4 + SBCS R5, R1, R5 + SBCS R6, R2, R6 + SBCS R7, R3, R7 + + // if no borrow, return q, else return t + CSEL CS, R4, R0, R0 + CSEL CS, R5, R1, R1 + STP (R0, R1), 0(R8) + CSEL CS, R6, R2, R2 + CSEL CS, R7, R3, R3 + STP (R2, R3), 16(R8) + RET diff --git a/vendor/github.com/consensys/gnark-crypto/field/asm/element_6w/asm.go b/vendor/github.com/consensys/gnark-crypto/field/asm/element_6w/asm.go new file mode 100644 index 00000000000..ab349840438 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/field/asm/element_6w/asm.go @@ -0,0 +1,14 @@ +// Package asm is a workaround to force go mod vendor to include the asm files +// see https://github.com/Consensys/gnark-crypto/issues/619 +package asm + +const DUMMY = 0 +const qInvNeg = 0 +const mu = 0 +const q = 0 +const q0 = 0 +const q1 = 0 +const q2 = 0 +const q3 = 0 +const q4 = 0 +const q5 = 0 diff --git a/vendor/github.com/consensys/gnark-crypto/field/asm/element_6w/element_6w_amd64.s b/vendor/github.com/consensys/gnark-crypto/field/asm/element_6w/element_6w_amd64.s new file mode 100644 index 00000000000..1b4f66c04f2 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/field/asm/element_6w/element_6w_amd64.s @@ -0,0 +1,670 @@ +// Code generated by gnark-crypto/generator. DO NOT EDIT. +#include "textflag.h" +#include "funcdata.h" +#include "go_asm.h" + +#define REDUCE(ra0, ra1, ra2, ra3, ra4, ra5, rb0, rb1, rb2, rb3, rb4, rb5) \ + MOVQ ra0, rb0; \ + SUBQ ·qElement(SB), ra0; \ + MOVQ ra1, rb1; \ + SBBQ ·qElement+8(SB), ra1; \ + MOVQ ra2, rb2; \ + SBBQ ·qElement+16(SB), ra2; \ + MOVQ ra3, rb3; \ + SBBQ ·qElement+24(SB), ra3; \ + MOVQ ra4, rb4; \ + SBBQ ·qElement+32(SB), ra4; \ + MOVQ ra5, rb5; \ + SBBQ ·qElement+40(SB), ra5; \ + CMOVQCS rb0, ra0; \ + CMOVQCS rb1, ra1; \ + CMOVQCS rb2, ra2; \ + CMOVQCS rb3, ra3; \ + CMOVQCS rb4, ra4; \ + CMOVQCS rb5, ra5; \ + +TEXT ·reduce(SB), NOSPLIT, $0-8 + MOVQ res+0(FP), AX + MOVQ 0(AX), DX + MOVQ 8(AX), CX + MOVQ 16(AX), BX + MOVQ 24(AX), SI + MOVQ 32(AX), DI + MOVQ 40(AX), R8 + + // reduce element(DX,CX,BX,SI,DI,R8) using temp registers (R9,R10,R11,R12,R13,R14) + REDUCE(DX,CX,BX,SI,DI,R8,R9,R10,R11,R12,R13,R14) + + MOVQ DX, 0(AX) + MOVQ CX, 8(AX) + MOVQ BX, 16(AX) + MOVQ SI, 24(AX) + MOVQ DI, 32(AX) + MOVQ R8, 40(AX) + RET + +// MulBy3(x *Element) +TEXT ·MulBy3(SB), NOSPLIT, $0-8 + MOVQ x+0(FP), AX + MOVQ 0(AX), DX + MOVQ 8(AX), CX + MOVQ 16(AX), BX + MOVQ 24(AX), SI + MOVQ 32(AX), DI + MOVQ 40(AX), R8 + ADDQ DX, DX + ADCQ CX, CX + ADCQ BX, BX + ADCQ SI, SI + ADCQ DI, DI + ADCQ R8, R8 + + // reduce element(DX,CX,BX,SI,DI,R8) using temp registers (R9,R10,R11,R12,R13,R14) + REDUCE(DX,CX,BX,SI,DI,R8,R9,R10,R11,R12,R13,R14) + + ADDQ 0(AX), DX + ADCQ 8(AX), CX + ADCQ 16(AX), BX + ADCQ 24(AX), SI + ADCQ 32(AX), DI + ADCQ 40(AX), R8 + + // reduce element(DX,CX,BX,SI,DI,R8) using temp registers (R15,R9,R10,R11,R12,R13) + REDUCE(DX,CX,BX,SI,DI,R8,R15,R9,R10,R11,R12,R13) + + MOVQ DX, 0(AX) + MOVQ CX, 8(AX) + MOVQ BX, 16(AX) + MOVQ SI, 24(AX) + MOVQ DI, 32(AX) + MOVQ R8, 40(AX) + RET + +// MulBy5(x *Element) +TEXT ·MulBy5(SB), NOSPLIT, $0-8 + MOVQ x+0(FP), AX + MOVQ 0(AX), DX + MOVQ 8(AX), CX + MOVQ 16(AX), BX + MOVQ 24(AX), SI + MOVQ 32(AX), DI + MOVQ 40(AX), R8 + ADDQ DX, DX + ADCQ CX, CX + ADCQ BX, BX + ADCQ SI, SI + ADCQ DI, DI + ADCQ R8, R8 + + // reduce element(DX,CX,BX,SI,DI,R8) using temp registers (R9,R10,R11,R12,R13,R14) + REDUCE(DX,CX,BX,SI,DI,R8,R9,R10,R11,R12,R13,R14) + + ADDQ DX, DX + ADCQ CX, CX + ADCQ BX, BX + ADCQ SI, SI + ADCQ DI, DI + ADCQ R8, R8 + + // reduce element(DX,CX,BX,SI,DI,R8) using temp registers (R15,R9,R10,R11,R12,R13) + REDUCE(DX,CX,BX,SI,DI,R8,R15,R9,R10,R11,R12,R13) + + ADDQ 0(AX), DX + ADCQ 8(AX), CX + ADCQ 16(AX), BX + ADCQ 24(AX), SI + ADCQ 32(AX), DI + ADCQ 40(AX), R8 + + // reduce element(DX,CX,BX,SI,DI,R8) using temp registers (R14,R15,R9,R10,R11,R12) + REDUCE(DX,CX,BX,SI,DI,R8,R14,R15,R9,R10,R11,R12) + + MOVQ DX, 0(AX) + MOVQ CX, 8(AX) + MOVQ BX, 16(AX) + MOVQ SI, 24(AX) + MOVQ DI, 32(AX) + MOVQ R8, 40(AX) + RET + +// MulBy13(x *Element) +TEXT ·MulBy13(SB), $40-8 + MOVQ x+0(FP), AX + MOVQ 0(AX), DX + MOVQ 8(AX), CX + MOVQ 16(AX), BX + MOVQ 24(AX), SI + MOVQ 32(AX), DI + MOVQ 40(AX), R8 + ADDQ DX, DX + ADCQ CX, CX + ADCQ BX, BX + ADCQ SI, SI + ADCQ DI, DI + ADCQ R8, R8 + + // reduce element(DX,CX,BX,SI,DI,R8) using temp registers (R9,R10,R11,R12,R13,R14) + REDUCE(DX,CX,BX,SI,DI,R8,R9,R10,R11,R12,R13,R14) + + ADDQ DX, DX + ADCQ CX, CX + ADCQ BX, BX + ADCQ SI, SI + ADCQ DI, DI + ADCQ R8, R8 + + // reduce element(DX,CX,BX,SI,DI,R8) using temp registers (R15,s0-8(SP),s1-16(SP),s2-24(SP),s3-32(SP),s4-40(SP)) + REDUCE(DX,CX,BX,SI,DI,R8,R15,s0-8(SP),s1-16(SP),s2-24(SP),s3-32(SP),s4-40(SP)) + + MOVQ DX, R15 + MOVQ CX, s0-8(SP) + MOVQ BX, s1-16(SP) + MOVQ SI, s2-24(SP) + MOVQ DI, s3-32(SP) + MOVQ R8, s4-40(SP) + ADDQ DX, DX + ADCQ CX, CX + ADCQ BX, BX + ADCQ SI, SI + ADCQ DI, DI + ADCQ R8, R8 + + // reduce element(DX,CX,BX,SI,DI,R8) using temp registers (R9,R10,R11,R12,R13,R14) + REDUCE(DX,CX,BX,SI,DI,R8,R9,R10,R11,R12,R13,R14) + + ADDQ R15, DX + ADCQ s0-8(SP), CX + ADCQ s1-16(SP), BX + ADCQ s2-24(SP), SI + ADCQ s3-32(SP), DI + ADCQ s4-40(SP), R8 + + // reduce element(DX,CX,BX,SI,DI,R8) using temp registers (R9,R10,R11,R12,R13,R14) + REDUCE(DX,CX,BX,SI,DI,R8,R9,R10,R11,R12,R13,R14) + + ADDQ 0(AX), DX + ADCQ 8(AX), CX + ADCQ 16(AX), BX + ADCQ 24(AX), SI + ADCQ 32(AX), DI + ADCQ 40(AX), R8 + + // reduce element(DX,CX,BX,SI,DI,R8) using temp registers (R9,R10,R11,R12,R13,R14) + REDUCE(DX,CX,BX,SI,DI,R8,R9,R10,R11,R12,R13,R14) + + MOVQ DX, 0(AX) + MOVQ CX, 8(AX) + MOVQ BX, 16(AX) + MOVQ SI, 24(AX) + MOVQ DI, 32(AX) + MOVQ R8, 40(AX) + RET + +// Butterfly(a, b *Element) sets a = a + b; b = a - b +TEXT ·Butterfly(SB), $48-16 + MOVQ a+0(FP), AX + MOVQ 0(AX), CX + MOVQ 8(AX), BX + MOVQ 16(AX), SI + MOVQ 24(AX), DI + MOVQ 32(AX), R8 + MOVQ 40(AX), R9 + MOVQ CX, R10 + MOVQ BX, R11 + MOVQ SI, R12 + MOVQ DI, R13 + MOVQ R8, R14 + MOVQ R9, R15 + XORQ AX, AX + MOVQ b+8(FP), DX + ADDQ 0(DX), CX + ADCQ 8(DX), BX + ADCQ 16(DX), SI + ADCQ 24(DX), DI + ADCQ 32(DX), R8 + ADCQ 40(DX), R9 + SUBQ 0(DX), R10 + SBBQ 8(DX), R11 + SBBQ 16(DX), R12 + SBBQ 24(DX), R13 + SBBQ 32(DX), R14 + SBBQ 40(DX), R15 + MOVQ CX, s0-8(SP) + MOVQ BX, s1-16(SP) + MOVQ SI, s2-24(SP) + MOVQ DI, s3-32(SP) + MOVQ R8, s4-40(SP) + MOVQ R9, s5-48(SP) + MOVQ $const_q0, CX + MOVQ $const_q1, BX + MOVQ $const_q2, SI + MOVQ $const_q3, DI + MOVQ $const_q4, R8 + MOVQ $const_q5, R9 + CMOVQCC AX, CX + CMOVQCC AX, BX + CMOVQCC AX, SI + CMOVQCC AX, DI + CMOVQCC AX, R8 + CMOVQCC AX, R9 + ADDQ CX, R10 + ADCQ BX, R11 + ADCQ SI, R12 + ADCQ DI, R13 + ADCQ R8, R14 + ADCQ R9, R15 + MOVQ s0-8(SP), CX + MOVQ s1-16(SP), BX + MOVQ s2-24(SP), SI + MOVQ s3-32(SP), DI + MOVQ s4-40(SP), R8 + MOVQ s5-48(SP), R9 + MOVQ R10, 0(DX) + MOVQ R11, 8(DX) + MOVQ R12, 16(DX) + MOVQ R13, 24(DX) + MOVQ R14, 32(DX) + MOVQ R15, 40(DX) + + // reduce element(CX,BX,SI,DI,R8,R9) using temp registers (R10,R11,R12,R13,R14,R15) + REDUCE(CX,BX,SI,DI,R8,R9,R10,R11,R12,R13,R14,R15) + + MOVQ a+0(FP), AX + MOVQ CX, 0(AX) + MOVQ BX, 8(AX) + MOVQ SI, 16(AX) + MOVQ DI, 24(AX) + MOVQ R8, 32(AX) + MOVQ R9, 40(AX) + RET + +// mul(res, x, y *Element) +TEXT ·mul(SB), $24-24 + + // Algorithm 2 of "Faster Montgomery Multiplication and Multi-Scalar-Multiplication for SNARKS" + // by Y. El Housni and G. Botrel https://doi.org/10.46586/tches.v2023.i3.504-521 + // See github.com/Consensys/gnark-crypto/field/generator for more comments. + + NO_LOCAL_POINTERS + CMPB ·supportAdx(SB), $1 + JNE noAdx_1 + MOVQ x+8(FP), R8 + + // x[0] -> R10 + // x[1] -> R11 + // x[2] -> R12 + MOVQ 0(R8), R10 + MOVQ 8(R8), R11 + MOVQ 16(R8), R12 + MOVQ y+16(FP), R13 + + // A -> BP + // t[0] -> R14 + // t[1] -> R15 + // t[2] -> CX + // t[3] -> BX + // t[4] -> SI + // t[5] -> DI +#define MACC(in0, in1, in2) \ + ADCXQ in0, in1 \ + MULXQ in2, AX, in0 \ + ADOXQ AX, in1 \ + +#define DIV_SHIFT() \ + MOVQ $const_qInvNeg, DX \ + IMULQ R14, DX \ + XORQ AX, AX \ + MULXQ ·qElement+0(SB), AX, R9 \ + ADCXQ R14, AX \ + MOVQ R9, R14 \ + MACC(R15, R14, ·qElement+8(SB)) \ + MACC(CX, R15, ·qElement+16(SB)) \ + MACC(BX, CX, ·qElement+24(SB)) \ + MACC(SI, BX, ·qElement+32(SB)) \ + MACC(DI, SI, ·qElement+40(SB)) \ + MOVQ $0, AX \ + ADCXQ AX, DI \ + ADOXQ BP, DI \ + +#define MUL_WORD_0() \ + XORQ AX, AX \ + MULXQ R10, R14, R15 \ + MULXQ R11, AX, CX \ + ADOXQ AX, R15 \ + MULXQ R12, AX, BX \ + ADOXQ AX, CX \ + MULXQ 24(R8), AX, SI \ + ADOXQ AX, BX \ + MULXQ 32(R8), AX, DI \ + ADOXQ AX, SI \ + MULXQ 40(R8), AX, BP \ + ADOXQ AX, DI \ + MOVQ $0, AX \ + ADOXQ AX, BP \ + DIV_SHIFT() \ + +#define MUL_WORD_N() \ + XORQ AX, AX \ + MULXQ R10, AX, BP \ + ADOXQ AX, R14 \ + MACC(BP, R15, R11) \ + MACC(BP, CX, R12) \ + MACC(BP, BX, 24(R8)) \ + MACC(BP, SI, 32(R8)) \ + MACC(BP, DI, 40(R8)) \ + MOVQ $0, AX \ + ADCXQ AX, BP \ + ADOXQ AX, BP \ + DIV_SHIFT() \ + + // mul body + MOVQ 0(R13), DX + MUL_WORD_0() + MOVQ 8(R13), DX + MUL_WORD_N() + MOVQ 16(R13), DX + MUL_WORD_N() + MOVQ 24(R13), DX + MUL_WORD_N() + MOVQ 32(R13), DX + MUL_WORD_N() + MOVQ 40(R13), DX + MUL_WORD_N() + + // reduce element(R14,R15,CX,BX,SI,DI) using temp registers (R9,R8,R13,R10,R11,R12) + REDUCE(R14,R15,CX,BX,SI,DI,R9,R8,R13,R10,R11,R12) + + MOVQ res+0(FP), AX + MOVQ R14, 0(AX) + MOVQ R15, 8(AX) + MOVQ CX, 16(AX) + MOVQ BX, 24(AX) + MOVQ SI, 32(AX) + MOVQ DI, 40(AX) + RET + +noAdx_1: + MOVQ res+0(FP), AX + MOVQ AX, (SP) + MOVQ x+8(FP), AX + MOVQ AX, 8(SP) + MOVQ y+16(FP), AX + MOVQ AX, 16(SP) + CALL ·_mulGeneric(SB) + RET + +TEXT ·fromMont(SB), $8-8 + NO_LOCAL_POINTERS + + // Algorithm 2 of "Faster Montgomery Multiplication and Multi-Scalar-Multiplication for SNARKS" + // by Y. El Housni and G. Botrel https://doi.org/10.46586/tches.v2023.i3.504-521 + // when y = 1 we have: + // for i=0 to N-1 + // t[i] = x[i] + // for i=0 to N-1 + // m := t[0]*q'[0] mod W + // C,_ := t[0] + m*q[0] + // for j=1 to N-1 + // (C,t[j-1]) := t[j] + m*q[j] + C + // t[N-1] = C + CMPB ·supportAdx(SB), $1 + JNE noAdx_2 + MOVQ res+0(FP), DX + MOVQ 0(DX), R14 + MOVQ 8(DX), R15 + MOVQ 16(DX), CX + MOVQ 24(DX), BX + MOVQ 32(DX), SI + MOVQ 40(DX), DI + XORQ DX, DX + + // m := t[0]*q'[0] mod W + MOVQ $const_qInvNeg, DX + IMULQ R14, DX + XORQ AX, AX + + // C,_ := t[0] + m*q[0] + MULXQ ·qElement+0(SB), AX, BP + ADCXQ R14, AX + MOVQ BP, R14 + + // (C,t[0]) := t[1] + m*q[1] + C + ADCXQ R15, R14 + MULXQ ·qElement+8(SB), AX, R15 + ADOXQ AX, R14 + + // (C,t[1]) := t[2] + m*q[2] + C + ADCXQ CX, R15 + MULXQ ·qElement+16(SB), AX, CX + ADOXQ AX, R15 + + // (C,t[2]) := t[3] + m*q[3] + C + ADCXQ BX, CX + MULXQ ·qElement+24(SB), AX, BX + ADOXQ AX, CX + + // (C,t[3]) := t[4] + m*q[4] + C + ADCXQ SI, BX + MULXQ ·qElement+32(SB), AX, SI + ADOXQ AX, BX + + // (C,t[4]) := t[5] + m*q[5] + C + ADCXQ DI, SI + MULXQ ·qElement+40(SB), AX, DI + ADOXQ AX, SI + MOVQ $0, AX + ADCXQ AX, DI + ADOXQ AX, DI + XORQ DX, DX + + // m := t[0]*q'[0] mod W + MOVQ $const_qInvNeg, DX + IMULQ R14, DX + XORQ AX, AX + + // C,_ := t[0] + m*q[0] + MULXQ ·qElement+0(SB), AX, BP + ADCXQ R14, AX + MOVQ BP, R14 + + // (C,t[0]) := t[1] + m*q[1] + C + ADCXQ R15, R14 + MULXQ ·qElement+8(SB), AX, R15 + ADOXQ AX, R14 + + // (C,t[1]) := t[2] + m*q[2] + C + ADCXQ CX, R15 + MULXQ ·qElement+16(SB), AX, CX + ADOXQ AX, R15 + + // (C,t[2]) := t[3] + m*q[3] + C + ADCXQ BX, CX + MULXQ ·qElement+24(SB), AX, BX + ADOXQ AX, CX + + // (C,t[3]) := t[4] + m*q[4] + C + ADCXQ SI, BX + MULXQ ·qElement+32(SB), AX, SI + ADOXQ AX, BX + + // (C,t[4]) := t[5] + m*q[5] + C + ADCXQ DI, SI + MULXQ ·qElement+40(SB), AX, DI + ADOXQ AX, SI + MOVQ $0, AX + ADCXQ AX, DI + ADOXQ AX, DI + XORQ DX, DX + + // m := t[0]*q'[0] mod W + MOVQ $const_qInvNeg, DX + IMULQ R14, DX + XORQ AX, AX + + // C,_ := t[0] + m*q[0] + MULXQ ·qElement+0(SB), AX, BP + ADCXQ R14, AX + MOVQ BP, R14 + + // (C,t[0]) := t[1] + m*q[1] + C + ADCXQ R15, R14 + MULXQ ·qElement+8(SB), AX, R15 + ADOXQ AX, R14 + + // (C,t[1]) := t[2] + m*q[2] + C + ADCXQ CX, R15 + MULXQ ·qElement+16(SB), AX, CX + ADOXQ AX, R15 + + // (C,t[2]) := t[3] + m*q[3] + C + ADCXQ BX, CX + MULXQ ·qElement+24(SB), AX, BX + ADOXQ AX, CX + + // (C,t[3]) := t[4] + m*q[4] + C + ADCXQ SI, BX + MULXQ ·qElement+32(SB), AX, SI + ADOXQ AX, BX + + // (C,t[4]) := t[5] + m*q[5] + C + ADCXQ DI, SI + MULXQ ·qElement+40(SB), AX, DI + ADOXQ AX, SI + MOVQ $0, AX + ADCXQ AX, DI + ADOXQ AX, DI + XORQ DX, DX + + // m := t[0]*q'[0] mod W + MOVQ $const_qInvNeg, DX + IMULQ R14, DX + XORQ AX, AX + + // C,_ := t[0] + m*q[0] + MULXQ ·qElement+0(SB), AX, BP + ADCXQ R14, AX + MOVQ BP, R14 + + // (C,t[0]) := t[1] + m*q[1] + C + ADCXQ R15, R14 + MULXQ ·qElement+8(SB), AX, R15 + ADOXQ AX, R14 + + // (C,t[1]) := t[2] + m*q[2] + C + ADCXQ CX, R15 + MULXQ ·qElement+16(SB), AX, CX + ADOXQ AX, R15 + + // (C,t[2]) := t[3] + m*q[3] + C + ADCXQ BX, CX + MULXQ ·qElement+24(SB), AX, BX + ADOXQ AX, CX + + // (C,t[3]) := t[4] + m*q[4] + C + ADCXQ SI, BX + MULXQ ·qElement+32(SB), AX, SI + ADOXQ AX, BX + + // (C,t[4]) := t[5] + m*q[5] + C + ADCXQ DI, SI + MULXQ ·qElement+40(SB), AX, DI + ADOXQ AX, SI + MOVQ $0, AX + ADCXQ AX, DI + ADOXQ AX, DI + XORQ DX, DX + + // m := t[0]*q'[0] mod W + MOVQ $const_qInvNeg, DX + IMULQ R14, DX + XORQ AX, AX + + // C,_ := t[0] + m*q[0] + MULXQ ·qElement+0(SB), AX, BP + ADCXQ R14, AX + MOVQ BP, R14 + + // (C,t[0]) := t[1] + m*q[1] + C + ADCXQ R15, R14 + MULXQ ·qElement+8(SB), AX, R15 + ADOXQ AX, R14 + + // (C,t[1]) := t[2] + m*q[2] + C + ADCXQ CX, R15 + MULXQ ·qElement+16(SB), AX, CX + ADOXQ AX, R15 + + // (C,t[2]) := t[3] + m*q[3] + C + ADCXQ BX, CX + MULXQ ·qElement+24(SB), AX, BX + ADOXQ AX, CX + + // (C,t[3]) := t[4] + m*q[4] + C + ADCXQ SI, BX + MULXQ ·qElement+32(SB), AX, SI + ADOXQ AX, BX + + // (C,t[4]) := t[5] + m*q[5] + C + ADCXQ DI, SI + MULXQ ·qElement+40(SB), AX, DI + ADOXQ AX, SI + MOVQ $0, AX + ADCXQ AX, DI + ADOXQ AX, DI + XORQ DX, DX + + // m := t[0]*q'[0] mod W + MOVQ $const_qInvNeg, DX + IMULQ R14, DX + XORQ AX, AX + + // C,_ := t[0] + m*q[0] + MULXQ ·qElement+0(SB), AX, BP + ADCXQ R14, AX + MOVQ BP, R14 + + // (C,t[0]) := t[1] + m*q[1] + C + ADCXQ R15, R14 + MULXQ ·qElement+8(SB), AX, R15 + ADOXQ AX, R14 + + // (C,t[1]) := t[2] + m*q[2] + C + ADCXQ CX, R15 + MULXQ ·qElement+16(SB), AX, CX + ADOXQ AX, R15 + + // (C,t[2]) := t[3] + m*q[3] + C + ADCXQ BX, CX + MULXQ ·qElement+24(SB), AX, BX + ADOXQ AX, CX + + // (C,t[3]) := t[4] + m*q[4] + C + ADCXQ SI, BX + MULXQ ·qElement+32(SB), AX, SI + ADOXQ AX, BX + + // (C,t[4]) := t[5] + m*q[5] + C + ADCXQ DI, SI + MULXQ ·qElement+40(SB), AX, DI + ADOXQ AX, SI + MOVQ $0, AX + ADCXQ AX, DI + ADOXQ AX, DI + + // reduce element(R14,R15,CX,BX,SI,DI) using temp registers (R8,R9,R10,R11,R12,R13) + REDUCE(R14,R15,CX,BX,SI,DI,R8,R9,R10,R11,R12,R13) + + MOVQ res+0(FP), AX + MOVQ R14, 0(AX) + MOVQ R15, 8(AX) + MOVQ CX, 16(AX) + MOVQ BX, 24(AX) + MOVQ SI, 32(AX) + MOVQ DI, 40(AX) + RET + +noAdx_2: + MOVQ res+0(FP), AX + MOVQ AX, (SP) + CALL ·_fromMontGeneric(SB) + RET diff --git a/vendor/github.com/consensys/gnark-crypto/field/asm/element_6w/element_6w_arm64.s b/vendor/github.com/consensys/gnark-crypto/field/asm/element_6w/element_6w_arm64.s new file mode 100644 index 00000000000..7dbd7ecaf3f --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/field/asm/element_6w/element_6w_arm64.s @@ -0,0 +1,220 @@ +// Code generated by gnark-crypto/generator. DO NOT EDIT. +#include "textflag.h" +#include "funcdata.h" +#include "go_asm.h" + +// butterfly(a, b *Element) +// a, b = a+b, a-b +TEXT ·Butterfly(SB), NOFRAME|NOSPLIT, $0-16 + LDP x+0(FP), (R25, R26) + LDP 0(R25), (R0, R1) + LDP 16(R25), (R2, R3) + LDP 32(R25), (R4, R5) + LDP 0(R26), (R6, R7) + LDP 16(R26), (R8, R9) + LDP 32(R26), (R10, R11) + ADDS R0, R6, R12 + ADCS R1, R7, R13 + ADCS R2, R8, R14 + ADCS R3, R9, R15 + ADCS R4, R10, R16 + ADC R5, R11, R17 + SUBS R6, R0, R6 + SBCS R7, R1, R7 + SBCS R8, R2, R8 + SBCS R9, R3, R9 + SBCS R10, R4, R10 + SBCS R11, R5, R11 + LDP ·qElement+0(SB), (R0, R1) + CSEL CS, ZR, R0, R19 + CSEL CS, ZR, R1, R20 + LDP ·qElement+16(SB), (R2, R3) + CSEL CS, ZR, R2, R21 + CSEL CS, ZR, R3, R22 + LDP ·qElement+32(SB), (R4, R5) + CSEL CS, ZR, R4, R23 + CSEL CS, ZR, R5, R24 + + // add q if underflow, 0 if not + ADDS R6, R19, R6 + ADCS R7, R20, R7 + STP (R6, R7), 0(R26) + ADCS R8, R21, R8 + ADCS R9, R22, R9 + STP (R8, R9), 16(R26) + ADCS R10, R23, R10 + ADC R11, R24, R11 + STP (R10, R11), 32(R26) + + // q = t - q + SUBS R0, R12, R0 + SBCS R1, R13, R1 + SBCS R2, R14, R2 + SBCS R3, R15, R3 + SBCS R4, R16, R4 + SBCS R5, R17, R5 + + // if no borrow, return q, else return t + CSEL CS, R0, R12, R12 + CSEL CS, R1, R13, R13 + STP (R12, R13), 0(R25) + CSEL CS, R2, R14, R14 + CSEL CS, R3, R15, R15 + STP (R14, R15), 16(R25) + CSEL CS, R4, R16, R16 + CSEL CS, R5, R17, R17 + STP (R16, R17), 32(R25) + RET + +// mul(res, x, y *Element) +// Algorithm 2 of Faster Montgomery Multiplication and Multi-Scalar-Multiplication for SNARKS +// by Y. El Housni and G. Botrel https://doi.org/10.46586/tches.v2023.i3.504-521 +TEXT ·mul(SB), NOFRAME|NOSPLIT, $0-24 +#define DIVSHIFT() \ + MUL R17, R16, R0 \ + ADDS R0, R8, R8 \ + MUL R19, R16, R0 \ + ADCS R0, R9, R9 \ + MUL R20, R16, R0 \ + ADCS R0, R10, R10 \ + MUL R21, R16, R0 \ + ADCS R0, R11, R11 \ + MUL R22, R16, R0 \ + ADCS R0, R12, R12 \ + MUL R23, R16, R0 \ + ADCS R0, R13, R13 \ + ADC R14, ZR, R14 \ + UMULH R17, R16, R0 \ + ADDS R0, R9, R8 \ + UMULH R19, R16, R0 \ + ADCS R0, R10, R9 \ + UMULH R20, R16, R0 \ + ADCS R0, R11, R10 \ + UMULH R21, R16, R0 \ + ADCS R0, R12, R11 \ + UMULH R22, R16, R0 \ + ADCS R0, R13, R12 \ + UMULH R23, R16, R0 \ + ADCS R0, R14, R13 \ + +#define MUL_WORD_N() \ + MUL R2, R1, R0 \ + ADDS R0, R8, R8 \ + MUL R8, R15, R16 \ + MUL R3, R1, R0 \ + ADCS R0, R9, R9 \ + MUL R4, R1, R0 \ + ADCS R0, R10, R10 \ + MUL R5, R1, R0 \ + ADCS R0, R11, R11 \ + MUL R6, R1, R0 \ + ADCS R0, R12, R12 \ + MUL R7, R1, R0 \ + ADCS R0, R13, R13 \ + ADC ZR, ZR, R14 \ + UMULH R2, R1, R0 \ + ADDS R0, R9, R9 \ + UMULH R3, R1, R0 \ + ADCS R0, R10, R10 \ + UMULH R4, R1, R0 \ + ADCS R0, R11, R11 \ + UMULH R5, R1, R0 \ + ADCS R0, R12, R12 \ + UMULH R6, R1, R0 \ + ADCS R0, R13, R13 \ + UMULH R7, R1, R0 \ + ADC R0, R14, R14 \ + DIVSHIFT() \ + +#define MUL_WORD_0() \ + MUL R2, R1, R8 \ + MUL R3, R1, R9 \ + MUL R4, R1, R10 \ + MUL R5, R1, R11 \ + MUL R6, R1, R12 \ + MUL R7, R1, R13 \ + UMULH R2, R1, R0 \ + ADDS R0, R9, R9 \ + UMULH R3, R1, R0 \ + ADCS R0, R10, R10 \ + UMULH R4, R1, R0 \ + ADCS R0, R11, R11 \ + UMULH R5, R1, R0 \ + ADCS R0, R12, R12 \ + UMULH R6, R1, R0 \ + ADCS R0, R13, R13 \ + UMULH R7, R1, R0 \ + ADC R0, ZR, R14 \ + MUL R8, R15, R16 \ + DIVSHIFT() \ + + MOVD y+16(FP), R24 + MOVD x+8(FP), R0 + LDP 0(R0), (R2, R3) + LDP 16(R0), (R4, R5) + LDP 32(R0), (R6, R7) + MOVD 0(R24), R1 + MOVD $const_qInvNeg, R15 + LDP ·qElement+0(SB), (R17, R19) + LDP ·qElement+16(SB), (R20, R21) + LDP ·qElement+32(SB), (R22, R23) + MUL_WORD_0() + MOVD 8(R24), R1 + MUL_WORD_N() + MOVD 16(R24), R1 + MUL_WORD_N() + MOVD 24(R24), R1 + MUL_WORD_N() + MOVD 32(R24), R1 + MUL_WORD_N() + MOVD 40(R24), R1 + MUL_WORD_N() + + // reduce if necessary + SUBS R17, R8, R17 + SBCS R19, R9, R19 + SBCS R20, R10, R20 + SBCS R21, R11, R21 + SBCS R22, R12, R22 + SBCS R23, R13, R23 + MOVD res+0(FP), R0 + CSEL CS, R17, R8, R8 + CSEL CS, R19, R9, R9 + STP (R8, R9), 0(R0) + CSEL CS, R20, R10, R10 + CSEL CS, R21, R11, R11 + STP (R10, R11), 16(R0) + CSEL CS, R22, R12, R12 + CSEL CS, R23, R13, R13 + STP (R12, R13), 32(R0) + RET + +// reduce(res *Element) +TEXT ·reduce(SB), NOFRAME|NOSPLIT, $0-8 + LDP ·qElement+0(SB), (R6, R7) + LDP ·qElement+16(SB), (R8, R9) + LDP ·qElement+32(SB), (R10, R11) + MOVD res+0(FP), R12 + LDP 0(R12), (R0, R1) + LDP 16(R12), (R2, R3) + LDP 32(R12), (R4, R5) + + // q = t - q + SUBS R6, R0, R6 + SBCS R7, R1, R7 + SBCS R8, R2, R8 + SBCS R9, R3, R9 + SBCS R10, R4, R10 + SBCS R11, R5, R11 + + // if no borrow, return q, else return t + CSEL CS, R6, R0, R0 + CSEL CS, R7, R1, R1 + STP (R0, R1), 0(R12) + CSEL CS, R8, R2, R2 + CSEL CS, R9, R3, R3 + STP (R2, R3), 16(R12) + CSEL CS, R10, R4, R4 + CSEL CS, R11, R5, R5 + STP (R4, R5), 32(R12) + RET diff --git a/vendor/github.com/consensys/gnark-crypto/field/generator/config/extension.go b/vendor/github.com/consensys/gnark-crypto/field/generator/config/extension.go deleted file mode 100644 index 53221f89c37..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/field/generator/config/extension.go +++ /dev/null @@ -1,244 +0,0 @@ -package config - -import "math/big" - -type Element []big.Int - -// Extension is a simple radical extension, obtained by adjoining ⁿ√α to Fp -type Extension struct { - Base *FieldConfig //Fp - Size big.Int //q - Degree int //n such that q = pⁿ TODO: Make uint8 so forced to be positive and small - RootOf int64 //α -} - -func NewTower(base *FieldConfig, degree uint8, rootOf int64) Extension { - ret := Extension{ - Degree: int(degree), - RootOf: rootOf, - Base: base, - } - ret.Size.Exp(base.ModulusBig, big.NewInt(int64(degree)), nil) - return ret -} - -func (f *Extension) FromInt64(i ...int64) Element { - z := make(Element, f.Degree) - for n := 0; n < len(i) && n < int(f.Degree); n++ { - z[n].SetInt64(i[n]) - } - return z -} - -func (f *Extension) Neg(x Element) Element { - z := make(Element, len(x)) - for n := 0; n < len(x); n++ { - z[n].Neg(&x[n]) - } - return z -} - -func max(x int, y int) int { - if x > y { - return x - } - return y -} - -func (f *Extension) Add(x Element, y Element) Element { - z := make(Element, f.Degree) - - for i := 0; i < f.Degree; i++ { - z[i]. - Add(&x[i], &y[i]). - Mod(&z[i], f.Base.ModulusBig) - } - return z -} - -func (f *Extension) Mul(x Element, y Element) Element { - z := make(Element, f.Degree) - maxP := len(x) + len(y) - 2 - alpha := big.NewInt(f.RootOf) - - for p := maxP; p >= 0; p-- { - - var rp big.Int - - for m := max(p-(len(y)-1), 0); m < len(x) && m <= p; m++ { - n := p - m - var prod big.Int - prod.Mul(&x[m], &y[n]) - rp.Add(&rp, &prod) - } - - rI := p % int(f.Degree) //reduced index - - z[rI].Add(&z[rI], &rp).Mod(&z[rI], f.Base.ModulusBig) - - if p >= int(f.Degree) { - z[rI].Mul(&z[rI], alpha) - } - } - - return z -} - -func (f *Extension) MulScalar(c *big.Int, x Element) Element { - z := make(Element, len(x)) - for i := 0; i < len(x); i++ { - f.Base.Mul(&z[i], c, &x[i]) - } - return z -} - -func (f *Extension) Halve(z Element) { - for i := 0; i < len(z); i++ { - if z[i].Bit(0) != 0 { - z[i].Add(&z[i], f.Base.ModulusBig) - } - z[i].Rsh(&z[i], 1) - } -} - -func (f *Extension) reduce(z Element) { - for i := 0; i < len(z); i++ { - z[i].Mod(&z[i], f.Base.ModulusBig) - } -} - -// Sqrt returning √ x, or nil if x is not qr. -func (f *Extension) Sqrt(x Element) Element { - - z := make(Element, f.Degree) - switch f.Degree { - case 1: - if z[0].ModSqrt(&x[0], f.Base.ModulusBig) == nil { - return nil - } - case 2: - // z = z₀ + z₁ i - - if x[0].BitLen() == 0 { - z[1].ModInverse(big.NewInt(f.RootOf), f.Base.ModulusBig).Mul(&z[1], &x[1]) - } - - var discriminant big.Int - z[0].Mul(&x[0], &x[0]) - z[1].Mul(&x[1], &x[1]).Mul(&z[1], big.NewInt(-f.RootOf)) - z[0].Sub(&z[0], &z[1]) - if discriminant.ModSqrt(&z[0], f.Base.ModulusBig) == nil { - return nil - } - z[0].Add(&x[0], &discriminant) - f.Base.halve(&z[0], &z[0]) - if z[0].ModSqrt(&z[0], f.Base.ModulusBig) == nil { - z[0].Sub(&z[0], &discriminant) - if z[0].ModSqrt(&z[0], f.Base.ModulusBig) == nil { - return nil - } - } - z[1].Lsh(&z[0], 1).ModInverse(&z[1], f.Base.ModulusBig).Mul(&z[1], &x[1]) - - default: - panic("only degrees 1 and 2 are supported") - } - - f.reduce(z) - return z -} - -func (f *Extension) ToMont(x Element) Element { - z := make([]big.Int, len(x)) - for i := 0; i < len(x); i++ { - z[i] = f.Base.ToMont(x[i]) - } - return z -} - -func (f *Extension) Equal(x Element, y Element) bool { - if len(x) != len(y) { - return false - } - for i := 0; i < len(x); i++ { - var diff big.Int - if diff.Sub(&x[i], &y[i]).Mod(&diff, f.Base.ModulusBig).BitLen() != 0 { - return false - } - } - return true -} - -func (f *Extension) norm(z *big.Int, x Element) *Extension { - if f.Degree != 2 { - panic("only degree 2 supported") - } - var x0Sq big.Int - - x0Sq.Mul(&x[0], &x[0]) - - res := big.NewInt(-f.RootOf) - res.Mul(res, &x[1]).Mul(res, &x[1]).Add(res, &x0Sq) - - z.Set(res) - - return f -} - -func (f *Extension) Inverse(x Element) Element { - z := make(Element, f.Degree) - switch f.Degree { - case 1: - z[0].ModInverse(&x[0], f.Base.ModulusBig) - case 2: - var normInv big.Int - f.norm(&normInv, x) - normInv.ModInverse(&normInv, f.Base.ModulusBig) - z[0].Mul(&x[0], &normInv) - - z[1].Neg(&x[1]).Mul(&z[1], &normInv) - default: - panic("can't invert in extensions of degree > 2") - } - return z -} - -func (f *Extension) Exp(x Element, exp *big.Int) Element { - - if exp.BitLen() == 0 { - return f.FromInt64(1) - } - - z := x - - for i := exp.BitLen() - 2; i >= 0; i-- { - z = f.Mul(z, z) - if exp.Bit(i) == 1 { - z = f.Mul(z, x) - } - } - - return z -} - -// Div returns u/v -func (f *Extension) Div(u, v Element) Element { - return f.Mul(u, f.Inverse(v)) -} - -func (f *Extension) IsZero(u Element) bool { - for i := 0; i < len(u); i++ { - if u[i].BitLen() != 0 { - return false - } - } - return true -} - -func NewElement(s []string) []big.Int { - res := make([]big.Int, len(s)) - for i, S := range s { - res[i].SetString(S, 0) - } - return res -} diff --git a/vendor/github.com/consensys/gnark-crypto/field/generator/config/field_config.go b/vendor/github.com/consensys/gnark-crypto/field/generator/config/field_config.go deleted file mode 100644 index 457a89d7d2e..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/field/generator/config/field_config.go +++ /dev/null @@ -1,434 +0,0 @@ -// Copyright 2020 ConsenSys Software Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package config provides Golang code generation for efficient field arithmetic operations. -package config - -import ( - "errors" - "fmt" - "math" - "math/big" - "strconv" - "strings" - - "github.com/consensys/bavard" - "github.com/consensys/gnark-crypto/field/generator/internal/addchain" -) - -var ( - errParseModulus = errors.New("can't parse modulus") -) - -// FieldConfig precomputed values used in template for code generation of field element APIs -type FieldConfig struct { - PackageName string - ElementName string - ModulusBig *big.Int - Modulus string - ModulusHex string - NbWords int - NbBits int - NbBytes int - NbWordsLastIndex int - NbWordsIndexesNoZero []int - NbWordsIndexesFull []int - P20InversionCorrectiveFac []uint64 - P20InversionNbIterations int - UsingP20Inverse bool - IsMSWSaturated bool // indicates if the most significant word is 0xFFFFF...FFFF - Q []uint64 - QInverse []uint64 - QMinusOneHalvedP []uint64 // ((q-1) / 2 ) + 1 - ASM bool - RSquare []uint64 - One, Thirteen []uint64 - LegendreExponent string // big.Int to base16 string - NoCarry bool - NoCarrySquare bool // used if NoCarry is set, but some op may overflow in square optimization - SqrtQ3Mod4 bool - SqrtAtkin bool - SqrtTonelliShanks bool - SqrtE uint64 - SqrtS []uint64 - SqrtAtkinExponent string // big.Int to base16 string - SqrtSMinusOneOver2 string // big.Int to base16 string - SqrtQ3Mod4Exponent string // big.Int to base16 string - SqrtG []uint64 // NonResidue ^ SqrtR (montgomery form) - NonResidue big.Int // (montgomery form) - LegendreExponentData *addchain.AddChainData - SqrtAtkinExponentData *addchain.AddChainData - SqrtSMinusOneOver2Data *addchain.AddChainData - SqrtQ3Mod4ExponentData *addchain.AddChainData - UseAddChain bool -} - -// NewFieldConfig returns a data structure with needed information to generate apis for field element -// -// See field/generator package -func NewFieldConfig(packageName, elementName, modulus string, useAddChain bool) (*FieldConfig, error) { - // parse modulus - var bModulus big.Int - if _, ok := bModulus.SetString(modulus, 0); !ok { - return nil, errParseModulus - } - - // field info - F := &FieldConfig{ - PackageName: packageName, - ElementName: elementName, - Modulus: bModulus.Text(10), - ModulusHex: bModulus.Text(16), - ModulusBig: new(big.Int).Set(&bModulus), - UseAddChain: useAddChain, - } - // pre compute field constants - F.NbBits = bModulus.BitLen() - F.NbWords = len(bModulus.Bits()) - F.NbBytes = F.NbWords * 8 // (F.NbBits + 7) / 8 - - F.NbWordsLastIndex = F.NbWords - 1 - - // set q from big int repr - F.Q = toUint64Slice(&bModulus) - F.IsMSWSaturated = F.Q[len(F.Q)-1] == math.MaxUint64 - _qHalved := big.NewInt(0) - bOne := new(big.Int).SetUint64(1) - _qHalved.Sub(&bModulus, bOne).Rsh(_qHalved, 1).Add(_qHalved, bOne) - F.QMinusOneHalvedP = toUint64Slice(_qHalved, F.NbWords) - - // setting qInverse - _r := big.NewInt(1) - _r.Lsh(_r, uint(F.NbWords)*64) - _rInv := big.NewInt(1) - _qInv := big.NewInt(0) - extendedEuclideanAlgo(_r, &bModulus, _rInv, _qInv) - _qInv.Mod(_qInv, _r) - F.QInverse = toUint64Slice(_qInv, F.NbWords) - - // Pornin20 inversion correction factors - k := 32 // Optimized for 64 bit machines, still works for 32 - - p20InvInnerLoopNbIterations := 2*F.NbBits - 1 - // if constant time inversion then p20InvInnerLoopNbIterations-- (among other changes) - F.P20InversionNbIterations = (p20InvInnerLoopNbIterations-1)/(k-1) + 1 // ⌈ (2 * field size - 1) / (k-1) ⌉ - F.P20InversionNbIterations += F.P20InversionNbIterations % 2 // "round up" to a multiple of 2 - - kLimbs := k * F.NbWords - p20InversionCorrectiveFacPower := kLimbs*6 + F.P20InversionNbIterations*(kLimbs-k+1) - p20InversionCorrectiveFac := big.NewInt(1) - p20InversionCorrectiveFac.Lsh(p20InversionCorrectiveFac, uint(p20InversionCorrectiveFacPower)) - p20InversionCorrectiveFac.Mod(p20InversionCorrectiveFac, &bModulus) - F.P20InversionCorrectiveFac = toUint64Slice(p20InversionCorrectiveFac, F.NbWords) - - { - c := F.NbWords * 64 - F.UsingP20Inverse = F.NbWords > 1 && F.NbBits < c - } - - // rsquare - _rSquare := big.NewInt(2) - exponent := big.NewInt(int64(F.NbWords) * 64 * 2) - _rSquare.Exp(_rSquare, exponent, &bModulus) - F.RSquare = toUint64Slice(_rSquare, F.NbWords) - - var one big.Int - one.SetUint64(1) - one.Lsh(&one, uint(F.NbWords)*64).Mod(&one, &bModulus) - F.One = toUint64Slice(&one, F.NbWords) - - { - var n big.Int - n.SetUint64(13) - n.Lsh(&n, uint(F.NbWords)*64).Mod(&n, &bModulus) - F.Thirteen = toUint64Slice(&n, F.NbWords) - } - - // indexes (template helpers) - F.NbWordsIndexesFull = make([]int, F.NbWords) - F.NbWordsIndexesNoZero = make([]int, F.NbWords-1) - for i := 0; i < F.NbWords; i++ { - F.NbWordsIndexesFull[i] = i - if i > 0 { - F.NbWordsIndexesNoZero[i-1] = i - } - } - - // See https://hackmd.io/@gnark/modular_multiplication - // if the last word of the modulus is smaller or equal to B, - // we can simplify the montgomery multiplication - const B = (^uint64(0) >> 1) - 1 - F.NoCarry = (F.Q[len(F.Q)-1] <= B) && F.NbWords <= 12 - const BSquare = ^uint64(0) >> 2 - F.NoCarrySquare = F.Q[len(F.Q)-1] <= BSquare - - // Legendre exponent (p-1)/2 - var legendreExponent big.Int - legendreExponent.SetUint64(1) - legendreExponent.Sub(&bModulus, &legendreExponent) - legendreExponent.Rsh(&legendreExponent, 1) - F.LegendreExponent = legendreExponent.Text(16) - if F.UseAddChain { - F.LegendreExponentData = addchain.GetAddChain(&legendreExponent) - } - - // Sqrt pre computes - var qMod big.Int - qMod.SetUint64(4) - if qMod.Mod(&bModulus, &qMod).Cmp(new(big.Int).SetUint64(3)) == 0 { - // q ≡ 3 (mod 4) - // using z ≡ ± x^((p+1)/4) (mod q) - F.SqrtQ3Mod4 = true - var sqrtExponent big.Int - sqrtExponent.SetUint64(1) - sqrtExponent.Add(&bModulus, &sqrtExponent) - sqrtExponent.Rsh(&sqrtExponent, 2) - F.SqrtQ3Mod4Exponent = sqrtExponent.Text(16) - - // add chain stuff - if F.UseAddChain { - F.SqrtQ3Mod4ExponentData = addchain.GetAddChain(&sqrtExponent) - } - - } else { - // q ≡ 1 (mod 4) - qMod.SetUint64(8) - if qMod.Mod(&bModulus, &qMod).Cmp(new(big.Int).SetUint64(5)) == 0 { - // q ≡ 5 (mod 8) - // use Atkin's algorithm - // see modSqrt5Mod8Prime in math/big/int.go - F.SqrtAtkin = true - e := new(big.Int).Rsh(&bModulus, 3) // e = (q - 5) / 8 - F.SqrtAtkinExponent = e.Text(16) - if F.UseAddChain { - F.SqrtAtkinExponentData = addchain.GetAddChain(e) - } - } else { - // use Tonelli-Shanks - F.SqrtTonelliShanks = true - - // Write q-1 =2ᵉ * s , s odd - var s big.Int - one.SetUint64(1) - s.Sub(&bModulus, &one) - - e := s.TrailingZeroBits() - s.Rsh(&s, e) - F.SqrtE = uint64(e) - F.SqrtS = toUint64Slice(&s) - - // find non residue - var nonResidue big.Int - nonResidue.SetInt64(2) - one.SetUint64(1) - for big.Jacobi(&nonResidue, &bModulus) != -1 { - nonResidue.Add(&nonResidue, &one) - } - - // g = nonresidue ^ s - var g big.Int - g.Exp(&nonResidue, &s, &bModulus) - // store g in montgomery form - g.Lsh(&g, uint(F.NbWords)*64).Mod(&g, &bModulus) - F.SqrtG = toUint64Slice(&g, F.NbWords) - - // store non residue in montgomery form - F.NonResidue = F.ToMont(nonResidue) - - // (s+1) /2 - s.Sub(&s, &one).Rsh(&s, 1) - F.SqrtSMinusOneOver2 = s.Text(16) - - if F.UseAddChain { - F.SqrtSMinusOneOver2Data = addchain.GetAddChain(&s) - } - } - } - - // note: to simplify output files generated, we generated ASM code only for - // moduli that meet the condition F.NoCarry - // asm code generation for moduli with more than 6 words can be optimized further - F.ASM = F.NoCarry && F.NbWords <= 12 && F.NbWords > 1 - - return F, nil -} - -func toUint64Slice(b *big.Int, nbWords ...int) (s []uint64) { - if len(nbWords) > 0 && nbWords[0] > len(b.Bits()) { - s = make([]uint64, nbWords[0]) - } else { - s = make([]uint64, len(b.Bits())) - } - - for i, v := range b.Bits() { - s[i] = (uint64)(v) - } - return -} - -// https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm -// r > q, modifies rinv and qinv such that rinv.r - qinv.q = 1 -func extendedEuclideanAlgo(r, q, rInv, qInv *big.Int) { - var s1, s2, t1, t2, qi, tmpMuls, riPlusOne, tmpMult, a, b big.Int - t1.SetUint64(1) - rInv.Set(big.NewInt(1)) - qInv.Set(big.NewInt(0)) - a.Set(r) - b.Set(q) - - // r_i+1 = r_i-1 - q_i.r_i - // s_i+1 = s_i-1 - q_i.s_i - // t_i+1 = t_i-1 - q_i.s_i - for b.Sign() > 0 { - qi.Div(&a, &b) - riPlusOne.Mod(&a, &b) - - tmpMuls.Mul(&s1, &qi) - tmpMult.Mul(&t1, &qi) - - s2.Set(&s1) - t2.Set(&t1) - - s1.Sub(rInv, &tmpMuls) - t1.Sub(qInv, &tmpMult) - rInv.Set(&s2) - qInv.Set(&t2) - - a.Set(&b) - b.Set(&riPlusOne) - } - qInv.Neg(qInv) -} - -// StringToMont takes an element written in string form, and returns it in Montgomery form -// Useful for hard-coding in implementation field elements from standards documents -func (f *FieldConfig) StringToMont(str string) big.Int { - - var i big.Int - i.SetString(str, 0) - i = f.ToMont(i) - - return i -} - -func (f *FieldConfig) ToMont(nonMont big.Int) big.Int { - var mont big.Int - mont.Lsh(&nonMont, uint(f.NbWords)*64) - mont.Mod(&mont, f.ModulusBig) - return mont -} - -func (f *FieldConfig) FromMont(nonMont *big.Int, mont *big.Int) *FieldConfig { - - if f.NbWords == 0 { - nonMont.SetInt64(0) - return f - } - f.halve(nonMont, mont) - for i := 1; i < f.NbWords*64; i++ { - f.halve(nonMont, nonMont) - } - - return f -} - -func (f *FieldConfig) Exp(res *big.Int, x *big.Int, pow *big.Int) *FieldConfig { - res.SetInt64(1) - - for i := pow.BitLen() - 1; ; { - - if pow.Bit(i) == 1 { - res.Mul(res, x) - } - - if i == 0 { - break - } - i-- - - res.Mul(res, res).Mod(res, f.ModulusBig) - } - - res.Mod(res, f.ModulusBig) - return f -} - -func (f *FieldConfig) halve(res *big.Int, x *big.Int) { - var z big.Int - if x.Bit(0) == 0 { - z.Set(x) - } else { - z.Add(x, f.ModulusBig) - } - res.Rsh(&z, 1) -} - -func (f *FieldConfig) Mul(z *big.Int, x *big.Int, y *big.Int) *FieldConfig { - z.Mul(x, y).Mod(z, f.ModulusBig) - return f -} - -func (f *FieldConfig) Add(z *big.Int, x *big.Int, y *big.Int) *FieldConfig { - z.Add(x, y).Mod(z, f.ModulusBig) - return f -} - -func (f *FieldConfig) ToMontSlice(x []big.Int) []big.Int { - z := make(Element, len(x)) - for i := 0; i < len(x); i++ { - z[i] = f.ToMont(x[i]) - } - return z -} - -// TODO: Spaghetti Alert: Okay to have codegen functions here? -func CoordNameForExtensionDegree(degree uint8) string { - switch degree { - case 1: - return "" - case 2: - return "A" - case 6: - return "B" - case 12: - return "C" - } - panic(fmt.Sprint("unknown extension degree", degree)) -} - -func (f *FieldConfig) WriteElement(element Element) string { - var builder strings.Builder - - builder.WriteString("{") - length := len(element) - var subElementNames string - if length > 1 { - builder.WriteString("\n") - subElementNames = CoordNameForExtensionDegree(uint8(length)) - } - for i, e := range element { - if length > 1 { - builder.WriteString(subElementNames) - builder.WriteString(strconv.Itoa(i)) - builder.WriteString(": fp.Element{") - } - mont := f.ToMont(e) - bavard.WriteBigIntAsUint64Slice(&builder, &mont) - if length > 1 { - builder.WriteString("},\n") - } - } - builder.WriteString("}") - return builder.String() -} diff --git a/vendor/github.com/consensys/gnark-crypto/field/generator/internal/addchain/addchain.go b/vendor/github.com/consensys/gnark-crypto/field/generator/internal/addchain/addchain.go deleted file mode 100644 index 7dd42b1837c..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/field/generator/internal/addchain/addchain.go +++ /dev/null @@ -1,327 +0,0 @@ -// Original copyright : -// BSD 3-Clause License - -// Copyright (c) 2019, Michael McLoughlin -// All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: - -// 1. Redistributions of source code must retain the above copyright notice, this -// list of conditions and the following disclaimer. - -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. - -// 3. Neither the name of the copyright holder nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. - -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Package addchain is derived from github.com/mmcloughlin/addchain internal packages or examples -package addchain - -import ( - "bufio" - "encoding/gob" - "log" - "math/big" - "os" - "path/filepath" - "reflect" - "strings" - "sync" - - "github.com/mmcloughlin/addchain" - "github.com/mmcloughlin/addchain/acc" - "github.com/mmcloughlin/addchain/acc/ast" - "github.com/mmcloughlin/addchain/acc/ir" - "github.com/mmcloughlin/addchain/acc/pass" - "github.com/mmcloughlin/addchain/acc/printer" - "github.com/mmcloughlin/addchain/alg/ensemble" - "github.com/mmcloughlin/addchain/alg/exec" - "github.com/mmcloughlin/addchain/meta" -) - -// most of these functions are derived from github.com/mmcloughlin/addchain internal packages or examples - -var ( - once sync.Once - addChainDir string - mAddchains map[string]*AddChainData // key is big.Int.Text(16) -) - -// GetAddChain returns template data of a short addition chain for given big.Int -func GetAddChain(n *big.Int) *AddChainData { - - // init the cache only once. - once.Do(initCache) - - key := n.Text(16) - if r, ok := mAddchains[key]; ok { - return r - } - - // Default ensemble of algorithms. - algorithms := ensemble.Ensemble() - - // Use parallel executor. - ex := exec.NewParallel() - results := ex.Execute(n, algorithms) - - // Output best result. - best := 0 - for i, r := range results { - if r.Err != nil { - log.Fatal(r.Err) - } - if len(results[i].Program) < len(results[best].Program) { - best = i - } - } - r := results[best] - data := processSearchResult(r.Program, key) - - mAddchains[key] = data - // gob encode - file := filepath.Join(addChainDir, key) - log.Println("saving addchain", file) - f, err := os.Create(file) - if err != nil { - log.Fatal(err) - } - enc := gob.NewEncoder(f) - - if err := enc.Encode(r.Program); err != nil { - _ = f.Close() - log.Fatal(err) - } - _ = f.Close() - - return data -} - -func processSearchResult(_p addchain.Program, n string) *AddChainData { - p, err := acc.Decompile(_p) - if err != nil { - log.Fatal(err) - } - chain, err := acc.Build(p) - if err != nil { - log.Fatal(err) - } - - data, err := prepareAddChainData(chain, n) - if err != nil { - log.Fatal(err) - } - return data -} - -// Data provided to templates. -type AddChainData struct { - // Chain is the addition chain as a list of integers. - Chain addchain.Chain - - // Ops is the complete sequence of addition operations required to compute - // the addition chain. - Ops addchain.Program - - // Script is the condensed representation of the addition chain computation - // in the "addition chain calculator" language. - Script *ast.Chain - - // Program is the intermediate representation of the addition chain - // computation. This representation is likely the most convenient for code - // generation. It contains a sequence of add, double and shift (repeated - // doubling) instructions required to compute the chain. Temporary variable - // allocation has been performed and the list of required temporaries - // populated. - Program *ir.Program - - // Metadata about the addchain project and the specific release parameters. - // Please use this to include a reference or citation back to the addchain - // project in your generated output. - Meta *meta.Properties - - N string // base 16 value of the value -} - -// PrepareData builds input template data for the given addition chain script. -func prepareAddChainData(s *ast.Chain, n string) (*AddChainData, error) { - // Prepare template data. - allocator := pass.Allocator{ - Input: "x", - Output: "z", - Format: "t%d", - } - // Translate to IR. - p, err := acc.Translate(s) - if err != nil { - return nil, err - } - - // Apply processing passes: temporary variable allocation, and computing the - // full addition chain sequence and operations. - if err := pass.Exec(p, allocator, pass.Func(pass.Eval)); err != nil { - return nil, err - } - - return &AddChainData{ - Chain: p.Chain, - Ops: p.Program, - Script: s, - Program: p, - Meta: meta.Meta, - N: n, - }, nil -} - -// Function is a function provided to templates. -type Function struct { - Name string - Description string - Func interface{} -} - -// Signature returns the function signature. -func (f *Function) Signature() string { - return reflect.ValueOf(f.Func).Type().String() -} - -// Functions is the list of functions provided to templates. -var Functions = []*Function{ - { - Name: "add_", - Description: "If the input operation is an `ir.Add` then return it, otherwise return `nil`", - Func: func(op ir.Op) ir.Op { - if a, ok := op.(ir.Add); ok { - return a - } - return nil - }, - }, - { - Name: "double_", - Description: "If the input operation is an `ir.Double` then return it, otherwise return `nil`", - Func: func(op ir.Op) ir.Op { - if d, ok := op.(ir.Double); ok { - return d - } - return nil - }, - }, - { - Name: "shift_", - Description: "If the input operation is an `ir.Shift` then return it, otherwise return `nil`", - Func: func(op ir.Op) ir.Op { - if s, ok := op.(ir.Shift); ok { - return s - } - return nil - }, - }, - { - Name: "inc_", - Description: "Increment an integer", - Func: func(n int) int { return n + 1 }, - }, - { - Name: "format_", - Description: "Formats an addition chain script (`*ast.Chain`) as a string", - Func: printer.String, - }, - { - Name: "split_", - Description: "Calls `strings.Split`", - Func: strings.Split, - }, - { - Name: "join_", - Description: "Calls `strings.Join`", - Func: strings.Join, - }, - { - Name: "lines_", - Description: "Split input string into lines", - Func: func(s string) []string { - var lines []string - scanner := bufio.NewScanner(strings.NewReader(s)) - for scanner.Scan() { - lines = append(lines, scanner.Text()) - } - return lines - }, - }, - { - Name: "ptr_", - Description: "adds & if it's a value", - Func: func(s *ir.Operand) string { - if s.String() == "x" { - return "&" - } - return "" - }, - }, - { - Name: "last_", - Func: func(x int, a interface{}) bool { - return x == reflect.ValueOf(a).Len()-1 - }, - }, -} - -// to speed up code generation, we cache addchain search results on disk -func initCache() { - mAddchains = make(map[string]*AddChainData) - - // read existing files in addchain directory - path, err := os.Getwd() - if err != nil { - log.Fatal(err) - } - addChainDir = filepath.Join(path, "addchain") - _ = os.Mkdir(addChainDir, 0700) - files, err := os.ReadDir(addChainDir) - if err != nil { - log.Fatal(err) - } - - // preload pre-computed add chains - for _, entry := range files { - if entry.IsDir() { - continue - } - f, err := os.Open(filepath.Join(addChainDir, entry.Name())) - if err != nil { - log.Fatal(err) - } - - // decode the addchain.Program - dec := gob.NewDecoder(f) - var p addchain.Program - err = dec.Decode(&p) - _ = f.Close() - if err != nil { - log.Fatal(err) - } - data := processSearchResult(p, filepath.Base(f.Name())) - log.Println("read", filepath.Base(f.Name())) - - // save the data - mAddchains[filepath.Base(f.Name())] = data - - } - -} diff --git a/vendor/github.com/consensys/gnark-crypto/field/hash/hashutils.go b/vendor/github.com/consensys/gnark-crypto/field/hash/hashutils.go index db7cff3e130..7c3b970686d 100644 --- a/vendor/github.com/consensys/gnark-crypto/field/hash/hashutils.go +++ b/vendor/github.com/consensys/gnark-crypto/field/hash/hashutils.go @@ -6,8 +6,8 @@ import ( ) // ExpandMsgXmd expands msg to a slice of lenInBytes bytes. -// https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06#section-5 -// https://tools.ietf.org/html/rfc8017#section-4.1 (I2OSP/O2ISP) +// https://datatracker.ietf.org/doc/html/rfc9380#name-expand_message_xmd +// https://datatracker.ietf.org/doc/html/rfc9380#name-utility-functions (I2OSP/O2ISP) func ExpandMsgXmd(msg, dst []byte, lenInBytes int) ([]byte, error) { h := sha256.New() @@ -22,7 +22,7 @@ func ExpandMsgXmd(msg, dst []byte, lenInBytes int) ([]byte, error) { // Z_pad = I2OSP(0, r_in_bytes) // l_i_b_str = I2OSP(len_in_bytes, 2) - // DST_prime = I2OSP(len(DST), 1) ∥ DST + // DST_prime = DST ∥ I2OSP(len(DST), 1) // b₀ = H(Z_pad ∥ msg ∥ l_i_b_str ∥ I2OSP(0, 1) ∥ DST_prime) h.Reset() if _, err := h.Write(make([]byte, h.BlockSize())); err != nil { diff --git a/vendor/github.com/consensys/gnark-crypto/field/pool/pool.go b/vendor/github.com/consensys/gnark-crypto/field/pool/pool.go index 6bb10bdbdc6..373610588ff 100644 --- a/vendor/github.com/consensys/gnark-crypto/field/pool/pool.go +++ b/vendor/github.com/consensys/gnark-crypto/field/pool/pool.go @@ -22,7 +22,7 @@ func (bigIntPool) Get() *big.Int { func (bigIntPool) Put(v *big.Int) { if v == nil { - return // see https://github.com/ConsenSys/gnark-crypto/issues/316 + return // see https://github.com/Consensys/gnark-crypto/issues/316 } _bigIntPool.Put(v) } diff --git a/vendor/github.com/consensys/gnark-crypto/internal/generator/config/bls12-377.go b/vendor/github.com/consensys/gnark-crypto/internal/generator/config/bls12-377.go deleted file mode 100644 index 62bb79b0719..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/internal/generator/config/bls12-377.go +++ /dev/null @@ -1,322 +0,0 @@ -package config - -var BLS12_377 = Curve{ - Name: "bls12-377", - CurvePackage: "bls12377", - EnumID: "BLS12_377", - FrModulus: "8444461749428370424248824938781546531375899335154063827935233455917409239041", - FpModulus: "258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458177", - G1: Point{ - CoordType: "fp.Element", - CoordExtDegree: 1, - PointName: "g1", - GLV: true, - CofactorCleaning: true, - CRange: defaultCRange(), - }, - G2: Point{ - CoordType: "fptower.E2", - CoordExtDegree: 2, - CoordExtRoot: -5, - PointName: "g2", - GLV: true, - CofactorCleaning: true, - CRange: defaultCRange(), - Projective: true, - }, - // 2-isogeny - HashE1: &HashSuiteSswu{ - A: []string{"0x1ae3a4617c510ea34b3c4687866d1616212919cefb9b37e860f40fde03873fc0a0bf847bffffff8b9857ffffffffff2"}, - B: []string{"0x16"}, - Z: []int{5}, - Isogeny: &Isogeny{ - XMap: RationalPolynomial{ - Num: [][]string{ - {"0x142abb491d3ccb00d65810beba93dbb0a661fd85974d6aa82c4bb2e1a3c84ffdd6ef419b80000000000000000000000"}, - {"0x4d9d782ee8a7b7630cd57be9a2ca555e2f689a3cb86f60022910be6480000004284600000000001"}, - {"0x142abb491d3ccb014ac44505178f6ec539a237640b7ceab573689a3cb86f600114885f32400000063c6900000000001"}, - }, - Den: [][]string{ - {"0x13675e0bba29edd8c3355efa68b295578bda268f2e1bd8008a442f99200000010a11800000000004"}, - }, - }, - YMap: RationalPolynomial{ - Num: [][]string{ - {"0x142abb491d3ccb014ac44505178f6ec539a237640b7ceab573689a3cb86f600114885f32400000063c68fffffffffff"}, - {"0x35c748c2f8a21d6af848e30c1b78229a46644922460e73f6faf06c327b438084815848140000010a11800000000002"}, - {"0xd71d230be288756a6446249c205dced645709767bd81c863eb7f8d8e4f15003f5f407b84000000a64af00000000002"}, - {"0x17872fd54cc6ecd6d73a5085f0d2013b6de7eb4a0d6711d3b14f5e9c2c81f001429f19baa0000007467a80000000001"}, - }, - Den: [][]string{ - {"0x1ae3a4617c510eac63b05c06ca1493b1a22d9f300f5138f1ef3622fba094800170b5d44300000008508bffffffffff9"}, - {"0x746c34465cfb9314934039de742f800d471ce75b14a710033d991d96c00000063c6900000000000c"}, - {"0x3a361a232e7dc98a49a01cef3a17c006a38e73ad8a5388019ecc8ecb600000031e3480000000000c"}, - }, - }, - }, - }, - - // 23-isogeny - HashE2: &HashSuiteSswu{ - A: []string{"0x152964189f4c623685ae0423eb10294ce6458c064f093208504005b37d04d5d336dc9d66a97093f84d62e778f8c82be", "0x735c455387ab435839e5a5dbc1a30510070300f4becac797642fe56985064e95f7d6521a1a6e71004047f835c1f957"}, - B: []string{"0x19e38372e0d4bf401d2fa5f2261e1e3fc95d51a3857fc23b1385d51ea9c973a89c22148a93dff96447700bf1c3aebac", "0x1579ddb5c1c595b7c08c3a3cef5626143c25757c6b67d0a2677b22fc0c890d8b2b1a17895d047a98c49047069f725"}, - Z: []int{12, 1}, - Isogeny: &Isogeny{ - XMap: RationalPolynomial{ - Num: [][]string{ - {"0x113b0abb7ba48832ffb7aaaa7ce085078312d4bf0bf8882e8f4a0a6e24d91b535b6c81277ad9369cacc733de5cf86d9", - "0x11e62d211119d8108bbf13b3b4b79a1aabbe2d6004858109139667b300e5097370015d42782ca1bf7652dba1d4cac3c"}, - {"0x51a19546efd3c582ec16ee049bafb8ccbdd87d98f753e654e0b93ae62a627a6f610b30f76016baa8d18dc4677dc401", - "0xddc3aac50aa5af86f8c1d31db787f4b6ac0262a8ea40c07d61389c2a70b06c51fb59520394e05c55c72e363b9607a1"}, - {"0x93198927f09c55a596756ab909a06ab3c0127be6538fb275f2b7b5bfaa1ab85b12a45ef345d628d5c6e69effd7e76a", - "0x2c02fb38b1440c7b2d4fae061763cd734c40b1eddf1ca9552554d2859906f8d6290038a485a655f8178f99b1fe43e1"}, - {"0x19091208a40d61bd9a55359da28b532617da69a58addac35288930ccd5083166d791cc7dd3c6533e01f786000c532f7", - "0xcf913d369130273a81f982f469bc8fd98a8983af247d28845d76729468a777836e1d3cdf1e1adea6b08566db5b514f"}, - {"0x181a36b975099a83b4773c6e62d93365d5fd3787c2b62d0a315245f6226ab13cd462f731b73a436a598b34dc0ec58d0", - "0xdeebd58f0234fa272439c69d9f0ed559b955d416256645c2ab1857d988b49109ff460206e2b978d877fc9274fe4840"}, - {"0x10cd4f85b581fa9bbd614f001a2e64839a4635373187b57373f17f77e11ea30ce505e6ebab860ee2aa46c9e6b327add", - "0xc1f11111a68f3346dfeb807985c61491498efd3439c5c7a0b77e9d819a48be950e43c9f30cd21e5e439815a2ab6a9a"}, - {"0x1813ccf2b39896b88561d57592c5e7d7594146f9eb341852cdbc192e88792058059bd79b248c5b8c415d6149d51130a", - "0xeb958c5ed40e2b75a170536e42368207df82fcc26518f6f83f40cea65efdd81dcc248290c660107e0a2d650a38d526"}, - {"0xa143ff2d94ba2d2322d63cb3769874b17c00fe76fff4b53fb5fa4744da3114899adaca240bde7d88357aa80b144bb1", - "0xa25054cd91b2b06cdad439cdf86265929d35738f09e759a56164861f45586602c630ef182e9262f0413374b154dd20"}, - {"0x1f0a897c94b01589c9eb5cdd999c580c284f39c6fa6f2ad0c569c3b219cc245484ed7310b858f980b2917508d94f59", - "0x5c56eb37beca858c993f39fbf09b73efbd98934b5b1d8de0c21fc75d20075e6d7720601832565b1823339bffc17a6d"}, - {"0x13a21ac110c90240e49de23070e86bcb64b8c500d8f9d792095a0a7f9133f4d8d94c518f9eb1359c8c82926e41d004c", - "0x18471a982b5d8d7756ff4971fbba3945be37cea5cda74e17674b76cbf527f8ae51a27236a95d815a4f36a2461df5b67"}, - {"0x380e386dce2ad72755e1d21461a3d33ce275b036c2a11a755df7e948161f3318531311b8dfaad26a2b6af699e42f07", - "0xc86f279fd500d0594160f87a462ff89f4b0db7b7fe6bc809871f11183f13235d343e0a8bae13c9f5791a2821ce8bf"}, - {"0xd73c34c8f904e327cd1fc22e8a90e04bed13e46eb98e3d47d18cde142b9e0f3a03eaac69214acac03042aa9b9b6495", - "0x76ea3cf6b7185d7d6e3e73ac03a21b645e5aaee7a99dccecc485620fdf64e7486c7b1e4f8b6e069240b7a1e76b0609"}, - {"0xca983f9f6ea728c5b4bb9a6dc72d24ecab7833e1a8242bf1a84140deb996176a8f7c7d6fe34fdb4660afd6dfa5fd74", - "0x7e4badbdba86487f1b87daccf8d14f62bcb01bca058d8e318ad40ae8343a47d40f6b18af1e0bf9860eeb32db4f02aa"}, - {"0x1552beaa2371b711181b528b4ea3e801e3a71c2bc0bde70a2babef6d5702ff12af4f5f2823599093d5485b94c873d36", - "0x11783b91dc5ce3d03283278116bb901408dc61ef8bad40991144de2f3509787d83b566820fd315b558ccd76c9debd5d"}, - {"0x175374ccff26ce81965dce12856efd5cb587251e70a588e2e4633110d65bf17f2991df664e727ebc65b42d74a938e4b", - "0xe75b2e26120b6428e51285251602a89ca9f865d444853ac3527b940d7b218df89806e725ec52e75b92dfcf63616483"}, - {"0xecfa3729a48226a477e72d4067aa372a29fa8943324495f2f39f754bd1d114fc2d9c62453fde06e3272bf09faea06f", - "0xe95c673c49bda6dacee18f07327cee3902582326fbe658d3e8cb15b40327b8b7c1b04e0160071f1e8c617361754705"}, - {"0x155dd556a15b55b766cc98f3455788f3ca450ac5c613b2e1464b53f0e5412a626e423cf9dd5127edaa6deeaa5638f93", - "0x15ac434170f220d28273b44c48eca01f2cfaae20e2342429ca6f3668e0825821a3d7f1227db23b1a7a36e7f8abf89e"}, - {"0xe785dde291472723e95d737c7bc0bb72a8125cfbd91b122beedd3f45dedefc1480e9350bbfb6a5ca2fb9ec905573fa", - "0xe01e2c8ab4ddf439c8d4028ccc68b13de8099e3aa7d5120867366605682a4db4ec308cf07e043cf7256e35c23ecbc7"}, - {"0x4e2c05f403fa31d03e91053fb52a3fc12ae58977575f53cd8a52b53d1067cc61de65daada7c7c1bf5bdb07f3719b14", - "0x18de34a92f81eba3a57d55a9d4bd5cf7da7b1794a0f9ece37abd537ddcdb29edbb01aa88baef416408d34a227874c33"}, - {"0xe4a28f5d9cdcb181099868140cf3064cd573f892aceb79e3df63546686df19a3164efedc851333bbe232be84e3e627", - "0xd31f8027ef5f6b916364d998dbc4640196191cf0ca44e2c2c4825bf4babd706351d21f1f6177ee4c3f5d16928d059b"}, - {"0x602985c2bf7472638e59af721dc3e635d08ede15ad23084d54441a493d515ab9d727832a06110b8a5e4cdf978980d1", - "0x159cb19fac8df89c704efce7423d8965e1477606471d21f77988cd744d0ea0938a85eb4a21d41a34c97d64a409f7314"}, - {"0x12f6020b2f6dc691f96e6a7c5e42a221a861c1b27223e30adbb75022ff42f318e8d96e0a964dfcb9dd0d20fd3a7c247", - "0x1766ffa6c449787005d03e90251c271190a3c8e6db8383ce2925b91c87ae29c989d503705ed7566fe5c7bfefb6902c6"}, - {"0x471dda72677bf4df7027fff15bb88083362b56b41dbbeb3e3f9afed6c7fd9b8e03a7b66f7dde784cdb94ef12714ed1", - "0xb95429ba2726547f58f812d8516a9c7545fb43d2080d1b154e4e8aaa689a378141fd28ad946cf12fef100e180c9762"}, - {"0x1ac99df3bf98db5235d2892b0f00a86db204cc8f367535d37ff878fd945bcd6f4991d08e3d7598788e2f860c950d110", - "0x0"}, - }, - Den: [][]string{ - {"0x146e50faa64a7651c3b0b61836501a66805927dcb051b32662d0d261c3b5458776918917726e7ab20050fb3f1e9d32c", - "0xb1ea777f7008d8bcafa4799bac2e33475d6b287b6c831af5c06bb778507412d8aa8d347a14ea074b7983518d668616"}, - {"0x79f0dba8c34b89c8d1fd2363421e1f97f7f12579ab42f520b86c9e7b44e822fadf62f6e98bfebed3065ef7e6d873e2", - "0x40dd9ff7e21f5f6802ef1e47c240880f84fbe0232f659145f22f9c842736890572e9a0018ff427005b45140ad2597d"}, - {"0xde82c1e45e55039d5d8ae4684e278f230e94285b4bc97eae01f84acf258e9be8888a96dd0fdccde825922ec5517ec5", - "0x101b161db02dadd38c1b219d253f01728d2b3ba65e3dc05ebf102ff9fab2f2ef1cc95047570148228b4915820b0301d"}, - {"0x19c6b7b7a90b244a9cc8e9cf77c1fc40ffeae17efe57efaad45c6b85105effe955b8aec25cd5a33b5fe1b403099cc87", - "0x1658235a28d3dcd62a783eb6e135a65f19ee1ded96bf717f26fb9e81763b6d1d0d32ef686998776504a5c6426ba2ddc"}, - {"0x1374e714d24649d3de48ea7e809ed20ba8de79a7a95b59e26babe22856e57c5f9e6667da8107e27b1215afe2846471", - "0x9fa434f0a714ff9b2bb5ea51856efce45659377666fe4377774d04ca63a1ae957c5cc11376defad113c94ae6ce4652"}, - {"0x11796b770f7504fb0a25336ae91aca083bb600d5523a27885e44f3bedff57966411346d44cce4bbaf50770a210445b7", - "0xa5dc732bb3f95325df484711467e89dc69a7986d2439a692fb9667c22512d87f968d452c1a7a4af94629d6fbfab126"}, - {"0x36fc8fd543e00229e3e56ca9655db01cb161ad493c35d5225acea1924f2673890b0981feb9170a2b73e1ed5852276a", - "0x11e47853a548367d9473b4251c2641a1a05ded1721fb74dfd4455bb41894cd35ffa77ac1a1dda4171e8e3c598cc0cf"}, - {"0xec3aecb4916b2621d73c22adf37fd2bd067cfcd09f38cfa7060c1dc08573f6e6da62ae459d00c719b153b23eb30380", - "0x33b7e5c5174d637291e17246bd01864eaf2b12d27ab74b84e029ed82c9cf3551faa44b79bdbb079a9f57f598e8c35"}, - {"0x14d8b5c3fe739ff9bca51db2433814bd39a0ba8f082801125801599b81682fe51896aeed82936cfc3d7850d2f9622a3", - "0x7adf53096d8b637caa65a6703d654842a9b7d4d82a1ebd6ae4eb4cf7df07912638d359dbfe6f8443fcae492cb150c5"}, - {"0x16e8eda7dfd1927fe1dc22dacaa78237dfa0714315f535e804649326acfe5c67a86dcbee4d78a5d662ff122b8580245", - "0x40de374242af4c470b0952cc13dae780d77d43729e9598ba3173ac586624ebe305c8c9e6e5e7245f98a970af1ee60d"}, - {"0x16c94723b3eacaa13fef87169f4eca0959eecf2184d6a7468da9d8f32acb6a36c5254bf31d733f5b1c053dd88e54282", - "0x19c508401f6e0cdcf9e2b694c12550eba4247c85c52b8aba5991f9aeecbefee61355271663b842b0b23c0de66bcb8f1"}, - {"0xf3ffd87f27eee739719fa368e3d9bebdb8f06a192b5ae980b629ad78421034b2f919d658fbcd1490fc7692e1e916ce", - "0x1468f37ed6477c421170d67235b0370aa3388db7e4c0cb3dbcf1fef55b2c7cd6989451199b411d7aaf8a5b24436f6e3"}, - {"0x1035e4ec93dc6bc358f961e7dc4c82087605cbe2bfdbe713fa5e7b21d75c1ad45088bdbc6daaa2e12d1f0bcfb4b84f7", - "0x11e842bd544d0bbee76808f0a1ba264be31aedda57ceb64330b587d5a89d03598cdb8d2b528fe56a02dbfd48e8aaa83"}, - {"0xe57bf7b799080766c07fa8b997f65da74043a005d785b60215c0875d8d80a2a55de8c81dc081ee75cafdcb6d9f5bab", - "0x4f2c024aca0ee3f8be88ed1450ac2448d3bd8b540d7cb9b5d93d68eedc20119213d260c02c7dbaa180aa008407b0dc"}, - {"0xe0b435cad88cfd17508b5b3da274b76521f715b9129c3141f70a3c7dd22e14c3fe58a5db7c168f47c673d91a05c02f", - "0x16ba8b632d08a5abe396f990cfc790f6d29725220c89e7dacb3be59699757c6245bc0793bfeb5b2f917508cdd949a79"}, - {"0x17c5e37674a25c3385908a02be0a23c1623eb710deb01632301277cb968ae2bccd3e5b38e144e424a9da459c4b8600a", - "0x503556d7e47b59d5888f787cb7cec46d917d02f8118e01a63ffc3b01398260d7c722dc26c7cd03d7c05e1a996e5471"}, - {"0x890e4e58ded34996cf252dc184d7aec1c1866ad2da0b50ffc208a1ef31dd9e277b3f5e2fd1f3cf9422b81c526bbd0d", - "0x108938787e3377815ba98065f7c57b955fb7bc2247a21fd516fcad09652e92819c4bd34cf9be483e261639e540ce577"}, - {"0x665b1acc1e271d15bf9416f014ae1ddc76838a60230be0cd17cc7505d6b5f7cb01037545fd2c3b9997b0745ad8ad9c", - "0x1ae0fc9e185ac85323228f01780e30ba86767c59cc90d2d05ddbba8d6cf35bbd737b7fcd09b3850af513ebb6fc3ced9"}, - {"0x16db2dd779c2cc1699abf727df65339443007994b70c43a8d9767e265dfe45809093cc631ba5b79f1280236ac93fddf", - "0x43671e62ee377b90bbd80c91a3dc1eb53ed37ea8ae6ccc0154e2f1cf498198acc92b2ce3c07e292b2b5f038c6c04c9"}, - {"0x93b2b87c160c52f6b056e4c085930add9aeb706709ee013eb54ca60bc820b0da42fbca8e9c9a579585bdb8af77acbe", - "0xcb5381cf50932ff1dd7fed460732ae9311b24ab543d98304b80963cf706598ef147c2b047d6c2e49357f5704e568ba"}, - {"0x731b19b58014b17a0be1915dfee088ceb8ca7964deed74d985adfbe0e9aa99cac1453ae4210abf949afc9c7425f2b6", - "0x3f906b21602c1254dc293fbddc3974f24bef13d0291760083c7a125c8ad5c49ed9ba755743e9344387d1e712d7ede2"}, - {"0xbee29453de653858b3b37cd3b85e7941177c94de27ab781cb8ea619a1b9668a0b0ddd01318b6699bc582051c23dd8a", - "0x1793e129728346d60828550ad395de628b4f4ab2952bd0e95003c382bebd49daa486d981fb51dee163ded1fb204d09f"}, - }, - }, - YMap: RationalPolynomial{ - Num: [][]string{ - {"0x19474819a519191689e0816c7f84b2a58a6a5aaf5adfd7fb0204d8623f67c19e9a64d522ce4c963e32de8edfd367284", - "0x100e238102de877617418a44564d9379372b6f69c721b205c60af2e298bfa546a7c7a39883e433f947601b24266a306"}, - {"0xb58b352e8f9bc6162e40b4ab27f066cb71ed844e9b5e376cdef8e8be14e38d2f13392f19da19ca1faa758bbb083dc6", - "0x3293cacae9e6251abad8ac4d8263754f1301062d54ff721d183d201f9133db07341cd48c721d8b9ec40e41d4bd0db0"}, - {"0xdfec4d8ecb1cb0adbe13f68ccb2e070bcbf5ee3ee8328cb6613a63a543c252ef4ecb525fbf65ca12f33b425da04d5", - "0x177fa15abb4e47ced85ae0765a6aef971131743de887073556fe92f142b83a8355edc8544530ed7296a3e21c4f9828a"}, - {"0x17bbcf8bf3802b3f868ec94dcbb32a8b0cfd5f62daa2079cf8370b487cf440c664863e710ffeafc40cf374a58263139", - "0x16f6e49903922180e44d4bc45aeb65f093fe4fad10cf29583c3664cfbd76b9ca5b9a7ef2337a62cb2e45623cee7ced3"}, - {"0xc1fa03051d6150ed02ce658113c5b9de9232db80782740741c13e95afb61ddc78d32e0af5fa67e2df4203ea7c7f720", - "0x1a20dfca20c821fa263e1b04009e6e0f5a373e665afe7f603f0bb9703ce6864cc9ce09aa1e2d694a16082973591eed7"}, - {"0xed3c8528803a2e8ea1d51fbc40888c93aacdbabaf485d5a8a037472849450ed254f2bf0876516c81b466d03adc0b37", - "0xe0b3c359ae53e4901f777b107add779bd384d8da8a46c02f044cbeb099743b6888cc191d97bd035de9136783ac7866"}, - {"0x108e5399fb0e462641e346430020b47260782a557c8476b06aff3fa95b6251bfbd40dec8c213b3355c50a24b96d95d5", - "0x1aa7ad61ba7c96aaf8b72db59b48309bd72b50ec5781988ba9a55a43b4e4a595e36aceec3a51a1804a788848e9f96cb"}, - {"0xb16e02b02354b93cbf74b3551a94aabd0acfea5d6f20c56eb2f46433003d2dc4225912600eda79dc7e3adf0702e763", - "0xec85210b0e638ec662fc76335f470cbe21a165a66aad036058932f6d52e77f1b6e3269cce0432e1404b0810c053c2c"}, - {"0xc0b22a4dda3741b4fcd5b6c2abb9d2e8481ebd442e00d81865d70c8717d4c6c78a41e6f85c97b10fd010d8a966cbaa", - "0x1396ca7d90b82b12adcfcc5d81a850203097d56d9ef35381dc666cbaf594b4e033e6a525460e4ff6ba10bbf1afd94ce"}, - {"0x14c78f774a2896fa64a052004df6fb736bf806e662e9d7097f589b0df03fee5aee9609407005296ea99b879fa0ab8ac", - "0xcd6467d031974a892ff5ecff9f2f8d46a53e674500111351806a15432a6cf8744725b9c101161d59c792807b253a3e"}, - {"0x1526589e372650ab85ccf35382db0e7cf5d02f0de09e848caa73396338a01b9f6064695efe06eabef61098ea1c0c638", - "0x68acae9cd1355b5c9781656519838b804fbeeb960df4bff77dd2477ef674d7240676b62cb03a51326f8f47f14377e"}, - {"0x167a5b9940feddfc5ea3bae9c03a52e10fdb3b7055e547d27fa804baab5c74796d2f1cf56675c664229ecd622f32ed3", - "0x44f0cdf3744beae8718ae72373f6a01838b210bf23bbc13d3522d5595f45980057324c394fdd5f4a588716b2c0cf2e"}, - {"0x1511bd492587501195e9a7df7360c8e8fe72d53b57cec62eed296b202b156724087121691d7e7ac6d80656b40604602", - "0x51219c71bb96909a005e363c5ec60f36c77e407fcc05e801c3962f83566d18ae9ff4a658d0dd08e1d90de6c758bbe3"}, - {"0x48208860fc71ea0cb4a266e00c3ba02f8c272902831fc7d0a26d4734eb1fde8d496dec19ef8b076fde5c77b534f4ff", - "0x6707d246dda7a0a59b2b054307653dca9144172aa6281893bc9f681368f71325baca1eba0229dc19f9a7853088ca8c"}, - {"0x32a1895b110a91f8fb9e1bd01a312d28281131018a0ad9470c3c3ea1952f63ce90112b8d5ea7bc933d4f1cb426abe", - "0x6fced059c7cb1819994a13bcb3d805cb1170eb16e35561c90c1454c4af849c5eff11b66554ee507fec5c0ebc4eebf0"}, - {"0x182a668115cbca00c180b580798d261e58b4d2c140ccb68342ee5a859b51af3076e871060c103c2a0b4ca8a80a43a08", - "0x458656746821dc18aacaf7533ef33077889590c4eb36a545e120d40c812dad8bf3c8b3425a427a0f58e49460a4f7f0"}, - {"0x1371823e71e71d670cd8509978788f70e4aa0ad9e88dd3983c8b52a688c11865b8d1a183a82c866cebeaa40f4f87295", - "0x3fafdb6deb055c9eaa8a59bb2fafee94632d4c538c8837cca7743fec86a8f9ce24bdbf3e34595d1bb9e43571cf2370"}, - {"0xda0900c121f7a9a289faa9bd55ceaffe9d93a38a2b0890875289abe4a4491757eb96eebf7c2babb6169994d7eb414", - "0xfaa7103de621a04fad6afeb3e1334e1fe69a19029bf77e32833684a5e6c9f1a9fd6cbd6efdb6496b95fa4b20521f9"}, - {"0xdf001ab5b668caa34f373dea333476adfb1243e35453af80a6e66dabd825256f185763cb22112686723a50c47acaba", - "0xffdc67df2a8983f611da939f6b81abc4db37ecbbdb4409abf9e1eb6f763aaa51fce86f4ea92e4500079313a249d7a3"}, - {"0x2967da20443829494af8becbaac23650aab235202a7a20e64e52e0bfa17d045a066167931e3dbd41d55eb956d2ed10", - "0xc7f02fdee5f78a0a03e3abe964cb50d03313df2c8fe42b99d16f3af8a2a0bcc1a88449924ebe0acd21bd3ce63128fe"}, - {"0x13cac271335756e85815b2d299b18f25f34c16d33b8ff67e923b74f5c468196cc31ab24a3a7ee56ab9e4e10676fc0eb", - "0x18a1b7092e497c2b1ce9e73f447618dcb50b43e20f6115931833d0d1e79da6f3d728e4a1b651c0ff536cf2549919282"}, - {"0xd4ec1a90744458ece499140238ae77c1de76f242a8a05f1482eb221783eead306e1ee6c15da37f4363df82b6cbfd56", - "0x7eee2877ada79fb65b13e1af4d49a98ac24dbe7965a7dd9d4150274a31032ceb4a3a0aff0369ce7b15235d91cbbc25"}, - {"0x2b277ffeee377436109a9f871027362a333ae2d49c65c7452be93c50a2220673b21006879b1fa9b10c5c5f0d933f38", - "0x9b2ffda579da5430137b22b26fdaa13f52ff11c13f4f88fac0bfa0c30b5c1bb190d8728a60153ec7986dcd7dc5640b"}, - {"0x949aedd81f20923b0b0e5f5cbfc2c0cf7ba155ed488e756404f6adf9ad0c85e8bbe102a83693e805aff42b7f21617d", - "0x176910539df9c32d55b92b8f843c668db490d8905e108f18d1b136d45989a2d2ef4cfae817975c2729cc92032d905eb"}, - {"0xdd974b42d37d78da2e8761e99596fd113add085fc115b9ca57a94c218b278addb80c8430bab38b8d53738fbb33b75c", - "0x163fb82f31df72b309c3422ad404ce953f5fb5292fe68cb61b73100bc262a987e46299e183fc582cca8bc848dd7c621"}, - {"0x15d0fae7eabe20ca577fc60964b17e021e699c1f8ad28ecae4f3766dfcc924a5a89dfc48fa0945e9e650c45980affc3", - "0x16d1223b7d1b6311f2462306650b490d11b3772de34b66fd06810fd3dc56e90d15382767477c4952d25d0da2656d6e1"}, - {"0xb34a5e0ece8efa676afb297e8a81b8c5af019a878bee197bc4ecfabfbdaa46da1ed1a51cf3b0f1ed90691dcfd2d594", - "0x164c4047b6cc6e62f7c7a00c215157206c7b50adfc52435469ca2846701fd8857ca14c5ce17fde980afdf2b8ea58d2d"}, - {"0x167fdf7ff361330674041cc850f227daa736a1b450928a621273de03cb104998d76a529c84a9cd93a91ccde3cb4623d", - "0x18a6f2eb4840007bb2157cd6809ac05f522ae2e4047f77f4de06732445c7f03290de120acdbfe3d4590edf09ac3d0c"}, - {"0xf8649870cd6866641205263c10df90d9ba3c8b56d8ceb178c4897ead46bc3be88ef7e0e31952dd1396ac6f7905b8c7", - "0x9a05a5b1cba4d191bc5098efa547c070297e57748416d8386d72875a5cc5127d3a9109b88bb74bd7552b4eb3106175"}, - {"0x1378329c9fadb2e63f34a6f55ab5335ff1b5d913c2d7edbbba48295caa230f00150d65d25dd44880cb562ca912495c9", - "0xe5f0b2d55f8713e807c8fb1f96f13e0b5caa3de8607f04bd93a7260e3d8810a48860a9626c7b4a424bdaad21741308"}, - {"0x11386a65a011fb28d612fbc7d0f76b2dec1330512b504f541d09517a0cc00f0f49b6fc1fa52a8725965385dbae1f4b8", - "0x170632bca9a590287a0ffac955344cc8f15e59118f03adbf86e07bb82f5bb76cfb7fbf1e42a1eb384ff9c11f21b910c"}, - {"0xded86746533417ce10e14535b4811d2246eae38429763e4427ffa9dd12120df30c8c36497d089a06066626724c6cac", - "0x40ad9ca1fa683544a978c718fae74751b37a5dac2b57dcac813479f9ebb387e9ac1eafb90b12483b5282391738f286"}, - {"0xdfda607fa565d6becc5842deda97367bbf14db84a0cae4783dfb89d2ea2ccedefca2ec5883577294bba68a29815d6", - "0x137601d38808323444ab0018632b9e567be332256b624b8ce929756c42eab72fca278590b52071b38b711be22f5b0d5"}, - {"0x13dec721e4606cc9691488c3d003366a1462ba6a713277de0503f1131d1d61fab5c79cba5bb7332c6abc80435464be0", - "0x0"}, - }, - Den: [][]string{ - {"0x126e7ae82b984bc44d0e37b08e50643a99f06396f1ae9e20117c4bd86b9b1939fd92c3d95ebd307fce9080a95674e4f", - "0x18561a650deca0ad7df837e9ffaa27f0b8e85ff347362f1259d3b1e529e892327aa7c6ccf4a3ad6e365226b8d875fe1"}, - {"0x1a9963059b91cc5aab175a23fb536129d851da9e2f8c5bb7165e05937bdca1db1508e98843f1f62c047ce3d6ec8fc60", - "0x1fb73b0a8e121906f51d20eec7cb8491cb61bbb3b3ecaded3df7283d9128fc3635307f3c3ca133af720d9775729e91"}, - {"0x8b9ff20c9eba7b3dc948e79ce661704cf236ce6bd8361d146491031d3fc9e58b338a67ddc8548f4a36460fb5dceb40", - "0x3c27d81172a310833e5ab3bf81225b01c4068b13026ca1deeebad80a558665100bad779466ea0bc4ccf4c4ba3d9c7d"}, - {"0x1642ab99157e12e44ad3e54b1fa7a4ec2d80b545653fa336b5aa5deb0452f3d47824cdc51de8d83775d658426e24e3e", - "0x7d42c28d3d9fae9c3286c2dcb8826e91d7b36fc45468e8f64b8a029c91863cebd4add2412ee5f3bd090bcccda03ab6"}, - {"0xb233cdfc79172767df7df3731177932ce335fcff5e0b1579c01cf6d34d3747bebe1bfe3b111ef9176fbbba581e459e", - "0xbe45fabc97a7c23a215db4b2aae647fa5749ad332d9a66eccdcd7195a412def4d28ecb256f45d5879cb6b4e6e1d396"}, - {"0x4684f66af9512c51edcd89002de77e666b71ff7151c341319a44095d8113addf41f718b54842a7c29432ea9e2b8b88", - "0x88b603e95e15fff2d8bd1f77ceaf19ee06b7a9301faf29d983a8962bf7969a6b3ddbdfea1ee16f30cfb81cf7e21715"}, - {"0x354c69013ae211b621a899ca7a65f4bcbea4d39ea633002758cb777ba71f570995d52adceb2fc931d92a12398eb12c", - "0x175ca20c6e2e1b0b8305dc90cced8b1e4c3f4493d341e46e39b6e33741b604f1ae9f8b2be59f4a9a52e948c802a108c"}, - {"0x58a2ae5eeb2f349aa139ef3ddffd1df269c2cf99e23d6f64ed7ee9bd2cbfde0027449827b1e2b116da86ec051e0f07", - "0x47776d799a1f49c7bfa7feebaf8012282bb0dbc4b1ce41448474e41e53f64a098c71c79ecf21bece5867750a030982"}, - {"0x1a0a1098c733a0ba9c9ed018ecb794dfb3b84b048ad03850b46e6cfd1e1018fd25ecd9924e4cc4f61e490d92fe1ed89", - "0xdb1cc6b3b535c13494ba5c4ce330f401298118fb2c774b057daf91e1919b84ea0982828f8a07fa58cb3ea8f0201cfa"}, - {"0x1a19656718399a35e838587e3ca3aad4337c715ec6baf72f3c7e3fca08fce3651140c73a45031117e9e0ab0f7496b3c", - "0x11d225e689b1c5533a4da5615ccfd27032d2a33de261bc8c83e1d938637efe7b0612df05f42d2d858376b499c652d75"}, - {"0x1a97aec63b6f352e2a2494186b69f0276247a857d82f7879e7d6c01e4a38f6e9d97e347e87ce507a5b94f2b3773eac6", - "0x8256cc2663dc6938ae7605931d1a8f441ef85d2cef47445416cb593d2860d2eefcfd9a3c35d76d25d17109a764ebce"}, - {"0x9deeddd201ebe394bc84236d884b755378a169e31bb81e389ed375576782cb5fd30a4cbbcecabdacb808eab7c6d4fe", - "0x174a2760a9f8253d0539dec3d626f269841b51a989ce5205fcc09366eebf6535bab520fc56d623cd04fcde78d685a0b"}, - {"0x1e3c14cdeaa4ed3e266a36616cd141dcb32072e63e4b9c1b19eefc2d6b490397977352e865b5016f148f74d1234df6", - "0x5d1a7ce417ff6c955a2d06c4c840b541f386fe4a4370228afae2be534e2a5417fade1ead66031d64458270725699d6"}, - {"0xb44bcb83f10d65248dcf486aa2bdfbedc610b3f42aaea5a4581cacaad83d83a5bc9af704bbfd377d916268ed5be0ca", - "0x154a6f2aebf4c09b1e69a0a4d435958eab0b85a6f405246a1c6af4a4432e13ba0ae3e631b4cbb9958962a2bc05dadce"}, - {"0x43ec129619c24c903d1e8ced9e08af5e09deaaad2f85f5ff1a65a070055bda662d6b0ec13b2a12dce07dca1ca0d34e", - "0xc696b6c3b4b65ba99f95b0419f35d9f5a13e81f259173b4babc0bf290a0e2d9979511b5a6e1122aa7a572eb04c937b"}, - {"0x5f8d9df1cd3ea471f926003dae6e4cbe4eac8676d97693f76b082468922496ab47cf0a6fdbab2717328446ddecdc17", - "0x588223c67657eb350a8aba1f5ac04ccee4c02ab4a5c7d038c8a3eb8c8ebc0233950f6c7f12cdbb6fa6a423e97cd661"}, - {"0xe23936ef578d86d6e629e2146599905c9a3cfc4d158bb35f4513ade1031830de7ca355bfb3ec74c487f7e91dbaeb22", - "0x1168faccfe32c916ceece34bd697bfa7aad4048bf1ef00409f0c7ad20564f46eac4e7710083011e85e8543b1b8b3c3e"}, - {"0xce947ebe5063aafb2a3e9796bf3677237ecd980026889351d1120fa73b24a1a04e971deab8ad4c7f189e9559b0d1b1", - "0x156b554c56db14b68a4ed5367a442fac6d95d2714fc59e9eaa235dba01a804277302625ce66f99e4eead7b7c7137a90"}, - {"0xeb0854aaaa2035ec173a3419093ef828c51df43b492dfad54fa62fcdcf40621c21d040f678a3eab5831e12e4a0d02f", - "0x380b52ae6bdef0a4cfeab3cbef0efd4017286319f2e1dd8022fd896cb0cb8be986c4abb1ec2bd6aa90c45b1a61b6aa"}, - {"0x19cee627a52ee5d83bfba584b81e8da3e9fee36a4785cc5e277a0635ad178c03863d708258214e80851cec3bab077b0", - "0x19a62cec87d6fa62a59d35af20772f84611a11d62e573e008cf6cc4e6e473a93a89b0b2b4579827b835109ffae07696"}, - {"0x193224b2c9149c504131017f21f51adb859b41abcf51ad61eca54273f7962d47bbe4c33a96e0938b31d4d475e20c472", - "0x17c9844cbfaebc9866e792216a887a4efe3c85a55891e1f8e0f0c5bcd1276e607087e9a67b9ca05b30577a70e0b9cd3"}, - {"0x1a381bff3a99144474ed68d432a55cc7a87a77ec8ef9ec7dc8207bebe95d55bda2ec40d34992be5e68691717ad25e87", - "0x1998a69751dae99d28fafd96b81cc341482051957408078e8ea74617fba8242075a8f8b079f1e18a274a9defcf12cf9"}, - {"0x1436817e660a5107b3d259cb3f2af5d373b951ad6a54ad6831ff9d7053cd857ae5abcdf0e44bb1a45dc4dc43be82a24", - "0x7d2fe1f55c31673b19f9fc000ffa74819d7001a3f1bfcd87bad06d6642b6ebd2d69836d88e9e43fa6af8225a380ed6"}, - {"0x321b8a5f187405be1d90830e71a287eadc2722bc45bb9f5e84a921331835127361f4544d86b4ace8ceed8886063f02", - "0x58cd6cd7c128e53ec5f4b55e8cb0356e36b4f4673890bd57600018e658100e9ebe25311b6c0a9b21b95a6414a88ad1"}, - {"0xa88afc381c5826291bd27ee2a6d88bbf10068154b09f1df0b3cbe9478e2f2f835133d5486b0797d9ade242e0d442c7", - "0xf76768c2ed3f4e85913f870de4ef972299114025ab5bd97a70dff551d3fdb6e780876e8d5979631e170590f104b3c6"}, - {"0x6bca067bf3c3fda8fe8060531d6f5550fef83c2769c7686682abf9585ca3fc04d64a75061c9965a8782864126167f9", - "0xa0e802a11d90c37cd105a8c597cb844efb81706dedf9a6a19254dc7db8b0bec5127ab383370ddf3ea8426be5d2d9d"}, - {"0x46d4e78de408979012bcc8d12b78d6d85d8beca1b7700c410fa6a3b78de2b181a3b2d464d3d1745f5a4f722bcf667c", - "0xdcb51648143fc79a24093a797cda524c95512a51d521ec38321e624b1cbcdb9dd278c71eb0fa345eb67639e9563dd8"}, - {"0x1620bcb2404787ee39cae59ba2c85a2062aed25694677b198fed619d6558b859da3aaad5d38e773ca645cd710379803", - "0x10620b57ed7f896194775ed566c2e01276e4f7bcdf233a23ad1d3e9b77c3fa0cdf84c564c1021f5e584458ab26bd8b8"}, - {"0x6dabe74a1d15321e50aabfd662991b784c84a9b72e3340eee8efe520e68624376814038f2d1d683df0cc4f81c37a3", - "0x130be04e20fed0aabac1be1a13614e262414e7492e8701816e89b9982a435e2cf80b11474358c9bf758393f8fe05022"}, - {"0x83889427d535bd6411a28c2a0ac1d40396ee0e686f0052f0bf59abb62bd3004f1ff3a76bf93b70926638b5c05f0a3c", - "0x131b916656d906aeda904a98d7664ed693a9a793a051a824c4ed8c815835eed2bcf1d686414c859af676f850e3dfd71"}, - {"0x160c9ea53e9e85745773c4faccea8a4bc12d558b01068c2f3d88ca4d43b6f5e338a0ab7230fb044757ec2666f769dbb", - "0xb40e44b0581a642829ebdc74a3579c83018737cb432db5f3d692411082f2139753f6122e53566737d4ef53ac06ad1"}, - {"0x186657fc77b2f47a24d4ce9ff9978c8b856ebb1d23e75468ac95d73168cdd6f7ae9ed767ad52bc9a3ea835a37c34aa3", - "0xa216aa737f6a614825bc46fbbcd767235927731a2c14c71ac6e2a38da8479785028a30559d92f544c2cf5d24b542fd"}, - {"0x11e53de7dcd97d4850d8d3b3d948db5e1a33adf4d3b81342b155f926729619cf1094cb81ca5119e69a84307aa35cc4f", - "0x15ebff8d6d9c62eada64518cd85683baffe02073d8191ce5006a93c64dd1aec73e6f5c2178face4ded883af8b0738ee"}, - }, - }, - }, - }, -} - -var tBLS12_77 = TwistedEdwardsCurve{ - Name: BLS12_377.Name, - Package: "twistededwards", - EnumID: BLS12_377.EnumID, - A: "-1", - D: "3021", - Cofactor: "4", - Order: "2111115437357092606062206234695386632838870926408408195193685246394721360383", - BaseX: "717051916204163000937139483451426116831771857428389560441264442629694842243", - BaseY: "882565546457454111605105352482086902132191855952243170543452705048019814192", -} - -func init() { - addCurve(&BLS12_377) - addTwistedEdwardCurve(&tBLS12_77) -} diff --git a/vendor/github.com/consensys/gnark-crypto/internal/generator/config/bls12-378.go b/vendor/github.com/consensys/gnark-crypto/internal/generator/config/bls12-378.go deleted file mode 100644 index b30d9b05943..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/internal/generator/config/bls12-378.go +++ /dev/null @@ -1,74 +0,0 @@ -package config - -var BLS12_378 = Curve{ - Name: "bls12-378", - CurvePackage: "bls12378", - EnumID: "BLS12_378", - FrModulus: "14883435066912132899950318861128167269793560281114003360875131245101026639873", - FpModulus: "605248206075306171733248481581800960739847691770924913753520744034740935903401304776283802348837311170974282940417", - G1: Point{ - CoordType: "fp.Element", - CoordExtDegree: 1, - PointName: "g1", - GLV: true, - CofactorCleaning: true, - CRange: defaultCRange(), - }, - G2: Point{ - CoordType: "fptower.E2", - CoordExtDegree: 2, - PointName: "g2", - GLV: true, - CofactorCleaning: true, - CRange: defaultCRange(), - Projective: true, - }, - // 2-isogeny - HashE1: &HashSuiteSswu{ - A: []string{"0x3eeb0416684d18f2c41f0ac56b4172c97877b1f2170ca6f42387dd67a2cc5c175e179b1a06ffff79e0723fffffffff2"}, - B: []string{"0x16"}, - Z: []int{11}, - Isogeny: &Isogeny{ - XMap: RationalPolynomial{ - Num: [][]string{ - {"0x2f304310ce39d2c3011a6d50eb4ece730cab541269dbc53c7594241b1c244eff01c0ce03cbe00000000000000000000"}, - {"0x9d9ea03fd9a908c76d1012fb4743eb0c720b5849c7b761ff1e3f31fc34200004ca4510000000001"}, - {"0x2f304310ce39d2c3ed885db0b1cc5b9e3043708b54c1a5cf20a52889c7b761fdaf1f98fe1a1000072f6798000000001"}, - }, - Den: [][]string{ - {"0x2767a80ff66a4231db4404bed1d0fac31c82d61271edd87fc78fcc7f0d0800013291440000000004"}, - }, - }, - YMap: RationalPolynomial{ - Num: [][]string{ - {"0x2f304310ce39d2c3ed885db0b1cc5b9e3043708b54c1a5cf20a52889c7b761fdaf1f98fe1a1000072f6797fffffffff"}, - {"0x7dd6082cd09a322f6a993378ddbf030e107849ad95ef7bbdbc611d64e38ea7c4e9cea46c7d00013291440000000002"}, - {"0x1f75820b34268c838ac8d9803d05ca3f43c5122b2366f9c76b7f1f7530b7fefd221e864e5f90000bf9aca8000000002"}, - {"0x370da3939b4375e4951f17f8cf6e6ae3384eadf7e2e1ec1c50c0af4b69009cfd4c4f87d31e68000861f8dc000000001"}, - }, - Den: [][]string{ - {"0x3eeb0416684d19053cb5d240ed107a284059eb647102326980dc360d0a49d7fce97f76a822c00009948a1fffffffff9"}, - {"0xec6df05fc67d8d2b23981c78eae5e092ab11046eab9312fead5ecafa4e3000072f6798000000000c"}, - {"0x7636f82fe33ec69591cc0e3c7572f0495588823755c9897f56af657d2718000397b3cc000000000c"}, - }, - }, - }, - }, -} - -var tBLS12_78 = TwistedEdwardsCurve{ - Name: BLS12_378.Name, - Package: "twistededwards", - EnumID: BLS12_378.EnumID, - A: "16249", - D: "826857503717340716663906603396009292766308904506333520048618402505612607353", - Cofactor: "8", - Order: "1860429383364016612493789857641020908721690454530426945748883177201355593303", - BaseX: "6772953896463446981848394912418300623023000177913479948380771331313783560843", - BaseY: "9922290044608088599966879240752111513195706854076002240583420830067351093249", -} - -func init() { - addCurve(&BLS12_378) - addTwistedEdwardCurve(&tBLS12_78) -} diff --git a/vendor/github.com/consensys/gnark-crypto/internal/generator/config/bls12-381.go b/vendor/github.com/consensys/gnark-crypto/internal/generator/config/bls12-381.go deleted file mode 100644 index 15d5c3f4b8c..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/internal/generator/config/bls12-381.go +++ /dev/null @@ -1,168 +0,0 @@ -package config - -var BLS12_381 = Curve{ - Name: "bls12-381", - CurvePackage: "bls12381", - EnumID: "BLS12_381", - FrModulus: "52435875175126190479447740508185965837690552500527637822603658699938581184513", - FpModulus: "4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787", - G1: Point{ - CoordType: "fp.Element", - CoordExtDegree: 1, - PointName: "g1", - GLV: true, - CofactorCleaning: true, - CRange: defaultCRange(), - }, - G2: Point{ - CoordType: "fptower.E2", - CoordExtDegree: 2, - CoordExtRoot: -1, - PointName: "g2", - GLV: true, - CofactorCleaning: true, - CRange: defaultCRange(), - Projective: true, - }, - // 11-isogeny - HashE1: &HashSuiteSswu{ - A: []string{"0x144698a3b8e9433d693a02c96d4982b0ea985383ee66a8d8e8981aefd881ac98936f8da0e0f97f5cf428082d584c1d"}, - B: []string{"0x12e2908d11688030018b12e8753eee3b2016c1f0f24f4070a0b9c14fcef35ef55a23215a316ceaa5d1cc48e98e172be0"}, - Z: []int{11}, - Isogeny: &Isogeny{ - XMap: RationalPolynomial{ - Num: [][]string{ - {"0x11a05f2b1e833340b809101dd99815856b303e88a2d7005ff2627b56cdb4e2c85610c2d5f2e62d6eaeac1662734649b7"}, - {"0x17294ed3e943ab2f0588bab22147a81c7c17e75b2f6a8417f565e33c70d1e86b4838f2a6f318c356e834eef1b3cb83bb"}, - {"0xd54005db97678ec1d1048c5d10a9a1bce032473295983e56878e501ec68e25c958c3e3d2a09729fe0179f9dac9edcb0"}, - {"0x1778e7166fcc6db74e0609d307e55412d7f5e4656a8dbf25f1b33289f1b330835336e25ce3107193c5b388641d9b6861"}, - {"0xe99726a3199f4436642b4b3e4118e5499db995a1257fb3f086eeb65982fac18985a286f301e77c451154ce9ac8895d9"}, - {"0x1630c3250d7313ff01d1201bf7a74ab5db3cb17dd952799b9ed3ab9097e68f90a0870d2dcae73d19cd13c1c66f652983"}, - {"0xd6ed6553fe44d296a3726c38ae652bfb11586264f0f8ce19008e218f9c86b2a8da25128c1052ecaddd7f225a139ed84"}, - {"0x17b81e7701abdbe2e8743884d1117e53356de5ab275b4db1a682c62ef0f2753339b7c8f8c8f475af9ccb5618e3f0c88e"}, - {"0x80d3cf1f9a78fc47b90b33563be990dc43b756ce79f5574a2c596c928c5d1de4fa295f296b74e956d71986a8497e317"}, - {"0x169b1f8e1bcfa7c42e0c37515d138f22dd2ecb803a0c5c99676314baf4bb1b7fa3190b2edc0327797f241067be390c9e"}, - {"0x10321da079ce07e272d8ec09d2565b0dfa7dccdde6787f96d50af36003b14866f69b771f8c285decca67df3f1605fb7b"}, - {"0x6e08c248e260e70bd1e962381edee3d31d79d7e22c837bc23c0bf1bc24c6b68c24b1b80b64d391fa9c8ba2e8ba2d229"}, - }, - Den: [][]string{ - {"0x8ca8d548cff19ae18b2e62f4bd3fa6f01d5ef4ba35b48ba9c9588617fc8ac62b558d681be343df8993cf9fa40d21b1c"}, - {"0x12561a5deb559c4348b4711298e536367041e8ca0cf0800c0126c2588c48bf5713daa8846cb026e9e5c8276ec82b3bff"}, - {"0xb2962fe57a3225e8137e629bff2991f6f89416f5a718cd1fca64e00b11aceacd6a3d0967c94fedcfcc239ba5cb83e19"}, - {"0x3425581a58ae2fec83aafef7c40eb545b08243f16b1655154cca8abc28d6fd04976d5243eecf5c4130de8938dc62cd8"}, - {"0x13a8e162022914a80a6f1d5f43e7a07dffdfc759a12062bb8d6b44e833b306da9bd29ba81f35781d539d395b3532a21e"}, - {"0xe7355f8e4e667b955390f7f0506c6e9395735e9ce9cad4d0a43bcef24b8982f7400d24bc4228f11c02df9a29f6304a5"}, - {"0x772caacf16936190f3e0c63e0596721570f5799af53a1894e2e073062aede9cea73b3538f0de06cec2574496ee84a3a"}, - {"0x14a7ac2a9d64a8b230b3f5b074cf01996e7f63c21bca68a81996e1cdf9822c580fa5b9489d11e2d311f7d99bbdcc5a5e"}, - {"0xa10ecf6ada54f825e920b3dafc7a3cce07f8d1d7161366b74100da67f39883503826692abba43704776ec3a79a1d641"}, - {"0x95fc13ab9e92ad4476d6e3eb3a56680f682b4ee96f7d03776df533978f31c1593174e4b4b7865002d6384d168ecdd0a"}, - }, - }, - YMap: RationalPolynomial{ - Num: [][]string{ - {"0x90d97c81ba24ee0259d1f094980dcfa11ad138e48a869522b52af6c956543d3cd0c7aee9b3ba3c2be9845719707bb33"}, - {"0x134996a104ee5811d51036d776fb46831223e96c254f383d0f906343eb67ad34d6c56711962fa8bfe097e75a2e41c696"}, - {"0xcc786baa966e66f4a384c86a3b49942552e2d658a31ce2c344be4b91400da7d26d521628b00523b8dfe240c72de1f6"}, - {"0x1f86376e8981c217898751ad8746757d42aa7b90eeb791c09e4a3ec03251cf9de405aba9ec61deca6355c77b0e5f4cb"}, - {"0x8cc03fdefe0ff135caf4fe2a21529c4195536fbe3ce50b879833fd221351adc2ee7f8dc099040a841b6daecf2e8fedb"}, - {"0x16603fca40634b6a2211e11db8f0a6a074a7d0d4afadb7bd76505c3d3ad5544e203f6326c95a807299b23ab13633a5f0"}, - {"0x4ab0b9bcfac1bbcb2c977d027796b3ce75bb8ca2be184cb5231413c4d634f3747a87ac2460f415ec961f8855fe9d6f2"}, - {"0x987c8d5333ab86fde9926bd2ca6c674170a05bfe3bdd81ffd038da6c26c842642f64550fedfe935a15e4ca31870fb29"}, - {"0x9fc4018bd96684be88c9e221e4da1bb8f3abd16679dc26c1e8b6e6a1f20cabe69d65201c78607a360370e577bdba587"}, - {"0xe1bba7a1186bdb5223abde7ada14a23c42a0ca7915af6fe06985e7ed1e4d43b9b3f7055dd4eba6f2bafaaebca731c30"}, - {"0x19713e47937cd1be0dfd0b8f1d43fb93cd2fcbcb6caf493fd1183e416389e61031bf3a5cce3fbafce813711ad011c132"}, - {"0x18b46a908f36f6deb918c143fed2edcc523559b8aaf0c2462e6bfe7f911f643249d9cdf41b44d606ce07c8a4d0074d8e"}, - {"0xb182cac101b9399d155096004f53f447aa7b12a3426b08ec02710e807b4633f06c851c1919211f20d4c04f00b971ef8"}, - {"0x245a394ad1eca9b72fc00ae7be315dc757b3b080d4c158013e6632d3c40659cc6cf90ad1c232a6442d9d3f5db980133"}, - {"0x5c129645e44cf1102a159f748c4a3fc5e673d81d7e86568d9ab0f5d396a7ce46ba1049b6579afb7866b1e715475224b"}, - {"0x15e6be4e990f03ce4ea50b3b42df2eb5cb181d8f84965a3957add4fa95af01b2b665027efec01c7704b456be69c8b604"}, - }, - Den: [][]string{ - {"0x16112c4c3a9c98b252181140fad0eae9601a6de578980be6eec3232b5be72e7a07f3688ef60c206d01479253b03663c1"}, - {"0x1962d75c2381201e1a0cbd6c43c348b885c84ff731c4d59ca4a10356f453e01f78a4260763529e3532f6102c2e49a03d"}, - {"0x58df3306640da276faaae7d6e8eb15778c4855551ae7f310c35a5dd279cd2eca6757cd636f96f891e2538b53dbf67f2"}, - {"0x16b7d288798e5395f20d23bf89edb4d1d115c5dbddbcd30e123da489e726af41727364f2c28297ada8d26d98445f5416"}, - {"0xbe0e079545f43e4b00cc912f8228ddcc6d19c9f0f69bbb0542eda0fc9dec916a20b15dc0fd2ededda39142311a5001d"}, - {"0x8d9e5297186db2d9fb266eaac783182b70152c65550d881c5ecd87b6f0f5a6449f38db9dfa9cce202c6477faaf9b7ac"}, - {"0x166007c08a99db2fc3ba8734ace9824b5eecfdfa8d0cf8ef5dd365bc400a0051d5fa9c01a58b1fb93d1a1399126a775c"}, - {"0x16a3ef08be3ea7ea03bcddfabba6ff6ee5a4375efa1f4fd7feb34fd206357132b920f5b00801dee460ee415a15812ed9"}, - {"0x1866c8ed336c61231a1be54fd1d74cc4f9fb0ce4c6af5920abc5750c4bf39b4852cfe2f7bb9248836b233d9d55535d4a"}, - {"0x167a55cda70a6e1cea820597d94a84903216f763e13d87bb5308592e7ea7d4fbc7385ea3d529b35e346ef48bb8913f55"}, - {"0x4d2f259eea405bd48f010a01ad2911d9c6dd039bb61a6290e591b36e636a5c871a5c29f4f83060400f8b49cba8f6aa8"}, - {"0xaccbb67481d033ff5852c1e48c50c477f94ff8aefce42d28c0f9a88cea7913516f968986f7ebbea9684b529e2561092"}, - {"0xad6b9514c767fe3c3613144b45f1496543346d98adf02267d5ceef9a00d9b8693000763e3b90ac11e99b138573345cc"}, - {"0x2660400eb2e4f3b628bdd0d53cd76f2bf565b94e72927c1cb748df27942480e420517bd8714cc80d1fadc1326ed06f7"}, - {"0xe0fa1d816ddc03e6b24255e0d7819c171c40f65e273b853324efcd6356caa205ca2f570f13497804415473a1d634b8f"}, - }, - }, - }, - }, - - // 3-isogeny - HashE2: &HashSuiteSswu{ - A: []string{"0", "240"}, // A = 240 * I - B: []string{"1012", "1012"}, // B = 1012 * (I+1) - Z: []int{-2, -1}, // Z = -(2+I) - Isogeny: &Isogeny{ - XMap: RationalPolynomial{ - Num: [][]string{ - {"0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97d6", "0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97d6"}, - {"0x0", "0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71a"}, - {"0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71e", "0x8ab05f8bdd54cde190937e76bc3e447cc27c3d6fbd7063fcd104635a790520c0a395554e5c6aaaa9354ffffffffe38d"}, - {"0x171d6541fa38ccfaed6dea691f5fb614cb14b4e7f4e810aa22d6108f142b85757098e38d0f671c7188e2aaaaaaaa5ed1", "0x0"}, - }, - Den: [][]string{ - {"0x0", "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa63"}, - {"0xc", "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa9f"}, - }, - }, - YMap: RationalPolynomial{ - Num: [][]string{ - {"0x1530477c7ab4113b59a4c18b076d11930f7da5d4a07f649bf54439d87d27e500fc8c25ebf8c92f6812cfc71c71c6d706", "0x1530477c7ab4113b59a4c18b076d11930f7da5d4a07f649bf54439d87d27e500fc8c25ebf8c92f6812cfc71c71c6d706"}, - {"0x0", "0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97be"}, - {"0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71c", "0x8ab05f8bdd54cde190937e76bc3e447cc27c3d6fbd7063fcd104635a790520c0a395554e5c6aaaa9354ffffffffe38f"}, - {"0x124c9ad43b6cf79bfbf7043de3811ad0761b0f37a1e26286b0e977c69aa274524e79097a56dc4bd9e1b371c71c718b10", "0x0"}, - }, - Den: [][]string{ - {"0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa8fb", "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa8fb"}, - {"0x0", "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa9d3"}, - {"0x12", "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa99"}, - }, - }, - }, - }, -} - -var tBLS12_381 = TwistedEdwardsCurve{ - Name: BLS12_381.Name, - Package: "twistededwards", - EnumID: BLS12_381.EnumID, - A: "-1", - D: "19257038036680949359750312669786877991949435402254120286184196891950884077233", - Cofactor: "8", - Order: "6554484396890773809930967563523245729705921265872317281365359162392183254199", - BaseX: "23426137002068529236790192115758361610982344002369094106619281483467893291614", - BaseY: "39325435222430376843701388596190331198052476467368316772266670064146548432123", -} - -var bandersnatch = TwistedEdwardsCurve{ - Name: BLS12_381.Name, - Package: "bandersnatch", - EnumID: BLS12_381.EnumID, - A: "-5", - D: "45022363124591815672509500913686876175488063829319466900776701791074614335719", - Cofactor: "4", - Order: "13108968793781547619861935127046491459309155893440570251786403306729687672801", - BaseX: "18886178867200960497001835917649091219057080094937609519140440539760939937304", - BaseY: "19188667384257783945677642223292697773471335439753913231509108946878080696678", - HasEndomorphism: true, - Endo0: "37446463827641770816307242315180085052603635617490163568005256780843403514036", - Endo1: "49199877423542878313146170939139662862850515542392585932876811575731455068989", - Lambda: "8913659658109529928382530854484400854125314752504019737736543920008458395397", -} - -func init() { - addCurve(&BLS12_381) - addTwistedEdwardCurve(&tBLS12_381) - addTwistedEdwardCurve(&bandersnatch) -} diff --git a/vendor/github.com/consensys/gnark-crypto/internal/generator/config/bls24-315.go b/vendor/github.com/consensys/gnark-crypto/internal/generator/config/bls24-315.go deleted file mode 100644 index 835e01ee98c..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/internal/generator/config/bls24-315.go +++ /dev/null @@ -1,74 +0,0 @@ -package config - -var BLS24_315 = Curve{ - Name: "bls24-315", - CurvePackage: "bls24315", - EnumID: "BLS24_315", - FrModulus: "11502027791375260645628074404575422495959608200132055716665986169834464870401", - FpModulus: "39705142709513438335025689890408969744933502416914749335064285505637884093126342347073617133569", - G1: Point{ - CoordType: "fp.Element", - CoordExtDegree: 1, - PointName: "g1", - GLV: true, - CofactorCleaning: true, - CRange: defaultCRange(), - }, - G2: Point{ - CoordType: "fptower.E4", - CoordExtDegree: 4, - PointName: "g2", - GLV: true, - CofactorCleaning: true, - CRange: defaultCRange(), - Projective: true, - }, - // 2-isogeny - HashE1: &HashSuiteSswu{ - A: []string{"0x4c23a0197b9ca68541a4cef14af4cfe81cc324cac5626d9ff4ee66df9ea2678877910f40300001f"}, - B: []string{"0x16"}, - Z: []int{13}, - Isogeny: &Isogeny{ - XMap: RationalPolynomial{ - Num: [][]string{ - {"0x2611d014c792a8ffd30982483b3ee757787d35c9e880e096a850c8e24edf5c71f880eff103c0002"}, - {"0x2611d01644a40e35d2dad31956fafeee9f1a0831db5b7b49ac10c81d6ff9afd483bf88000000000"}, - {"0x391ab82082520bc9ef97728ef1d4703e7115c13f9db942831972c63be0e6bc1d3ee023f70240001"}, - }, - Den: [][]string{ - {"0x261b56ebccc821ae82c6025bea42e1d731e2a911e6c66652b682a1f0411fdc017f9ffffe"}, - }, - }, - YMap: RationalPolynomial{ - Num: [][]string{ - {"0x391ab82082520bc9ef97728ef1d4703e7115c13f9db942831972c63be0e6bc1d3ee023f7023ffff"}, - {"0x391ab822bdec239aef516bc89b6e93a12b00fcdb8a012a8f9f12c514928e39310fbe080d7c9fffd"}, - {"0x391ab82166f61550bc483ca602787e65eea70c4ac90938ee82192c2c27f687bec59f4c000000000"}, - {"0x429f2c25ed5fb86b978605a6c4cd2d9e2e996174e2ad78439db091f0866286221eb029f582a0001"}, - }, - Den: [][]string{ - {"0x4c23a02b586d650d3f7498be97c5eafdec1d01aa27a1ae0421ee5da52bde5026fe802ff402ffff9"}, - {"0xe4a40986ccb0ca1710a40e277d914b0b2b4ff66b68a665f0470fcba186bf2808fdbfffe8"}, - {"0x725204c36658650b88520713bec8a58595a7fb35b45332f82387e5d0c35f94047edffffa"}, - }, - }, - }, - }, -} - -var tBLS24_315 = TwistedEdwardsCurve{ - Name: BLS24_315.Name, - Package: "twistededwards", - EnumID: BLS24_315.EnumID, - A: "-1", - D: "8771873785799030510227956919069912715983412030268481769609515223557738569779", - Cofactor: "8", - Order: "1437753473921907580703509300571927811987591765799164617677716990775193563777", - BaseX: "750878639751052675245442739791837325424717022593512121860796337974109802674", - BaseY: "1210739767513185331118744674165833946943116652645479549122735386298364723201", -} - -func init() { - addCurve(&BLS24_315) - addTwistedEdwardCurve(&tBLS24_315) -} diff --git a/vendor/github.com/consensys/gnark-crypto/internal/generator/config/bls24-317.go b/vendor/github.com/consensys/gnark-crypto/internal/generator/config/bls24-317.go deleted file mode 100644 index 2c5a3f89675..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/internal/generator/config/bls24-317.go +++ /dev/null @@ -1,86 +0,0 @@ -package config - -var BLS24_317 = Curve{ - Name: "bls24-317", - CurvePackage: "bls24317", - EnumID: "BLS24_317", - FrModulus: "30869589236456844204538189757527902584594726589286811523515204428962673459201", - FpModulus: "136393071104295911515099765908274057061945112121419593977210139303905973197232025618026156731051", - G1: Point{ - CoordType: "fp.Element", - CoordExtDegree: 1, - PointName: "g1", - GLV: true, - CofactorCleaning: true, - CRange: defaultCRange(), - }, - G2: Point{ - CoordType: "fptower.E4", - CoordExtDegree: 4, - PointName: "g2", - GLV: true, - CofactorCleaning: true, - CRange: defaultCRange(), - Projective: true, - }, - // 5-isogeny - HashE1: &HashSuiteSswu{ - A: []string{"0x8e4edadd82ff003e6762cff9b559b8cd0f3f6c9311276a6d560dcce30e697a982e1866e3e7c28d5"}, - B: []string{"0x2064f87ea0196ecbb9b075804c613d4776224e78064823a8568e30f5ad5af3bb70ee17723af3a0d"}, - Z: []int{8}, - Isogeny: &Isogeny{ - XMap: RationalPolynomial{ - Num: [][]string{ - {"0x236b5fd9cca05871bd84a4837633e369779c83cdd8e57f5e6c225b947983cf102a89412ca193804"}, - {"0xbd5fdd72856b15e73452512781cb8a44afc43fd20722b37bf41b260fcb6b2a53697eaaf34dd4055"}, - {"0xe48ccd9c11799e37b9f9713ad4c23c792bfe9cce20bb64b953983bb7789d7a5d28b1cfdd29c6212"}, - {"0x3c02ee7a69adc553341746545c583c06a0d844f638330a35305f5e8e312457c0ab57bc2702dc270"}, - {"0xc836be99bb812fca77c672366482945f54dd793103efb9504eb992da7132416060b75c14fb7999e"}, - {"0xfb165e39e1f3c02308a056717044d039ad1a5aa191127f2160837936541ff83badd4b3430f63d71"}, - }, - Den: [][]string{ - {"0xac526aaa4ccfab9e20d1af55e1b46e59df4ccdf5efa58766d0c18ac6326551818ee9e90fa19a875"}, - {"0xd8ed9eb76dc3ca65e3c54629ff1dbc57619627e2efb082c3f4601ec65d293de69e57eb95404a6b1"}, - {"0x6fc49fca38657cde5fab7a027bf50b888cb23b6952698615ff744257a41fa35df7f708c34184a19"}, - {"0x23e8941f0cfac565a7a6787558193984724c940bb5db04b86f4a98572244fc21a180f77d539d5bd"}, - }, - }, - YMap: RationalPolynomial{ - Num: [][]string{ - {"0xff4f99c01dfcb3892a91fa883b348828de9460cb96389fb35ffb06434cdeef1ce46b03c5dd5d0f7"}, - {"0x81224ed3f6692419ae30d702d3eda4710053bdbae2d49fe1f4ae22ca850ba727e1ccf7e5701c164"}, - {"0x45054affadf894503d5833cfd9dbad5eb905a527a12b5e7dcabd0052793f9b49e64e957dd42da4"}, - {"0x18eeec003ff866c9fb04c7371fc3383d385a2be91d8a0433f6974c71a0ce405f122c83719f1393e"}, - {"0x31dd068a643f47a6596e317e958886ea2ac504968e1c5cf09c8d5776c6643ef4de74fbdd8c4a619"}, - {"0x2c8e3ae176f645fc860fce8de1b13b50c4000167d09963c6e1a9c672f88f4f8d0503c022726fc95"}, - {"0x9f05a21397a2e89eb8a9d058e93ca60265193966535883b745a89991576994ae547e2d441247c3f"}, - }, - Den: [][]string{ - {"0xd3e018c50c3942dd4d09a4ab202a25696610ba38204d026ecdaf526c2f6f7087e577ad578cd63a4"}, - {"0x8287e2ff37ee6fdebecdbb7847a885def88d0241d5cff2567cb4bc388b67da5687eb6031701f843"}, - {"0x59d82ad3a832a32188e27cac33b5e6c5598cb76c8ac13ef00b5d65852db61f05669c372e5dcc771"}, - {"0x56b84eb18c4f8eadcddfdda011cc2f7b5c06990035936f127ba77996f19017f4ff02c13009b3e70"}, - {"0x7d08817b694fb1681686e845fda634911d8d84dc73472bbe89ad038a351d9729f4e2626dc0ec353"}, - {"0xb8a32f420e7c71800ff7e1b5c3f4580f6045ed45b702294b5e89b3a4548d7626dccae5eeeac55f1"}, - }, - }, - }, - }, -} - -var tBLS24_317 = TwistedEdwardsCurve{ - Name: BLS24_317.Name, - Package: "twistededwards", - EnumID: BLS24_317.EnumID, - A: "-1", - D: "20748505950524021841644589704740731932416084248011369709738936344973878925081", - Cofactor: "8", - Order: "3858698654557105525567273719690987823069521430163883173133245580997415449969", - BaseX: "4348505656527095883506785370890963704100065639426869666063106978260788240233", - BaseY: "1929349327278552762783636859845493911537170411830425720219700276810167091201", -} - -func init() { - addCurve(&BLS24_317) - addTwistedEdwardCurve(&tBLS24_317) -} diff --git a/vendor/github.com/consensys/gnark-crypto/internal/generator/config/bn254.go b/vendor/github.com/consensys/gnark-crypto/internal/generator/config/bn254.go deleted file mode 100644 index c3c90748c37..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/internal/generator/config/bn254.go +++ /dev/null @@ -1,72 +0,0 @@ -package config - -var BN254 = Curve{ - Name: "bn254", - CurvePackage: "bn254", - EnumID: "BN254", - FrModulus: "21888242871839275222246405745257275088548364400416034343698204186575808495617", - FpModulus: "21888242871839275222246405745257275088696311157297823662689037894645226208583", - G1: Point{ - CoordType: "fp.Element", - CoordExtDegree: 1, - PointName: "g1", - GLV: true, - CofactorCleaning: false, - CRange: defaultCRange(), - }, - G2: Point{ - CoordType: "fptower.E2", - CoordExtDegree: 2, - PointName: "g2", - GLV: true, - CofactorCleaning: true, - CRange: defaultCRange(), - Projective: true, - }, - HashE1: &HashSuiteSvdw{ - z: []string{"1"}, - c1: []string{"4"}, - c2: []string{"10944121435919637611123202872628637544348155578648911831344518947322613104291"}, - c3: []string{"8815841940592487685674414971303048083897117035520822607866"}, - c4: []string{"7296080957279758407415468581752425029565437052432607887563012631548408736189"}, - }, - HashE2: &HashSuiteSvdw{ - z: []string{ - "1", - "0", - }, - c1: []string{ - "19485874751759354771024239261021720505790618469301721065564631296452457478374", - "266929791119991161246907387137283842545076965332900288569378510910307636690", - }, - c2: []string{ - "10944121435919637611123202872628637544348155578648911831344518947322613104291", - "0", - }, - c3: []string{ - "18992192239972082890849143911285057164064277369389217330423471574879236301292", - "21819008332247140148575583693947636719449476128975323941588917397607662637108", - }, - c4: []string{ - "10499238450719652342378357227399831140106360636427411350395554762472100376473", - "6940174569119770192419592065569379906172001098655407502803841283667998553941", - }, - }, -} - -var tBN254 = TwistedEdwardsCurve{ - Name: BN254.Name, - Package: "twistededwards", - EnumID: BN254.EnumID, - A: "-1", - D: "12181644023421730124874158521699555681764249180949974110617291017600649128846", - Cofactor: "8", - Order: "2736030358979909402780800718157159386076813972158567259200215660948447373041", - BaseX: "9671717474070082183213120605117400219616337014328744928644933853176787189663", - BaseY: "16950150798460657717958625567821834550301663161624707787222815936182638968203", -} - -func init() { - addCurve(&BN254) - addTwistedEdwardCurve(&tBN254) -} diff --git a/vendor/github.com/consensys/gnark-crypto/internal/generator/config/bw6-633.go b/vendor/github.com/consensys/gnark-crypto/internal/generator/config/bw6-633.go deleted file mode 100644 index a0584e29ea8..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/internal/generator/config/bw6-633.go +++ /dev/null @@ -1,127 +0,0 @@ -package config - -var BW6_633 = Curve{ - Name: "bw6-633", - CurvePackage: "bw6633", - EnumID: "BW6_633", - FrModulus: "39705142709513438335025689890408969744933502416914749335064285505637884093126342347073617133569", - FpModulus: "20494478644167774678813387386538961497669590920908778075528754551012016751717791778743535050360001387419576570244406805463255765034468441182772056330021723098661967429339971741066259394985997", - G1: Point{ - CoordType: "fp.Element", - CoordExtDegree: 1, - PointName: "g1", - GLV: true, - CofactorCleaning: true, - CRange: []int{4, 5, 8, 16}, - Projective: true, - }, - G2: Point{ - CoordType: "fp.Element", - CoordExtDegree: 1, - PointName: "g2", - GLV: true, - CofactorCleaning: true, - CRange: []int{4, 5, 8, 16}, - }, - // 7-isogeny - HashE1: &HashSuiteSswu{ - A: []string{"0xb5b90ddda6922f2689cf6d2cd62fc7c093d1edbb9b9cb78ba3a6fbeb5740830110ea006288b01bc5c3ff21599bc76c3cc068855d91995e0a03f25ad67e9b0cb86f833df84de9affcac130e2de80208"}, - B: []string{"0xbb475f2945d16aae79792dd2f17748101c2558a952d4221e5a52bee6083040e779fc8d5e9c51ac35df601e0273b10c72f2b0d48da6bbc3859a3b185a7ee3060030e001265b3803227cb9d879f408d9"}, - Z: []int{11}, - Isogeny: &Isogeny{ - XMap: RationalPolynomial{ - Num: [][]string{ - {"0x172ae0280920320d5154453cfc38fb78e8f3cc1f3e35c38bfe870403008707ab1c9d324595b739426a3f8e03cc03f4d2e6a3b21c833c83d2c147adc9dd927523d2b556276090b4e6217d4125c656bc"}, - {"0x3ac72438aeb5851d31e592b661151b037c9a2aab88cd7a2da79158e39dddee35c360788859c6aa878660fba8caaa9f8ff6480a0abcb9f9122c929e9b673eb8cb8ea164ca1e9eddd03b4155f0ca87aa"}, - {"0x6f2cca97746292add854c01e5d06bfd8282d74cbcd0e7169e2e310ca27302cee61398208840e20a9d6ffe43db9c520799710059df25e8ce05c304f59d65d4e596cd1c587a7f6f1096e53656f93f1cc"}, - {"0xab5eb0567468008b2665f73dd0c7711c3166659434e0df8f5902de8acae5cccd4707d236e5af68f88a02aacae38e2a2bd3b5bf4442e127a36d13a47260eee3fc97ba5d9d5e15d105e256c0d86e9b96"}, - {"0xd6c992e6deb66a0d2cc1008c227fcbfdedcd136cca4dd9708cf0217e554124030fb2032803e9620d8af19f3aed51abf6d98ab2be038495edf761550d84fd1fc92f803661d045879877b8eeb2d62c3f"}, - {"0x5964f96bcd18903bd4385390d129f87d141bfa129dd9b10c1657e88b13aa4830591458fe69f1c5422f8a9c04dd9ae4dfc55d44546d129f4b4bc708af118b9ce685bd0b9480e21af262b9fdde470769"}, - {"0xdea100c7e48b278c46938a6636d0988eabab86cc555a2988cae5b7c5ec0c8e9090740796a622b4ba807360da51be9823c7844464113d8cf0d134409f68758d4500cdf13cf6bc705cbb3b26a6b91ffd"}, - {"0xcc44dbc9cd7135b427007ff6d3fe49ce12b5c3cdec0a6af272524c19b15decb7c66941fc70b0e1cea225709a41d8da2dac0afeaf69770aaa930ca8be861e392fb2f3f5b8662e2a3757495ea31eb1ab"}, - }, - Den: [][]string{ - {"0xdcedc9bc56dade3f84967eaab07772e6382d825c853b5f21b2aa334ece09ca419a918ad532943018c0af9c373d006d5a5db3dae9cacbac8e1f7ca091dbb63f6e6f6beaee1370beaea58439a6b07a79"}, - {"0x195b81736d1c96d7a634ccd1a30ce5322c4d511b000e0c45cbe40e4fc193787b0b60086e3e4d2eeaf56537fcc1d7dde1305f6f1f43da15fa5a860515b5ebd80a71de65dfa88d88b4dde8a70ebbe4d0"}, - {"0x7306846c2c81b999dc05637178c43d7bcaa8f060fa6118084a2a801ba72736fbd0a2af9da70982f1e36c1c2485775de607d049a5faf6494d4d3eedd3ff5a760faf17ed0596c1e1a8aee8112ae305ff"}, - {"0xf148e1a26098d0488ff6183b6455f5e6605c502a1eb3c11e32096d10f777563a99faa0dba8835bfea9529f125f36903c681c7d9dd0bc814a1786cf0813388a804eca85fbaa5bdd78f7d746269d6bba"}, - {"0xde8e351bd12bb3d5af8b63954d0f78bfb4bc60813ad171eb74cf3eba9f691dfb1dfe147ffef06b9aca6a77d845184de3d4ea5948fe12fccec2371477802f2f6e865c39af78f97e392a54f81cb069fb"}, - {"0x10795e5f91d91e69bcdf124c64c0f1e2507ffc99bacb24dbe7d3cb6a07de6bfab41b8f939edbacfafd0ce0b72a847fa1169d64cae412d7eac428a1e2a570a85c42e5ab2bd355b6a2460289e03f1d8c"}, - }, - }, - YMap: RationalPolynomial{ - Num: [][]string{ - {"0xc0e9192eb96da62a98ed351e9c479d437e885f7b173bc0e8b5e117be8f9bc0b8784293b4edd36184584c570f1bbacfa6390dfdab92c1102aff64793eba4e0ca54166b6ea37f041d97e17d6b8793f59"}, - {"0x2ad94cfbe3e7c1f6c73f4b7986081a8747e453a324f5fef697f4bcd681b93764606aea1c234fcc16f02941c568e7e0fc9c970db8891079fecbb13a701870973155097603fa2a95f3a9814d630920ce"}, - {"0x4fe83943570d36473c925cb80651566f48ed1a12583a0ba466a4002cd5d81324bedc2af4685ce69e8ac8c982eff0e88e8983860fc7c365efd617110a18f8d2cd2c5f5a764656d1f0acd219dfa36482"}, - {"0xb2169bd7a853b597c830c30e580e9a4d2e3c25dd81b72667ca4370b2a978cdeb7bc9812693ef630bc510a4151170ad8c0618c4a038608977391fd3d83479456ea6802236a0b3de82ce1017e1a8ca6d"}, - {"0x7f25b01ef9844f28aa0a93cffc07a16e1cc68544c7f6772babb491e4a268f152a38b8b45123c9b054de66169553ba6059e8af4dc33ee26093d08489f85450d8c5be80f1ba5aeb2c0d0afd9f92a9122"}, - {"0x566545c6ba909462ad89503f026cd53fa3d34c013226c353b14aa982fb2fb682901be8b4a6341ee81a65270009af992892249cef724bf97898b1c3fc17377d4432a23894970c6dcb3583b60c84fa24"}, - {"0x63e2ccd9a60b841370ac46210ce9788ae1562f251ffddbf6c1999647217f1fb641c6b28725006db4784cda2bb6149c5f7e8a0e1262cf65258d29f63eedcf4651d9cc6f36cf1754ac816f22fc61b9c7"}, - {"0x3f2fa1f528148f6695c61636ddc28b114cbe73a59ff01987fa09ce591615c9c3588f43eee553df2b678321a7348d1d9609316cb0a7a99d816beb08586b2c6f140dbef23f030253c0e4c06208d60788"}, - {"0xf607a90cc520cf3642e858f10134f611165201f1a19d8aa556830a8d119c70f050ade9579d2af2437e4daed7e8413b7eaa57066a4f1637a9eb355979a9069b53019d4f6a3b12bd11e65f30fb97928"}, - {"0xcdfc4b597b44fc122ba1d93dbe1c643d84e251481f80d31b34e546493c89bd3a651ed920fb518fce37f21fcd0850fe6e97f9e08e774242b04f71dff19a9b401ee3c8d55d71cb9849041ef6054c20e"}, - }, - Den: [][]string{ - {"0xecfc2a8f34b76242cf9989e6693e365112eac88902ea95115bccd5bb49a664d72b2eec54104241f9c5f1a68018d8eb3db2d854d09b081df9a369bd4312614d50899c909fbb2d2b52a7635c4d17f8b7"}, - {"0x742dda08c1fcb9436c2bc5f52af4d8189585537efd4b1a7f91fa77b5f737b8c6fabc388a01078294e7dd2198b8a32fa89354400dcec753d887b198f206ae05288915451a752ef75b75d8c360ea36bb"}, - {"0xc1d1190593e7a0686859a609ff1b46e11c0327a20872f72279a21b183a44281d0cee21d747715e9dc19f973b098c1dd3599593b70f85733addf045ea08642a6f840f99002986bec1f94bee017cd4f1"}, - {"0x97e05de3ca9556f56ecf4d1ea23a7e2d2712c0ae94ae9e446d965d7004b483b7422f99fed04fdddbc0c2d7fcc1145f04ad2f384637ed52da52a2fda64c67d29b756381ab78f85d74ec8086cfcb9179"}, - {"0x75ad4fd71ac6a390fe643f2d7e58ab8e47679afea937b2fa282221167c5e439b8d0b71d9d9c415aced0755ce72f558c6b966b4103521c4d576e232006e02ce0aea7d969d59bb6aa7fd0464bb753ee9"}, - {"0xaf031142ce65bb40b7b4a865ddf8b662e90c8f6496d6e4efd790353e79905de96971b0e90ecbe0ca95cb602145603cf7e33d79207c766500002418e725368fd15fef6ad5fd2d70dde8e192180d408b"}, - {"0x906c22013e788817b69f3c5705a7dbb9efeedabf5d8f091b518cde2891e351aa73cff16f909a2aeb160dc3e26f0ea78b07d327cc073494f8fa334f7b15c42f6454ec151ac079a3a0802d1f9eabbbc1"}, - {"0x9435c646c7573441604b5c0e0a53569e9440440e3e8df291c6ad158f942080d9a60829e933883e3bdbc574fc459c167608aa11e7b0ad4ec1c35e29c0cc81bf2b7481e35d0821b52e5ee02dde63ecf2"}, - {"0x18b60d8f5ac5ad9e9b4e9b7297216ad378bffae69830b749dbbdb11f0bcda1f80e29575d6e4983787b935112bfc6bf71a1ec1730561c43e0263cf2d3f828fc8a645880c1bd0091f36903ced05eac52"}, - }, - }, - }, - }, - // 2-isogeny - HashE2: &HashSuiteSswu{ - A: []string{"0x37406b7fa0e08ee1ffbb1ff2ff0ac49e29ba75a3caa8356b90991ae70b94d33807a85e57856205541ab2cb490d6980835d627d3d10b29e4d73a43caf3b5042cf1f7ab420fd005e2d747ffe14"}, - B: []string{"0xb0"}, - Z: []int{2}, - Isogeny: &Isogeny{ - XMap: RationalPolynomial{ - Num: [][]string{ - {"0x75c14b832491ee6015aa114d85d2ae69f27a247446da31831298835185ff04f44ee6dccb2179be43cf8cd0695188add97e49c08a2a617963eb40e8291283e4750d0e7862161f19fc5d41132e666653"}, - {"0x3ae0a5bf44ef27340179bf3c1b1d57bfae1f8ba310fd8743c24a07d811f3b8d9abeaa1653f0e462703b0da08e15133e1856a302131162f7bee2f30da626a15980dd9c8e5109d60f3a3f1f25d03333f"}, - {"0xdcca6d90b6878afd13917b416160083ebda295861b5e157ac318f4234ce3a3a0fdfd10bc26fb6c8aa3f786e2f81d371e8ae63cb24e3b05e1c85adc0a2b519bede8f4de4cf5f96da176d12fb414000a"}, - }, - Den: [][]string{ - {"0xeb8296fd13bc9cd005e6fcf06c755efeb87e2e8c43f61d0f09281f6047cee366afaa8594fc39189c0ec368238544cf8615a8c084c458bdefb8bcc36989a8566037672394427583ce8fc7c9740cccfc"}, - }, - }, - YMap: RationalPolynomial{ - Num: [][]string{ - {"0x126633cc0f35f63fc1a174f01d72ab5a8fcd8c75d79d2c74e59769ad9bbda2f8152a6c0fadea490b8da9f5e83f57c497e0e8850edbda407d7b5ce7ab839c2253d369bd31147f73cd74916ea456fffff"}, - {"0x93319e5991a24209f0f9cb40f4315c749d13cfe9859aaf2dd7b49ffacac9badf36b8f97c7a467d6bc10f04bea464bb9d5a14180b32825c49c49373ada8597cb731458fa4b4a51a4c047faf74280044"}, - {"0xeb8296ff61166ccc0f42465b14415e74039bb5235665ae8cd02a5930f8daad072b3352954de7b196f2d8f64f4cb7f2914f6370a8a8734b25c02e06a3b0803302b01496e03ce7afd91a7660ae3ccce5"}, - {"0x6e6536c85b43c57e89c8bda0b0b0041f5ed14ac30daf0abd618c7a11a671d1d07efe885e137db64551fbc3717c0e9b8f45731e59271d82f0e42d6e0515a8cdf6f47a6f267afcb6d0bb6897da0a0005"}, - }, - Den: [][]string{ - {"0x126633cc0f35f63fc1a174f01d72ab5a8fcd8c75d79d2c74e59769ad9bbda2f8152a6c0fadea490b8da9f5e83f57c497e0e8850edbda407d7b5ce7ab839c2253d369bd31147f73cd74916ea456fffcd"}, - {"0xb0a1f1145e7cd5e35c021434850010ffc24b2c49e7205af348b606dbc306fd4454217a29fee410d1018e8f069ddb24da811e2ddd8964a0a74496d8786c10bd5bad5b3f5795d10a1d2b8f34ffa99b2b"}, - {"0x75c14b7554770e77dd8658cd970ab1aa2fc8fce9d83cc890688b286d5fb84b3169b20ec937622862770b7b62a4d5db9623e99fb2d1c22a1fbe9954cc2974b8a638fdc49a377211bd1d2987d14666da"}, - }, - }, - }, - }, -} - -var tBW6_633 = TwistedEdwardsCurve{ - Name: BW6_633.Name, - Package: "twistededwards", - EnumID: BW6_633.EnumID, - A: "-1", - D: "37248940285811842784899494310834635440994424264352085037441815381151934266434102922992043546621", - Cofactor: "8", - Order: "4963142838689179791878211236301121218116687802119716497817028544854034649070444389864454748079", - BaseX: "37635937024655419978837220647164498012335808680404874556501960268316961933409049243153117555100", - BaseY: "23823085625708063001015413934245381846960101450148849601038571303382730455875805408244170280142", -} - -func init() { - addCurve(&BW6_633) - addTwistedEdwardCurve(&tBW6_633) -} diff --git a/vendor/github.com/consensys/gnark-crypto/internal/generator/config/bw6-756.go b/vendor/github.com/consensys/gnark-crypto/internal/generator/config/bw6-756.go deleted file mode 100644 index 4657c6cc4bf..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/internal/generator/config/bw6-756.go +++ /dev/null @@ -1,177 +0,0 @@ -package config - -var BW6_756 = Curve{ - Name: "bw6-756", - CurvePackage: "bw6756", - EnumID: "BW6_756", - FrModulus: "605248206075306171733248481581800960739847691770924913753520744034740935903401304776283802348837311170974282940417", - FpModulus: "366325390957376286590726555727219947825377821289246188278797409783441745356050456327989347160777465284190855125642086860525706497928518803244008749360363712553766506755227344593404398783886857865261088226271336335268413437902849", - G1: Point{ - CoordType: "fp.Element", - CoordExtDegree: 1, - PointName: "g1", - GLV: true, - CofactorCleaning: true, - CRange: []int{4, 5, 8, 16}, - Projective: true, - }, - G2: Point{ - CoordType: "fp.Element", - CoordExtDegree: 1, - PointName: "g2", - GLV: true, - CofactorCleaning: true, - CRange: []int{4, 5, 8, 16}, - }, - // 2-isogeny - HashE1: &HashSuiteSswu{ - A: []string{"0xf76adbb5bb98ade21e8fbe4eef81b6e9756798f2e64bff3cb65781179d6b076b17683f3cd5042655e16802b1a5b1b5b5e386e23e2731d24c843595d5c79ca4b8b9179cf10cb86e782d614a1f78930c25aeacdc30c0008fb417dfffffffff2"}, - B: []string{"0x16"}, - Z: []int{11}, - Isogeny: &Isogeny{ - XMap: RationalPolynomial{ - Num: [][]string{ - {"0xb99024c84cb2829c6f231ad6488f8ecbe73b35d177c03c95a1b5d4aff107d954726713be7dc02432d0d2d3f919a6b98b6ff46f95026f313a3f953d1776abdcc48d809cb0a92e2b7464ed6eab9312f612a13505b1d000072f6798000000000"}, - {"0x26bd1df0d7ae6c65ccce9c94a71497cd125c27c5fea6d502de92ee64cfe6161e0e05eb4aa16bb7f4c55960f84e03d6b986c05315e0dc296ea61a6ce0bfe7584381b90f97adb14083c7e63f8683ffffb35baf0000000001"}, - {"0xb99024c84cb282a010dde96a80e9b8571a99e3c121ae77cf5a598f3fd0abd199502d6d31fb5237042160e2f83bbff87df05586dc52cb529ee19d07248b4fbf241ffad1c2a6de71c88e46e4e3dbb1026d5ecafa4e300000000000000000001"}, - }, - Den: [][]string{ - {"0x9af477c35eb9b197333a72529c525f3449709f17fa9b540b7a4bb9933f9858783817ad2a85aedfd3156583e1380f5ae61b014c578370a5ba9869b382ff9d610e06e43e5eb6c5020f1f98fe1a0ffffecd6ebc0000000004"}, - }, - }, - YMap: RationalPolynomial{ - Num: [][]string{ - {"0xb99024c84cb282a010dde96a80e9b8571a99e3c121ae77cf5a598f3fd0abd199502d6d31fb5237042160e2f83bbff87df05586dc52cb529ee19d07248b4fbf241ffad1c2a6de71c88e46e4e3dbb1026d5ecafa4e2ffffffffffffffffffff"}, - {"0x1eed5b76b77315ce6c7800aef7b306952f8658ccae70a80831fd94f251e13a45b7ccc7290e7ae2e14ef34b51df3471733e5650ac56b2e140baada4fc20270074f385fcf816086d73d46b785d5a289f4a69c36293f7ffee097d04000000002"}, - {"0x7bb56ddaddcc5719024ebf85e3a0a46fefc545c5c0628b194a34c4ba6ac12eab1339f794cfc8e22966cea64f49ee8f4675ef712f878e58793870797ac6d90c77a7cc163e6cef3cd9dd88b97adb140df8fcc7f0d07ffff8d09868000000002"}, - {"0xd87d803f042598656902e5a6ebbb571049b389b6a74b8bc73ebdd1ca73731f32dd8a54ba4fdfeada26f108cc45b54c92edb91d566097e064073732fff7dd09aa254f4a0dc2ae2f69fb52b5b4804e82d4ee97795b380000000000000000001"}, - }, - Den: [][]string{ - {"0xf76adbb5bb98ae2ac127e1e3568cf5c978cd2fac2ce89fbf23221455163a6ccc6ae73c42a46d9eb02c812ea04faaa0a7eb1cb3d06e646e292cd15edb646a54302aa3c258de7ded0b685e868524ec033c7e63f8683fffffffffffffffffff9"}, - {"0x3a1bace94385a298b335eadefa9ee3b39b8a3ba8fdfa3f844ddc659737d9212d1508e0eff22193ef280611747505c2164a207ca0d14a3e25f927a3511fdb0465429597638489e0c5abd95f49c5ffff8d09868000000000c"}, - {"0x1d0dd674a1c2d14c599af56f7d4f71d9cdc51dd47efd1fc226ee32cb9bec90968a847077f910c9f7940308ba3a82e10b25103e5068a51f12fc93d1a88fed8232a14acbb1c244f062d5ecafa4e2ffffc684c34000000000c"}, - }, - }, - }, - }, - // 17-isogeny - HashE2: &HashSuiteSswu{ - A: []string{"0x2693fe3f93094f745f2f924da1a4260675024d398700e46db4678d6c77e732927310a52e43b73de56540c9dde1f7896d115a7661f0e25e7c54754324cb2ab353f985c8bdaccf0b3ae0e6ee49e40dd2b5d8aee87356b60e17f9de343033534"}, - B: []string{"0x4577fc0edab719863d99d99fa7737b795dd19e05021cf50e2bfaadf8d3cf9670ba09ab81773af807f37f714475a819c9dd47d9d9b93ec37c70f3b857252cd99cac4151e0b42eb00271779d66c0b0c79e7f450a1fd85b66a23256679146fcb"}, - Z: []int{11}, - Isogeny: &Isogeny{ - XMap: RationalPolynomial{ - Num: [][]string{ - {"0x57b49e22a638e7ce6fd84adb98fef2ee37a078dad5e6db136e00515b7db476b3092fe24c634db1c19b32784bd06db0e1bdbcc194bd2ea84b5485485423516adaf53426ca54ef27fe07de0370f3473b05fab20bba48a8ceeb8f39138734a79"}, - {"0x4eb16246adf77c244d7c96da07c828728ec8cf4f73b36f9d3b8638cd7d5f00932de546ce6d666b6c1c78a99b824336da2aa7cf8017843619aba11c4e20eed632ffbd4ed04676972f223e842b7d9f408585f879993e979cefce07f6b320f98"}, - {"0xb0fe2b7d5cc6757f09eb475d4ec4eb2892eec65ebb4d0b73dffe388dc8b625ae1094586e7d5f12d55eae19f405323e54346d6e75fe5e30ed86a66f3bd956f2e0cf3b68afc427260f3782828672bc312081de7f76b025cb18780f79ccbb931"}, - {"0x63ae87b32561b93fb20fe607e846b376b2db30eb8774a0c741bc2c2525053672f753b6ea1b420fc0817c91332c754ee91bbdf25a5e5fb852314dc28a26aef1a6fc6bae25a0285b8355a97b597283baeb152f6a0ff281a7a6029551336d19a"}, - {"0x8e95e735b9b8a53ec343d0960e4ee6f8d38aaadd78fb413533fb771a3be16d1dfb91d669d0fdf927aa93c60a147c23c6b26b66cab157b3b1381e64646aae66dfc53e2698852470de8fb92e17b4504bc43249a9a2e7330e3b5e25da416f46f"}, - {"0x5f0f6d5f0ff7ce8777840d1c4d25d85f9a63f04df2479c5b73f1a95a3caf20143e0bf4e9412a9d9d63de7b03be54cfe59522fa2405cd2b02340479f9c8776d6ea9fca2dea8d6d71f455162a6e9f40b76311257170313a8682db61095c7bb5"}, - {"0xce64c0bb237310b05120e54a6ce7ca932dc2d6411b9761463cf0c31e07d4caf5bac19db735631219b68c1dd00e79f19e2653d050137a01218f5b1371d9a276a8938dfd36a0565662a1c60e970b0ba6ca1e330ca446d4863f5c44cf57dfe70"}, - {"0x5c79bf1abe91cef7276af031994044074bd33da0fdde5d1356095b3d02fa2d46345e935838131a84e7408ef41afb492c5a5cf8256daa4be842a0c4e9056f1f3eae94b3d47a78956718cec82b21f3e51338e5e2dea165bb52ed3c3fef55e2 "}, - {"0x528d835a2e6a30781df335a708c54aeb2b71dea9a27564944950b4eb0d8298a44b86f039ac8815883395a340deb72664ce9ef1d01799fe56b8141ffa816ff7ce020b37944db6c438b78a9e78e96ccbc63cff0f7f7e9366ee17fcce48ded23"}, - {"0x778a6ab417356eb65d79c0a0a1cf6d67f3de72168b1ac6c13f3f619fbb33e1da96b6b4b7f07ab0d82d1702006321158b231b405cfbffe44d033ba590dd218224ea7c800dfa1f00dfc41bc8d4f7d6ae966107bf5589f8ba66cfa90c23216c3"}, - {"0x4147349d36fc97c1ff5e168c56d665d0b6f1a8a048eb903e134490eac3b6d62e9c4741b77e0290a585bfa7a1c0dc29fe0b8000728ae4d7f01a849fde08e5c268914f0dee8ed42612e1531f958cf84126358cd261871bded7381b133541604"}, - {"0xc471c9e9bbb09990d5e6c9f5017fe1382bcb0835464ce01b69391ec611babbeca074b376ad1d5ee9c49a2214a89824f408b8eb1dbf80b9851997a2d7f4fc288fb2ee7c3c4fa9d52283e977c924af4c360c5332fce61c340d6af7edef6cfff"}, - {"0x44d18369bb41e08dea957a700307d9929a58b5565bb4fc9b985b6e98047cf473b636f6afa8ddf5cbf053e02477a616339eaef3bdf402e782850a2dc76555e82e8e803f2aa39f76249929725c6ca5d292d4b10aee3535e3c9d9368f01216da"}, - {"0xd46505c4491681e80a79fca2f3899ddefc5c765972f1ff4f4d20c6b8b89b0be5decd3e700f31ca2a0a24759dab83fd694a850902b3e14d656e4864b6fc2bf1f4aac08ed4fd147884840cb0cea7f94b0f923fb94ce65f77b5992c71e1e5038"}, - {"0x6f9632f9f15470710c2004132ef3ad5f5600087a3195f06fa2a1e69c0aea80a94e43c427cd681cd23040668e3aef649d09455fa213ab6364c58327073c8c798963672d092a60943e08d17f05771a42e6abc0d30ef3f1ec16195ff2e6d455d"}, - {"0x9a51e637dd926867d26d4fea699ddbf56041fb4767c71b5cef365a2a944cb79879168c5a93b9fde6be4d414a4016b01b70c039253548cc08b8309388a1a511ebf1dc8f8b9c436cb21aa944c9240a0c1834fc199be1153717ea4ad6f5cf86 "}, - {"0x52852129f19b369553182b651e1a006b282bec349935ab9fd2b392c7e43de42da08efb80da828e5bdb508c3a396e6e22a4f596da57126b2c654700cca80014fab35dd74dabc755ea253556e3d6a77d3d93f85b80b56fa4d4011970a59dcc4"}, - {"0x1c4076fbf2dfd41be9c3e3c24375f6dc8ab18fa163e8f502566471ef2432f6472cfb668c7b4d2e7753eb5181083607b70cac77be553df58c3b26f757f1c70c45474e0c72ac735c9e176ee3f4a10142ce372df6465e1e1e1e1e1e1e1e1e1e2"}, - }, - Den: [][]string{ - {"0x67ca0a05ba18be2717328e9da3d366da18fe119dbf0c150dd6e49daa6ed4f8de92e85a04bc69f045366c80877116759af4bc0c2a6f49ec158f0a2ba5e118ba6d26ac9f2821aa917978d4a606d940397818481adb5ab3f2c9670d2faac21bf"}, - {"0x461d07431e8397832b6ae980dc75548271ce6a87465b5ea5292316b8b1eb078b69e551472f41df43806e24ad887fcb1f551938ec0efc00499f7c3ba5bf7d8ec6d63a4ddd274aad64d716307d11a0ddb9d1c0f40296317c29455075bffb2ba"}, - {"0x43635d242d3fb85cfd3a36bfa1e3628afb5e1e14ae9f67f5ab735f8f6723bc48ba9c507c50e703220244876a482f00f4d7f2d022eccac8301995542df93cc151c10b4a622565832b8793de295ab227054118d673efecd6c50fea7b111606e"}, - {"0x86095d084f72a9be4c483ccc2c746e6ef6e26720fe2700df898dd5a5b20d6a832e2025d2d00a8447279691db55bea69a97e63e4acff6b5bc3254c3fa00017cb0adf4980a85af177485637c02ccc568a182ae232f54eada9391e3d98ed5ffe"}, - {"0xb017fcf26b80fc4af09015d106339becd5762ccb32eae4554d8eac08772a9335ccb7a8a916bd84caf4bcd4d5e53ad1ddf931deda6d5bc04c2df1682d31c696bf2321a2f005e77db814de79b98353ea4625962b9e30e78311ec0d9825e1f61"}, - {"0x45fb599a0f0a1dc49bb19803f84cb2e31e0c7c36dbdd187ab5bd8f024061a702d3e9dea95dc499b77fc32f4824fbaf91d82433dafbec16e1c977b20efd359e1334357a6a5b2d4b5c9452e665fc212908db0d18cfc0b5a5f3706b47c8868d1"}, - {"0x6b33147c7484eee118a499d769e8cd5067e77bae02abf17f8a47b040d39891089ffc19052ed287404aa3e3d2eb7787cd08bb0bfcc1c990a73d649cbfeadd6c4cf9ae2580101c1a1f45a90d32b0ff13e02b5836642634c7e952b6486d29f8 "}, - {"0x387e570f75f5fa085d262c1cb47c27f872beec94798787b8ea11debe75533ea5b0031eb544968899daacb97792dc67039eabcb6e64559a202f2529af243b2d7f993cf4896d9cd1af66b9cdf2753e483999115c0caa96403d360aa9841aaae"}, - {"0x1257e076f478ad94029dfb12ae9d928ce4550151c5a02aac92329f2ecfbdbd0a41567dc38e5fe5a0d5d3adcee3d1d84639145de0de9644244c34c031bd5d564a483ca617084e2829bd8e898733dfb99cc3cb655161d5854f687d9592c67de"}, - {"0xcb293e9849238ea68db183154dd3318b7a97d2c8b5911164a377e42468284ac8f489f97435e2ae5587efc9390ec8fe2dd55a466388491e21b477cf483333fa4f481bade0f0a80dc35c4d967dad4a5aaa1864323a8ab11f376eb6ee6440cd5"}, - {"0xecfd07101cf66ec654369b1dab1bb19588285083358b3f41fbcfa9a8667bee9f2e009a65b4588590ba71ba35bfbf3f11e0e38cfc02bf8e01475be7ce2fce4a6fcc8aaa3aae1d4696fcf86deff15d543c992e08aa4ef0822fa2da7d3dd82b9"}, - {"0x505e4b45c2fd0610b6de37cee0cb9a6e5434fe87b45190ff65418b316e4852a031583c3b5c28b4f78e5cdebbd7ac1675f1bbabb6bbd07ffad253349ed13c6a1e605856fc83288739254e877b0cca8c895a2119d0c9371fc59deded45cb1b4"}, - {"0x4356cbf741137297e9995a239f126c8e69898333c8a0891ee9ae4acb9f66cd1fb8b5c550d54b3d3516d27fc5ebb31b938d50d18a5d1fd92c4fbc246ae3a12886bab0e3b38692d26b5cc13372389c7c65df91ba04dcb040f2c8356bfb78783"}, - {"0x2d30af585d5961e587be65e1b61869b980d0a9a66510b0013800455621c06ab17bbf7cdb49df67795dba802f4a5dc215300a3a409408de7801f2f0a8e5b3587d478f94c523087fda1b7d9fce00d99ad124ae782dd5a6033e14141ae7af925"}, - {"0x89ce51dbfa7cf438f4174452a0159618713a55916e86698c00023059f53812346d2e996cd2be2ce603938b6e28add4df16fac31411400aaab469b668d9fc0efe45b04c071a2e09243a6f1c24fd2927823ba1b82803796b4c5ee8d14b6eca "}, - {"0x60380c3366f74e8a5f5447e6867e4d6b0ca3c6d01e5ad7bfaff113c053f5cada2ab35379044733a1e57cd19cf5ae16240e7bde52e621adad86a454c400381cf47f872d5b7ccf190cddc4a5477a932bd4a5e22534d30913553db82af7238e4"}, - }, - }, - YMap: RationalPolynomial{ - Num: [][]string{ - {"0x9f93a11a37f333a5052a497f2ff8959bc7b3e69bd5f470445f01d6071d144dbe992d4ea3783f0fe7d017f5dcc1e6d2980590726773e6b4bd7bc10cd999e2c38c2aabb90c484462c378b64918c1a48e51921fb837ac5feba926c3f623c4160"}, - {"0x577ef753befab81d08fb0ce7402dc357e7dcd98cd569530135f3ad339845cfcceb84f041cab594864b56060469cc8e0cefa322613061cf50bb7f8b3adba1caa0a522a5df2481f64cc0fbde989a13c70a8168d6cd40a30a342c186f229597 "}, - {"0xa68f14dfeb538700dd4d74482406ffae6be6396e04519ff32a9d0962b7250cd4a6a14a17fbc36032b9a79cb3f79b06d9918b4a34b8302120baf4757568bd3987d5bad8222ea01116c54237a31599acdc600517d3f733f5150930c07a9b8ac"}, - {"0x62f40704a8cef5860a7c1a0e953d8ab65ae5e0cb6e49d58da6e2501eabf797a77b043818a3bfa545a51060e24c3b7c2773412e527e1b72acf2044d95548b72836851a635e50c4c24b35c5a769b985fe464d857d16cecf2f8060374067589b"}, - {"0x1930bec080bcf38ef774f04e675193fc123f266b80e62e1b294b0978abeb31b3afcb02e33f65309399d12e3803fa052098b473eea25be9b9064c8821c0bbb90d9eba711b1dfddf00c2ae407d79382ccad4c6df7d43c160ed257138fdbd403"}, - {"0x65e5a193d3016af59101e156a7a886a3d15bfebab72190e437dcd4ee1a42a17f739c140aead0cf987e922daaf716fb7b36b61e0996fe6abaa4656b8a7f5b87f41ab28135a032b51957e955ce8efb83242cc62fe08a71dd8065c66720c000d"}, - {"0x7efada35b7158ff27d88e0ebb8775bb5e3c7f4224e20a223bb2acc78e0176802b998265a7d6473b22171bc9a57bf3943ebf43f71fd0f9006e5a7af6e6e76f11b949e7adb6b7d252bb4c36338ad539a9a7c77cea84280e7cd2964e5591d226"}, - {"0x29eb281af9b44d21986ba03590afd087e477f3cad3234825f131a31eab2adb59ed830aeab5e5156f8c5de90f81c12d8231604c9e25c4b358501edef95ed2926a79bf118f22d9c4f6455c8c7e37d618c9bc16c46c974437daf821bbd839df9"}, - {"0x47e261e740726acbe699eac8c486186ec6492f0adc2b3dc99615e874b4b7e093bcdafe1075392c49bca1ed7d4d043e2798c971e73535be10e8f4d6aa23b3bed69de7e75a8d3a8373e8ab0621582fb7cc43d2643095843d47003dccbecfc7d"}, - {"0xbd7d4e63943690a235389a6bb5d448042414a1fd9dcf42116515f6f7e5dbaf168a9830e70255aefd2bc14ca35eeb922039ab85ba718d3e6d23d86b08381e413ce18ab5c378c43675af0695ee62eb42790c5d5f89c2d0db6460678d5d7d2ed"}, - {"0x41c2f299e34019cb40e2af5a6bded90f03c9e6e0cbdd853e783f4f3d95935d39ee31fbb61d17610387b84ba9519c16881183a72c59fe7383aa5ae217b42b7480f8f058ad146edf6b4a7549cccea967ded9fd28d150274cee458208907ced2"}, - {"0x405da38064d76408c3adde67a954882f3c8fd36eabe3201a9dfd75629c8f4036c1d63831453109f54cfbc4cc8b9e5f663d3db51eefcefbce9b533b82e005bd9ee7af344ca3dcc40775a3fd24231ad6aa8ec93782ca5005c54856f0d85c04a"}, - {"0x5bafa78c01429499eed6e25e9349a6ca3d2e0ac1267e137174d00a6c433c6095e3d1f312fef70a5703698371ddd1c06e302261b4f6069ec4b78ad4e3dcb37b5253c0787566ba225638b446092283e42cbe85907b5ebff3b33c270a868f0c "}, - {"0x39c152b20238115dd4e6df5508cab1e2c8a7ee9eefdc292f058b6f89586654c8b3586b6f76e713ba51824ca6e2e3ac7a381a8f1746d7d5e500312a7c8513c46a5736425da606f7b9d34fb95df8e54ba0e7cdaef0079df1eced56133412cd "}, - {"0xfeac73088d841e8e555bfc8117068298c2aa3b88c0172c8339c4c507dc212472eccc77267a6946c0c4c260135b4a5f0665194fdf129bc15fc9623987abc4b4d251feb6696737b390dd48da1ee8eae6123b350c4356ab64e534709643ac84 "}, - {"0x6a9a250e9bafa906b1ee1517ad74a816a62c5706d13b5a198fbefb1d2d3dbda735841e67a0adc0ad30495670bd2b83953c65b19aa017ee928b6d5d195b3d16590edf554767224c79b07e803db87acc6a54b60d71b15eb75702f9168c5181e"}, - {"0xe1aeadc4bbd21621ff33dcea2e0ec99a6ea667741cf62af0494afde045b4ccb713836169de252f3018df60a9b42972f3ce650e5fd93a8e06e4fc281fead12a631e834d5753f175a5d76c2c3582caf46cdce6228ce2e767d59573c748ffe55"}, - {"0x7ed20aa5207c66a812970c473f270e99e5974d86d49be1e1976f669388cd568cf799f5c57d9a251960bad6c97dd3fc335eb51b4852cca361a95fc3eff218be4b9b46bfebfc552521659092156b85da783cc46a24ba5d1c1af9ddf017443b0"}, - {"0x7235fb0eb41c06b940ccf7b11788831523a2347562d30c2b147b7381f37a4a63dbae4794c8bd7d0f681bf17aa86221277496fd257af5814f73c8303e1ba09fb80ecf6627b00d453dc712e67aec504f7ece5f39d54f49f6212e792ec1b67dc"}, - {"0xba8193a4d3130aa424d39453c76c8ed262b2e2e0d07f453061b253ce779e1ba0a03f90d00a58f8d08c681204aa771512b68cd12d2dd4e7ee320514a2d5f56a1b8dd2a33c1d4d60a503cade7e0eafd341d8ac667b1c8ccee77ee263808a2c0"}, - {"0xf58592db221a5b17116ecd2bf86c7cb449dd623e49bf58ccb63baaf1cfbaae68778caa8b2f5d9b9211636f79b7ef12b9aa2155c4ef99276190af85a5121b9beccd7c747e153187c668b1846a179312b7fdccb9fd8273ffd3b058c2a97e99f"}, - {"0x2fb957ed355d384286b2f6153caad9da4cd75da2f960d2b0162badab4e6bb653f08a4ba1c93813fd4bdc0ed7ff19073696c16685bc73c7924f3f094e19db49cdce7365a991e22911fe27b1ddf631c5f8775210eee3de31057c27f397c5db2"}, - {"0x9a597c03b1977869ca1a58b04c6c7b5a8136d673428d8077c01fef3fcf1b7661dd2c9a0a9f258d60ac5cddbaddb91dc17e171cb4a48d32d3eaf5be484430496052e4e835781bbdb2f52aa838da2b488143dc2266adbcc6dad98b7bc422c65"}, - {"0xe19735baa44196f6aa3be94274abd8e8669acdf6e9d985820bf1adf34d66305e0a9c697ae0996b67513553a1a5b6e2c465895925873497d56cb7796a3a3fb58bea27d51180a658bcd7d81c7a86577ed8ed84b61484b70703a5be7ae16fce5"}, - {"0x3be0b32a85b89ede867e519b45827587ac1c9b3201628e5a499574e5da2edccadf907d9f793c735da5ff0fc3e60d3550653e133c3d1b467b5951ac65f8ac41b50e3a2e76024288847449f0d35d73d783c6a1c167f67a3e01c5894d10d4986"}, - }, - Den: [][]string{ - {"0x6fce5ce514cee5debaed37973056b6a3edfe727211c6e6a1fab570eed4f2a508e96d6b081ff4a1b1a8acdf79fd0bd33c663045955b8cc064b8b92b7bbfd15fec96bb04be80bae195d8d9d51c240630f776a199d13ecad6bc53f75189d614d"}, - {"0xe0962cd218121ad29e5d7490bf192c86380cb1f4aa91a0e3a86aa73be92a1c3e8a440a35f0248ee807f47a4239a421000433a638d113dca21313ab532984ee2abf3b38d1170fc51c7ae131c57a7449c65cfdd78de9c937528723d0712be77"}, - {"0x1ccc8c1978c03d019911928c1fafaafbfd603ad5590c6854d54c3ea722f18a19020e256e2d2f66418fd103b42765a5195c910f10097fe452c4ba4b5d5ce5a67ee3adde1a6b2cdf3b7721da38f676e97788cc4c64e2e7962fb81bbdc0f28ba"}, - {"0xe22f7cbf189dff65136339d090ea28fc60f120cfa26dd8433c6960b418362be2336be5e929dcc61beb4412dcb232db75be87f17b02742c2206620c090b9799e3ed9d988b69316875970f19cf14388a4fde13f176355fd16b702a250a65024"}, - {"0xe8f52882ce0a0e52ca01be901b93d21fdffae3d31b385750e422cc08cf926c7958a67728e2d26aae7ebf673a840d9d1f8aeb9e58a379f690461f8100817b8185a3e87401b650d473bea9733277bd2166d9f1d7f6fbe6711012bb354d2e636"}, - {"0x875fe99541a3b4273eb0e06ca68021e7b484844fe1276a3dd6c1ca17fff7bfa81a7fe367de671cbfe1498baea048a898dfd77b2d7ffbd4bbf204f862d8771bd35197f0575f6ddaf2dd8915747726e2aae3ddd49c58e47d732e7dc74aaccfa"}, - {"0x4dfd80356811a35a65acb00c46d07a392658904a4fc0cbda29046c44a833a31ed9850230c5f4ed0c1e1e76576ad104d193292821897138fdb5700b90c70041f6f5570cba9b4f4d7def07d469b4c892e87d2ec709ba01068510b911e9e8ad3"}, - {"0xa7f230aa84f2547cbe501721f030ed5bc4376f897cc22d1df86da38d73b27c3903e3e44109d24de87f66a029b5cfd5f68fa440f57de9533515f9912fc130ee39f65d7fb8da98d707cbcb268a3f32cb3b40ab7dcac9128d916a20625e28985"}, - {"0x7f35f1b0caeeffdd8711317415c54cfc5a1a04ab3cd08e6b4415b78b5760ce5dc99acd7c5a4a4c1238c478461e7b79c4f09bc4b7c9c42468fabcfdf142db1403d5b01a4cd818594dfaf729a18514e62aeb7a3733765836d2a9d893325c7a9"}, - {"0x9bce845eb9ff707815ed7ed3fb74d199d492671d29a3bf2072594b9154f530a311514634ef4fb471e883c854dde519b85f679d07aea459f7c3870ba31b1bd2c3548152cc0ce70241c24572d7eb65069b1a97f2bd155a4185ef91ea5659b13"}, - {"0xf0e88310ee09722be8558b6ee541afb4441bc1e77ae82ebcd5d792f6330980c3d36914d73138f0da01be4580c0c2188c0e2a010746b596d80755e71d07028f78bc29af82e7e5be87fb3430b1696810ea95758f3924d846cc0192a1e4f6e10"}, - {"0x8237fb8a7d102cfa45e7020363d892aa7380d1b5ee84b792c65fc2b167552c67623578c416e9922772f3ec99fddaef25907d91bbf0c72b8f0a0070a4d635a1ccdc78a8c6d4a175ed00a68a1eb0e7b90a6a5f33c6555486c77d4aed026ebaa"}, - {"0xacc8c17e87078f38e1056204eea4bd9343903c88966d0ddc2ca5166a97a99db4b66f74480eaf6030d42f8f23f00f1e7a1a6d13f086a76f04f14e98f12917de8d7998089c48bd860301813a95f708c6bd0417acadf80cb9831ee34286cfea8"}, - {"0xa9c3c892d49a5c3e506bfa242431f2b9f3934c51c40045e40478e1f4120da439ba6f0cc154e80bf1ea7ced993b7310545b6af11a6b3bbab611e648afe77297a776ef9468f51706bfbf60a100b53571a0a7361cb592a4f3000a45c013c950f"}, - {"0xeeade4edfeeeef2bc9f34296787829c99b544f11722d55db8789550c5e005ae27d651137cbdf9cb95ca030e3d84544dd21d7dca37bcab9f0e1ddc4cf633b5986746b0371648bac79367a9512396e9789031acc705cbff8c6d15d828c6bdd8"}, - {"0x6b6c82e8a5d0faec7af39bbaa40d86ea47acaac61910aaf01c238d8ac0f2587e2f993835b77e0312a3d23a2da61cfe7d68c91af4d0e24dfa29d5ce2c470c29c5ff6d89f060a0c0546daa1287fa3ab18a20cc1666ad84e3343d25997269773"}, - {"0xdb9102798323f938aa773da2a56ebce58aee6da13e2b10b8a56bea0398ad2d5fa0585d35f7b8b0e9076577c6e36ccf6f9d12e9018bbc8424d38620b874e24d4265bbf27fe0940ddd713e2bf225f0cac7a82c92516c75fc6d88cdbbdd58ec0"}, - {"0x3ad0edad38f3ac9e11e7c078c6e80cf48879547ea9efe567d0fcf53151b71697643a4940c375e6593b96a3370c56964ea3fc16bb574197886c0d9da0064eeb7e4121296069a4509b10f97a4b4a4943d083dbe0a221465711128d1778f332 "}, - {"0xc23a66e6ae7cebc4e55e5a301aa0bb92932e809fc326fc2a9e5ca5711241c8c77313b93e8065e8ecfeb3765a53e2b48bbbd6e27b960e76d00dd5f212f51c2381f6571a0a2d1bdb232ae1fea083b5573ebc76b53c5e8c53434a3e0ba80c3e4"}, - {"0x9dea557e9d9328f93a7a014265d3e7bb51164ef0a4eee3dd1219b918c457f7f0818521d498b13552933f9ead5b0b48d6b3db282c72ec06d7ca1721d3732f3fb59c6c655f3526db0cc833984a0f4957f312abf88133767cad4485c2f9b9af2"}, - {"0x9497a4421814871b03a96cb5d6b294880db80435d857c2fe9f4e97d75b37c795a1728121d66ce742793f98090d0c894f715a7e81dce84f594369b8bb2b9be0d482436c1ceffdc50efae8d85be760beecec788b5f1b08180dfe69567a0c102"}, - {"0x9ca415b1068cafcb60219e17f1350a1ba427a276689247978356bc51e19fbc7bde4a260c33e175dfc83ab230d17ed24c88d8de8c145213227d443192eeb2e1e4c61b7be341bd88638d5b44cedf93d445b344552c004f4b02bcc04b4c235e5"}, - {"0x2a27787477dddb1679fedf03a1e406b8df8cee954e12fd31e027d2d20f5dd6ffe6dc92a5c9ab16be8f21439232809c6187cdae5a5c6fb2f48617d22f6f2a719c5fa6125df02e551fc5c88bf21ff67de5c3cae2f8553bea742fdb7cc29c9cd"}, - {"0x9054124d1a72f5cf8efe6bd9c9bd742092f5aa382d88439f87e99da07df0b047400cfd35866acd72d83b3a6b7085213615b9cd7c5932848449f67f2600542b6ebf4ac4093b36a5934ca6f7eb37dcc1bef8d337cf3c8d9cffdc944072b5556"}, - }, - }, - }, - }, -} - -var tBW6_756 = TwistedEdwardsCurve{ - Name: BW6_756.Name, - Package: "twistededwards", - EnumID: BW6_756.EnumID, - A: "35895", - D: "35894", - Cofactor: "8", - Order: "75656025759413271466656060197725120092480961471365614219134998880569790930794516726065877484428941069706901665493", - BaseX: "357240753431396842603421262238241571158569743053156052278371293545344505472364896271378029423975465332156840775830", - BaseY: "279345325880910540799960837653138904956852780817349960193932651092957355032339063742900216468694143617372745972501", -} - -func init() { - addCurve(&BW6_756) - addTwistedEdwardCurve(&tBW6_756) -} diff --git a/vendor/github.com/consensys/gnark-crypto/internal/generator/config/bw6-761.go b/vendor/github.com/consensys/gnark-crypto/internal/generator/config/bw6-761.go deleted file mode 100644 index 33f34ae6994..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/internal/generator/config/bw6-761.go +++ /dev/null @@ -1,279 +0,0 @@ -package config - -var BW6_761 = Curve{ - Name: "bw6-761", - CurvePackage: "bw6761", - EnumID: "BW6_761", - FrModulus: "258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458177", - FpModulus: "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068299", - G1: Point{ - CoordType: "fp.Element", - CoordExtDegree: 1, - PointName: "g1", - GLV: true, - CofactorCleaning: true, - CRange: []int{4, 5, 8, 16}, - Projective: true, - }, - G2: Point{ - CoordType: "fp.Element", - CoordExtDegree: 1, - PointName: "g2", - GLV: true, - CofactorCleaning: true, - CRange: []int{4, 5, 8, 16}, - }, - // 2-isogeny - HashE1: &HashSuiteSswu{ - A: []string{"0x122e824fb83ce0ad187c94004faff3eb926186a81d14688528275ef8087be41707ba638e584e91903cebaff25b423048689c8ed12f9fd9071dcd3dc73ebff2e98a116c25667a8f8160cf8aeeaf0a437e6913e6870000082f49d00000000007c"}, - B: []string{"0x122e824fb83ce0ad187c94004faff3eb926186a81d14688528275ef8087be41707ba638e584e91903cebaff25b423048689c8ed12f9fd9071dcd3dc73ebff2e98a116c25667a8f8160cf8aeeaf0a437e6913e6870000082f49d000000000075"}, - Z: []int{2}, - Isogeny: &Isogeny{ - XMap: RationalPolynomial{ - Num: [][]string{ - {"0x48ba093ee0f382b461f250013ebfcfae49861aa07451a214a09d7be021ef905c1ee98e39613a4640f3aebfc96d08c121a2723b44be7f641c7734f71cfaffcba62845b09599ea3e05833e2bbabc290df9a44f9a1c000020bd27400000000022"}, - {"0x9174127dc1e70568c3e4a0027d7f9f5c930c3540e8a34429413af7c043df20b83dd31c72c2748c81e75d7f92da11824344e476897cfec838ee69ee39f5ff974c508b612b33d47c0b067c577578521bf3489f34380000417a4e800000000046"}, - {"0x48ba093ee0f382b461f250013ebfcfae49861aa07451a214a09d7be021ef905c1ee98e39613a4640f3aebfc96d08c121a2723b44be7f641c7734f71cfaffcba62845b09599ea3e05833e2bbabc290df9a44f9a1c000020bd27400000000023"}, - }, - Den: [][]string{ - {"2"}, - }, - }, - YMap: RationalPolynomial{ - Num: [][]string{ - {"0xda2e1bbca2da881d25d6f003bc3f6f0adc924fe15cf4e63de1d873a065ceb1145cbcaaac23aed2c2db0c3f5c471a4364e756b1ce3b7e2c55659ee556f0ff62f278d111c0cdbeba1089ba8330347b29ececeece540000623775c0000000006a"}, - {"0x6d170dde516d440e92eb7801de1fb7856e4927f0ae7a731ef0ec39d032e7588a2e5e555611d769616d861fae238d21b273ab58e71dbf162ab2cf72ab787fb1793c6888e066df5d0844dd41981a3d94f67677672a0000311bbae00000000036"}, - {"0xda2e1bbca2da881d25d6f003bc3f6f0adc924fe15cf4e63de1d873a065ceb1145cbcaaac23aed2c2db0c3f5c471a4364e756b1ce3b7e2c55659ee556f0ff62f278d111c0cdbeba1089ba8330347b29ececeece540000623775c00000000069"}, - {"0xb5d1171d3260c6c2f4ddc8031cdf8733b7cf429122cc15339189b5b054d6e8e64d47e38f7311afa26134df779095e2d4161d942bdc3e7a472a0469c8737f7d1f64ae397600c99b0dc81b6d52d666a2f01ac70146000051d8e2200000000057"}, - }, - Den: [][]string{ - {"8"}, - {"12"}, - {"6"}, - }, - }, - }, - }, - - // 37-isogeny - HashE2: &HashSuiteSswu{ - A: []string{"0x10f6a7725da2bcbd3df98cd57fb04b0378eb7ff3d8fa48869b2b9ddf31d3fc46fa7c4805b5d4a79e54f495b52586a15154dca22425367989fae305ea22f0b5a4f979aa9f1d46f7cad2f21696aab503eb53485d6ccbfdedca97936b7702a7d20"}, - B: []string{"0xe1c43bfe2767901cf467cf40adfb7afe484d0d477552a8570a117661033c8dce4d56ccf35850bb0a5c646e4433a9b0e43b8701384b604cf95ffbd668698f8bd2f2739baa20c154eb7c88974a36fb5487c4cd8a1eb00205769d93924cfb0ba0"}, - Z: []int{11}, - Isogeny: &Isogeny{ - - XMap: RationalPolynomial{ - Num: [][]string{ - {"0x25398befd780935a98ddee5ea60e4ee96dcc3cc7e2f9f2ce97adb5eee13f1f1d35eba83968f25cdff13be2d0446e1ee6e19d332712d7b1f63509e090425865b0383f77a43ec7c63055a6631892a33b84b81457257314d13bbfbcc995aa9def"}, - {"0xbf9fff0b23525e2cea97716a08dd64003da7fce131cc13876e7ae922718e7c7b8a219fde11b35b7442d2f97a46f689a9c48636800a987bbfb5878e89b551db4b37469c6d446d4d6b59255708ea4a3f127b3199065213283b886788a53960bb"}, - {"0x4eff3f1c655d2a87d2d8283ee2451dd85a772545d9213f5dbe1f3410d2e21ac1808ca7876eae1110b33a6fd2073d467ece168630a242486579def540c85a2d66fec67d057d6091b08e20aaf4c3900a8c9f901844d51d38ec5ef4abb1b0f811"}, - {"0x1e9c0bcdf00775a750d64d31305f42117cd59252c0a3ed281e6b08cc26c3503e7d05a200d062300d173f5bc69a0c0fed0be50d429b72ddefc9aebb14a47596d061f1bd6ecc6a303dfd9b3a47a35b12829b3c40eb8012f2b68c765be361f50e"}, - {"0x116276c9e850399fd7f4da35f933e4b185e5932d984665cfb821f13cbc8726a455e5efa50ccc596ccddfe93c3d9bb016f1b95e42631f82ba4207ccbc0c1aa33ba899a6c1bb9a54571ac158f417dcf0ad4eff05a3ba55e9b9dcb0e5b01bbf218"}, - {"0x5619dcaec9c5296187bd9bae9507ba8e6c764f581fcd92d618cd9a9246e7fc50fc7f9fc8b5ac87c1897dd329ce72a85b9194b010ac6877b5ff0e5fc60379ece4bffe6e7b08d3aaba9a2301aaa0a77ccc80e216f0a8bb8b4a261eb76080b1a0"}, - {"0xc6b516997dc93cdfa17c6218ac94a6a91248abd4c6f43fa5b4fc697fc3a51effd39e55b261bc89b4aa71955df8380a40b7dfc1ffa29a01e26df9ffad6e3f3d756cf5b0793b92846b66d18057e2cf6366e3030836caad9abe69b47472abe20"}, - {"0x4159773ff45be12f91af867bbc0af2809e340c244c1e4be605650a2d3c609120ceedba9b1808a1307ec320948f88df769d1b678fc9de1c010756fe9464e4b5e0d11010524bc0cc292cae038ff9590096b71194706660fa88f6a001f17e4148"}, - {"0xaa0ec8348732fa3c9a97761f624ea4478cf6d4419f0b2f9dd9a54f91c5a95df61a058d1be7bd5c791e5b7f3a662bff96ad246272e77d2955ac52b817e161e397d8ade57c4f1be9df28eab1ae49a7d53ab57fc1dd84dc967f8bfb768731e132"}, - {"0x5626a46d9768ffdae515e2f43220eb9bc29cad1e6793bc78b1f1be6d8f55cd60cdc4d6653c7fd12024398d4ab901d283ca67c9798e8a1b6983a8a07db5897134b381dc523cdf9799229e5aedfd6b680cd75083a78b24cc73f6b3e515a00fc5"}, - {"0x68dd735eddf59490dad172f6aa60ae8110aaadb1fd2e1b708a8d429feca6b81381225666854277c93a5275ba75045d83e407ddc6a763ae980dfefa0b2523cd61362d7a658c622b5766e55a1b1d054b7199a9e0ccfac1d6bcfee34dff34b476"}, - {"0xf4d4ce5273a64c3463d1f51ed0895d3e20ea073bd4ca22febba741c47b6f6883866e984d62de4976b2890d5541e63af463d3b0b96b17b8b5821149389544a0c7bad5736bbe9b58395827786cd4f06f2c7c882980b290e4e5d7799004039838"}, - {"0x7563caac9e1636456f2e72d9034a59342e3a863bcce6b762e1b683fd1f9d7851b192b15bc2e19ffeff8560621285497077cacf7a160b59a22f3c3db6aadec7f650a575732b62884994e454ec534c0e955a38c42bb24a748129f53becb91d3c"}, - {"0x8250dc5250d43ba6fd216c9b07c2a8553cf26f9486c053518e2ef1d3acb59f2413bbfa33967b4225c1e3beb6ddcd94465c6f5dc1486d70853b86f092fa65e0d1786a8c3fb2f2dd10b309a98fc123d556e30c14737e05ed4cc7cec012423f4a"}, - {"0x110eb883b84c0238f7acbb20d75f08db04da7ecdf1c7dd8ed99d8f75c923154e280a750318163921759043a5c88c1cc2ba425380bb8486f9c3a9f9d716cdb0f4c2f1dcf96686fe582d4a88fdf21727d4342d7183b1d58de15587a280e1b16ba"}, - {"0x12187cc667349a16a75bdaea33e2993f7cd21d582124bdb248d746264fdd53091cb92188d8da7ba18e5ae858f047724f0d088320747de67e34ceff1e0199fb760f49dd57670711a1be6d4b6898f568fa44b560463b95adc10267acc34419791"}, - {"0xc40934532a6e2559a91a4b56f795bb6d7ab621deac562916e0fac5082c42d6ad331b9b83d4b9741925518bb8d963fa934dd3ec288a062437669f25104de2110e4ce5fc21a60590e0cbda800df12e1900d474846c0276c9f11084032b75a610"}, - {"0x950b7a24e3005b05c4d6cff3719f15f292b33ab2b6b52f5e0f4562d44233fb554d53bfc048ebc9bb5fcd3c92a88824de5ffbb5c1eb887c0dbb4fc5c20663dca7f66b5cec7bd641f751e21af2136f5e8eeb5dedf9d0d5e866566fc73de38afe"}, - {"0xd9e2458632e3e1f2a102f36965e3130f9d5e5eb0dce8240464bf79d11cf57f41c8fe66c04d820811d9d2af9f9e09d0265070fccc415e0aabdc0fd0ad081e12a5290090f531562d4c717b411165d8e1eb1a4cbaf5f239fcb6581c1a75712a1c"}, - {"0x122bf1411d59559e306075c9a9e73edba1dcba34443b235a1f3942a0f8edbc955d9ea0d9af240d05809eb3c0ca980527fd545e5988e6dece2da9e35061a2f637bd9f1f35aed13871ae23e6283c7e18e7459971cdbfde54507f7f22f281b63e8"}, - {"0x87f8706b78c7434a1e7d3eb3bd363eebf95d01ad6872e8660a6946347699f965417b8fff42df607d4fb609f414ab8eec9c02a4eb0e9b887a1765aabacdb3c1dba24cd1834095e31d358be65cde6d7a498163678ba1bc763da43c538dacda43"}, - {"0x99598dd5d2443bac8cd6e5c3ecc45cc4aeacf527c1b3567d300698a2ad073f5568544c5b71529380fd88d628416643b95c1afc65436bd2d12bcb4072876e5117b0e5c841b35a019fdffa973882e72a6118c03201210f4161d8179a77fa96c1"}, - {"0x395ccb482186b0d3462ee62749d639e3c946f14379eb2adfae39a686af0d4f512da5e99d9af6022457a75ece4bbad3c805d8d4a74640e02abc3ad625ef7c5b763d0b6c1251f66c991e087a392b0beb82edf72225a85c8d6466b035edbf2627"}, - {"0x3770ad705bdb83b47be929dc5dbd908ea8d79598a767879033c5fc2a0c7b91722c960bc130c0efe87d53576e8c5584a26c62a0e740d13db50d1adb0312b21f33b91fa89dedb493a757ca9aeed1bc2a4dca12793197678cc8fc57fb2e6a56ac"}, - {"0xb257db251cd766a618b10b3eb05d4af66e0aea31f5b3ad460f9d2ee1692d5e8bee298b3ff61841b1706de0438fc9e2081e54ef4b70ab63a355cbf3e06dea5b41435f7b3882192ba5af9b9414da295a0f419f4b95b543208c06f7ecb2cee716"}, - {"0x7c600c60c02239ce8ebf41f0319bd21e2552cd6d452ac9e8aa6608a38158307eab1e9425d494bbea54615c07dfa0470939e3434510c0d1241407c57b28097da2b181d27d3886d4856fd784a1d2dc53001117ecc1f7fd1e581f192e17b098e4"}, - {"0x6045e5de1830a58673c025130d7e80ca97bdf40887772da41dfa549d9869292e1739c1a407e6beb8fe2b99199b4e942be609f5dff7996e0af243b4b11f95f1786c4a1ca576a1265de1e7c3b2546ffa8a5bedea1ca96dc7a81f84a5e4c77a04"}, - {"0x1116eaf37b6d0408ff038d49e29bbcbeb447cdbf49cc259e3f4d48a852ae1ab74c117ff277ca19f08fdc9e4216d315b3a9119460a4f60001dd6be6807db300b5ea9afdd5dc63959275c79bb59c4f32368ea77ec4a4d15a476cd0590165bfa10"}, - {"0x10c94d5d3bb80cf510755331b3761f7ec4df14992881bfca3bc7c43801a077bcb294c8186153487ac19f724a22735b8979e9b86fe34fb6c262367c41a8c76af62fc7da83db17f6ed4eca215750b6d12d2b278585c654ec29d0937b7788940cf"}, - {"0x1adc9be54368e5538aea2182f9892b6fc66405c9a6ee59731427aad5ca1d09ede3e3dd2bcbe7e04c582d8b2fac638d2a329bef768de78a149589710130f3bd407b9ed5535d7b45778b5c1a5ce3957fb462cfea58a7c29dc22c876bc3992eba"}, - {"0xf92aafea05c0b551ae26fc31b31a624c28d43b2633de8dffa690d627760fd04ecc01e0a43cd2e7969263d703cde2cf4dce88410004356d82e535ece5f3ad1a38cd9d787aed584380a438416810b4e3d756be29b52f16db58cb885b83891e8a"}, - {"0xf6e4a497e67292d3b2ed5800dc4c716545175e45f04fbe0e16c6a905e5d2bf099b5c6d989299fa31f11352a7b0423cce76646b492696aeb3a7e139b8e5caa737c3cd3513cff20173437870a9943d5bf1d6c6dc4732032256fdfae43caae4af"}, - {"0xef6b9dc12aff103afb6d8f85d712538920f39072ae840d58faa0774a7df1f5a17e3f741298e9e83ac88fee4b5105f489e0b72b470b5219bf21f8af05c1f8f848904da49371d8c95b5cc896bf727d0fe6b0ddf965c1e3dd973bf8bcb5b2d932"}, - {"0x37bd2a9eca40df6fb0a16dea501ffc6dbe8b455c21dc65f29692d9d31a98ca815a302e0d0b8bbcefe63b793e4c81bd825704414613e8457453e1be9bac8a7f7b282310f4f7e8a281c422256ceed512339ecb348bc9bab690ee7db0b90202c9"}, - {"0xa29355f9bb4369fe4ed85ef14ed5a3c7307701d32c7f31d71947530f8064d5ec499eb17ae6d82853c8ed14eca3b3bcc1cf7cf698b7364a7aa6e63a8ddf20d34757eb4f206648f43a009d6c9caa25290617164247c47dc48ff1743446f7b562"}, - {"0xc505e34288c6805efcec5bd0586564640e784560bca7cafccb08a8b0a53d7c8d646fb60288a071f5cf1e2454d1ee1866365f32535d94e4a8cd0a05c209dedcc42eabbc105c080a94185fc6bbb331d3b77382a663a40b36098c030d178e3021"}, - {"0x110e5f69e48a34b6f6fbbf1c7525e873245669b5fced30ad78975d61b872b5d5e91dab7f4cd23259d7e04c517730240eaec702f238c42fae550b64d4deb617b0b6fd1beb61403c45268912bf795ba2d35d9e292ea1add7e535361761270669a"}, - {"0x11d2b5f8809e696da7ce154a2b558753626d70bd7b5067f4698f205252bde384b7ba440c014b56084035045d969b63e08179de17ac29216aa5592e88f8e24f8c1c021e7750d2a67b1628c2e8dab61965aa233740750f8d5a4cd83d55d4fd9a3"}, - }, - Den: [][]string{ - {"0x83be65e9149262d3203a99fc9235079469fd8d9c911ccd0f38c12cfa4c622ce757f49b41f1ea4687b29ee8e01212e58d238c956a5b1649f1c477e1ff8a6a6bc1f109dfcad55d5a778c8fb21cb49743c66d8cb6619163d013bb217cfcd15e05"}, - {"0xaa517d92a19b280dbc13f7f29fa923a05e4e8bb01bc2e44c40a96c6af237ba313bae0ea41f64bf4fe6b7d864dfb1c747ef73e9a6dfc1b5b4d299b0826c99357c1676f61345c05f9d8a532ca415fabb4199a33cd0a482c684e3c8c259d78aa1"}, - {"0xe1629421ebe8e0a16cb1565702c894b7f3a2509d42812b8937a081006435279fc5e3243489c3ae9448f42e0cc419c63b57cb203c524bec8fd171c1866ac52b773ce80494d0e2637d4bec5faa81b7c2c2f21e91d8fbee3c7f16cb858eb70520"}, - {"0x57980339d02e07fff4324765c596e2799aae01736d752ced8e6086fda14d435dcb1297ff21ee6d272be5d2bd6fc2bfc3190ac40dfa02e83990d5fe9a026656f64c6d99261dfd05fba525230d034791591e40c7aa7e73b38cbf54f627495f04"}, - {"0x807a9d43baffb4c128a86c128170656322ef19ef433ef5111ebf61c6ffa11be2f2efe09bd80e833650c2c6387de30f62198c8e02b2e812bead3143f06ade297f06f14b1646dc66cf282ca33cf458990ac6f3c071503a7932c19b9c48043f7d"}, - {"0x4da51c8bf1b1c0bdbf2c7825ef3b1fdea3b7fe74d8f897a874b2c4ca00b378d789d36d51d1dd7da1d548867183f030b9670a67b481c8fc587e8d9b67f363a4a0185cef41f30caa824b6e9411dd28dad32434ed655c99623e00314350319ed7"}, - {"0xd678e47f25725d1140f98408eebb2bf4db0ea59317a2e77c4ffa7f5e9c346d01387f79c929418fda184a7276209c9b05ae0b9a176d9757100b3713e1098c0ab035ad8969adea919a6200a879e27f01d2e5f2637dafe1ab78e03ac41fe61f71"}, - {"0x5d25a1d2d6b36bce592661279a360506c0422e78491c50618be960b85a7754b3a2fc8773c11d48c73cce13c69c5779d336405c1e236474d499fc63f0200673c4de4ee42dd2f2f295dc48d093e671b13eb94bb2a9534bf739c4a19098760a7b"}, - {"0x4fc12158207d5bd8cce8d1ea3f5c39517edc59e368546db2527caa4d5435654fa55fe40851cbd6c51c0ea8a22fdc4a5c0c180b1849b078b708a83b0f58edce813c6fd60f8d55063343a94722d0185cd273db90cc68a8daa7b2e2031557671b"}, - {"0x31c9b9108620d96f550a9746df4c3d85583fdb9d2d0f68a5bece080110ee8014cebe83083d1faf3b9389969a2481ebb2a98a90b207abd3743414a7365368e689738bdf5ba4b922d15f5dd1e2c40fe9565ad6338b0799d81ed1399106858606"}, - {"0x1117948c172e353417c135bb8d8da0d60ad5c7a0134739917b9f4eac2962e531e85faaf3642bee15183c801da80af4ca79e14256eb769421adc15349fd7a64d945f2916a9e673fcb5bf70f115045a314aefc405e3d277514bba37e932c814df"}, - {"0x3c242e9ec4fbecd4bb2508c41d59c4b626cf707a0bcee49bbec0b8a4a2777c5763c1ac8a0fecb629123f4c9648b5ef86fc81d40ec29525105ab3852df29d4123e143f005ca3445d6a5bff17dfff186eb5f4e257790dde0f1a0b35b7c519b02"}, - {"0x12004baa7bf2797052c48564d94448af483b791a8a58bb0fdfac7206aa30d90a19c75fa26826f6c0e50883fb357d08a13eb13f7b5c64a4a25dcf61cd4c2c04de84df8239a04ec26af80bd483d5843ba5e761284263c974e3877bc21f1dbc197"}, - {"0x40fb8a400112da16c9c847085bd345e2ce2b11e484e5b3361e5e12b0e9b99eef6e1a527cdd123882805d27b8c39737634b9ba27e953a7f26e7bbbaf3a92eaf7cc3496b7505c67958ef08de00740cf7168bb49e7be687c65630847ec9cf64c9"}, - {"0xdb841e9665a8721fbe1361196f1abffbaaf8e61aa13128b8595719b3f8fb1cbdd3b350ca0de1c3188ef820ad8490998744bc8a5e177284ff0d43c84428deee9d41f7f1a042eefb03d02cdcef7653fc6be44f80826df6dc54146f14e3aec5cb"}, - {"0x86d23a6f45e1098d00b8ffec6b12be016250481227e1f2d81b90c3e1cda0ebd2f4efdf381c8bb523f227f275bb681f78a6c95523259720ac3723be36b282cf191288be453008a231c23b67db1eb959d0e149a8135000c5b44ffd1ca5c2439f"}, - {"0x109f5d1ef11a74270bc231cf7083d7278ba957f6d56fbfb3e8fde415ec551664198b8505ffffe1e15dd118b0a4331a8c17a3b98b50643e84dda3165037e42bb9c6019281a3f4be180a738fcb5168c9d76140a06e27d5089ba7f377b9132a05d"}, - {"0x1f274511e3255d4b4a9ad16cce613ed711a05c14758fc9493891cd2d7648807dd6e4556cad36a50945e3e31e4056d27cd49d3dd9ad86701305943bda400c3751bb082764aeda446723655be92a8100fe76f0c7933540daa8afabdc002806b4"}, - {"0x59843e330375000405b054eb5a19aa651450f2c5e26bfaa5032ad4778fbfad597a13691eb8576642f74dc05243b74750701ca40bd7308dae55746104e41cba2226d91cd70b541be8944e403b8930c835f8fc924f556f0274dc8c241c1b1fec"}, - {"0x171ec81a25db9e6028013ed9a5456bb33310e6d3198f21a8e7cf9ce447f30b8830709b9888078e38d676bef24209e26fc81cfd8b80a13d17461841767498fb47afd44ec6239c843f1312f26b0c8025f05f13e8f68db73bba437745b394b0aa"}, - {"0xd1b60042578201579ee9af7daf134f171ac865a3c7165f7a5732ad4a9f2bd301d10e4fee128e96037d468e035e418c46d3c9a11d00622b09d61761fb05f99f2aa2a9ce622cda95c2b321122e7e5c5a1f664e1c44fe46fc9db8a745eb0837af"}, - {"0x6bded64c75b35c01a8313a4bc6695d762020056e0fe4d87677e9088d5cf5585c8482facc8637ee4e619906637a26245ee4694f78d1afd6cb0071844e710d7498e924478db66d35e1f8eb480537873ace7d72c4cce9c5e409e93fd19cb4390f"}, - {"0x409e187b5c36bc9b744db93e60f4f26fe820f8f9ac1731a4ec4220adb0ad1d92b89b69bdabc9bd1db1b99d029c083a5345d9b8681866f3100a77a5e69a9616a7142416b98a84f701740c4f95de3cdda3a198e9861b6cec6e26255bbe772da2"}, - {"0x10366573a3c6655de24305051f27ed68efeec35822c0137e5e2b286cfb2c535c78ff42dc67539545ef780f8cbd8044e9f96e58387cc4f1ebcc1fe836cf359d02e71eb64eb313279edae20943c0642d57338e60b031adfd4bbb424dda4d2872d"}, - {"0x4146d8d1bb6cb1c43ded16f5c07010cb808fa767a0b59047519679124a5a1ab4a1f2cee179146460ff296440254807b842c968e364611b56d0ce862f3e4f79a9d3dc0d7f5c0a3aec81ace2208b3d6710fded09f7864d29bbef79886571cb09"}, - {"0x8f94d7b08b0685963d24fc8b9281d6c290a4124e987136973122a30db0749c48ffc8fdca733627914344dc1077e20be895e36ba93ced63e9792812913c9762277d8556ebc293c4cfe6f89c5f7358e9284b59c1fbdd37b0e066cd8bf282b1a9"}, - {"0xae19c1dd2ea2e1f7a7e0a05a24945897e533f3bd719347b3050acf6d68480a01d574f10498145d27d505bdeb3bcb9bcf931275c48c6e1a4f18a46b7c03d9c0bd458032e2198b4823371c9ced7c68826b05a1b94f09bcb2e16217baf4c9a2b7"}, - {"0x3937cfd56241d0c6ece2dbbba9fbf5b7e5e4432feb90c2641baa78ee87828a5c3659d9f06dc762dd5d91cb5fece510f4d29802513a25db34f734d4338a4e473fb50e4cd4617ed3a93f2f00f00d543522dc42a4255be811e68869ffcf502f13"}, - {"0xf056010b5a01c99c3eb8515f0c20cf81567cdfd453df66412443c4853dc34a994126d11fa6c1a59c5b3de3d5572c95cf0daebd76733cd1a61436adf73571077dfcd4ee452ef07acba0fd15371473f7c7127b4dc1f97da8227b87dad9530dfa"}, - {"0x1193e22533f0c5ea8a191ae0ae6055d62c68c59d05e3dd03eb343777b3615485da3ea5174759b34b9f486f97b6657580d810f573e57ed46c8649c002a6441c3666526fe8f7140b870760ca5be04a3339bdfc10d996752c61819e18d862f868c"}, - {"0x788926be987f1259c031ac18dd6771beef4ff0580dcb455bc125fe1385113df0cbff993559f55752ea1502a3e8e84087b4f9531a48e939cdf4f41f31a10198e9a82cb07f0d78e82deb8aa18cb2e3cee5319d4df2fe4f4bf69201e84fd2f575"}, - {"0x66be610c58e904d4b5827f9b746ea5fcdf60f2e66e1ab240fb5c65eafc982d5e3eec9134d29b991497cc387471e05462a1925828c6e296c6f1a965c209f33e48cba22997fb02d315c63aaaca45b6ef7c0beaa2a96da60e839cf4957d6bbcc9"}, - {"0x3487a8ea28fc7b67a089b3e70e5eb268ab99485f31d1c7d7f281853c4e0d1e7d9e0c9521839d7286e6e1729df7da275bc576bbcf8b1e00d1e2f996150fbc725b904bc0077173d29ffcfcf6e03469176987f60ba39a8f6ee0c29d448a7a750f"}, - {"0xc68234b4d6bd5a4a37d13151f8e0f13a90cb6ce91d72e9ae916b2a29837bd01e5d4ce2adb1d90e883a1f6b5ac9b25ff7a37cefb7d9e29fd88ec1e9f3578cda671ce824b3253bc69319490268f60bcb93de665904d44acf45dd4c19861070f7"}, - {"0xe84f9cfffdd42f1f808768789dbcfcc30a49ab979995fda69cdf696e4f6b8d453573937c1801d258fcfbb3836f79e39ffff9f88084f61369cba6ed1f84bdeda53f1d7615f2971ad92d6ca0aa810ee44e94c6c5df4aed9b849eac77e0ee83c0"}, - {"0x496a56f15bd023ff76aad9ec934a63320f3eb03b60d13cc7bfa0b88d00a6168dccec5cee5fd2b01e059a414a876a757f502701eb366739350845b04410654aa1027e22511ca88e182106cca0b8f36489af9fd429a7e7b8b57030689b11f45e"}, - }, - }, - YMap: RationalPolynomial{ - Num: [][]string{ - {"0x5d38ef6582e5d7a838009ac71ecc25a6c64fdd19f4bc0d74af29b637cf51a14f40aa1bfc18a0f412ee1275c5211795d5dabcb7f7512dd4444f8725595ab965db9a2a330376fd7467616cf35fb20d8f65c93d02c1ee651929bfef3a02010998"}, - {"0x4dc036c1f4c016a18f48ccaeee3d1fce48ead68ff10b5d267a4e8090ef866a3fbfc9c826b1794ee575247585a3ee598e23e636b0e4f8a54b1bd182ccae0edd530e76c56b88bf2af50ac380ae79d88debeef0b16ca39f174df39b08284a51bc"}, - {"0x3032bb517e9743a55bb8f645f20cc63ceb8e92584534d6b157d461483dc394441df9ffd30fa13a5bad96c22b1ba1c0bb6f88899d3133f4b56cb1fc503627425bfe13de5eed7f9819a9afc6944c7537df20aafc097ad6650d17ae743d1cee77"}, - {"0x971c6e281c15dd21949eebccdb904c1ce2ddb0e4b541c93acbea7528285822fc660b6fdda6b92cd4872bc83ee741775f2d9c3a5765d7e70ae7ba2de60c3c73a1a54ccafae655deebaab1c03efa9bea4f5f51a718088eefe57f0292b5b14798"}, - {"0x7ab3de0b6540aac0819b8e9e40d8ab1599106f942af09c137f4242c9c26ea921dd782682c76b266b6e44cbe3843b0ad523e02a80d2af69efa3eec5c39e58566df3cd8157a20ca4c7383eee7b2c32f2459464abd5b9ffd5351c3d881a41dcf6"}, - {"0xfaecdb4a216f5c7f32b59689f8faa85d747f95adb8920419474afb8d55def7b52682c26fba23bdea292ebe6076a67e9ff4740cd2c0d222dc90412eef46c7902dfde4eac64e1d7399d4e2fa756be80bccca12b9b64f0bd9ebb616458aa651af"}, - {"0x8397c87fe6e56393d59e832cc69bf1daa706aff0f68f038d9cc3049d41dce6557e412256d8cc41d57deeff92852eb959fd7d2e8bbc39a3bee17b956ba9645f05e5cfa1fc66ce57d80cdcc9ae937c26555f0c238f158150aa6aab8494457159"}, - {"0xfd13e17f5b33195a3e4c6d3ef8d0fa3de081bf635cc38b22101eebbc673ad40e5212a5cae0285df75c6769b83d84610f3ea9b5a93dd2081ceb23cf5834c7efb2e39153e8d40277887343b630410b7581b9629a92f85236e04d1aa471383f36"}, - {"0xd2a831f4ed31fc9f53cf9e502189be67bf2ef9a4f1a05187e18f2f0158c40e421e8e747c5fb1c706c7830f2fd8186e99bfc4ee25a2f5a2e9adb4509e98c131abdf595fea29a48cadf69d57c9b08d71fe6661c6b597dfb30d4c4d83cd504522"}, - {"0x10f83707440c9575bbfb5e4779d00f3adab570857d6b2811efc6a36563c05877d23b8aee98b99e041a5d5677a5da2d59e16d1b9918956f720339f140f4b09ee23748dcb557135e538413f14e78199b2a7f5cc106c644fcb2ea142dce8f1fd4b"}, - {"0xea00809253d1081f62d4bca37aa536bd29dfa9d57ff211e93bf7d291dba621af65fbc05fea7fbd771e330b360ac2ef1c86f267f7d790a4c49b3a35855de520fae53b016499e2e4d34572ddf22182f45e0427f4e2af38dabca89918101013a6"}, - {"0x7a484843420c7079e43d6ec50dc2f94949b813b16c3e517c61034acab7ff1d212d5a6599460cb97a848e98ff86b779b57b9230fafdcb310bce8bdff32facfb7e8ff5d5a6a141e9aff51d0638810bfad02b374b56b167e1ce274d752d80cec0"}, - {"0x549b03fc6497586f83bd2db5fe2657effee7d0e500b4e694f966895bffda5393c27db4075cde98805be3c10994e10de502ea076e860ddca3dcb79e63ce6bee9a1b6703bcb605c43087318f0d9036c301e7841d0c7b032de1661ccd715d16c4"}, - {"0x76b1f83abc358751cf969aad2c4e59899996d0dafddf76f497fb693264670c7a65a536aae27c30bb34d8511d64c396cea615ef78c116d62dd81eee16e9882159fe92c56df94c27eb7aaac74e5a8ba04244451552360419feee867f6cac723"}, - {"0xd92f770caca73c3505c3a4e58a7eae19c1851ef9db25f07a785cbb78e4f4aecedfa7a5a5046f4622f3179b37ba00c45cc4bdc6b1fe86ebe49c8e9fa4290d257bc319185c825b66e8b180472ab7f80ad3c71a1dce9938ede56e2d7ece900d05"}, - {"0xfd5ac3a657102e0a54acb58d0a04e488934116e5d876c58b86a4e35d3af411aa83627651dc8198133a4eebf14e19286ef5b491286e562465445f465b742f94cc23dd887057cbb808afd477ab63bc467215b1971ba490fa2827e0d81a108f04"}, - {"0x10d6bec8b4dc04bbec4fb4149db3eb29604aae9f7a45f258015e66821b85b690cebb16777021aa0cfa0fa34d3e1f85161d11bc16183faa6051d6f726d0d26d1e7772543c32487fe27d852626b42cbd04256b5f9f5929cce9e84ce3a35eca852"}, - {"0x10d36f163c2f08d03557ace6308c74b4985dda1228f121e4c469dc37fe80c9b15fb569f5620065425a517010c93c0957a3bfe5b960d77e28d9bbe429518b494ffd268084140d17ab534b79f2bc5cfa780e5cb6fd5857f00251437d184fc3f36"}, - {"0x94302fe280a10e8c5c6601016f8744495ca119f4195d4eaa219e74506a25e93030a47862ca125d213b260738ab01882fb14e1971bd92b5c59e8f29172ed2f4ae8c9cc142a1044b8d3219e9bb292ca5e7bb3f5c0294f64a67e33642c8cedebd"}, - {"0xf062482aea1a30b121edd74c39fc070f3981682f0566f5c9143c65ef8f33182291639e5ab1db19070742f6e39d7bf38f66171536a9f164d1e7a5b478bcc9638a908135644b4fdb979659c28be6bf01b89adf6dbe5108084824251a5eec8f4e"}, - {"0x867a161c059d9df42b5fd6674cd91ecf88204c3bd498d793b67baf81420007af8dcf3327ac0402d6a72ba8af92b62c55509e3fb37bf8ce4bf048104f61229f8b52ee9a4bb45d6dd2362173e276d6857d5adb961662cf301618899b2c8acee4"}, - {"0xbac156f5735f9db804c79b3be77614d0365928205198a8405fe744332cbe784d46a3754dff8864841a2095232a01803ff43459f8904e6158f003b6917075bc588ac2424bbb9546ed2a7df59247dec3675e3150a892d82d592a2dac11077577"}, - {"0x9db7d39ec19ee775c663f000d726ff2373d9355bc9bad384d0f297b0a5b5e3173f6ba8dda95db0e29f6440102e90ee524a30eec0be66e95780a25e43123ee678c407256a77ac16334bf85e2ec00871599facc241bb42e6e8aef8454bc2193c"}, - {"0x5d679b51a45e040c495721d309dc5d813db4670a1f71d020beeb499fd28e420b9c46edbd145d83fc514c5af80a70690b8ad616242723b732929ed3780050ed2802adc6bddaaf8180303c7ed3723c217acd225430db169b18377f482c9c67ed"}, - {"0x1083a6218e20e989bd3d5a8dc6b72927ee61b6f1ae6520d5058f8414abdae3dc928be29740397c34e7c47099981a6418227b692bd23e6d8e0f17c9ecdcac75fc71b9746675772b093583c55451077c29cfbcfc20f10cc3c33b6d3fa576fb798"}, - {"0x2a2684b5ed4c54325a36d5472a22ddb44e499780360ac833a0d88b5bc6ae75c58a7f62540701579c56d530f8d7681c8c784854e40a58816f5fbb6432eaa776534dd47b3611bec33b6e87464163f7e9e44d485b2e47d9a07e64ec57dd29cc4d"}, - {"0x47402b33b50d3ddcf4a15f745e0102d11be7528f1f5996e4042f107bd090237bf5d75cd37f0912d86e971ef9452cc46312b7428a952dcbbe959fa1d767ecca1a0b36e1e30a30e0f71dfc457c548a04390371a2221556232dae36edb8da064f"}, - {"0x11da53c9271b02c7158fb2ee86ebdae385da9ea1fbc07ffd9dbd8c3e8aa15ecda86d607469df1146982d7261aa35c97b7d74d09bb9ffb479f935e71c69f3c60005dbca5491a4954b01fb413b5e506092664ad2cfb727419b104acd72e036f7"}, - {"0x536cf5aa2222d8de443b557d093c9f29f4a16dfd168e6afc1382d9841697ffd7ddeba4d099d2bced00a1aa2285b1788db932d59fb3fa891ce97d2f74e9475927fd9616c5594b9152e99dd586d5ca8ae8be11cb213289ae895cbdd4b2fd465f"}, - {"0x1da860f7c3597b35726e87cb3bf0b209effb0ef9ff5b2f116098e644235ff06707de8383e4cedca3defa727819c6a7fa4574dcca3844096d8e55ec3405ea3036e724ad26480fc08be1d562c7db9a0e0795b37e337e09e16c7e5033546ee8f5"}, - {"0xd07de606072f1a8a527374c766ddbbf30dbcf9fcc9ef0dbee36409d153931702895dff106c34aec8d2f6b85c4e2b310c4a6df78a37e45b4cce27062ae58f9a7ab8b3e8d7b3b60585903ff5bb83b5861ad82d740046741b91f7b951a5dc3cbf"}, - {"0x2606343340db37698dead78d4cddcaf70a6850b005f27101986c5c402a6d7b86ebaab95f8345807c243ae39a51ad91df6b27ebd90b4aff85afec988b3889012caa8fffad0c621eee9993dcc69f370fc96b5e854cb8eee096061ae383c00b4c"}, - {"0x5eef4743e715650a29dfe5d51bd349b00d506292b178708638d69fb99ad660056b8b80f206e1d507b863f2b1b7a26f3a2c115ad138ad6aef6591d911993705da206b6107e5469f8cc1d7623bcc867c10fc3bf41c10b4104dadc1914da7a424"}, - {"0x76727dcb29badfdf33c34dbb80cddf85084d5def7241d7ac8b6b29fa04e1097c534b5272704c75de0b439d26ae3089a3db2899041e275f3bcdcf5364b8505ecd98cae322ff7b37fafba7a8c9f7b81bbead4e4831bfa37dce31ccd4c0ec0393"}, - {"0x1121863773817cea34fb74e529bb85fb5eedd5cd253a9b209f248b1095a79371ba0d58cc7ab19fe62fc91bff7d55b99a1c92b6f299a157d6abd061c56b99a40f4ae8f571ca8bae37cc46f7d72e31283358d089786ed293882489deb19f2fa5c"}, - {"0x380aa09030f5968743a51f91b9f4f2e76ffdfdf93c0c1e481db8f7ab2f12b6f1af4c65388b2283f4dafed85cbc94f02482426fb73d27c1f9bbb98fd1ee37baf2ff25c8d28160f91cb356679908cc289c5ddd7c3b0c10d70ce520877d6a5ed8"}, - {"0x3d32fd2068147a3f7da278555ed406ade542cf524e674563b2cf9b4e8bded523fe0c6cfa7ba4366049ef1853ec49dbec71308f9d9c07fb2c92669f403228ec339e9c0d854340e32a0d312366872b84850b002246a56dc42da0d78a794f82e0"}, - {"0x8d03083b6680f456a6ca2f12731aec4d9bc3047f1338dca3dface56f3e5dcaa248034a8008c1cb6e2103cb759d3ee7f9bf050ccf5fa589cf3da4fc83ad8abad35cadd716d51de0f823f8874aa7b1759c1265d7767ce44a23e0fa26cfede36b"}, - {"0xc153033cca117585a8e7e559a8b5afee72d31ac7c96ea9660856b636d26664619b0d16312f43c760798af878a41561ac18b87cb636c456d653b58d0343cc76cac997ca14928b935bf6c9b9912d6cd88ce3ad7b2525c09727dc2e15752ff950"}, - {"0x9e424fec6f5e28209f0dccf860a5bf271461173cb2f2c63922b520ea861c8b17876b00af0a926be498559104ab3701da59cde8972717093092fdcf0f4f1cf5ef798db7f5bb86db0db37c4ded8e979869c1a62aa3e84f2091906b0838a3822e"}, - {"0x1f7b0fd3b4c9a79f8302d026517b9018ec27da4cae421b702cf5e7c4923c438d89a24c946e473af82528298e92df34b54ec696ef86299d10c3fd8252b951b2b4dfd3b829a59c81c6ace17f6001df90e6be71bd5d68d42de866f3ab1a202423"}, - {"0x9402f37c7ba1e44be19ae14fe91a6545acef0b2a0a5e36b28179853b1f2c7f98e988945246a9d0bd433602ad0a75d66c4ccaad92800b997574767815e9ace78b11abe421571bf819ccdc2068accedae0e729315b2a1520c7bf579272dffd49"}, - {"0x331d1df12f90a78ef9e864e208ca152c9de1601075da588eeac25127988d0f04e16af1f2c817b2c33bfacf0c4696b86f5015b0f66c40cdb768aa2eec7bb555a17a245f7136ff01da8de4970bcba352e698e1f350dd17890e07447f13f2928b"}, - {"0xf6fe753cc6edfb75968c8f6b8cd121a06115ed350ee30dee74f5bf91816efa1a47d450f52febdbd8ebcb5483c9b169ceae1125e2f69f254cc91e9077d7e6e409b9e80ea5e76ec5e6d9a84a25bfda45ab2555314aa4a458243fe5c225c1d149"}, - {"0xc1034618a75481d52de528c17b76c6f30c350df5827accfe92a886055129790032d1cc01eac8727255e1ba03557cacd704ba2912a0737ed16a69f98bd196588d474d6cad779bb90d87f6743a87573f081a734090b05d1a591bcb6d4526c7c2"}, - {"0x19ecb6f5a4ad4557134ccbd3ebbbf4d3d0062a9a5d288da6f0e21bf98f2c04ec673033817c2ba1e808a23e96b99e945ce33a695884cacbdf15991bf2b9c4b3b9a5133888ae5f3947be1f9d499316f170f8218494d43536d883db4c24584adb"}, - {"0x32f37e3a71b888b9fe0a88c42666b32112b5444f24cbc4d7a805dc02b4538e0bf86cc74ac277acf8acb9dbf815605dc54a746ff5595cf472eabd6299597dd15d479dfb59307169b2b2f1e50c9c6d83d28eaedd5569d7f6f1f40657df2614c3"}, - {"0x107ee94600281e0d5b68e55349f03c7b886c4b2fc8a827b7a353fda767beabf06fccae229fc2bc576b49ab29263c7d21499172898b4757f3b44aa54fbe99015cc1b263d929c94b3a7019490d6e28b2c7475a7977d4822a065bdefc470912dc3"}, - {"0x3b4583aa3c1f1cdcbd1b268fecbd5c85c46d7ecac4cfa94d2ed766887ea79549a9580d8a0ce47039ff60bc4d3aa202435af74c97403c172ece712bf15c246650d6612baac5f7019cb0bdc7175840fe1d7c8c2e9d5c8663cd12a62501e9164d"}, - {"0xf6eab8fc5a94f484333df010d6f2c6b620520cdac1a40546769fa2b02f9d6e466724df638732a4eff5446436296dface1495dcaa6ad4e24b3a14a0c6c98364d2022406167ce327f82da7c59056962b5238085af38db3f39758e9d1bee007f6"}, - {"0x9157bcfa227476f05aae9ed56e79824236cb30f1f47dc82a9648703881f75342ea4dd3f208102bb034ad52f7c0a64d33806df1634fc233317e55e17c70abec3d1fc16cd473e7a1693dc312a5dc498709166bf78607b2726557f1dbfa3af42"}, - {"0x13e95f1b69c1bb059b35da52693903820813354d0c2a3ee18c0077aa967afc4b7115d0fb99e814c7b256acc47cc4f9995bb0df178a604f5ca838ace81cb080dbd40e67dd731e8c54ace47e999d79841e38881f52e8ba7eb82420e457069bc7"}, - {"0x5d6d5a496bda19771b6fcdf7cefd6dfbcaa8945fe445b5223cc538ac2ba0df97e495af83fd6f9c272e3e4914ebf9277380079d9290a356d9111bc382492cbc13ae4ddd0e0d7ba5a1f3c117569a2a8e96d169af588d1d4085d0d801a598d121"}, - {"0x12ed009e830c3052d44ec9cd6787457249084772a2cc3118ce49b1bf668dd1a977f524abcda366867cdbbbdbea655cb336d2a088df78456d3d21df942137d25b1343edd948cd5e3b49c76ad5937e25f032d00fb29262f071c5e4d0e512650a"}, - {"0xe3da5cd6c4e06d21025932bc0ef3fb4863115ec20420cb77b2f8017df249e00422a4d2dc652400c82dd4dea5de342e9d61fd2f1f842b9e5ac519eb62860061562526e56e1087eef9ce359a629824f703f5c1ea62cad6ae10980a7b6363064b"}, - }, - Den: [][]string{ - {"0xb35848a97889d06c9d137621e2f283fedffc9d4fc1a32da73338a90d0a46fb076bee393363f551ec5bc14317a92290831636fb97eb217a7dfa6e64ee0250a2f0ae408c60ad721aca20082b11124ed0af26b9b472706b58c8e258dec46457d6"}, - {"0x11bd48159d3f3f0a15e56f4758e253a1d2b3b14bc308c858f3837abb8e3868658920679627e8a93ad269631ef17b1b1693afc409afe41a71e49f64a1e2535fea30f085d24b7b6cf9aebcb322358f81a34b6599c88bc90b978d0218b755cf2c1"}, - {"0x1c14b675d0ee3fe6c012a5be16d84618112e7838d3621e79f62729f8c76dee05199cd66a64c52aa80351363fc91830a3e7eff500235ff5c69ff02823bc95ac6a89a3fd461e7921c71a8ccb57635f073f3a1b29a71071003fc0be48a5aa8990"}, - {"0xa40a04a2472305ed9478e4c4eb679c1cf87bad62fff861126ad8969c548ffa26543e86f1c1d27957a59aa160465d5ef918cd65e450a2973cd329b5480adf5911a750b83ec47ca6f60866eba9f5cb0f2c11b38e7caa549f970d2a3190a03dca"}, - {"0x1e0f2070926cb9da608e7a9daad66a92ea5236683edecabeb6fa27abf86c91f8007095f818b4581f306698731cda8328dbf7ec5526cd091746e7a9545a34f943ed863ba6982ce022f6f63d9102c7508f332dc3b5de64c22435f0937548c9a2"}, - {"0xc3a32f1093a2d37f26a614efc790a279c8284c321c191637dd146829dc90518ff37b4801cf7688fdbedf8984cd0292c99034198757d5b07e946c0f4aaf869d7613162bdb8c2b9f64e958a97391e099d0f12f032c6458e1213a0a44282225fa"}, - {"0xe02ea67182f3fe3d578b08f0d7928b7c6fdca2115b687ebf858dfa3ed273ed68a9853fa0675254cdbf5e038e2dff11fe6be1ac0acfb7e2d69713c9e5053107232558137964f4d8c75f9d499b5d1172c7c7c7ca17ba1552c181482c6fde568c"}, - {"0xb7bdc820045b8cb4750d2cf14442e75e71ff88850bb68c703a9d570b4ead2265e1433921511be60f0f494ef406d6ffab61439f2492902d06a47ab797611ed56a2db85dbc6ca66ea91fbded330d1607a8f0665333167eac5036e8809c424602"}, - {"0x4b874c4266a94c9645d7235482a22dc864d3a95f9123f6dd42ac37687a32fb96d6d078704623519d355e7d2942b96183761b60a96d86b24158041b2d27e0b6d83f524e2dfd36aa32c722dc52e6c8f90b372e4c69b8d57c400535580e741931"}, - {"0xed7683d3ed7bd7b795127161c1c3d283e2e5264b38ec25fff29cd620f0f35b50bae6134ca7c707fda9f21f1e5ed72dba00b4db93a2289a0ca3325006b7901fd25eb3112b01280113100c8c706e5cf754cfebdadea45bfb1bcad9b55b6a8bec"}, - {"0x798e60091f0baff46af8096d5d385c3ac834078bc68a5a0264b38d84d3e575383492076590dd1c78ce517c938bb2977a4a53c19a224ef3c06480ba9458bc3810382e54b052a61ea2a9eab88b7f2e4379616e835e8aaf9ceb8f7725c00e473b"}, - {"0xe25d6afa99d9845550da2d8be7e54972c881f60e60fc44e1aa4639a469895429c40ded2c5a915747487760917ba655e5bd70e760a60bce724ebe669a6f9a26e612a7e471c491eb901f086651f804b2e8ae65cbc30fbfecc3ab056254152e1e"}, - {"0xd3bd269478c18fe4ae906db51c2c61c8e8eba8c0ffeafee1a4590f0f771c420738c368e903c5bb0ab4ae5d764f1db9d32dd0941af5abdcb799a0a7868ab22b8066bb43409f5618113ee9dbd7095a1132467d7cf792c2edcee3f32fc76e377"}, - {"0x10d8abdaa3480b89ebfe1c4f750c43d1ebec7cfd63adfdcff0904e9b54b762843fc0dd9edb82ce3a6dab718b3805f8bf23d59fe0be8558d3168557f22e481614c83c08a53ef37d647faecda297e45535112f46edc37101ca78aa36db8baa52e"}, - {"0x73757c884a1e868d44f45a39a70be12ca5fbca1045af3c5dfce747238edd7926dc150df6bae0de22fe58a951f68e395e3c6b58285afb6e13d04f58f3be13f468f1d95d89be6973f4af4a03c854d956e4bb87cdb1e85aea019e5f0e2bca4543"}, - {"0x43b12c0a691c949e92b6c9de3f2fd57d511a8f558567437c329ea1602a4f9575c328c6ce9abe3a41d6977eef727257a82e1bbdc6cd86ef0176fbe891af806075e500c1f05f54880ec857442d6fdfe701cfac8e0bfed571913c10eb250e0022"}, - {"0x5dd753e576c5e17fdb31053f4583d11a7efc9842522012c64dcdf4fb1813de9e2342aca1ea200c8e8ea86c846041648ea1ab64d8286960d339fc3605f38472ebd8a8a371d7a6a99360c4a35173bbc8fea0433e13b00707ca26f29726c1201"}, - {"0xf9cb66cab40e4b021cb9ab0d6ecb29134a25c87261d856001610a3d7fcfc485c34c1acb355a69c9fb3e171b3e36814b50b1d58b14f86d2fd7eeed7fd1ab7785800dece186c33a4fab38104a0c5a8abd353622161daf40d37a6d072443c4d84"}, - {"0x11aa8006f5e3cf018df2a06234daddc183d82f632c47e1adfba4c1747e717c7bc6708aef8baaf81d65520bf3eb7543d6ba7267adac6c2b1fdaaada6f47d96485e0ae6a1a959da775932766eb8c044905d42d295e4609c41019d3215a0ecf1ce"}, - {"0x11cebd8fefc74f456542424a4260474172f2ea3de5ae199758cff05a90330816514c564a4ea7b56ff8173a10c9be915b4c4cbc6dacbfde9ae946a963ecfde2fff66ff267019fb3f6bb80f77aaea5a09d18b8fa6f0b9c4f730c41077a869ea60"}, - {"0x43816faa84ded72d8298e803ffd4500b0d6fc6e4fd2febb9f773a0b2b9a7d2d6e2737798e7a85433717d7c3df4cca47295c9763cd9a14a2a5efd2a535d7af007f795da423ddc4709a0fb39ef1159d316b9a072d30a28f62b79383ae61672c"}, - {"0xbd64fcab7189eba72da0f52543636cdf11c17cf200f39297021b4ddd528da640175c9e79cab502feda518f5643053e92672e569935848dde1411b4f9abf62875b4b0dae6f8a249a05f984d8e2cbe7bc8216896251fc9c801d232ee0a6ace1e"}, - {"0x11908b0ee96ce37dfa9655c3cf2417961b6890de361366d3c889cd33cf5d9726801f9db61f7a445bf3d30e5d2632d899a45da474ca5bc5257cdbeaefee742e5549975d293d3a211b0bff06206bd8da0d66a31684300aa30275ec98af2204fe"}, - {"0x7e3dd2299ac6f6c9b0ca812e5250a5a0a9ac696649ea44304efc9eb17873ba05758cc68535699b63a921dca0c065bc0c74f47dcf13eddfa9a49ade0dfcff10a185ad8a1ea9c0546fd04335ed21eb0c32813b8d98d38ac8444619053ab9e9db"}, - {"0xcecbd40f99ea98da90fa06c98dd11219e5e9dda72c183523827b1fc889ab4a306695fe674307047144468aef1f17993762be4b859483db87b27f442bddb107489d094a51ddf3b5dde5499d79a806e31528ecbebc9894584135547e9875dee7"}, - {"0x8fcd9b98a111fb0b88bc45e05c13e919903c015e73e51c79b1d76f351e36c5640624fcde3e60ad3a5949f9a35dae56bcc3a1886854433eeb48c3498b4b32a913b34b78220b02b0a1cbce157f236d37fb69ef96e98f07644e37c9abd1ceea1c"}, - {"0xbc6e2187eb737df544826df89d5279d06046a2b47664dbb87fce1ab6a3f7edba758835bf0810b4ec4237719e7f801e24e64247f3fec548baf27dbfd691eec0e490ac592e1e066480706aae437bd7bb3ee5c982a9c0ca1575b556005bbea58f"}, - {"0x12170c6c8cd5d3a968d03315342c1251b7e384f85fdfa0d3926b793bd740afa3dc0dc8a51eb829450218c01c0ac8b4eb6163ec1132283f4d366dfbc0582225a6b14163a15df63a27a2ffa2a5da74ee5845d71a8346187ca736714ccbd2b00ce"}, - {"0x1d8792a1d4b4411685a26918d785823cc142a0912ee9a8c1981586b35fb2581492b26b7150fdf1899f678b13789c48c28bae260fb93742507d0323f3f2c908a4b089a4e018ed7b351cf17d05cdca5d13c92201596045f7f89bb44c7e42e17f"}, - {"0x1b457948b6d5eab15ce534d9c997bc32978fce85a19025d325c1705231586ff07f2e334ea9bf39f572423f10f0938ddfb7b44ca8dc8d21317f5ab1c66248922f53126875ee0e35c060f413f4376c474938abc5b57a9ce17c15cdac17c7fce1"}, - {"0x509b78d33906267310fb5764df3a83af5e10b24b3d04ff9a64f1e87872403650d8f05e039b0bbfa50ac9a9a496f509541a5d1ae590acd31e0efea18f9f9b0eae82f2214364c91528dd297288a4a3e04cc82aea73b257947cba2d3c027f3b4e"}, - {"0x34c92249a79e2afe89113c83ff829e7376ebd2bd99f61023336e601144565a3060888f77f83071095752205b778702253fa2a187d9cc0f240fa1401be60298736dabcea50ba63065cc6aae3a089c3bb77dbceefc83fc029a2adf90289d5269"}, - {"0x6158d56b2f6902c287d980c970d8aca6f6d10072eb749afaabdd9a9d098bc6e7bcf07bd1bc8958cb79cbf53dcce6eb72bc34a5c2613384bcde79a64b340640e821855e49f71c073c715dd55768fbbb5a27397cf584fa639d927837ba9a52cf"}, - {"0x6e3c4990d0e48167ffd607fe2c5f4d5e22afdbd2c39113dfb8ff2583d930a9bfa6c2074eefb455bb8ee0618600768b2f85e634791a2f6465642268d8f46d3f10a38d980a60d05c71030b500691002cd7cd01a5497eda666bd77bf2498dfdcf"}, - {"0x2b15f6bcfe35e5d93d3c369fa9e283b137865559be088eb6dcc6e73eb50854b68943546f83849a34668275fa3292da90ea6941391738c9abdda4bdee838b80e7959ad5d72b9fafc33bd1526c7c993dadfed5a79b9bb119c277cef9c7a71dc"}, - {"0xdaf7f2929e35d0ba56ce2742d5d9cce74d572dac5882c678bd6b5f39d7c6d74ee3ec0e4c2e052c635a12ca1389bf62b147c6c85df6adba1b2c70ed3c60424c84dc6b5265e11ec4788ae277f04576101c11009182de27a8eb5953c1aab8e1e2"}, - {"0x4a1b0c9af273773fdf3bd29eae337f09acb8e1b10457187a5f7d43450a6de3b93d3cf86a298a6e99030c0cd203113c46a67fc1689dca1cfbbc663899b2ebf8781db80872c647934862ca898a564fa156b58c554786a7712fdea39d78a366fd"}, - {"0xe22946eb7bdbef6cf67b1b30ff0c6ff4a2d3108d338c55bc561b3ab50db2cb0826365f812464f2cdfd2940476d7fb7db692ce19e2f53bd3486412d1258f91ef75cc0a09b3d72955a6e867452e4e7aa2f1c496fec0b41ff2d5df172664683f0"}, - {"0xcaf9adb7a9fe17c553022cb9fa3ed693a6fe017b6c667b9b3fee7f904fe34ea15e1b671bda21c0e3b8bb07f3301bec8986d8ed48b1461666a88d1b1ec3d12a51b07930b81e544907804d14c5ed8834fc6edc7d660254d8491968ce6034642d"}, - {"0xdae7c72155f240753502352e5ef320d206adde735e9fdda0c6cea0bd48acc5eeca42e615e6a79bfe4f57a3c75816ec327b0fe017bdafda135db84ee4a5cadd38b6c3f32216f411f2a69a45daf35d5242c9ea218557aedfc0c241bef5c25d47"}, - {"0xa44e2a4243eb71846e0c033d0b508654b71ddcbf86b859adcfe48fc5330c4226986f8fe2b405a587c37fb51173e2f438759dd8250235b555a7f99915aba1961c0c1e4abaefcc9ba4d88d08254bef4b4ad5efdebb0f15586981614e65f5a262"}, - {"0x11d90321c1a5e68ce6aeb22eb2c666145d256b2541178474d03d8e918d8ad4fb6e584f004810f1d3e5ebf0ae73645bc8851cd382bb88abf2e65019ca263ce9f961956f03db70d927acff8a5ce8918f6ed96762782c5c78ae56ef3741eeec30e"}, - {"0x73067c544d14eb0fbe73111b96dc68c493c312a408bd3138e176ade7405d93b6553004d77e05da6cf32defa9e65e1267ffe94f6d971f8de118e3bc21fa8b59896ba9a3a1494f176e24195c65730b3fb2c3d0d048de7e13cbe64f64cff8a466"}, - {"0xea2438249db0c31564caec1d831128fe9688db01a3e9b017c68f007bf1dc6782d46226efc730bceb0a4b5d6413f7048bc5b704affb912aed0fdb9d26a3d0add40ebe02bf786a38e8e29e88c6143b9eb289b27fba11a6979905a0bae8c272ce"}, - {"0xb8998d5ec7393dedffe4f708881d1cc145104c8485261ab6df727bc0fa4a7b55dea1a7893791a93790e6af9d1bc0bf3ebe5feb40b340e9e89cee859bc443162e3dbdcda09f1680d74700f56f037e4388aa741daee7bbca5ac789d34210b9ac"}, - {"0x9db9607a944de0743644a01a2bbc68dd869d4df41655c78b91678efa6b297efa53ea116f68a0d01b696ba23cccc34a180d0e888c9d0cd6170b21c7cc47e7040193e605122d2487d0960d31f40fa0f9fb1979f3c9f070ae21d4987aa10635e6"}, - {"0x1064c0575f32e8a01dbb0902016549291db671757d01133b941f80b48ffc6cf6e97ca4112be781a452e4bdaf8188c3db4245c089a8cd9a20a9380970a2f583371a03a3306955b512b8c15992c2689ddd948200fefbd9a23b581426419bdd44a"}, - {"0xb38eb53f5c01ec437a38102c26e021ceab2096dbff88cf994a5e676c67b5e9e2aa0b7b8e5fbf481b9ebb1f2e1143c5d2331b4a7307543827f08ac9b085c9f763eace96795934aaececdb8d5667438f023bd0dcc10a1f53751b46aca1e1a0b3"}, - {"0xd3a1a4efb742aa1a15b063d6601a48f9119b6ad86d32432ed0d80e91fdd274b5a2fb4178cdb5cfadfa462775bed589a228c2974d988b40a7856b1e6f5b7a69201c7226f38239c0e4f57729b74a2a35d56876815defeff9019a4aeaec8ace2a"}, - {"0x890f6b8f09c172a9759a98d2992c4ec9a89e19af59dd9aabcd54dbae2c8bec58b63b35d8b2e0434532e8aea16ac6155c20c944777a8ca9003afa8dd3d6d6ba35ba41c8ea40710297a073dbf4f4b7e2828b20eeb168b3ed9513f7359f8fc075"}, - {"0xec2327808b9cd4a32bc9540933cb13b19057ddfb9d0815a9c3570d94158d5ffff7b1a837c905ea8515e45f571e080770a6d574c1735ec3000d79a494dbab3b2e7c463c8f518ab36199573c42837d74f7b42b001d232aa9847548b8d8c2e9c0"}, - {"0x3347dd7683ba2e167d3b718be720970c262bf6aac6783b7c0c56059a2e218e3983530c568d9666b9e7b1bfd947e1e321e1ef041fad5fdd9e7392055a45b9a13accfb5e13fa30a15f00355721459f71856aa768476a8ea9e0b18cade6ab4f49"}, - {"0x64a3e6bd3ee53dcd1ae4764d398d44760b5c5192d0745d71a452accbbfd3f0f9f106f9866b973d599c20c64ec4b9311f4ec1b991ab43b5b23e865875b56926456fe6399c3f69b7cf8d3bbf6254aef3c137e16a22792898bdf6265a4275368"}, - {"0x6e1f826a09b835ff320046e2dcef94cb16de08591139db2b9f7114d380f921d4b3628b658fbc082d086761efcb1fb03ef83a82e0d19ad5cf8c6888661897eff183bd3379aafcd524318a32f1156d16ce876fbe3e7bdb951028489ce89aee8d"}, - }, - }, - }, - }, -} - -var tBW6_761 = TwistedEdwardsCurve{ - Name: BW6_761.Name, - Package: "twistededwards", - EnumID: BW6_761.EnumID, - A: "-1", - D: "79743", - Cofactor: "8", - Order: "32333053251621136751331591711861691692049189094364332567435817881934511297123972799646723302813083835942624121493", - BaseX: "109887223397525145051017418760180386187632078445902299543670312117371514695798874370143656894667315818446285582389", - BaseY: "31146823455109675839494591101665406662142618451815824757336761504421066243585705807124836638254810186490790034654", -} - -func init() { - addCurve(&BW6_761) - addTwistedEdwardCurve(&tBW6_761) -} diff --git a/vendor/github.com/consensys/gnark-crypto/internal/generator/config/curve.go b/vendor/github.com/consensys/gnark-crypto/internal/generator/config/curve.go deleted file mode 100644 index 0c55a6a9762..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/internal/generator/config/curve.go +++ /dev/null @@ -1,102 +0,0 @@ -package config - -import ( - "math/big" - - "github.com/consensys/gnark-crypto/field/generator/config" -) - -// Curve describes parameters of the curve useful for the template -type Curve struct { - Name string - CurvePackage string - Package string // current package being generated - EnumID string - FpModulus string - FrModulus string - - Fp *config.FieldConfig - Fr *config.FieldConfig - FpUnusedBits int - - FpInfo, FrInfo Field - G1 Point - G2 Point - - HashE1 HashSuite - HashE2 HashSuite -} - -type TwistedEdwardsCurve struct { - Name string - Package string - EnumID string - - A, D, Cofactor, Order, BaseX, BaseY string - - // set if endomorphism - HasEndomorphism bool - Endo0, Endo1 string - Lambda string -} - -type Field struct { - Bits int - Bytes int - Modulus func() *big.Int -} - -func (c Curve) Equal(other Curve) bool { - return c.Name == other.Name -} - -type Point struct { - CoordType string - CoordExtDegree uint8 // value n, such that q = pⁿ - CoordExtRoot int64 // value a, such that the field is Fp[X]/(Xⁿ - a) - PointName string - GLV bool // scalar multiplication using GLV - CofactorCleaning bool // flag telling if the Cofactor cleaning is available - CRange []int // multiexp bucket method: generate inner methods (with const arrays) for each c - Projective bool // generate projective coordinates - A []string //A linear coefficient in Weierstrass form - B []string //B constant term in Weierstrass form -} - -var Curves []Curve -var TwistedEdwardsCurves []TwistedEdwardsCurve - -func defaultCRange() []int { - // default range for C values in the multiExp - return []int{4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} -} - -func addCurve(c *Curve) { - // init FpInfo and FrInfo - c.FpInfo = newFieldInfo(c.FpModulus) - c.FrInfo = newFieldInfo(c.FrModulus) - Curves = append(Curves, *c) -} - -func addTwistedEdwardCurve(c *TwistedEdwardsCurve) { - TwistedEdwardsCurves = append(TwistedEdwardsCurves, *c) -} - -func newFieldInfo(modulus string) Field { - var F Field - var bModulus big.Int - if _, ok := bModulus.SetString(modulus, 10); !ok { - panic("invalid modulus " + modulus) - } - - F.Bits = bModulus.BitLen() - F.Bytes = (F.Bits + 7) / 8 - F.Modulus = func() *big.Int { return new(big.Int).Set(&bModulus) } - return F -} - -type FieldDependency struct { - FieldPackagePath string - ElementType string - FieldPackageName string -} diff --git a/vendor/github.com/consensys/gnark-crypto/internal/generator/config/hash_to_curve.go b/vendor/github.com/consensys/gnark-crypto/internal/generator/config/hash_to_curve.go deleted file mode 100644 index cb7c5b91429..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/internal/generator/config/hash_to_curve.go +++ /dev/null @@ -1,202 +0,0 @@ -package config - -import ( - "math/big" - - field "github.com/consensys/gnark-crypto/field/generator/config" -) - -type FieldElementToCurvePoint string - -const ( - SSWU FieldElementToCurvePoint = "SSWU" - SVDW FieldElementToCurvePoint = "SVDW" -) - -type Isogeny struct { - - //Isogeny to original curve - XMap RationalPolynomial - YMap RationalPolynomial // The y map is also evaluated on x. The result is multiplied by y. -} - -type RationalPolynomial struct { - Num [][]string //Num is stored - Den [][]string //Den is stored. It is also monic. The leading coefficient (1) is omitted. -} - -type HashSuite interface { - GetInfo(baseField *field.FieldConfig, g *Point, name string) HashSuiteInfo -} - -type HashSuiteSswu struct { - //TODO: Move into Isogeny - A []string // A is the Weierstrass curve coefficient of x in the isogenous curve over which the SSWU map is evaluated. - B []string // B is the Weierstrass curve constant term in the isogenous curve over which the SSWU map is evaluated. - - Z []int // z (or zeta) is a quadratic non-residue with //TODO: some extra nice properties, refer to WB19 - Isogeny *Isogeny -} - -func toBigIntSlice(z []int) []big.Int { - res := make([]big.Int, len(z)) - for i := 0; i < len(z); i++ { - res[i].SetInt64(int64(z[i])) - } - return res -} - -type HashSuiteSvdw struct { - z []string - c1 []string - c2 []string - c3 []string - c4 []string -} - -func (parameters *HashSuiteSvdw) GetInfo(baseField *field.FieldConfig, g *Point, name string) HashSuiteInfo { - f := field.NewTower(baseField, g.CoordExtDegree, g.CoordExtRoot) - c := []field.Element{ - field.NewElement(parameters.z), - field.NewElement(parameters.c1), - field.NewElement(parameters.c2), - field.NewElement(parameters.c3), - field.NewElement(parameters.c4), - } - return HashSuiteInfo{ - PrecomputedParams: c, - CofactorClearing: g.CofactorCleaning, - Point: g, - MappingAlgorithm: SVDW, - Name: name, - FieldCoordName: field.CoordNameForExtensionDegree(g.CoordExtDegree), - Field: &f, - } -} - -func (suite *HashSuiteSswu) GetInfo(baseField *field.FieldConfig, g *Point, name string) HashSuiteInfo { - - f := field.NewTower(baseField, g.CoordExtDegree, g.CoordExtRoot) - fieldSizeMod256 := uint8(f.Size.Bits()[0]) - - Z := toBigIntSlice(suite.Z) - var c []field.Element - - if fieldSizeMod256%4 == 3 { - c = make([]field.Element, 2) - c[0] = make([]big.Int, 1) - c[0][0].Rsh(&f.Size, 2) - - c[1] = f.Neg(Z) - c[1] = f.Sqrt(c[1]) - - } else if fieldSizeMod256%8 == 5 { - c = make([]field.Element, 3) - c[0] = make([]big.Int, 1) - c[0][0].Rsh(&f.Size, 3) - - c[1] = make([]big.Int, f.Degree) - c[1][0].SetInt64(-1) - c[1] = f.Sqrt(c[1]) - - c[2] = f.Inverse(c[1]) - c[2] = f.Mul(Z, c[2]) - c[2] = f.Sqrt(c[2]) - - } else if fieldSizeMod256%8 == 1 { - ONE := big.NewInt(1) - c = make([]field.Element, 3) - - c[0] = make([]big.Int, 5) - // c1 .. c5 stored as c[0][0] .. c[0][4] - c[0][0].Sub(&f.Size, big.NewInt(1)) - c1 := c[0][0].TrailingZeroBits() - c[0][0].SetUint64(uint64(c1)) - - var twoPowC1 big.Int - twoPowC1.Lsh(ONE, c1) - c[0][1].Rsh(&f.Size, c1) - c[0][2].Rsh(&c[0][1], 1) - c[0][3].Sub(&twoPowC1, ONE) - c[0][4].Rsh(&twoPowC1, 1) - - // c6, c7 stored as c[1], c[2] respectively - c[1] = f.Exp(Z, &c[0][1]) - - var c7Pow big.Int - c7Pow.Add(&c[0][1], ONE) - c7Pow.Rsh(&c7Pow, 1) - c[2] = f.Exp(Z, &c7Pow) - - } else { - panic("this is logically impossible") - } - - return HashSuiteInfo{ - A: field.NewElement(suite.A), - B: field.NewElement(suite.B), - Z: Z, - Point: g, - CofactorClearing: g.CofactorCleaning, - Name: name, - Isogeny: newIsogenousCurveInfoOptional(suite.Isogeny), - FieldSizeMod256: fieldSizeMod256, - PrecomputedParams: c, - Field: &f, - FieldCoordName: field.CoordNameForExtensionDegree(g.CoordExtDegree), - MappingAlgorithm: SSWU, - } -} - -func stringMatrixToIntMatrix(s [][]string) []field.Element { - res := make([]field.Element, len(s)) - for i, S := range s { - res[i] = field.NewElement(S) - } - return res -} - -func newIsogenousCurveInfoOptional(isogenousCurve *Isogeny) *IsogenyInfo { - if isogenousCurve == nil { - return nil - } - return &IsogenyInfo{ - XMap: RationalPolynomialInfo{ - stringMatrixToIntMatrix(isogenousCurve.XMap.Num), - stringMatrixToIntMatrix(isogenousCurve.XMap.Den), - }, - YMap: RationalPolynomialInfo{ - stringMatrixToIntMatrix(isogenousCurve.YMap.Num), - stringMatrixToIntMatrix(isogenousCurve.YMap.Den), - }, - } -} - -type IsogenyInfo struct { - XMap RationalPolynomialInfo - YMap RationalPolynomialInfo // The y map is also evaluated on x. The result is multiplied by y. -} - -type RationalPolynomialInfo struct { - Num []field.Element - Den []field.Element //denominator is monic. The leading coefficient (1) is omitted. -} - -type HashSuiteInfo struct { - //Isogeny to original curve - Isogeny *IsogenyInfo //pointer so it's nullable. - - A []big.Int //TODO: Move inside IsogenyInfo - B []big.Int - - Point *Point - Field *field.Extension - FieldCoordName string - Name string - FieldSizeMod256 uint8 - PrecomputedParams []field.Element // PrecomputedParams[0][n] correspond to integer cₙ₋₁ in std doc - // PrecomputedParams[n≥1] correspond to field element c_( len(PrecomputedParams[0]) + n - 1 ) in std doc - Z []big.Int // z (or zeta) is a quadratic non-residue with //TODO: some extra nice properties, refer to WB19 - CofactorClearing bool - MappingAlgorithm FieldElementToCurvePoint -} diff --git a/vendor/github.com/consensys/gnark-crypto/internal/generator/config/secp256k1.go b/vendor/github.com/consensys/gnark-crypto/internal/generator/config/secp256k1.go deleted file mode 100644 index 6c0d6b7d914..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/internal/generator/config/secp256k1.go +++ /dev/null @@ -1,28 +0,0 @@ -package config - -var SECP256K1 = Curve{ - Name: "secp256k1", - CurvePackage: "secp256k1", - EnumID: "SECP256k1", - FrModulus: "115792089237316195423570985008687907852837564279074904382605163141518161494337", - FpModulus: "115792089237316195423570985008687907853269984665640564039457584007908834671663", - G1: Point{ - CoordType: "fp.Element", - CoordExtDegree: 1, - PointName: "g1", - GLV: true, - CofactorCleaning: false, - CRange: []int{4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - }, - HashE1: &HashSuiteSvdw{ - z: []string{"1"}, - c1: []string{"8"}, - c2: []string{"57896044618658097711785492504343953926634992332820282019728792003954417335831"}, - c3: []string{"10388779673325959979325452626823788324994718367665745800388075445979975427086"}, - c4: []string{"77194726158210796949047323339125271902179989777093709359638389338605889781098"}, - }, -} - -func init() { - addCurve(&SECP256K1) -} diff --git a/vendor/github.com/consensys/gnark-crypto/internal/generator/config/stark-curve.go b/vendor/github.com/consensys/gnark-crypto/internal/generator/config/stark-curve.go deleted file mode 100644 index 34c267d8b10..00000000000 --- a/vendor/github.com/consensys/gnark-crypto/internal/generator/config/stark-curve.go +++ /dev/null @@ -1,28 +0,0 @@ -package config - -var STARK_CURVE = Curve{ - Name: "stark-curve", - CurvePackage: "starkcurve", - EnumID: "STARK_CURVE", - FrModulus: "3618502788666131213697322783095070105526743751716087489154079457884512865583", - FpModulus: "3618502788666131213697322783095070105623107215331596699973092056135872020481", - G1: Point{ - CoordType: "fp.Element", - CoordExtDegree: 1, - PointName: "g1", - GLV: false, - CofactorCleaning: false, - CRange: defaultCRange(), - }, - HashE1: &HashSuiteSvdw{ - z: []string{"1"}, - c1: []string{"3141592653589793238462643383279502884197169399375105820974944592307816406667"}, - c2: []string{"1809251394333065606848661391547535052811553607665798349986546028067936010240"}, - c3: []string{"747120397548504753672821049844706693752799645928246271384591722031176001048"}, - c4: []string{"272520077186478842991245371323181269386250180546566216570369979330317493608"}, - }, -} - -func init() { - addCurve(&STARK_CURVE) -} diff --git a/vendor/github.com/consensys/gnark-crypto/utils/cpu/adx_amd64.go b/vendor/github.com/consensys/gnark-crypto/utils/cpu/adx_amd64.go new file mode 100644 index 00000000000..4b0bac4dc33 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/utils/cpu/adx_amd64.go @@ -0,0 +1,9 @@ +//go:build !noadx && !purego + +package cpu + +import "golang.org/x/sys/cpu" + +var ( + SupportADX = cpu.X86.HasADX && cpu.X86.HasBMI2 +) diff --git a/vendor/github.com/consensys/gnark-crypto/utils/cpu/adx_purego.go b/vendor/github.com/consensys/gnark-crypto/utils/cpu/adx_purego.go new file mode 100644 index 00000000000..d4a0705277a --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/utils/cpu/adx_purego.go @@ -0,0 +1,5 @@ +//go:build noadx || purego || !amd64 + +package cpu + +const SupportADX = false diff --git a/vendor/github.com/consensys/gnark-crypto/utils/cpu/avx_amd64.go b/vendor/github.com/consensys/gnark-crypto/utils/cpu/avx_amd64.go new file mode 100644 index 00000000000..cf83517063c --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/utils/cpu/avx_amd64.go @@ -0,0 +1,9 @@ +//go:build !noavx && !purego + +package cpu + +import "golang.org/x/sys/cpu" + +var ( + SupportAVX512 = SupportADX && cpu.X86.HasAVX512 && cpu.X86.HasAVX512DQ && cpu.X86.HasAVX512VBMI2 +) diff --git a/vendor/github.com/consensys/gnark-crypto/utils/cpu/avx_purego.go b/vendor/github.com/consensys/gnark-crypto/utils/cpu/avx_purego.go new file mode 100644 index 00000000000..f2fe4de1e60 --- /dev/null +++ b/vendor/github.com/consensys/gnark-crypto/utils/cpu/avx_purego.go @@ -0,0 +1,5 @@ +//go:build noavx || purego || !amd64 + +package cpu + +const SupportAVX512 = false diff --git a/vendor/github.com/inconshreveable/mousetrap/LICENSE b/vendor/github.com/inconshreveable/mousetrap/LICENSE index 5f0d1fb6a7b..5f920e9732b 100644 --- a/vendor/github.com/inconshreveable/mousetrap/LICENSE +++ b/vendor/github.com/inconshreveable/mousetrap/LICENSE @@ -1,13 +1,201 @@ -Copyright 2014 Alan Shreve + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - http://www.apache.org/licenses/LICENSE-2.0 + 1. Definitions. -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2022 Alan Shreve (@inconshreveable) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/inconshreveable/mousetrap/trap_others.go b/vendor/github.com/inconshreveable/mousetrap/trap_others.go index 9d2d8a4bab9..06a91f0868b 100644 --- a/vendor/github.com/inconshreveable/mousetrap/trap_others.go +++ b/vendor/github.com/inconshreveable/mousetrap/trap_others.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows package mousetrap diff --git a/vendor/github.com/inconshreveable/mousetrap/trap_windows.go b/vendor/github.com/inconshreveable/mousetrap/trap_windows.go index 336142a5e3e..0c568802164 100644 --- a/vendor/github.com/inconshreveable/mousetrap/trap_windows.go +++ b/vendor/github.com/inconshreveable/mousetrap/trap_windows.go @@ -1,81 +1,32 @@ -// +build windows -// +build !go1.4 - package mousetrap import ( - "fmt" - "os" "syscall" "unsafe" ) -const ( - // defined by the Win32 API - th32cs_snapprocess uintptr = 0x2 -) - -var ( - kernel = syscall.MustLoadDLL("kernel32.dll") - CreateToolhelp32Snapshot = kernel.MustFindProc("CreateToolhelp32Snapshot") - Process32First = kernel.MustFindProc("Process32FirstW") - Process32Next = kernel.MustFindProc("Process32NextW") -) - -// ProcessEntry32 structure defined by the Win32 API -type processEntry32 struct { - dwSize uint32 - cntUsage uint32 - th32ProcessID uint32 - th32DefaultHeapID int - th32ModuleID uint32 - cntThreads uint32 - th32ParentProcessID uint32 - pcPriClassBase int32 - dwFlags uint32 - szExeFile [syscall.MAX_PATH]uint16 -} - -func getProcessEntry(pid int) (pe *processEntry32, err error) { - snapshot, _, e1 := CreateToolhelp32Snapshot.Call(th32cs_snapprocess, uintptr(0)) - if snapshot == uintptr(syscall.InvalidHandle) { - err = fmt.Errorf("CreateToolhelp32Snapshot: %v", e1) - return +func getProcessEntry(pid int) (*syscall.ProcessEntry32, error) { + snapshot, err := syscall.CreateToolhelp32Snapshot(syscall.TH32CS_SNAPPROCESS, 0) + if err != nil { + return nil, err } - defer syscall.CloseHandle(syscall.Handle(snapshot)) - - var processEntry processEntry32 - processEntry.dwSize = uint32(unsafe.Sizeof(processEntry)) - ok, _, e1 := Process32First.Call(snapshot, uintptr(unsafe.Pointer(&processEntry))) - if ok == 0 { - err = fmt.Errorf("Process32First: %v", e1) - return + defer syscall.CloseHandle(snapshot) + var procEntry syscall.ProcessEntry32 + procEntry.Size = uint32(unsafe.Sizeof(procEntry)) + if err = syscall.Process32First(snapshot, &procEntry); err != nil { + return nil, err } - for { - if processEntry.th32ProcessID == uint32(pid) { - pe = &processEntry - return + if procEntry.ProcessID == uint32(pid) { + return &procEntry, nil } - - ok, _, e1 = Process32Next.Call(snapshot, uintptr(unsafe.Pointer(&processEntry))) - if ok == 0 { - err = fmt.Errorf("Process32Next: %v", e1) - return + err = syscall.Process32Next(snapshot, &procEntry) + if err != nil { + return nil, err } } } -func getppid() (pid int, err error) { - pe, err := getProcessEntry(os.Getpid()) - if err != nil { - return - } - - pid = int(pe.th32ParentProcessID) - return -} - // StartedByExplorer returns true if the program was invoked by the user double-clicking // on the executable from explorer.exe // @@ -83,16 +34,9 @@ func getppid() (pid int, err error) { // It does not guarantee that the program was run from a terminal. It only can tell you // whether it was launched from explorer.exe func StartedByExplorer() bool { - ppid, err := getppid() + pe, err := getProcessEntry(syscall.Getppid()) if err != nil { return false } - - pe, err := getProcessEntry(ppid) - if err != nil { - return false - } - - name := syscall.UTF16ToString(pe.szExeFile[:]) - return name == "explorer.exe" + return "explorer.exe" == syscall.UTF16ToString(pe.ExeFile[:]) } diff --git a/vendor/github.com/inconshreveable/mousetrap/trap_windows_1.4.go b/vendor/github.com/inconshreveable/mousetrap/trap_windows_1.4.go deleted file mode 100644 index 9a28e57c3c3..00000000000 --- a/vendor/github.com/inconshreveable/mousetrap/trap_windows_1.4.go +++ /dev/null @@ -1,46 +0,0 @@ -// +build windows -// +build go1.4 - -package mousetrap - -import ( - "os" - "syscall" - "unsafe" -) - -func getProcessEntry(pid int) (*syscall.ProcessEntry32, error) { - snapshot, err := syscall.CreateToolhelp32Snapshot(syscall.TH32CS_SNAPPROCESS, 0) - if err != nil { - return nil, err - } - defer syscall.CloseHandle(snapshot) - var procEntry syscall.ProcessEntry32 - procEntry.Size = uint32(unsafe.Sizeof(procEntry)) - if err = syscall.Process32First(snapshot, &procEntry); err != nil { - return nil, err - } - for { - if procEntry.ProcessID == uint32(pid) { - return &procEntry, nil - } - err = syscall.Process32Next(snapshot, &procEntry) - if err != nil { - return nil, err - } - } -} - -// StartedByExplorer returns true if the program was invoked by the user double-clicking -// on the executable from explorer.exe -// -// It is conservative and returns false if any of the internal calls fail. -// It does not guarantee that the program was run from a terminal. It only can tell you -// whether it was launched from explorer.exe -func StartedByExplorer() bool { - pe, err := getProcessEntry(os.Getppid()) - if err != nil { - return false - } - return "explorer.exe" == syscall.UTF16ToString(pe.ExeFile[:]) -} diff --git a/vendor/github.com/mmcloughlin/addchain/.gitignore b/vendor/github.com/mmcloughlin/addchain/.gitignore deleted file mode 100644 index 849ddff3b7e..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/.gitignore +++ /dev/null @@ -1 +0,0 @@ -dist/ diff --git a/vendor/github.com/mmcloughlin/addchain/.golangci.yml b/vendor/github.com/mmcloughlin/addchain/.golangci.yml deleted file mode 100644 index 1a654ae7438..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/.golangci.yml +++ /dev/null @@ -1,39 +0,0 @@ -linters: - enable-all: true - disable: - - cyclop - - exhaustivestruct - - forbidigo - - funlen - - gochecknoglobals - - gocognit - - goerr113 - - gomnd - - ifshort - - interfacer - - lll - - maligned - - nlreturn - - paralleltest - - prealloc - - predeclared - - revive - - testpackage - - thelper - - wastedassign - - wrapcheck - - wsl - -linters-settings: - gci: - local-prefixes: github.com/mmcloughlin/addchain - -issues: - exclude-use-default: false - exclude: - # gosec: G304: Potential file inclusion via variable. - - G304 - # gosec: G306: Expect WriteFile permissions to be 0600 or less - - G306 - # gosec: G404: Use of weak random number generator - - G404 diff --git a/vendor/github.com/mmcloughlin/addchain/.goreleaser.yml b/vendor/github.com/mmcloughlin/addchain/.goreleaser.yml deleted file mode 100644 index 4c1df74be2f..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/.goreleaser.yml +++ /dev/null @@ -1,28 +0,0 @@ -before: - hooks: - - go mod tidy -builds: - - main: ./cmd/addchain - env: - - CGO_ENABLED=0 - goos: - - linux - - windows - - darwin - goarch: - - amd64 - - arm64 - ldflags: - - -s -w - - -X github.com/mmcloughlin/addchain/meta.buildversion={{ .Version }} -archives: - - format_overrides: - - goos: windows - format: zip - files: - - LICENSE* - - CITATION* - - README* -release: - draft: true - prerelease: auto diff --git a/vendor/github.com/mmcloughlin/addchain/.zenodo.json b/vendor/github.com/mmcloughlin/addchain/.zenodo.json deleted file mode 100644 index 4501f173c4a..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/.zenodo.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "title": "mmcloughlin/addchain: v0.4.0", - "description": "Cryptographic Addition Chain Generation in Go", - "version": "0.4.0", - "publication_date": "2021-10-30", - "upload_type": "software", - "access_right": "open", - "license": "BSD-3-Clause", - "creators": [ - { - "name": "McLoughlin, Michael Ben", - "orcid": "0000-0003-2347-6258" - } - ], - "related_identifiers": [ - { - "identifier": "https://github.com/mmcloughlin/addchain/tree/v0.4.0", - "relation": "isSupplementTo", - "scheme": "url" - } - ], - "references": [ - "Adamu Muhammad Noma, Abdullah Muhammed, Mohamad Afendee Mohamed and Zuriati Ahmad Zulkarnain. A Review on Heuristics for Addition Chain Problem: Towards Efficient Public Key Cryptosystems. Journal of Computer Science. 2017. https://thescipub.com/pdf/10.3844/jcssp.2017.275.289.pdf", - "Diego F. Aranha, Paulo S. L. M. Barreto, Geovandro C. C. F. Pereira and Jefferson E. Ricardini. A note on high-security general-purpose elliptic curves. Cryptology ePrint Archive, Report 2013/647. 2013. https://eprint.iacr.org/2013/647", - "Bos, Jurjen and Coster, Matthijs. Addition Chain Heuristics. In Advances in Cryptology --- CRYPTO' 89 Proceedings, pages 400--407. 1990. https://link.springer.com/content/pdf/10.1007/0-387-34805-0_37.pdf", - "Martin Otto. Brauer addition-subtraction chains. PhD thesis, Universitat Paderborn. 2001. http://www.martin-otto.de/publications/docs/2001_MartinOtto_Diplom_BrauerAddition-SubtractionChains.pdf", - "F Bergeron, J Berstel, S Brlek and C Duboc. Addition chains using continued fractions. Journal of Algorithms. 1989. http://www-igm.univ-mlv.fr/~berstel/Articles/1989AdditionChainDuboc.pdf", - "Richard E. Crandall. Method and apparatus for public key exchange in a cryptographic system. US Patent 5,159,632. 1992. https://patents.google.com/patent/US5159632A", - "Bernstein, Daniel J. Curve25519: New Diffie-Hellman Speed Records. In Public Key Cryptography - PKC 2006, pages 207--228. 2006. https://cr.yp.to/ecdh/curve25519-20060209.pdf", - "Brian Smith. The Most Efficient Known Addition Chains for Field Element and Scalar Inversion for the Most Popular and Most Unpopular Elliptic Curves. 2017. https://briansmith.org/ecc-inversion-addition-chains-01 (accessed June 30, 2019)", - "Bergeron, F., Berstel, J. and Brlek, S. Efficient computation of addition chains. Journal de theorie des nombres de Bordeaux. 1994. http://www.numdam.org/item/JTNB_1994__6_1_21_0", - "Daniel J. Bernstein, Mike Hamburg, Anna Krasnova and Tanja Lange. Elligator: Elliptic-curve points indistinguishable from uniform random strings. Cryptology ePrint Archive, Report 2013/325. 2013. https://eprint.iacr.org/2013/325", - "NIST. Digital Signature Standard (DSS). Federal Information Processing Standards Publication 186-2. 2000. https://csrc.nist.gov/csrc/media/publications/fips/186/2/archive/2000-01-27/documents/fips186-2.pdf", - "Amadou Tall and Ali Yassin Sanghare. Efficient computation of addition-subtraction chains using generalized continued Fractions. Cryptology ePrint Archive, Report 2013/466. 2013. https://eprint.iacr.org/2013/466", - "Kunihiro, Noboru and Yamamoto, Hirosuke. New Methods for Generating Short Addition Chains. IEICE Transactions on Fundamentals of Electronics Communications and Computer Sciences. 2000. https://pdfs.semanticscholar.org/b398/d10faca35af9ce5a6026458b251fd0a5640c.pdf", - "Riad S. Wahby. kwantam/addchain. Github Repository. Apache License, Version 2.0. 2018. https://github.com/kwantam/addchain", - "Mike Hamburg. Ed448-Goldilocks, a new elliptic curve. Cryptology ePrint Archive, Report 2015/625. 2015. https://eprint.iacr.org/2015/625", - "Riad S. Wahby and Dan Boneh. Fast and simple constant-time hashing to the BLS12-381 elliptic curve. Cryptology ePrint Archive, Report 2019/403. 2019. https://eprint.iacr.org/2019/403", - "Christophe Doche. Exponentiation. Handbook of Elliptic and Hyperelliptic Curve Cryptography, chapter 9. 2006. http://koclab.cs.ucsb.edu/teaching/ecc/eccPapers/Doche-ch09.pdf", - "Knuth, Donald E. Evaluation of Powers. The Art of Computer Programming, Volume 2 (Third Edition): Seminumerical Algorithms, chapter 4.6.3. 1997. https://www-cs-faculty.stanford.edu/~knuth/taocp.html", - "Ayan Nandy. Modifications of Bos and Coster’s Heuristics in search of a shorter addition chain for faster exponentiation. Masters thesis, Indian Statistical Institute Kolkata. 2011. http://library.isical.ac.in:8080/jspui/bitstream/10263/6441/1/DISS-285.pdf", - "F. L. Ţiplea, S. Iftene, C. Hriţcu, I. Goriac, R. Gordân and E. Erbiceanu. MpNT: A Multi-Precision Number Theory Package, Number Theoretical Algorithms (I). Technical Report TR03-02, Faculty of Computer Science, \"Alexandru Ioan Cuza\" University, Iasi. 2003. https://profs.info.uaic.ro/~tr/tr03-02.pdf", - "Daniel J. Bernstein and Tanja Lange. Security dangers of the NIST curves. 2013. https://cr.yp.to/talks/2013.09.16/slides-djb-20130916-a4.pdf", - "Michael Scott, Naomi Benger, Manuel Charlemagne, Luis J. Dominguez Perez and Ezekiel J. Kachisa. On the final exponentiation for calculating pairings on ordinary elliptic curves. Cryptology ePrint Archive, Report 2008/490. 2008. https://eprint.iacr.org/2008/490", - "Daniel J. Bernstein and Tanja Lange. SafeCurves: choosing safe curves for elliptic-curve cryptography. https://safecurves.cr.yp.to", - "Certicom Research. SEC 2: Recommended Elliptic Curve Domain Parameters, Version 2.0. Standards for Efficient Cryptography 2. 2010. https://safecurves.cr.yp.to/www.secg.org/sec2-v2.pdf", - "Jerome A. Solinas. Generalized Mersenne Primes. Technical Report CORR 99-39, Centre for Applied Cryptographic Research (CACR) at the University of Waterloo. 1999. http://cacr.uwaterloo.ca/techreports/1999/corr99-39.pdf", - "Stam, Martijn. Speeding up subgroup cryptosystems. PhD thesis, Technische Universiteit Eindhoven. 2003. https://cr.yp.to/bib/2003/stam-thesis.pdf" - ] -} diff --git a/vendor/github.com/mmcloughlin/addchain/CITATION.bib b/vendor/github.com/mmcloughlin/addchain/CITATION.bib deleted file mode 100644 index 4bddef61f5d..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/CITATION.bib +++ /dev/null @@ -1,11 +0,0 @@ -@misc{addchain, - title = {addchain: Cryptographic Addition Chain Generation in Go}, - author = {Michael B. McLoughlin}, - year = 2021, - month = oct, - howpublished = {Repository \url{https://github.com/mmcloughlin/addchain}}, - version = {0.4.0}, - license = {BSD 3-Clause License}, - doi = {10.5281/zenodo.5622943}, - url = {https://doi.org/10.5281/zenodo.5622943}, -} diff --git a/vendor/github.com/mmcloughlin/addchain/CITATION.cff b/vendor/github.com/mmcloughlin/addchain/CITATION.cff deleted file mode 100644 index 252327d5ee3..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/CITATION.cff +++ /dev/null @@ -1,19 +0,0 @@ -cff-version: 1.2.0 -message: "If you use addchain in your work, a citation would be appreciated using the following metadata." -title: "addchain: Cryptographic Addition Chain Generation in Go" -authors: - - family-names: "McLoughlin" - given-names: "Michael Ben" - orcid: "https://orcid.org/0000-0003-2347-6258" -version: "0.4.0" -date-released: "2021-10-30" -license: BSD-3-Clause -repository-code: https://github.com/mmcloughlin/addchain -doi: "10.5281/zenodo.5622943" -identifiers: - - type: doi - value: "10.5281/zenodo.4625263" - description: "The concept DOI of the work." - - type: doi - value: "10.5281/zenodo.5622943" - description: "The versioned DOI for version 0.4.0 of the work." diff --git a/vendor/github.com/mmcloughlin/addchain/LICENSE b/vendor/github.com/mmcloughlin/addchain/LICENSE deleted file mode 100644 index bc3d0d51028..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/LICENSE +++ /dev/null @@ -1,29 +0,0 @@ -BSD 3-Clause License - -Copyright (c) 2019, Michael McLoughlin -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/mmcloughlin/addchain/README.md b/vendor/github.com/mmcloughlin/addchain/README.md deleted file mode 100644 index 6a1664df09f..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/README.md +++ /dev/null @@ -1,402 +0,0 @@ -

- addchain -
- Build Status - go.dev - Go Report Card - DOI: 10.5281/zenodo.5622943 -

- -

Cryptographic Addition Chain Generation in Go

- -`addchain` generates short addition chains for exponents of cryptographic -interest with [results](#results) rivaling the best hand-optimized chains. -Intended as a building block in elliptic curve or other cryptographic code -generators. - -* Suite of algorithms from academic research: continued fractions, - dictionary-based and Bos-Coster heuristics -* Custom run-length techniques exploit structure of cryptographic exponents - with excellent results on Solinas primes -* Generic optimization methods eliminate redundant operations -* Simple domain-specific language for addition chain computations -* Command-line interface or library -* Code generation and templated output support - -## Table of Contents - -* [Background](#background) -* [Results](#results) -* [Usage](#usage) - * [Command-line Interface](#command-line-interface) - * [Library](#library) -* [Algorithms](#algorithms) - * [Binary](#binary) - * [Continued Fractions](#continued-fractions) - * [Bos-Coster Heuristics](#bos-coster-heuristics) - * [Dictionary](#dictionary) - * [Runs](#runs) - * [Optimization](#optimization) -* [Citing](#citing) -* [Thanks](#thanks) -* [Contributing](#contributing) -* [License](#license) - - -## Background - -An [_addition chain_](https://en.wikipedia.org/wiki/Addition_chain) for a -target integer _n_ is a sequence of numbers starting at 1 and ending at _n_ -such that every term is a sum of two numbers appearing earlier in the -sequence. For example, an addition chain for 29 is - -``` -1, 2, 4, 8, 9, 17, 25, 29 -``` - -Addition chains arise in the optimization of exponentiation algorithms with -fixed exponents. For example, the addition chain above corresponds to the -following sequence of multiplications to compute x29 - -
- x2 = x1 * x1
- x4 = x2 * x2
- x8 = x4 * x4
- x9 = x1 * x8
-x17 = x8 * x9
-x25 = x8 * x17
-x29 = x4 * x25
-
- -An exponentiation algorithm for a fixed exponent _n_ reduces to finding a -_minimal length addition chain_ for _n_. This is especially relevent in -cryptography where exponentiation by huge fixed exponents forms a -performance-critical component of finite-field arithmetic. In particular, -constant-time inversion modulo a prime _p_ is performed by computing -xp-2 (mod p), thanks to [Fermat's Little -Theorem](https://en.wikipedia.org/wiki/Fermat%27_little_theorem). Square root -also reduces to exponentiation for some prime moduli. Finding short addition -chains for these exponents is one important part of high-performance finite -field implementations required for elliptic curve cryptography or RSA. - -Minimal addition chain search is famously hard. No practical optimal -algorithm is known, especially for cryptographic exponents of size 256-bits -and up. Given its importance for the performance of cryptographic -implementations, implementers devote significant effort to hand-tune addition -chains. The goal of the `addchain` project is to match or exceed the best -hand-optimized addition chains using entirely automated approaches, building -on extensive academic research and applying new tweaks that exploit the -unique nature of cryptographic exponents. - -## Results - -The following table shows the results of the `addchain` library on popular -cryptographic exponents. For each one we also show the length of the [best -known hand-optimized addition chain](https://briansmith.org/ecc-inversion-addition-chains-01), and the -delta from the library result. - -| Name | This Library | Best Known | Delta | -| ---- | -----------: | ---------: | ----: | -| [Curve25519 Field Inversion](doc/results.md#curve25519-field-inversion) | 266 | 265 | +1 | -| [NIST P-256 Field Inversion](doc/results.md#nist-p-256-field-inversion) | 266 | 266 | **+0** | -| [NIST P-384 Field Inversion](doc/results.md#nist-p-384-field-inversion) | 397 | 396 | +1 | -| [secp256k1 (Bitcoin) Field Inversion](doc/results.md#secp256k1-bitcoin-field-inversion) | 269 | 269 | **+0** | -| [Curve25519 Scalar Inversion](doc/results.md#curve25519-scalar-inversion) | 283 | 284 | **-1** | -| [NIST P-256 Scalar Inversion](doc/results.md#nist-p-256-scalar-inversion) | 294 | 292 | +2 | -| [NIST P-384 Scalar Inversion](doc/results.md#nist-p-384-scalar-inversion) | 434 | 433 | +1 | -| [secp256k1 (Bitcoin) Scalar Inversion](doc/results.md#secp256k1-bitcoin-scalar-inversion) | 293 | 290 | +3 | - - -See [full results listing](doc/results.md) for more detail and -results for less common exponents. - -These results demonstrate that `addchain` is competitive with hand-optimized -chains, often with equivalent or better performance. Even when `addchain` is -slightly sub-optimal, it can still be considered valuable since it fully -automates a laborious manual process. As such, `addchain` can be trusted to -produce high quality results in an automated code generation tool. - -## Usage - -### Command-line Interface - -Install a pre-compiled [release -binary](https://github.com/mmcloughlin/addchain/releases): - -``` -curl -sSfL https://git.io/addchain | sh -s -- -b /usr/local/bin -``` - -Alternatively build from source: - -``` -go install github.com/mmcloughlin/addchain/cmd/addchain@latest -``` - -Search for a curve25519 field inversion addition chain with: - -```sh -addchain search '2^255 - 19 - 2' -``` - -Output: - -``` -addchain: expr: "2^255 - 19 - 2" -addchain: hex: 7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeb -addchain: dec: 57896044618658097711785492504343953926634992332820282019728792003956564819947 -addchain: best: opt(runs(continued_fractions(dichotomic))) -addchain: cost: 266 -_10 = 2*1 -_11 = 1 + _10 -_1100 = _11 << 2 -_1111 = _11 + _1100 -_11110000 = _1111 << 4 -_11111111 = _1111 + _11110000 -x10 = _11111111 << 2 + _11 -x20 = x10 << 10 + x10 -x30 = x20 << 10 + x10 -x60 = x30 << 30 + x30 -x120 = x60 << 60 + x60 -x240 = x120 << 120 + x120 -x250 = x240 << 10 + x10 -return (x250 << 2 + 1) << 3 + _11 -``` - -Next, you can [generate code from this addition chain](doc/gen.md). - -### Library - -Install: - -``` -go get -u github.com/mmcloughlin/addchain -``` - -Algorithms all conform to the [`alg.ChainAlgorithm`](https://pkg.go.dev/github.com/mmcloughlin/addchain/alg#ChainAlgorithm) or -[`alg.SequenceAlgorithm`](https://pkg.go.dev/github.com/mmcloughlin/addchain/alg#SequenceAlgorithm) interfaces and can be used directly. However the -most user-friendly method uses the [`alg/ensemble`](https://pkg.go.dev/github.com/mmcloughlin/addchain/alg/ensemble) package to -instantiate a sensible default set of algorithms and the [`alg/exec`](https://pkg.go.dev/github.com/mmcloughlin/addchain/alg/exec) -helper to execute them in parallel. The following code uses this method to -find an addition chain for curve25519 field inversion: - -```go -func Example() { - // Target number: 2²⁵⁵ - 21. - n := new(big.Int) - n.SetString("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeb", 16) - - // Default ensemble of algorithms. - algorithms := ensemble.Ensemble() - - // Use parallel executor. - ex := exec.NewParallel() - results := ex.Execute(n, algorithms) - - // Output best result. - best := 0 - for i, r := range results { - if r.Err != nil { - log.Fatal(r.Err) - } - if len(results[i].Program) < len(results[best].Program) { - best = i - } - } - r := results[best] - fmt.Printf("best: %d\n", len(r.Program)) - fmt.Printf("algorithm: %s\n", r.Algorithm) - - // Output: - // best: 266 - // algorithm: opt(runs(continued_fractions(dichotomic))) -} -``` - -## Algorithms - -This section summarizes the algorithms implemented by `addchain` along with -references to primary literature. See the [bibliography](doc/bibliography.md) -for the complete references list. - -### Binary - -The [`alg/binary`](https://pkg.go.dev/github.com/mmcloughlin/addchain/alg/binary) package implements the addition chain equivalent -of the basic [square-and-multiply exponentiation -method](https://en.wikipedia.org/wiki/Exponentiation_by_squaring). It is -included for completeness, but is almost always outperformed by more advanced -algorithms below. - -### Continued Fractions - -The [`alg/contfrac`](https://pkg.go.dev/github.com/mmcloughlin/addchain/alg/contfrac) package implements the continued fractions -methods for addition sequence search introduced by -Bergeron-Berstel-Brlek-Duboc in 1989 and later extended. This approach -utilizes a decomposition of an addition chain akin to continued fractions, -namely - -``` -(1,..., k,..., n) = (1,...,n mod k,..., k) ⊗ (1,..., n/k) ⊕ (n mod k). -``` - -for certain special operators ⊗ and ⊕. This -decomposition lends itself to a recursive algorithm for efficient addition -sequence search, with results dependent on the _strategy_ for choosing the -auxillary integer _k_. The [`alg/contfrac`](https://pkg.go.dev/github.com/mmcloughlin/addchain/alg/contfrac) package provides a -laundry list of strategies from the literature: binary, co-binary, -dichotomic, dyadic, fermat, square-root and total. - -#### References - -* F Bergeron, J Berstel, S Brlek and C Duboc. Addition chains using continued fractions. Journal of Algorithms. 1989. http://www-igm.univ-mlv.fr/~berstel/Articles/1989AdditionChainDuboc.pdf -* Bergeron, F., Berstel, J. and Brlek, S. Efficient computation of addition chains. Journal de theorie des nombres de Bordeaux. 1994. http://www.numdam.org/item/JTNB_1994__6_1_21_0 -* Amadou Tall and Ali Yassin Sanghare. Efficient computation of addition-subtraction chains using generalized continued Fractions. Cryptology ePrint Archive, Report 2013/466. 2013. https://eprint.iacr.org/2013/466 -* Christophe Doche. Exponentiation. Handbook of Elliptic and Hyperelliptic Curve Cryptography, chapter 9. 2006. http://koclab.cs.ucsb.edu/teaching/ecc/eccPapers/Doche-ch09.pdf - -### Bos-Coster Heuristics - -Bos and Coster described an iterative algorithm for efficient addition -sequence generation in which at each step a heuristic proposes new numbers -for the sequence in such a way that the _maximum_ number always decreases. -The [original Bos-Coster paper](https://link.springer.com/content/pdf/10.1007/0-387-34805-0_37.pdf) defined four -heuristics: Approximation, Divison, Halving and Lucas. Package -[`alg/heuristic`](https://pkg.go.dev/github.com/mmcloughlin/addchain/alg/heuristic) implements a variation on these heuristics: - -* **Approximation:** looks for two elements a, b in the current sequence with sum close to the largest element. -* **Halving:** applies when the target is at least twice as big as the next largest, and if so it will propose adding a sequence of doublings. -* **Delta Largest:** proposes adding the delta between the largest two entries in the current sequence. - -Divison and Lucas are not implemented due to disparities in the literature -about their precise definition and poor results from early experiments. -Furthermore, this library does not apply weights to the heuristics as -suggested in the paper, rather it simply uses the first that applies. However -both of these remain [possible avenues for -improvement](https://github.com/mmcloughlin/addchain/issues/26). - -#### References - -* Bos, Jurjen and Coster, Matthijs. Addition Chain Heuristics. In Advances in Cryptology --- CRYPTO' 89 Proceedings, pages 400--407. 1990. https://link.springer.com/content/pdf/10.1007/0-387-34805-0_37.pdf -* Riad S. Wahby. kwantam/addchain. Github Repository. Apache License, Version 2.0. 2018. https://github.com/kwantam/addchain -* Christophe Doche. Exponentiation. Handbook of Elliptic and Hyperelliptic Curve Cryptography, chapter 9. 2006. http://koclab.cs.ucsb.edu/teaching/ecc/eccPapers/Doche-ch09.pdf -* Ayan Nandy. Modifications of Bos and Coster’s Heuristics in search of a shorter addition chain for faster exponentiation. Masters thesis, Indian Statistical Institute Kolkata. 2011. http://library.isical.ac.in:8080/jspui/bitstream/10263/6441/1/DISS-285.pdf -* F. L. Ţiplea, S. Iftene, C. Hriţcu, I. Goriac, R. Gordân and E. Erbiceanu. MpNT: A Multi-Precision Number Theory Package, Number Theoretical Algorithms (I). Technical Report TR03-02, Faculty of Computer Science, "Alexandru Ioan Cuza" University, Iasi. 2003. https://profs.info.uaic.ro/~tr/tr03-02.pdf -* Stam, Martijn. Speeding up subgroup cryptosystems. PhD thesis, Technische Universiteit Eindhoven. 2003. https://cr.yp.to/bib/2003/stam-thesis.pdf - -### Dictionary - -Dictionary methods decompose the binary representation of a target integer _n_ into a set of dictionary _terms_, such that _n_ -may be written as a sum - -
-n = ∑ 2ei di
-
- -for exponents _e_ and elements _d_ from a dictionary _D_. Given such a decomposition we can construct an addition chain for _n_ by - -1. Find a short addition _sequence_ containing every element of the dictionary _D_. Continued fractions and Bos-Coster heuristics can be used here. -2. Build _n_ from the dictionary terms according to the sum decomposition. - -The efficiency of this approach boils down to the decomposition method. The [`alg/dict`](https://pkg.go.dev/github.com/mmcloughlin/addchain/alg/dict) package provides: - -* **Fixed Window:** binary representation of _n_ is broken into fixed _k_-bit windows -* **Sliding Window**: break _n_ into _k_-bit windows, skipping zeros where possible -* **Run Length**: decompose _n_ into runs of 1s up to a maximal length -* **Hybrid**: mix of sliding window and run length methods - -#### References - -* Martin Otto. Brauer addition-subtraction chains. PhD thesis, Universitat Paderborn. 2001. http://www.martin-otto.de/publications/docs/2001_MartinOtto_Diplom_BrauerAddition-SubtractionChains.pdf -* Kunihiro, Noboru and Yamamoto, Hirosuke. New Methods for Generating Short Addition Chains. IEICE Transactions on Fundamentals of Electronics Communications and Computer Sciences. 2000. https://pdfs.semanticscholar.org/b398/d10faca35af9ce5a6026458b251fd0a5640c.pdf -* Christophe Doche. Exponentiation. Handbook of Elliptic and Hyperelliptic Curve Cryptography, chapter 9. 2006. http://koclab.cs.ucsb.edu/teaching/ecc/eccPapers/Doche-ch09.pdf - -### Runs - -The runs algorithm is a custom variant of the dictionary approach that -decomposes a target into runs of ones. It leverages the observation that -building a dictionary consisting of runs of 1s of lengths -l1, l2, ..., lk can itself be -reduced to: - -1. Find an addition sequence containing the run lengths - li. As with dictionary approaches we can use - Bos-Coster heuristics and continued fractions here. However here we have the - advantage that the li are typically very _small_, - meaning that a wider range of algorithms can be brought to bear. -2. Use the addition sequence for the run lengths li - to build an addition sequence for the runs themselves - r(li) where r(e) = 2e-1. See - [`dict.RunsChain`](https://pkg.go.dev/github.com/mmcloughlin/addchain/alg/dict#RunsChain). - -This approach has proved highly effective against cryptographic exponents -which frequently exhibit binary structure, such as those derived from -[Solinas primes](https://en.wikipedia.org/wiki/Solinas_prime). - -> I have not seen this method discussed in the literature. Please help me find references to prior art if you know any. - -### Optimization - -Close inspection of addition chains produced by other algorithms revealed -cases of redundant computation. This motivated a final optimization pass over -addition chains to remove unecessary steps. The [`alg/opt`](https://pkg.go.dev/github.com/mmcloughlin/addchain/alg/opt) package -implements the following optimization: - -1. Determine _all possible_ ways each element can be computed from those prior. -2. Count how many times each element is used where it is the _only possible_ way of computing that entry. -3. Prune elements that are always used in computations that have an alternative. - -These micro-optimizations were vital in closing the gap between `addchain`'s -automated approaches and hand-optimized chains. This technique is reminiscent -of basic passes in optimizing compilers, raising the question of whether -other [compiler optimizations could apply to addition -chains](https://github.com/mmcloughlin/addchain/issues/24)? - -> I have not seen this method discussed in the literature. Please help me find references to prior art if you know any. - -## Citing - -If you use `addchain` in your research a citation would be appreciated. -Citing a specific release is preferred, since they are [archived on -Zenodo](https://doi.org/10.5281/zenodo.4625263) and assigned a DOI. Please use the -following BibTeX to cite the most recent [0.4.0 -release](https://github.com/mmcloughlin/addchain/releases/tag/v0.4.0). - -```bib -@misc{addchain, - title = {addchain: Cryptographic Addition Chain Generation in Go}, - author = {Michael B. McLoughlin}, - year = 2021, - month = oct, - howpublished = {Repository \url{https://github.com/mmcloughlin/addchain}}, - version = {0.4.0}, - license = {BSD 3-Clause License}, - doi = {10.5281/zenodo.5622943}, - url = {https://doi.org/10.5281/zenodo.5622943}, -} -``` - -If you need to cite a currently unreleased version please consider [filing an -issue](https://github.com/mmcloughlin/addchain/issues/new) to request a new -release, or to discuss an appropriate format for the citation. - -## Thanks - -Thank you to [Tom Dean](https://web.stanford.edu/~trdean/), [Riad -Wahby](https://wahby.org/), [Brian Smith](https://briansmith.org/) and -[str4d](https://github.com/str4d) for advice and encouragement. Thanks also to -[Damian Gryski](https://github.com/dgryski) and [Martin -Glancy](https://twitter.com/mglancy) for review. - -## Contributing - -Contributions to `addchain` are welcome: - -* [Submit bug reports](https://github.com/mmcloughlin/addchain/issues/new) to - the issues page. -* Suggest [test cases](https://github.com/mmcloughlin/addchain/blob/e6c070065205efcaa02627ab1b23e8ce6aeea1db/internal/results/results.go#L62) - or update best-known hand-optimized results. -* Pull requests accepted. Please discuss in the [issues section](https://github.com/mmcloughlin/addchain/issues) - before starting significant work. - -## License - -`addchain` is available under the [BSD 3-Clause License](LICENSE). diff --git a/vendor/github.com/mmcloughlin/addchain/acc/acc.go b/vendor/github.com/mmcloughlin/addchain/acc/acc.go deleted file mode 100644 index 6963ff44368..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/acc/acc.go +++ /dev/null @@ -1,91 +0,0 @@ -// Package acc implements the "addition chain calculator" language: a -// domain-specific language (DSL) for addition chain computation. -package acc - -import ( - "bytes" - "io" - "os" - "strings" - - "github.com/mmcloughlin/addchain/acc/ir" - "github.com/mmcloughlin/addchain/acc/parse" - "github.com/mmcloughlin/addchain/acc/pass" - "github.com/mmcloughlin/addchain/acc/printer" - "github.com/mmcloughlin/addchain/internal/errutil" -) - -// LoadFile is a convenience for loading an addition chain script from a file. -func LoadFile(filename string) (p *ir.Program, err error) { - f, err := os.Open(filename) - if err != nil { - return nil, err - } - defer errutil.CheckClose(&err, f) - return LoadReader(filename, f) -} - -// LoadString is a convenience for loading and evaluating an addition chain -// script from a string. -func LoadString(src string) (*ir.Program, error) { - return LoadReader("string", strings.NewReader(src)) -} - -// LoadReader is a convenience for loading and evaluating an addition chain -// script. -func LoadReader(filename string, r io.Reader) (*ir.Program, error) { - // Parse to AST. - s, err := parse.Reader(filename, r) - if err != nil { - return nil, err - } - - // Translate to IR. - p, err := Translate(s) - if err != nil { - return nil, err - } - - // Evaluate the program. - if err := pass.Eval(p); err != nil { - return nil, err - } - - return p, nil -} - -// Write is a convenience for writing a program as an addition chain script. -func Write(w io.Writer, p *ir.Program) error { - // Build AST. - s, err := Build(p) - if err != nil { - return err - } - - // Print. - if err := printer.Fprint(w, s); err != nil { - return err - } - - return nil -} - -// Save is a convenience for writing a program to a file. -func Save(filename string, p *ir.Program) (err error) { - f, err := os.Create(filename) - if err != nil { - return err - } - defer errutil.CheckClose(&err, f) - return Write(f, p) -} - -// String is a convenience for obtaining a program as an addition chain script -// in string form. -func String(p *ir.Program) (string, error) { - var buf bytes.Buffer - if err := Write(&buf, p); err != nil { - return "", err - } - return buf.String(), nil -} diff --git a/vendor/github.com/mmcloughlin/addchain/acc/ast/ast.go b/vendor/github.com/mmcloughlin/addchain/acc/ast/ast.go deleted file mode 100644 index 28948f55845..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/acc/ast/ast.go +++ /dev/null @@ -1,71 +0,0 @@ -// Package ast declares abstract syntax tree types for acc programs. -package ast - -// Chain represents a sequence of acc statements for an addition chain -// computation. -type Chain struct { - Statements []Statement -} - -// Statement assigns the result of an expression to a variable. -type Statement struct { - Name Identifier - Expr Expr -} - -// Operator precedence range. -const ( - LowestPrec = 0 - HighestPrec = 4 -) - -// Expr is an expression. -type Expr interface { - Precedence() int -} - -// Operand is an index into an addition chain. -type Operand int - -// Precedence of this expression type. -func (Operand) Precedence() int { return HighestPrec } - -// Identifier is a variable reference. -type Identifier string - -// Precedence of this expression type. -func (Identifier) Precedence() int { return HighestPrec } - -// Add expression. -type Add struct { - X, Y Expr -} - -// Precedence of this expression type. -func (Add) Precedence() int { return 1 } - -// Shift (repeated doubling) expression. -type Shift struct { - X Expr - S uint -} - -// Precedence of this expression type. -func (Shift) Precedence() int { return 2 } - -// Double expression. -type Double struct { - X Expr -} - -// Precedence of this expression type. -func (Double) Precedence() int { return 3 } - -// IsOp reports whether the expression is the result of an operator. -func IsOp(e Expr) bool { - switch e.(type) { - case Add, Shift, Double: - return true - } - return false -} diff --git a/vendor/github.com/mmcloughlin/addchain/acc/ast/print.go b/vendor/github.com/mmcloughlin/addchain/acc/ast/print.go deleted file mode 100644 index 4c4fcfea306..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/acc/ast/print.go +++ /dev/null @@ -1,101 +0,0 @@ -package ast - -import ( - "io" - "os" - - "github.com/mmcloughlin/addchain/internal/errutil" - "github.com/mmcloughlin/addchain/internal/print" -) - -// Print an AST node to standard out. -func Print(n interface{}) error { - return Fprint(os.Stdout, n) -} - -// Fprint writes the AST node n to w. -func Fprint(w io.Writer, n interface{}) error { - p := newprinter(w) - p.node(n) - return p.Error() -} - -type printer struct { - print.Printer -} - -func newprinter(w io.Writer) *printer { - p := &printer{ - Printer: print.New(w), - } - p.SetIndentString(". ") - return p -} - -func (p *printer) node(n interface{}) { - switch n := n.(type) { - case *Chain: - p.enter("chain") - for _, stmt := range n.Statements { - p.statement(stmt) - } - p.leave() - case Statement: - p.statement(n) - case Operand: - p.Linef("operand(%d)", n) - case Identifier: - p.Linef("identifier(%q)", n) - case Add: - p.add(n) - case Double: - p.double(n) - case Shift: - p.shift(n) - default: - p.SetError(errutil.UnexpectedType(n)) - } -} - -func (p *printer) statement(stmt Statement) { - p.enter("statement") - p.Printf("name = ") - p.node(stmt.Name) - p.Printf("expr = ") - p.node(stmt.Expr) - p.leave() -} - -func (p *printer) add(a Add) { - p.enter("add") - p.Printf("x = ") - p.node(a.X) - p.Printf("y = ") - p.node(a.Y) - p.leave() -} - -func (p *printer) double(d Double) { - p.enter("double") - p.Printf("x = ") - p.node(d.X) - p.leave() -} - -func (p *printer) shift(s Shift) { - p.enter("shift") - p.Linef("s = %d", s.S) - p.Printf("x = ") - p.node(s.X) - p.leave() -} - -func (p *printer) enter(name string) { - p.Linef("%s {", name) - p.Indent() -} - -func (p *printer) leave() { - p.Dedent() - p.Linef("}") -} diff --git a/vendor/github.com/mmcloughlin/addchain/acc/build.go b/vendor/github.com/mmcloughlin/addchain/acc/build.go deleted file mode 100644 index 38adda34994..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/acc/build.go +++ /dev/null @@ -1,158 +0,0 @@ -package acc - -import ( - "fmt" - - "github.com/mmcloughlin/addchain/acc/ast" - "github.com/mmcloughlin/addchain/acc/ir" - "github.com/mmcloughlin/addchain/acc/pass" - "github.com/mmcloughlin/addchain/internal/errutil" -) - -// complexitylimit is the maximum number of operators the builder will allow an -// expression to have. -const complexitylimit = 5 - -// Build AST from a program in intermediate representation. -func Build(p *ir.Program) (*ast.Chain, error) { - // Run some analysis passes first. - err := pass.Exec(p, - pass.Func(pass.ReadCounts), - pass.NameByteValues, - pass.NameXRuns, - ) - if err != nil { - return nil, err - } - - // Delegate to builder. - b := newbuilder(p) - if err := b.process(); err != nil { - return nil, err - } - - return b.chain, nil -} - -type builder struct { - chain *ast.Chain - prog *ir.Program - expr map[int]ast.Expr -} - -func newbuilder(p *ir.Program) *builder { - return &builder{ - chain: &ast.Chain{}, - prog: p, - expr: map[int]ast.Expr{}, - } -} - -func (b *builder) process() error { - insts := b.prog.Instructions - n := len(insts) - complexity := 0 - for i := 0; i < n; i++ { - complexity++ - inst := insts[i] - out := inst.Output - - // Build expression for the result of this instruction. - e, err := b.operator(inst.Op) - if err != nil { - return err - } - - b.expr[out.Index] = e - - // If this output is read only by the following instruction, we don't need to - // commit it to a variable. - anon := out.Identifier == "" - usedonce := b.prog.ReadCount[out.Index] == 1 - usednext := i+1 < n && ir.HasInput(insts[i+1].Op, out.Index) - if anon && usedonce && usednext && complexity < complexitylimit { - continue - } - - // Otherwise write a statement for it. - b.commit(inst.Output) - complexity = 0 - } - - // Clear the name of the final statement. - b.chain.Statements[len(b.chain.Statements)-1].Name = "" - - return nil -} - -func (b *builder) operator(op ir.Op) (ast.Expr, error) { - switch o := op.(type) { - case ir.Add: - return b.add(o) - case ir.Double: - return ast.Double{ - X: b.operand(o.X), - }, nil - case ir.Shift: - return ast.Shift{ - X: b.operand(o.X), - S: o.S, - }, nil - default: - return nil, errutil.UnexpectedType(op) - } -} - -func (b *builder) add(a ir.Add) (ast.Expr, error) { - // Addition operator construction is slightly delcate, since operand order - // determines ordering of execution. By the design of instruction processing - // above, the only way we can have multi-operator expressions is with a - // sequence of operands that are used only once and in the following - // instruction. This implies that only one of x and y can be an operator - // expression. In order to preserve execution order, whichever one that is - // needs to be the first operand. - - x := b.operand(a.X) - y := b.operand(a.Y) - - switch { - case ast.IsOp(x) && ast.IsOp(y): - return nil, errutil.AssertionFailure("only one of x and y should be an operator expression") - case ast.IsOp(y): - x, y = y, x - case ast.IsOp(x): - // Nothing, it's already the first operand. - } - - return ast.Add{ - X: x, - Y: y, - }, nil -} - -func (b *builder) commit(op *ir.Operand) { - name := ast.Identifier(b.name(op)) - stmt := ast.Statement{ - Name: name, - Expr: b.operand(op), - } - b.chain.Statements = append(b.chain.Statements, stmt) - b.expr[op.Index] = name -} - -// name returns the name for this operand. This is the identifier if available, -// otherwise a sensible default based on the index. -func (b *builder) name(op *ir.Operand) string { - if op.Identifier != "" { - return op.Identifier - } - return fmt.Sprintf("i%d", op.Index) -} - -func (b *builder) operand(op *ir.Operand) ast.Expr { - e, ok := b.expr[op.Index] - if !ok { - return ast.Operand(op.Index) - } - return e -} diff --git a/vendor/github.com/mmcloughlin/addchain/acc/decompile.go b/vendor/github.com/mmcloughlin/addchain/acc/decompile.go deleted file mode 100644 index da05ed932de..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/acc/decompile.go +++ /dev/null @@ -1,58 +0,0 @@ -package acc - -import ( - "github.com/mmcloughlin/addchain" - "github.com/mmcloughlin/addchain/acc/ir" -) - -// Decompile an unrolled program into concise intermediate representation. -func Decompile(p addchain.Program) (*ir.Program, error) { - numreads := p.ReadCounts() - r := &ir.Program{} - for i := 0; i < len(p); i++ { - op := p[i] - - // Regular addition. - if !op.IsDouble() { - r.AddInstruction(&ir.Instruction{ - Output: ir.Index(i + 1), - Op: ir.Add{ - X: ir.Index(op.I), - Y: ir.Index(op.J), - }, - }) - continue - } - - // We have a double. Look ahead to see if this is a chain of doublings, which - // can be encoded as a shift. Note we can only follow the the doublings as - // long as the intermediate values are not required anywhere else later in the - // program. - j := i + 1 - for ; j < len(p) && numreads[j] == 1 && p[j].I == j && p[j].J == j; j++ { - } - - s := j - i - - // Shift size 1 encoded as a double. - if s == 1 { - r.AddInstruction(&ir.Instruction{ - Output: ir.Index(i + 1), - Op: ir.Double{ - X: ir.Index(op.I), - }, - }) - continue - } - - i = j - 1 - r.AddInstruction(&ir.Instruction{ - Output: ir.Index(i + 1), - Op: ir.Shift{ - X: ir.Index(op.I), - S: uint(s), - }, - }) - } - return r, nil -} diff --git a/vendor/github.com/mmcloughlin/addchain/acc/ir/ir.go b/vendor/github.com/mmcloughlin/addchain/acc/ir/ir.go deleted file mode 100644 index 5f54fec82b2..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/acc/ir/ir.go +++ /dev/null @@ -1,193 +0,0 @@ -// Package ir declares an intermediate representation for acc programs. -package ir - -import ( - "fmt" - "strings" - - "github.com/mmcloughlin/addchain" -) - -// Program is a sequence of acc instructions. -type Program struct { - Instructions []*Instruction - - // Pass/analysis results. - Operands map[int]*Operand - ReadCount map[int]int - Program addchain.Program - Chain addchain.Chain - Temporaries []string -} - -// AddInstruction appends an instruction to the program. -func (p *Program) AddInstruction(i *Instruction) { - p.Instructions = append(p.Instructions, i) -} - -// Output returns the output of the last instruction. -func (p Program) Output() *Operand { - last := len(p.Instructions) - 1 - return p.Instructions[last].Output -} - -// Clone returns a copy of p. Pass results are not copied and would need to be -// rerun on the clone. -func (p Program) Clone() *Program { - c := &Program{} - for _, inst := range p.Instructions { - c.Instructions = append(c.Instructions, inst.Clone()) - } - return c -} - -func (p Program) String() string { - var b strings.Builder - for _, i := range p.Instructions { - fmt.Fprintln(&b, i) - } - return b.String() -} - -// Operand represents an element of an addition chain, with an optional -// identifier. -type Operand struct { - Identifier string - Index int -} - -// NewOperand builds a named operand for index i. -func NewOperand(name string, i int) *Operand { - return &Operand{ - Identifier: name, - Index: i, - } -} - -// Index builds an unnamed operand for index i. -func Index(i int) *Operand { - return NewOperand("", i) -} - -// One is the first element in the addition chain, which by definition always -// has the value 1. -var One = Index(0) - -// Clone returns a copy of the operand. -func (o Operand) Clone() *Operand { - clone := o - return &clone -} - -func (o Operand) String() string { - if len(o.Identifier) > 0 { - return o.Identifier - } - return fmt.Sprintf("[%d]", o.Index) -} - -// Instruction assigns the result of an operation to an operand. -type Instruction struct { - Output *Operand - Op Op -} - -// Operands returns the input and output operands. -func (i Instruction) Operands() []*Operand { - return append(i.Op.Inputs(), i.Output) -} - -// Clone returns a copy of the instruction. -func (i Instruction) Clone() *Instruction { - return &Instruction{ - Output: i.Output.Clone(), - Op: i.Op.Clone(), - } -} - -func (i Instruction) String() string { - return fmt.Sprintf("%s \u2190 %s", i.Output, i.Op) -} - -// Op is an operation. -type Op interface { - Inputs() []*Operand - Clone() Op - String() string -} - -// Add is an addition operation. -type Add struct { - X, Y *Operand -} - -// Inputs returns the addends. -func (a Add) Inputs() []*Operand { - return []*Operand{a.X, a.Y} -} - -// Clone returns a copy of the operation. -func (a Add) Clone() Op { - return Add{ - X: a.X.Clone(), - Y: a.Y.Clone(), - } -} - -func (a Add) String() string { - return fmt.Sprintf("%s + %s", a.X, a.Y) -} - -// Double is a double operation. -type Double struct { - X *Operand -} - -// Inputs returns the operand. -func (d Double) Inputs() []*Operand { - return []*Operand{d.X} -} - -// Clone returns a copy of the operation. -func (d Double) Clone() Op { - return Double{ - X: d.X.Clone(), - } -} - -func (d Double) String() string { - return fmt.Sprintf("2 * %s", d.X) -} - -// Shift represents a shift-left operation, equivalent to repeat doubling. -type Shift struct { - X *Operand - S uint -} - -// Inputs returns the operand to be shifted. -func (s Shift) Inputs() []*Operand { - return []*Operand{s.X} -} - -// Clone returns a copy of the operation. -func (s Shift) Clone() Op { - return Shift{ - X: s.X.Clone(), - S: s.S, - } -} - -func (s Shift) String() string { - return fmt.Sprintf("%s \u226a %d", s.X, s.S) -} - -// HasInput reports whether the given operation takes idx as an input. -func HasInput(op Op, idx int) bool { - for _, input := range op.Inputs() { - if input.Index == idx { - return true - } - } - return false -} diff --git a/vendor/github.com/mmcloughlin/addchain/acc/parse/acc.peg b/vendor/github.com/mmcloughlin/addchain/acc/parse/acc.peg deleted file mode 100644 index bd80d7e5789..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/acc/parse/acc.peg +++ /dev/null @@ -1,131 +0,0 @@ -{ - -package parser - -func exprs(first, rest interface{}) []ast.Expr { - es := []ast.Expr{first.(ast.Expr)} - if rest == nil { - return es - } - for _, i := range rest.([]interface{}) { - es = append(es, i.([]interface{})[3].(ast.Expr)) - } - return es -} - -} - -// Chain - -Chain <- as:Assignment* r:Return _ EOF { - ch := &ast.Chain{} - for _, a := range as.([]interface{}) { - ch.Statements = append(ch.Statements, a.(ast.Statement)) - } - ch.Statements = append(ch.Statements, r.(ast.Statement)) - return ch, nil -} - -// Statements - -Assignment <- _ n:Identifier _ '=' _ e:Expr _ EOL { - return ast.Statement{ - Name: n.(ast.Identifier), - Expr: e.(ast.Expr), - }, nil -} - -Return <- _ ("return" __)? e:Expr _ EOL? { - return ast.Statement{ - Name: "", - Expr: e.(ast.Expr), - }, nil -} - -// Expressions - -Expr <- e:AddExpr { - return e, nil -} - -AddExpr <- _ x:ShiftExpr rest:(_ AddOperator _ ShiftExpr)* _ { - es := exprs(x, rest) - r := es[0] - for _, e := range es[1:] { - r = ast.Add{ - X: r, - Y: e, - } - } - return r, nil -} - -ShiftExpr <- _ x:BaseExpr _ ShiftOperator _ s:UintLiteral _ { - return ast.Shift{ - X: x.(ast.Expr), - S: s.(uint), - }, nil -} / _ DoubleOperator _ x:BaseExpr { - return ast.Double{ - X: x.(ast.Expr), - }, nil -} / BaseExpr - -BaseExpr <- ParenExpr / Operand - -ParenExpr <- '(' _ e:Expr _ ')' { - return e, nil -} - -// Operators - -AddOperator <- '+' / "add" - -ShiftOperator <- "<<" / "shl" - -DoubleOperator <- '2' _ '*' / "dbl" - -// Operands - -Operand <- op:( One / Index / Identifier ) { - return op, nil -} - -One <- '1' { - return ast.Operand(0), nil -} - -Index <- '[' _ idx:UintLiteral _ ']' { - return ast.Operand(idx.(uint)), nil -} - -// Identifiers - -Identifier <- [a-zA-Z_] [a-zA-Z0-9_]* { - return ast.Identifier(c.text), nil -} - -// Primitives - -UintLiteral <- u64:Uint64Literal { - return uint(u64.(uint64)), nil -} - -Uint64Literal <- (HexUintLiteral / OctalUintLiteral / DecimalUintLiteral) { - return strconv.ParseUint(string(c.text), 0, 64) -} - -DecimalUintLiteral <- [0-9]+ - -HexUintLiteral <- "0x" [0-9a-fA-F]+ - -OctalUintLiteral <- '0' [0-7]+ - -// Character classes - -__ <- Whitespace+ -_ <- Whitespace* - -Whitespace <- [ \t\r] -EOL <- '\n' -EOF <- !. diff --git a/vendor/github.com/mmcloughlin/addchain/acc/parse/internal/parser/zparser.go b/vendor/github.com/mmcloughlin/addchain/acc/parse/internal/parser/zparser.go deleted file mode 100644 index 88ce3a8f618..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/acc/parse/internal/parser/zparser.go +++ /dev/null @@ -1,2203 +0,0 @@ -// Code generated by pigeon; DO NOT EDIT. - -package parser - -import ( - "bytes" - "errors" - "fmt" - "io" - "io/ioutil" - "math" - "os" - "sort" - "strconv" - "strings" - "sync" - "unicode" - "unicode/utf8" - - "github.com/mmcloughlin/addchain/acc/ast" -) - -func exprs(first, rest interface{}) []ast.Expr { - es := []ast.Expr{first.(ast.Expr)} - if rest == nil { - return es - } - for _, i := range rest.([]interface{}) { - es = append(es, i.([]interface{})[3].(ast.Expr)) - } - return es -} - -var g = &grammar{ - rules: []*rule{ - { - name: "Chain", - pos: position{line: 20, col: 1, offset: 290}, - expr: &actionExpr{ - pos: position{line: 20, col: 10, offset: 299}, - run: (*parser).callonChain1, - expr: &seqExpr{ - pos: position{line: 20, col: 10, offset: 299}, - exprs: []interface{}{ - &labeledExpr{ - pos: position{line: 20, col: 10, offset: 299}, - label: "as", - expr: &zeroOrMoreExpr{ - pos: position{line: 20, col: 13, offset: 302}, - expr: &ruleRefExpr{ - pos: position{line: 20, col: 13, offset: 302}, - name: "Assignment", - }, - }, - }, - &labeledExpr{ - pos: position{line: 20, col: 25, offset: 314}, - label: "r", - expr: &ruleRefExpr{ - pos: position{line: 20, col: 27, offset: 316}, - name: "Return", - }, - }, - &ruleRefExpr{ - pos: position{line: 20, col: 34, offset: 323}, - name: "_", - }, - &ruleRefExpr{ - pos: position{line: 20, col: 36, offset: 325}, - name: "EOF", - }, - }, - }, - }, - }, - { - name: "Assignment", - pos: position{line: 31, col: 1, offset: 566}, - expr: &actionExpr{ - pos: position{line: 31, col: 15, offset: 580}, - run: (*parser).callonAssignment1, - expr: &seqExpr{ - pos: position{line: 31, col: 15, offset: 580}, - exprs: []interface{}{ - &ruleRefExpr{ - pos: position{line: 31, col: 15, offset: 580}, - name: "_", - }, - &labeledExpr{ - pos: position{line: 31, col: 17, offset: 582}, - label: "n", - expr: &ruleRefExpr{ - pos: position{line: 31, col: 19, offset: 584}, - name: "Identifier", - }, - }, - &ruleRefExpr{ - pos: position{line: 31, col: 30, offset: 595}, - name: "_", - }, - &litMatcher{ - pos: position{line: 31, col: 32, offset: 597}, - val: "=", - ignoreCase: false, - want: "\"=\"", - }, - &ruleRefExpr{ - pos: position{line: 31, col: 36, offset: 601}, - name: "_", - }, - &labeledExpr{ - pos: position{line: 31, col: 38, offset: 603}, - label: "e", - expr: &ruleRefExpr{ - pos: position{line: 31, col: 40, offset: 605}, - name: "Expr", - }, - }, - &ruleRefExpr{ - pos: position{line: 31, col: 45, offset: 610}, - name: "_", - }, - &ruleRefExpr{ - pos: position{line: 31, col: 47, offset: 612}, - name: "EOL", - }, - }, - }, - }, - }, - { - name: "Return", - pos: position{line: 38, col: 1, offset: 720}, - expr: &actionExpr{ - pos: position{line: 38, col: 11, offset: 730}, - run: (*parser).callonReturn1, - expr: &seqExpr{ - pos: position{line: 38, col: 11, offset: 730}, - exprs: []interface{}{ - &ruleRefExpr{ - pos: position{line: 38, col: 11, offset: 730}, - name: "_", - }, - &zeroOrOneExpr{ - pos: position{line: 38, col: 13, offset: 732}, - expr: &seqExpr{ - pos: position{line: 38, col: 14, offset: 733}, - exprs: []interface{}{ - &litMatcher{ - pos: position{line: 38, col: 14, offset: 733}, - val: "return", - ignoreCase: false, - want: "\"return\"", - }, - &ruleRefExpr{ - pos: position{line: 38, col: 23, offset: 742}, - name: "__", - }, - }, - }, - }, - &labeledExpr{ - pos: position{line: 38, col: 28, offset: 747}, - label: "e", - expr: &ruleRefExpr{ - pos: position{line: 38, col: 30, offset: 749}, - name: "Expr", - }, - }, - &ruleRefExpr{ - pos: position{line: 38, col: 35, offset: 754}, - name: "_", - }, - &zeroOrOneExpr{ - pos: position{line: 38, col: 37, offset: 756}, - expr: &ruleRefExpr{ - pos: position{line: 38, col: 37, offset: 756}, - name: "EOL", - }, - }, - }, - }, - }, - }, - { - name: "Expr", - pos: position{line: 47, col: 1, offset: 865}, - expr: &actionExpr{ - pos: position{line: 47, col: 9, offset: 873}, - run: (*parser).callonExpr1, - expr: &labeledExpr{ - pos: position{line: 47, col: 9, offset: 873}, - label: "e", - expr: &ruleRefExpr{ - pos: position{line: 47, col: 11, offset: 875}, - name: "AddExpr", - }, - }, - }, - }, - { - name: "AddExpr", - pos: position{line: 51, col: 1, offset: 906}, - expr: &actionExpr{ - pos: position{line: 51, col: 12, offset: 917}, - run: (*parser).callonAddExpr1, - expr: &seqExpr{ - pos: position{line: 51, col: 12, offset: 917}, - exprs: []interface{}{ - &ruleRefExpr{ - pos: position{line: 51, col: 12, offset: 917}, - name: "_", - }, - &labeledExpr{ - pos: position{line: 51, col: 14, offset: 919}, - label: "x", - expr: &ruleRefExpr{ - pos: position{line: 51, col: 16, offset: 921}, - name: "ShiftExpr", - }, - }, - &labeledExpr{ - pos: position{line: 51, col: 26, offset: 931}, - label: "rest", - expr: &zeroOrMoreExpr{ - pos: position{line: 51, col: 31, offset: 936}, - expr: &seqExpr{ - pos: position{line: 51, col: 32, offset: 937}, - exprs: []interface{}{ - &ruleRefExpr{ - pos: position{line: 51, col: 32, offset: 937}, - name: "_", - }, - &ruleRefExpr{ - pos: position{line: 51, col: 34, offset: 939}, - name: "AddOperator", - }, - &ruleRefExpr{ - pos: position{line: 51, col: 46, offset: 951}, - name: "_", - }, - &ruleRefExpr{ - pos: position{line: 51, col: 48, offset: 953}, - name: "ShiftExpr", - }, - }, - }, - }, - }, - &ruleRefExpr{ - pos: position{line: 51, col: 60, offset: 965}, - name: "_", - }, - }, - }, - }, - }, - { - name: "ShiftExpr", - pos: position{line: 63, col: 1, offset: 1134}, - expr: &choiceExpr{ - pos: position{line: 63, col: 14, offset: 1147}, - alternatives: []interface{}{ - &actionExpr{ - pos: position{line: 63, col: 14, offset: 1147}, - run: (*parser).callonShiftExpr2, - expr: &seqExpr{ - pos: position{line: 63, col: 14, offset: 1147}, - exprs: []interface{}{ - &ruleRefExpr{ - pos: position{line: 63, col: 14, offset: 1147}, - name: "_", - }, - &labeledExpr{ - pos: position{line: 63, col: 16, offset: 1149}, - label: "x", - expr: &ruleRefExpr{ - pos: position{line: 63, col: 18, offset: 1151}, - name: "BaseExpr", - }, - }, - &ruleRefExpr{ - pos: position{line: 63, col: 27, offset: 1160}, - name: "_", - }, - &ruleRefExpr{ - pos: position{line: 63, col: 29, offset: 1162}, - name: "ShiftOperator", - }, - &ruleRefExpr{ - pos: position{line: 63, col: 43, offset: 1176}, - name: "_", - }, - &labeledExpr{ - pos: position{line: 63, col: 45, offset: 1178}, - label: "s", - expr: &ruleRefExpr{ - pos: position{line: 63, col: 47, offset: 1180}, - name: "UintLiteral", - }, - }, - &ruleRefExpr{ - pos: position{line: 63, col: 59, offset: 1192}, - name: "_", - }, - }, - }, - }, - &actionExpr{ - pos: position{line: 68, col: 5, offset: 1279}, - run: (*parser).callonShiftExpr13, - expr: &seqExpr{ - pos: position{line: 68, col: 5, offset: 1279}, - exprs: []interface{}{ - &ruleRefExpr{ - pos: position{line: 68, col: 5, offset: 1279}, - name: "_", - }, - &ruleRefExpr{ - pos: position{line: 68, col: 7, offset: 1281}, - name: "DoubleOperator", - }, - &ruleRefExpr{ - pos: position{line: 68, col: 22, offset: 1296}, - name: "_", - }, - &labeledExpr{ - pos: position{line: 68, col: 24, offset: 1298}, - label: "x", - expr: &ruleRefExpr{ - pos: position{line: 68, col: 26, offset: 1300}, - name: "BaseExpr", - }, - }, - }, - }, - }, - &ruleRefExpr{ - pos: position{line: 72, col: 5, offset: 1374}, - name: "BaseExpr", - }, - }, - }, - }, - { - name: "BaseExpr", - pos: position{line: 74, col: 1, offset: 1384}, - expr: &choiceExpr{ - pos: position{line: 74, col: 13, offset: 1396}, - alternatives: []interface{}{ - &ruleRefExpr{ - pos: position{line: 74, col: 13, offset: 1396}, - name: "ParenExpr", - }, - &ruleRefExpr{ - pos: position{line: 74, col: 25, offset: 1408}, - name: "Operand", - }, - }, - }, - }, - { - name: "ParenExpr", - pos: position{line: 76, col: 1, offset: 1417}, - expr: &actionExpr{ - pos: position{line: 76, col: 14, offset: 1430}, - run: (*parser).callonParenExpr1, - expr: &seqExpr{ - pos: position{line: 76, col: 14, offset: 1430}, - exprs: []interface{}{ - &litMatcher{ - pos: position{line: 76, col: 14, offset: 1430}, - val: "(", - ignoreCase: false, - want: "\"(\"", - }, - &ruleRefExpr{ - pos: position{line: 76, col: 18, offset: 1434}, - name: "_", - }, - &labeledExpr{ - pos: position{line: 76, col: 20, offset: 1436}, - label: "e", - expr: &ruleRefExpr{ - pos: position{line: 76, col: 22, offset: 1438}, - name: "Expr", - }, - }, - &ruleRefExpr{ - pos: position{line: 76, col: 27, offset: 1443}, - name: "_", - }, - &litMatcher{ - pos: position{line: 76, col: 29, offset: 1445}, - val: ")", - ignoreCase: false, - want: "\")\"", - }, - }, - }, - }, - }, - { - name: "AddOperator", - pos: position{line: 82, col: 1, offset: 1486}, - expr: &choiceExpr{ - pos: position{line: 82, col: 16, offset: 1501}, - alternatives: []interface{}{ - &litMatcher{ - pos: position{line: 82, col: 16, offset: 1501}, - val: "+", - ignoreCase: false, - want: "\"+\"", - }, - &litMatcher{ - pos: position{line: 82, col: 22, offset: 1507}, - val: "add", - ignoreCase: false, - want: "\"add\"", - }, - }, - }, - }, - { - name: "ShiftOperator", - pos: position{line: 84, col: 1, offset: 1514}, - expr: &choiceExpr{ - pos: position{line: 84, col: 18, offset: 1531}, - alternatives: []interface{}{ - &litMatcher{ - pos: position{line: 84, col: 18, offset: 1531}, - val: "<<", - ignoreCase: false, - want: "\"<<\"", - }, - &litMatcher{ - pos: position{line: 84, col: 25, offset: 1538}, - val: "shl", - ignoreCase: false, - want: "\"shl\"", - }, - }, - }, - }, - { - name: "DoubleOperator", - pos: position{line: 86, col: 1, offset: 1545}, - expr: &choiceExpr{ - pos: position{line: 86, col: 19, offset: 1563}, - alternatives: []interface{}{ - &seqExpr{ - pos: position{line: 86, col: 19, offset: 1563}, - exprs: []interface{}{ - &litMatcher{ - pos: position{line: 86, col: 19, offset: 1563}, - val: "2", - ignoreCase: false, - want: "\"2\"", - }, - &ruleRefExpr{ - pos: position{line: 86, col: 23, offset: 1567}, - name: "_", - }, - &litMatcher{ - pos: position{line: 86, col: 25, offset: 1569}, - val: "*", - ignoreCase: false, - want: "\"*\"", - }, - }, - }, - &litMatcher{ - pos: position{line: 86, col: 31, offset: 1575}, - val: "dbl", - ignoreCase: false, - want: "\"dbl\"", - }, - }, - }, - }, - { - name: "Operand", - pos: position{line: 90, col: 1, offset: 1595}, - expr: &actionExpr{ - pos: position{line: 90, col: 12, offset: 1606}, - run: (*parser).callonOperand1, - expr: &labeledExpr{ - pos: position{line: 90, col: 12, offset: 1606}, - label: "op", - expr: &choiceExpr{ - pos: position{line: 90, col: 17, offset: 1611}, - alternatives: []interface{}{ - &ruleRefExpr{ - pos: position{line: 90, col: 17, offset: 1611}, - name: "One", - }, - &ruleRefExpr{ - pos: position{line: 90, col: 23, offset: 1617}, - name: "Index", - }, - &ruleRefExpr{ - pos: position{line: 90, col: 31, offset: 1625}, - name: "Identifier", - }, - }, - }, - }, - }, - }, - { - name: "One", - pos: position{line: 94, col: 1, offset: 1662}, - expr: &actionExpr{ - pos: position{line: 94, col: 8, offset: 1669}, - run: (*parser).callonOne1, - expr: &litMatcher{ - pos: position{line: 94, col: 8, offset: 1669}, - val: "1", - ignoreCase: false, - want: "\"1\"", - }, - }, - }, - { - name: "Index", - pos: position{line: 98, col: 1, offset: 1709}, - expr: &actionExpr{ - pos: position{line: 98, col: 10, offset: 1718}, - run: (*parser).callonIndex1, - expr: &seqExpr{ - pos: position{line: 98, col: 10, offset: 1718}, - exprs: []interface{}{ - &litMatcher{ - pos: position{line: 98, col: 10, offset: 1718}, - val: "[", - ignoreCase: false, - want: "\"[\"", - }, - &ruleRefExpr{ - pos: position{line: 98, col: 14, offset: 1722}, - name: "_", - }, - &labeledExpr{ - pos: position{line: 98, col: 16, offset: 1724}, - label: "idx", - expr: &ruleRefExpr{ - pos: position{line: 98, col: 20, offset: 1728}, - name: "UintLiteral", - }, - }, - &ruleRefExpr{ - pos: position{line: 98, col: 32, offset: 1740}, - name: "_", - }, - &litMatcher{ - pos: position{line: 98, col: 34, offset: 1742}, - val: "]", - ignoreCase: false, - want: "\"]\"", - }, - }, - }, - }, - }, - { - name: "Identifier", - pos: position{line: 104, col: 1, offset: 1807}, - expr: &actionExpr{ - pos: position{line: 104, col: 15, offset: 1821}, - run: (*parser).callonIdentifier1, - expr: &seqExpr{ - pos: position{line: 104, col: 15, offset: 1821}, - exprs: []interface{}{ - &charClassMatcher{ - pos: position{line: 104, col: 15, offset: 1821}, - val: "[a-zA-Z_]", - chars: []rune{'_'}, - ranges: []rune{'a', 'z', 'A', 'Z'}, - ignoreCase: false, - inverted: false, - }, - &zeroOrMoreExpr{ - pos: position{line: 104, col: 25, offset: 1831}, - expr: &charClassMatcher{ - pos: position{line: 104, col: 25, offset: 1831}, - val: "[a-zA-Z0-9_]", - chars: []rune{'_'}, - ranges: []rune{'a', 'z', 'A', 'Z', '0', '9'}, - ignoreCase: false, - inverted: false, - }, - }, - }, - }, - }, - }, - { - name: "UintLiteral", - pos: position{line: 110, col: 1, offset: 1904}, - expr: &actionExpr{ - pos: position{line: 110, col: 16, offset: 1919}, - run: (*parser).callonUintLiteral1, - expr: &labeledExpr{ - pos: position{line: 110, col: 16, offset: 1919}, - label: "u64", - expr: &ruleRefExpr{ - pos: position{line: 110, col: 20, offset: 1923}, - name: "Uint64Literal", - }, - }, - }, - }, - { - name: "Uint64Literal", - pos: position{line: 114, col: 1, offset: 1977}, - expr: &actionExpr{ - pos: position{line: 114, col: 18, offset: 1994}, - run: (*parser).callonUint64Literal1, - expr: &choiceExpr{ - pos: position{line: 114, col: 19, offset: 1995}, - alternatives: []interface{}{ - &ruleRefExpr{ - pos: position{line: 114, col: 19, offset: 1995}, - name: "HexUintLiteral", - }, - &ruleRefExpr{ - pos: position{line: 114, col: 36, offset: 2012}, - name: "OctalUintLiteral", - }, - &ruleRefExpr{ - pos: position{line: 114, col: 55, offset: 2031}, - name: "DecimalUintLiteral", - }, - }, - }, - }, - }, - { - name: "DecimalUintLiteral", - pos: position{line: 118, col: 1, offset: 2108}, - expr: &oneOrMoreExpr{ - pos: position{line: 118, col: 23, offset: 2130}, - expr: &charClassMatcher{ - pos: position{line: 118, col: 23, offset: 2130}, - val: "[0-9]", - ranges: []rune{'0', '9'}, - ignoreCase: false, - inverted: false, - }, - }, - }, - { - name: "HexUintLiteral", - pos: position{line: 120, col: 1, offset: 2138}, - expr: &seqExpr{ - pos: position{line: 120, col: 19, offset: 2156}, - exprs: []interface{}{ - &litMatcher{ - pos: position{line: 120, col: 19, offset: 2156}, - val: "0x", - ignoreCase: false, - want: "\"0x\"", - }, - &oneOrMoreExpr{ - pos: position{line: 120, col: 24, offset: 2161}, - expr: &charClassMatcher{ - pos: position{line: 120, col: 24, offset: 2161}, - val: "[0-9a-fA-F]", - ranges: []rune{'0', '9', 'a', 'f', 'A', 'F'}, - ignoreCase: false, - inverted: false, - }, - }, - }, - }, - }, - { - name: "OctalUintLiteral", - pos: position{line: 122, col: 1, offset: 2175}, - expr: &seqExpr{ - pos: position{line: 122, col: 21, offset: 2195}, - exprs: []interface{}{ - &litMatcher{ - pos: position{line: 122, col: 21, offset: 2195}, - val: "0", - ignoreCase: false, - want: "\"0\"", - }, - &oneOrMoreExpr{ - pos: position{line: 122, col: 25, offset: 2199}, - expr: &charClassMatcher{ - pos: position{line: 122, col: 25, offset: 2199}, - val: "[0-7]", - ranges: []rune{'0', '7'}, - ignoreCase: false, - inverted: false, - }, - }, - }, - }, - }, - { - name: "__", - pos: position{line: 126, col: 1, offset: 2229}, - expr: &oneOrMoreExpr{ - pos: position{line: 126, col: 7, offset: 2235}, - expr: &ruleRefExpr{ - pos: position{line: 126, col: 7, offset: 2235}, - name: "Whitespace", - }, - }, - }, - { - name: "_", - pos: position{line: 127, col: 1, offset: 2247}, - expr: &zeroOrMoreExpr{ - pos: position{line: 127, col: 6, offset: 2252}, - expr: &ruleRefExpr{ - pos: position{line: 127, col: 6, offset: 2252}, - name: "Whitespace", - }, - }, - }, - { - name: "Whitespace", - pos: position{line: 129, col: 1, offset: 2265}, - expr: &charClassMatcher{ - pos: position{line: 129, col: 15, offset: 2279}, - val: "[ \\t\\r]", - chars: []rune{' ', '\t', '\r'}, - ignoreCase: false, - inverted: false, - }, - }, - { - name: "EOL", - pos: position{line: 130, col: 1, offset: 2287}, - expr: &litMatcher{ - pos: position{line: 130, col: 8, offset: 2294}, - val: "\n", - ignoreCase: false, - want: "\"\\n\"", - }, - }, - { - name: "EOF", - pos: position{line: 131, col: 1, offset: 2299}, - expr: ¬Expr{ - pos: position{line: 131, col: 8, offset: 2306}, - expr: &anyMatcher{ - line: 131, col: 9, offset: 2307, - }, - }, - }, - }, -} - -func (c *current) onChain1(as, r interface{}) (interface{}, error) { - ch := &ast.Chain{} - for _, a := range as.([]interface{}) { - ch.Statements = append(ch.Statements, a.(ast.Statement)) - } - ch.Statements = append(ch.Statements, r.(ast.Statement)) - return ch, nil -} - -func (p *parser) callonChain1() (interface{}, error) { - stack := p.vstack[len(p.vstack)-1] - _ = stack - return p.cur.onChain1(stack["as"], stack["r"]) -} - -func (c *current) onAssignment1(n, e interface{}) (interface{}, error) { - return ast.Statement{ - Name: n.(ast.Identifier), - Expr: e.(ast.Expr), - }, nil -} - -func (p *parser) callonAssignment1() (interface{}, error) { - stack := p.vstack[len(p.vstack)-1] - _ = stack - return p.cur.onAssignment1(stack["n"], stack["e"]) -} - -func (c *current) onReturn1(e interface{}) (interface{}, error) { - return ast.Statement{ - Name: "", - Expr: e.(ast.Expr), - }, nil -} - -func (p *parser) callonReturn1() (interface{}, error) { - stack := p.vstack[len(p.vstack)-1] - _ = stack - return p.cur.onReturn1(stack["e"]) -} - -func (c *current) onExpr1(e interface{}) (interface{}, error) { - return e, nil -} - -func (p *parser) callonExpr1() (interface{}, error) { - stack := p.vstack[len(p.vstack)-1] - _ = stack - return p.cur.onExpr1(stack["e"]) -} - -func (c *current) onAddExpr1(x, rest interface{}) (interface{}, error) { - es := exprs(x, rest) - r := es[0] - for _, e := range es[1:] { - r = ast.Add{ - X: r, - Y: e, - } - } - return r, nil -} - -func (p *parser) callonAddExpr1() (interface{}, error) { - stack := p.vstack[len(p.vstack)-1] - _ = stack - return p.cur.onAddExpr1(stack["x"], stack["rest"]) -} - -func (c *current) onShiftExpr2(x, s interface{}) (interface{}, error) { - return ast.Shift{ - X: x.(ast.Expr), - S: s.(uint), - }, nil -} - -func (p *parser) callonShiftExpr2() (interface{}, error) { - stack := p.vstack[len(p.vstack)-1] - _ = stack - return p.cur.onShiftExpr2(stack["x"], stack["s"]) -} - -func (c *current) onShiftExpr13(x interface{}) (interface{}, error) { - return ast.Double{ - X: x.(ast.Expr), - }, nil -} - -func (p *parser) callonShiftExpr13() (interface{}, error) { - stack := p.vstack[len(p.vstack)-1] - _ = stack - return p.cur.onShiftExpr13(stack["x"]) -} - -func (c *current) onParenExpr1(e interface{}) (interface{}, error) { - return e, nil -} - -func (p *parser) callonParenExpr1() (interface{}, error) { - stack := p.vstack[len(p.vstack)-1] - _ = stack - return p.cur.onParenExpr1(stack["e"]) -} - -func (c *current) onOperand1(op interface{}) (interface{}, error) { - return op, nil -} - -func (p *parser) callonOperand1() (interface{}, error) { - stack := p.vstack[len(p.vstack)-1] - _ = stack - return p.cur.onOperand1(stack["op"]) -} - -func (c *current) onOne1() (interface{}, error) { - return ast.Operand(0), nil -} - -func (p *parser) callonOne1() (interface{}, error) { - stack := p.vstack[len(p.vstack)-1] - _ = stack - return p.cur.onOne1() -} - -func (c *current) onIndex1(idx interface{}) (interface{}, error) { - return ast.Operand(idx.(uint)), nil -} - -func (p *parser) callonIndex1() (interface{}, error) { - stack := p.vstack[len(p.vstack)-1] - _ = stack - return p.cur.onIndex1(stack["idx"]) -} - -func (c *current) onIdentifier1() (interface{}, error) { - return ast.Identifier(c.text), nil -} - -func (p *parser) callonIdentifier1() (interface{}, error) { - stack := p.vstack[len(p.vstack)-1] - _ = stack - return p.cur.onIdentifier1() -} - -func (c *current) onUintLiteral1(u64 interface{}) (interface{}, error) { - return uint(u64.(uint64)), nil -} - -func (p *parser) callonUintLiteral1() (interface{}, error) { - stack := p.vstack[len(p.vstack)-1] - _ = stack - return p.cur.onUintLiteral1(stack["u64"]) -} - -func (c *current) onUint64Literal1() (interface{}, error) { - return strconv.ParseUint(string(c.text), 0, 64) -} - -func (p *parser) callonUint64Literal1() (interface{}, error) { - stack := p.vstack[len(p.vstack)-1] - _ = stack - return p.cur.onUint64Literal1() -} - -var ( - // errNoRule is returned when the grammar to parse has no rule. - errNoRule = errors.New("grammar has no rule") - - // errInvalidEntrypoint is returned when the specified entrypoint rule - // does not exit. - errInvalidEntrypoint = errors.New("invalid entrypoint") - - // errInvalidEncoding is returned when the source is not properly - // utf8-encoded. - errInvalidEncoding = errors.New("invalid encoding") - - // errMaxExprCnt is used to signal that the maximum number of - // expressions have been parsed. - errMaxExprCnt = errors.New("max number of expresssions parsed") -) - -// Option is a function that can set an option on the parser. It returns -// the previous setting as an Option. -type Option func(*parser) Option - -// MaxExpressions creates an Option to stop parsing after the provided -// number of expressions have been parsed, if the value is 0 then the parser will -// parse for as many steps as needed (possibly an infinite number). -// -// The default for maxExprCnt is 0. -func MaxExpressions(maxExprCnt uint64) Option { - return func(p *parser) Option { - oldMaxExprCnt := p.maxExprCnt - p.maxExprCnt = maxExprCnt - return MaxExpressions(oldMaxExprCnt) - } -} - -// Entrypoint creates an Option to set the rule name to use as entrypoint. -// The rule name must have been specified in the -alternate-entrypoints -// if generating the parser with the -optimize-grammar flag, otherwise -// it may have been optimized out. Passing an empty string sets the -// entrypoint to the first rule in the grammar. -// -// The default is to start parsing at the first rule in the grammar. -func Entrypoint(ruleName string) Option { - return func(p *parser) Option { - oldEntrypoint := p.entrypoint - p.entrypoint = ruleName - if ruleName == "" { - p.entrypoint = g.rules[0].name - } - return Entrypoint(oldEntrypoint) - } -} - -// Statistics adds a user provided Stats struct to the parser to allow -// the user to process the results after the parsing has finished. -// Also the key for the "no match" counter is set. -// -// Example usage: -// -// input := "input" -// stats := Stats{} -// _, err := Parse("input-file", []byte(input), Statistics(&stats, "no match")) -// if err != nil { -// log.Panicln(err) -// } -// b, err := json.MarshalIndent(stats.ChoiceAltCnt, "", " ") -// if err != nil { -// log.Panicln(err) -// } -// fmt.Println(string(b)) -// -func Statistics(stats *Stats, choiceNoMatch string) Option { - return func(p *parser) Option { - oldStats := p.Stats - p.Stats = stats - oldChoiceNoMatch := p.choiceNoMatch - p.choiceNoMatch = choiceNoMatch - if p.Stats.ChoiceAltCnt == nil { - p.Stats.ChoiceAltCnt = make(map[string]map[string]int) - } - return Statistics(oldStats, oldChoiceNoMatch) - } -} - -// Debug creates an Option to set the debug flag to b. When set to true, -// debugging information is printed to stdout while parsing. -// -// The default is false. -func Debug(b bool) Option { - return func(p *parser) Option { - old := p.debug - p.debug = b - return Debug(old) - } -} - -// Memoize creates an Option to set the memoize flag to b. When set to true, -// the parser will cache all results so each expression is evaluated only -// once. This guarantees linear parsing time even for pathological cases, -// at the expense of more memory and slower times for typical cases. -// -// The default is false. -func Memoize(b bool) Option { - return func(p *parser) Option { - old := p.memoize - p.memoize = b - return Memoize(old) - } -} - -// AllowInvalidUTF8 creates an Option to allow invalid UTF-8 bytes. -// Every invalid UTF-8 byte is treated as a utf8.RuneError (U+FFFD) -// by character class matchers and is matched by the any matcher. -// The returned matched value, c.text and c.offset are NOT affected. -// -// The default is false. -func AllowInvalidUTF8(b bool) Option { - return func(p *parser) Option { - old := p.allowInvalidUTF8 - p.allowInvalidUTF8 = b - return AllowInvalidUTF8(old) - } -} - -// Recover creates an Option to set the recover flag to b. When set to -// true, this causes the parser to recover from panics and convert it -// to an error. Setting it to false can be useful while debugging to -// access the full stack trace. -// -// The default is true. -func Recover(b bool) Option { - return func(p *parser) Option { - old := p.recover - p.recover = b - return Recover(old) - } -} - -// GlobalStore creates an Option to set a key to a certain value in -// the globalStore. -func GlobalStore(key string, value interface{}) Option { - return func(p *parser) Option { - old := p.cur.globalStore[key] - p.cur.globalStore[key] = value - return GlobalStore(key, old) - } -} - -// InitState creates an Option to set a key to a certain value in -// the global "state" store. -func InitState(key string, value interface{}) Option { - return func(p *parser) Option { - old := p.cur.state[key] - p.cur.state[key] = value - return InitState(key, old) - } -} - -// ParseFile parses the file identified by filename. -func ParseFile(filename string, opts ...Option) (i interface{}, err error) { - f, err := os.Open(filename) - if err != nil { - return nil, err - } - defer func() { - if closeErr := f.Close(); closeErr != nil { - err = closeErr - } - }() - return ParseReader(filename, f, opts...) -} - -// ParseReader parses the data from r using filename as information in the -// error messages. -func ParseReader(filename string, r io.Reader, opts ...Option) (interface{}, error) { - b, err := ioutil.ReadAll(r) - if err != nil { - return nil, err - } - - return Parse(filename, b, opts...) -} - -// Parse parses the data from b using filename as information in the -// error messages. -func Parse(filename string, b []byte, opts ...Option) (interface{}, error) { - return newParser(filename, b, opts...).parse(g) -} - -// position records a position in the text. -type position struct { - line, col, offset int -} - -func (p position) String() string { - return strconv.Itoa(p.line) + ":" + strconv.Itoa(p.col) + " [" + strconv.Itoa(p.offset) + "]" -} - -// savepoint stores all state required to go back to this point in the -// parser. -type savepoint struct { - position - rn rune - w int -} - -type current struct { - pos position // start position of the match - text []byte // raw text of the match - - // state is a store for arbitrary key,value pairs that the user wants to be - // tied to the backtracking of the parser. - // This is always rolled back if a parsing rule fails. - state storeDict - - // globalStore is a general store for the user to store arbitrary key-value - // pairs that they need to manage and that they do not want tied to the - // backtracking of the parser. This is only modified by the user and never - // rolled back by the parser. It is always up to the user to keep this in a - // consistent state. - globalStore storeDict -} - -type storeDict map[string]interface{} - -// the AST types... - -type grammar struct { - pos position - rules []*rule -} - -type rule struct { - pos position - name string - displayName string - expr interface{} -} - -type choiceExpr struct { - pos position - alternatives []interface{} -} - -type actionExpr struct { - pos position - expr interface{} - run func(*parser) (interface{}, error) -} - -type recoveryExpr struct { - pos position - expr interface{} - recoverExpr interface{} - failureLabel []string -} - -type seqExpr struct { - pos position - exprs []interface{} -} - -type throwExpr struct { - pos position - label string -} - -type labeledExpr struct { - pos position - label string - expr interface{} -} - -type expr struct { - pos position - expr interface{} -} - -type andExpr expr -type notExpr expr -type zeroOrOneExpr expr -type zeroOrMoreExpr expr -type oneOrMoreExpr expr - -type ruleRefExpr struct { - pos position - name string -} - -type stateCodeExpr struct { - pos position - run func(*parser) error -} - -type andCodeExpr struct { - pos position - run func(*parser) (bool, error) -} - -type notCodeExpr struct { - pos position - run func(*parser) (bool, error) -} - -type litMatcher struct { - pos position - val string - ignoreCase bool - want string -} - -type charClassMatcher struct { - pos position - val string - basicLatinChars [128]bool - chars []rune - ranges []rune - classes []*unicode.RangeTable - ignoreCase bool - inverted bool -} - -type anyMatcher position - -// errList cumulates the errors found by the parser. -type errList []error - -func (e *errList) add(err error) { - *e = append(*e, err) -} - -func (e errList) err() error { - if len(e) == 0 { - return nil - } - e.dedupe() - return e -} - -func (e *errList) dedupe() { - var cleaned []error - set := make(map[string]bool) - for _, err := range *e { - if msg := err.Error(); !set[msg] { - set[msg] = true - cleaned = append(cleaned, err) - } - } - *e = cleaned -} - -func (e errList) Error() string { - switch len(e) { - case 0: - return "" - case 1: - return e[0].Error() - default: - var buf bytes.Buffer - - for i, err := range e { - if i > 0 { - buf.WriteRune('\n') - } - buf.WriteString(err.Error()) - } - return buf.String() - } -} - -// parserError wraps an error with a prefix indicating the rule in which -// the error occurred. The original error is stored in the Inner field. -type parserError struct { - Inner error - pos position - prefix string - expected []string -} - -// Error returns the error message. -func (p *parserError) Error() string { - return p.prefix + ": " + p.Inner.Error() -} - -// newParser creates a parser with the specified input source and options. -func newParser(filename string, b []byte, opts ...Option) *parser { - stats := Stats{ - ChoiceAltCnt: make(map[string]map[string]int), - } - - p := &parser{ - filename: filename, - errs: new(errList), - data: b, - pt: savepoint{position: position{line: 1}}, - recover: true, - cur: current{ - state: make(storeDict), - globalStore: make(storeDict), - }, - maxFailPos: position{col: 1, line: 1}, - maxFailExpected: make([]string, 0, 20), - Stats: &stats, - // start rule is rule [0] unless an alternate entrypoint is specified - entrypoint: g.rules[0].name, - } - p.setOptions(opts) - - if p.maxExprCnt == 0 { - p.maxExprCnt = math.MaxUint64 - } - - return p -} - -// setOptions applies the options to the parser. -func (p *parser) setOptions(opts []Option) { - for _, opt := range opts { - opt(p) - } -} - -type resultTuple struct { - v interface{} - b bool - end savepoint -} - -const choiceNoMatch = -1 - -// Stats stores some statistics, gathered during parsing -type Stats struct { - // ExprCnt counts the number of expressions processed during parsing - // This value is compared to the maximum number of expressions allowed - // (set by the MaxExpressions option). - ExprCnt uint64 - - // ChoiceAltCnt is used to count for each ordered choice expression, - // which alternative is used how may times. - // These numbers allow to optimize the order of the ordered choice expression - // to increase the performance of the parser - // - // The outer key of ChoiceAltCnt is composed of the name of the rule as well - // as the line and the column of the ordered choice. - // The inner key of ChoiceAltCnt is the number (one-based) of the matching alternative. - // For each alternative the number of matches are counted. If an ordered choice does not - // match, a special counter is incremented. The name of this counter is set with - // the parser option Statistics. - // For an alternative to be included in ChoiceAltCnt, it has to match at least once. - ChoiceAltCnt map[string]map[string]int -} - -type parser struct { - filename string - pt savepoint - cur current - - data []byte - errs *errList - - depth int - recover bool - debug bool - - memoize bool - // memoization table for the packrat algorithm: - // map[offset in source] map[expression or rule] {value, match} - memo map[int]map[interface{}]resultTuple - - // rules table, maps the rule identifier to the rule node - rules map[string]*rule - // variables stack, map of label to value - vstack []map[string]interface{} - // rule stack, allows identification of the current rule in errors - rstack []*rule - - // parse fail - maxFailPos position - maxFailExpected []string - maxFailInvertExpected bool - - // max number of expressions to be parsed - maxExprCnt uint64 - // entrypoint for the parser - entrypoint string - - allowInvalidUTF8 bool - - *Stats - - choiceNoMatch string - // recovery expression stack, keeps track of the currently available recovery expression, these are traversed in reverse - recoveryStack []map[string]interface{} -} - -// push a variable set on the vstack. -func (p *parser) pushV() { - if cap(p.vstack) == len(p.vstack) { - // create new empty slot in the stack - p.vstack = append(p.vstack, nil) - } else { - // slice to 1 more - p.vstack = p.vstack[:len(p.vstack)+1] - } - - // get the last args set - m := p.vstack[len(p.vstack)-1] - if m != nil && len(m) == 0 { - // empty map, all good - return - } - - m = make(map[string]interface{}) - p.vstack[len(p.vstack)-1] = m -} - -// pop a variable set from the vstack. -func (p *parser) popV() { - // if the map is not empty, clear it - m := p.vstack[len(p.vstack)-1] - if len(m) > 0 { - // GC that map - p.vstack[len(p.vstack)-1] = nil - } - p.vstack = p.vstack[:len(p.vstack)-1] -} - -// push a recovery expression with its labels to the recoveryStack -func (p *parser) pushRecovery(labels []string, expr interface{}) { - if cap(p.recoveryStack) == len(p.recoveryStack) { - // create new empty slot in the stack - p.recoveryStack = append(p.recoveryStack, nil) - } else { - // slice to 1 more - p.recoveryStack = p.recoveryStack[:len(p.recoveryStack)+1] - } - - m := make(map[string]interface{}, len(labels)) - for _, fl := range labels { - m[fl] = expr - } - p.recoveryStack[len(p.recoveryStack)-1] = m -} - -// pop a recovery expression from the recoveryStack -func (p *parser) popRecovery() { - // GC that map - p.recoveryStack[len(p.recoveryStack)-1] = nil - - p.recoveryStack = p.recoveryStack[:len(p.recoveryStack)-1] -} - -func (p *parser) print(prefix, s string) string { - if !p.debug { - return s - } - - fmt.Printf("%s %d:%d:%d: %s [%#U]\n", - prefix, p.pt.line, p.pt.col, p.pt.offset, s, p.pt.rn) - return s -} - -func (p *parser) in(s string) string { - p.depth++ - return p.print(strings.Repeat(" ", p.depth)+">", s) -} - -func (p *parser) out(s string) string { - p.depth-- - return p.print(strings.Repeat(" ", p.depth)+"<", s) -} - -func (p *parser) addErr(err error) { - p.addErrAt(err, p.pt.position, []string{}) -} - -func (p *parser) addErrAt(err error, pos position, expected []string) { - var buf bytes.Buffer - if p.filename != "" { - buf.WriteString(p.filename) - } - if buf.Len() > 0 { - buf.WriteString(":") - } - buf.WriteString(fmt.Sprintf("%d:%d (%d)", pos.line, pos.col, pos.offset)) - if len(p.rstack) > 0 { - if buf.Len() > 0 { - buf.WriteString(": ") - } - rule := p.rstack[len(p.rstack)-1] - if rule.displayName != "" { - buf.WriteString("rule " + rule.displayName) - } else { - buf.WriteString("rule " + rule.name) - } - } - pe := &parserError{Inner: err, pos: pos, prefix: buf.String(), expected: expected} - p.errs.add(pe) -} - -func (p *parser) failAt(fail bool, pos position, want string) { - // process fail if parsing fails and not inverted or parsing succeeds and invert is set - if fail == p.maxFailInvertExpected { - if pos.offset < p.maxFailPos.offset { - return - } - - if pos.offset > p.maxFailPos.offset { - p.maxFailPos = pos - p.maxFailExpected = p.maxFailExpected[:0] - } - - if p.maxFailInvertExpected { - want = "!" + want - } - p.maxFailExpected = append(p.maxFailExpected, want) - } -} - -// read advances the parser to the next rune. -func (p *parser) read() { - p.pt.offset += p.pt.w - rn, n := utf8.DecodeRune(p.data[p.pt.offset:]) - p.pt.rn = rn - p.pt.w = n - p.pt.col++ - if rn == '\n' { - p.pt.line++ - p.pt.col = 0 - } - - if rn == utf8.RuneError && n == 1 { // see utf8.DecodeRune - if !p.allowInvalidUTF8 { - p.addErr(errInvalidEncoding) - } - } -} - -// restore parser position to the savepoint pt. -func (p *parser) restore(pt savepoint) { - if p.debug { - defer p.out(p.in("restore")) - } - if pt.offset == p.pt.offset { - return - } - p.pt = pt -} - -// Cloner is implemented by any value that has a Clone method, which returns a -// copy of the value. This is mainly used for types which are not passed by -// value (e.g map, slice, chan) or structs that contain such types. -// -// This is used in conjunction with the global state feature to create proper -// copies of the state to allow the parser to properly restore the state in -// the case of backtracking. -type Cloner interface { - Clone() interface{} -} - -var statePool = &sync.Pool{ - New: func() interface{} { return make(storeDict) }, -} - -func (sd storeDict) Discard() { - for k := range sd { - delete(sd, k) - } - statePool.Put(sd) -} - -// clone and return parser current state. -func (p *parser) cloneState() storeDict { - if p.debug { - defer p.out(p.in("cloneState")) - } - - state := statePool.Get().(storeDict) - for k, v := range p.cur.state { - if c, ok := v.(Cloner); ok { - state[k] = c.Clone() - } else { - state[k] = v - } - } - return state -} - -// restore parser current state to the state storeDict. -// every restoreState should applied only one time for every cloned state -func (p *parser) restoreState(state storeDict) { - if p.debug { - defer p.out(p.in("restoreState")) - } - p.cur.state.Discard() - p.cur.state = state -} - -// get the slice of bytes from the savepoint start to the current position. -func (p *parser) sliceFrom(start savepoint) []byte { - return p.data[start.position.offset:p.pt.position.offset] -} - -func (p *parser) getMemoized(node interface{}) (resultTuple, bool) { - if len(p.memo) == 0 { - return resultTuple{}, false - } - m := p.memo[p.pt.offset] - if len(m) == 0 { - return resultTuple{}, false - } - res, ok := m[node] - return res, ok -} - -func (p *parser) setMemoized(pt savepoint, node interface{}, tuple resultTuple) { - if p.memo == nil { - p.memo = make(map[int]map[interface{}]resultTuple) - } - m := p.memo[pt.offset] - if m == nil { - m = make(map[interface{}]resultTuple) - p.memo[pt.offset] = m - } - m[node] = tuple -} - -func (p *parser) buildRulesTable(g *grammar) { - p.rules = make(map[string]*rule, len(g.rules)) - for _, r := range g.rules { - p.rules[r.name] = r - } -} - -func (p *parser) parse(g *grammar) (val interface{}, err error) { - if len(g.rules) == 0 { - p.addErr(errNoRule) - return nil, p.errs.err() - } - - // TODO : not super critical but this could be generated - p.buildRulesTable(g) - - if p.recover { - // panic can be used in action code to stop parsing immediately - // and return the panic as an error. - defer func() { - if e := recover(); e != nil { - if p.debug { - defer p.out(p.in("panic handler")) - } - val = nil - switch e := e.(type) { - case error: - p.addErr(e) - default: - p.addErr(fmt.Errorf("%v", e)) - } - err = p.errs.err() - } - }() - } - - startRule, ok := p.rules[p.entrypoint] - if !ok { - p.addErr(errInvalidEntrypoint) - return nil, p.errs.err() - } - - p.read() // advance to first rune - val, ok = p.parseRule(startRule) - if !ok { - if len(*p.errs) == 0 { - // If parsing fails, but no errors have been recorded, the expected values - // for the farthest parser position are returned as error. - maxFailExpectedMap := make(map[string]struct{}, len(p.maxFailExpected)) - for _, v := range p.maxFailExpected { - maxFailExpectedMap[v] = struct{}{} - } - expected := make([]string, 0, len(maxFailExpectedMap)) - eof := false - if _, ok := maxFailExpectedMap["!."]; ok { - delete(maxFailExpectedMap, "!.") - eof = true - } - for k := range maxFailExpectedMap { - expected = append(expected, k) - } - sort.Strings(expected) - if eof { - expected = append(expected, "EOF") - } - p.addErrAt(errors.New("no match found, expected: "+listJoin(expected, ", ", "or")), p.maxFailPos, expected) - } - - return nil, p.errs.err() - } - return val, p.errs.err() -} - -func listJoin(list []string, sep string, lastSep string) string { - switch len(list) { - case 0: - return "" - case 1: - return list[0] - default: - return strings.Join(list[:len(list)-1], sep) + " " + lastSep + " " + list[len(list)-1] - } -} - -func (p *parser) parseRule(rule *rule) (interface{}, bool) { - if p.debug { - defer p.out(p.in("parseRule " + rule.name)) - } - - if p.memoize { - res, ok := p.getMemoized(rule) - if ok { - p.restore(res.end) - return res.v, res.b - } - } - - start := p.pt - p.rstack = append(p.rstack, rule) - p.pushV() - val, ok := p.parseExpr(rule.expr) - p.popV() - p.rstack = p.rstack[:len(p.rstack)-1] - if ok && p.debug { - p.print(strings.Repeat(" ", p.depth)+"MATCH", string(p.sliceFrom(start))) - } - - if p.memoize { - p.setMemoized(start, rule, resultTuple{val, ok, p.pt}) - } - return val, ok -} - -func (p *parser) parseExpr(expr interface{}) (interface{}, bool) { - var pt savepoint - - if p.memoize { - res, ok := p.getMemoized(expr) - if ok { - p.restore(res.end) - return res.v, res.b - } - pt = p.pt - } - - p.ExprCnt++ - if p.ExprCnt > p.maxExprCnt { - panic(errMaxExprCnt) - } - - var val interface{} - var ok bool - switch expr := expr.(type) { - case *actionExpr: - val, ok = p.parseActionExpr(expr) - case *andCodeExpr: - val, ok = p.parseAndCodeExpr(expr) - case *andExpr: - val, ok = p.parseAndExpr(expr) - case *anyMatcher: - val, ok = p.parseAnyMatcher(expr) - case *charClassMatcher: - val, ok = p.parseCharClassMatcher(expr) - case *choiceExpr: - val, ok = p.parseChoiceExpr(expr) - case *labeledExpr: - val, ok = p.parseLabeledExpr(expr) - case *litMatcher: - val, ok = p.parseLitMatcher(expr) - case *notCodeExpr: - val, ok = p.parseNotCodeExpr(expr) - case *notExpr: - val, ok = p.parseNotExpr(expr) - case *oneOrMoreExpr: - val, ok = p.parseOneOrMoreExpr(expr) - case *recoveryExpr: - val, ok = p.parseRecoveryExpr(expr) - case *ruleRefExpr: - val, ok = p.parseRuleRefExpr(expr) - case *seqExpr: - val, ok = p.parseSeqExpr(expr) - case *stateCodeExpr: - val, ok = p.parseStateCodeExpr(expr) - case *throwExpr: - val, ok = p.parseThrowExpr(expr) - case *zeroOrMoreExpr: - val, ok = p.parseZeroOrMoreExpr(expr) - case *zeroOrOneExpr: - val, ok = p.parseZeroOrOneExpr(expr) - default: - panic(fmt.Sprintf("unknown expression type %T", expr)) - } - if p.memoize { - p.setMemoized(pt, expr, resultTuple{val, ok, p.pt}) - } - return val, ok -} - -func (p *parser) parseActionExpr(act *actionExpr) (interface{}, bool) { - if p.debug { - defer p.out(p.in("parseActionExpr")) - } - - start := p.pt - val, ok := p.parseExpr(act.expr) - if ok { - p.cur.pos = start.position - p.cur.text = p.sliceFrom(start) - state := p.cloneState() - actVal, err := act.run(p) - if err != nil { - p.addErrAt(err, start.position, []string{}) - } - p.restoreState(state) - - val = actVal - } - if ok && p.debug { - p.print(strings.Repeat(" ", p.depth)+"MATCH", string(p.sliceFrom(start))) - } - return val, ok -} - -func (p *parser) parseAndCodeExpr(and *andCodeExpr) (interface{}, bool) { - if p.debug { - defer p.out(p.in("parseAndCodeExpr")) - } - - state := p.cloneState() - - ok, err := and.run(p) - if err != nil { - p.addErr(err) - } - p.restoreState(state) - - return nil, ok -} - -func (p *parser) parseAndExpr(and *andExpr) (interface{}, bool) { - if p.debug { - defer p.out(p.in("parseAndExpr")) - } - - pt := p.pt - state := p.cloneState() - p.pushV() - _, ok := p.parseExpr(and.expr) - p.popV() - p.restoreState(state) - p.restore(pt) - - return nil, ok -} - -func (p *parser) parseAnyMatcher(any *anyMatcher) (interface{}, bool) { - if p.debug { - defer p.out(p.in("parseAnyMatcher")) - } - - if p.pt.rn == utf8.RuneError && p.pt.w == 0 { - // EOF - see utf8.DecodeRune - p.failAt(false, p.pt.position, ".") - return nil, false - } - start := p.pt - p.read() - p.failAt(true, start.position, ".") - return p.sliceFrom(start), true -} - -func (p *parser) parseCharClassMatcher(chr *charClassMatcher) (interface{}, bool) { - if p.debug { - defer p.out(p.in("parseCharClassMatcher")) - } - - cur := p.pt.rn - start := p.pt - - // can't match EOF - if cur == utf8.RuneError && p.pt.w == 0 { // see utf8.DecodeRune - p.failAt(false, start.position, chr.val) - return nil, false - } - - if chr.ignoreCase { - cur = unicode.ToLower(cur) - } - - // try to match in the list of available chars - for _, rn := range chr.chars { - if rn == cur { - if chr.inverted { - p.failAt(false, start.position, chr.val) - return nil, false - } - p.read() - p.failAt(true, start.position, chr.val) - return p.sliceFrom(start), true - } - } - - // try to match in the list of ranges - for i := 0; i < len(chr.ranges); i += 2 { - if cur >= chr.ranges[i] && cur <= chr.ranges[i+1] { - if chr.inverted { - p.failAt(false, start.position, chr.val) - return nil, false - } - p.read() - p.failAt(true, start.position, chr.val) - return p.sliceFrom(start), true - } - } - - // try to match in the list of Unicode classes - for _, cl := range chr.classes { - if unicode.Is(cl, cur) { - if chr.inverted { - p.failAt(false, start.position, chr.val) - return nil, false - } - p.read() - p.failAt(true, start.position, chr.val) - return p.sliceFrom(start), true - } - } - - if chr.inverted { - p.read() - p.failAt(true, start.position, chr.val) - return p.sliceFrom(start), true - } - p.failAt(false, start.position, chr.val) - return nil, false -} - -func (p *parser) incChoiceAltCnt(ch *choiceExpr, altI int) { - choiceIdent := fmt.Sprintf("%s %d:%d", p.rstack[len(p.rstack)-1].name, ch.pos.line, ch.pos.col) - m := p.ChoiceAltCnt[choiceIdent] - if m == nil { - m = make(map[string]int) - p.ChoiceAltCnt[choiceIdent] = m - } - // We increment altI by 1, so the keys do not start at 0 - alt := strconv.Itoa(altI + 1) - if altI == choiceNoMatch { - alt = p.choiceNoMatch - } - m[alt]++ -} - -func (p *parser) parseChoiceExpr(ch *choiceExpr) (interface{}, bool) { - if p.debug { - defer p.out(p.in("parseChoiceExpr")) - } - - for altI, alt := range ch.alternatives { - // dummy assignment to prevent compile error if optimized - _ = altI - - state := p.cloneState() - - p.pushV() - val, ok := p.parseExpr(alt) - p.popV() - if ok { - p.incChoiceAltCnt(ch, altI) - return val, ok - } - p.restoreState(state) - } - p.incChoiceAltCnt(ch, choiceNoMatch) - return nil, false -} - -func (p *parser) parseLabeledExpr(lab *labeledExpr) (interface{}, bool) { - if p.debug { - defer p.out(p.in("parseLabeledExpr")) - } - - p.pushV() - val, ok := p.parseExpr(lab.expr) - p.popV() - if ok && lab.label != "" { - m := p.vstack[len(p.vstack)-1] - m[lab.label] = val - } - return val, ok -} - -func (p *parser) parseLitMatcher(lit *litMatcher) (interface{}, bool) { - if p.debug { - defer p.out(p.in("parseLitMatcher")) - } - - start := p.pt - for _, want := range lit.val { - cur := p.pt.rn - if lit.ignoreCase { - cur = unicode.ToLower(cur) - } - if cur != want { - p.failAt(false, start.position, lit.want) - p.restore(start) - return nil, false - } - p.read() - } - p.failAt(true, start.position, lit.want) - return p.sliceFrom(start), true -} - -func (p *parser) parseNotCodeExpr(not *notCodeExpr) (interface{}, bool) { - if p.debug { - defer p.out(p.in("parseNotCodeExpr")) - } - - state := p.cloneState() - - ok, err := not.run(p) - if err != nil { - p.addErr(err) - } - p.restoreState(state) - - return nil, !ok -} - -func (p *parser) parseNotExpr(not *notExpr) (interface{}, bool) { - if p.debug { - defer p.out(p.in("parseNotExpr")) - } - - pt := p.pt - state := p.cloneState() - p.pushV() - p.maxFailInvertExpected = !p.maxFailInvertExpected - _, ok := p.parseExpr(not.expr) - p.maxFailInvertExpected = !p.maxFailInvertExpected - p.popV() - p.restoreState(state) - p.restore(pt) - - return nil, !ok -} - -func (p *parser) parseOneOrMoreExpr(expr *oneOrMoreExpr) (interface{}, bool) { - if p.debug { - defer p.out(p.in("parseOneOrMoreExpr")) - } - - var vals []interface{} - - for { - p.pushV() - val, ok := p.parseExpr(expr.expr) - p.popV() - if !ok { - if len(vals) == 0 { - // did not match once, no match - return nil, false - } - return vals, true - } - vals = append(vals, val) - } -} - -func (p *parser) parseRecoveryExpr(recover *recoveryExpr) (interface{}, bool) { - if p.debug { - defer p.out(p.in("parseRecoveryExpr (" + strings.Join(recover.failureLabel, ",") + ")")) - } - - p.pushRecovery(recover.failureLabel, recover.recoverExpr) - val, ok := p.parseExpr(recover.expr) - p.popRecovery() - - return val, ok -} - -func (p *parser) parseRuleRefExpr(ref *ruleRefExpr) (interface{}, bool) { - if p.debug { - defer p.out(p.in("parseRuleRefExpr " + ref.name)) - } - - if ref.name == "" { - panic(fmt.Sprintf("%s: invalid rule: missing name", ref.pos)) - } - - rule := p.rules[ref.name] - if rule == nil { - p.addErr(fmt.Errorf("undefined rule: %s", ref.name)) - return nil, false - } - return p.parseRule(rule) -} - -func (p *parser) parseSeqExpr(seq *seqExpr) (interface{}, bool) { - if p.debug { - defer p.out(p.in("parseSeqExpr")) - } - - vals := make([]interface{}, 0, len(seq.exprs)) - - pt := p.pt - state := p.cloneState() - for _, expr := range seq.exprs { - val, ok := p.parseExpr(expr) - if !ok { - p.restoreState(state) - p.restore(pt) - return nil, false - } - vals = append(vals, val) - } - return vals, true -} - -func (p *parser) parseStateCodeExpr(state *stateCodeExpr) (interface{}, bool) { - if p.debug { - defer p.out(p.in("parseStateCodeExpr")) - } - - err := state.run(p) - if err != nil { - p.addErr(err) - } - return nil, true -} - -func (p *parser) parseThrowExpr(expr *throwExpr) (interface{}, bool) { - if p.debug { - defer p.out(p.in("parseThrowExpr")) - } - - for i := len(p.recoveryStack) - 1; i >= 0; i-- { - if recoverExpr, ok := p.recoveryStack[i][expr.label]; ok { - if val, ok := p.parseExpr(recoverExpr); ok { - return val, ok - } - } - } - - return nil, false -} - -func (p *parser) parseZeroOrMoreExpr(expr *zeroOrMoreExpr) (interface{}, bool) { - if p.debug { - defer p.out(p.in("parseZeroOrMoreExpr")) - } - - var vals []interface{} - - for { - p.pushV() - val, ok := p.parseExpr(expr.expr) - p.popV() - if !ok { - return vals, true - } - vals = append(vals, val) - } -} - -func (p *parser) parseZeroOrOneExpr(expr *zeroOrOneExpr) (interface{}, bool) { - if p.debug { - defer p.out(p.in("parseZeroOrOneExpr")) - } - - p.pushV() - val, _ := p.parseExpr(expr.expr) - p.popV() - // whether it matched or not, consider it a match - return val, true -} diff --git a/vendor/github.com/mmcloughlin/addchain/acc/parse/parse.go b/vendor/github.com/mmcloughlin/addchain/acc/parse/parse.go deleted file mode 100644 index 8523e146970..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/acc/parse/parse.go +++ /dev/null @@ -1,35 +0,0 @@ -// Package parse implements a parser for acc programs. -package parse - -import ( - "io" - "strings" - - "github.com/mmcloughlin/addchain/acc/ast" - "github.com/mmcloughlin/addchain/acc/parse/internal/parser" -) - -//go:generate pigeon -o internal/parser/zparser.go acc.peg - -// File parses filename. -func File(filename string) (*ast.Chain, error) { - return cast(parser.ParseFile(filename)) -} - -// Reader parses the data from r using filename as information in -// error messages. -func Reader(filename string, r io.Reader) (*ast.Chain, error) { - return cast(parser.ParseReader(filename, r)) -} - -// String parses s. -func String(s string) (*ast.Chain, error) { - return Reader("string", strings.NewReader(s)) -} - -func cast(i interface{}, err error) (*ast.Chain, error) { - if err != nil { - return nil, err - } - return i.(*ast.Chain), nil -} diff --git a/vendor/github.com/mmcloughlin/addchain/acc/pass/alloc.go b/vendor/github.com/mmcloughlin/addchain/acc/pass/alloc.go deleted file mode 100644 index 5c8e97d8232..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/acc/pass/alloc.go +++ /dev/null @@ -1,98 +0,0 @@ -package pass - -import ( - "fmt" - - "github.com/mmcloughlin/addchain/acc/ir" - "github.com/mmcloughlin/addchain/internal/container/heap" - "github.com/mmcloughlin/addchain/internal/errutil" -) - -// Allocator pass assigns a minimal number of temporary variables to execute a program. -type Allocator struct { - // Input is the name of the input variable. Note this is index 0, or the - // identity element of the addition chain. - Input string - - // Output is the name to give to the final output of the addition chain. This - // variable may itself be used as a temporary during execution. - Output string - - // Format defines how to format any temporary variables. This format string - // must accept one integer value. For example "t%d" would be a reasonable - // choice. - Format string -} - -// Execute performs temporary variable allocation. -func (a Allocator) Execute(p *ir.Program) error { - // Canonicalize operands and delete all names. - if err := Exec(p, Func(CanonicalizeOperands), Func(ClearNames)); err != nil { - return err - } - - // Initialize allocation. This maps operand index to variable index. The - // inidicies 0 and 1 are special, reserved for the input and output - // respectively. Any indicies above that are temporaries. - out := p.Output() - allocation := map[int]int{ - 0: 0, - out.Index: 1, - } - n := 2 - - // Keep a heap of available indicies. Initially none. - available := heap.NewMinInts() - - // Process instructions in reverse. - for i := len(p.Instructions) - 1; i >= 0; i-- { - inst := p.Instructions[i] - - // The output operand variable now becomes available. - v, ok := allocation[inst.Output.Index] - if !ok { - return errutil.AssertionFailure("output operand %d missing allocation", inst.Output.Index) - } - available.Push(v) - - // Inputs may need variables, if they are not already live. - for _, input := range inst.Op.Inputs() { - _, ok := allocation[input.Index] - if ok { - continue - } - - // If there's nothing available, we'll need one more temporary. - if available.Empty() { - available.Push(n) - n++ - } - - allocation[input.Index] = available.Pop() - } - } - - // Record allocation. - for _, op := range p.Operands { - op.Identifier = a.name(allocation[op.Index]) - } - - temps := []string{} - for i := 2; i < n; i++ { - temps = append(temps, a.name(i)) - } - p.Temporaries = temps - - return nil -} - -func (a Allocator) name(v int) string { - switch v { - case 0: - return a.Input - case 1: - return a.Output - default: - return fmt.Sprintf(a.Format, v-2) - } -} diff --git a/vendor/github.com/mmcloughlin/addchain/acc/pass/eval.go b/vendor/github.com/mmcloughlin/addchain/acc/pass/eval.go deleted file mode 100644 index 2dd85b1dd73..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/acc/pass/eval.go +++ /dev/null @@ -1,57 +0,0 @@ -package pass - -import ( - "errors" - - "github.com/mmcloughlin/addchain" - "github.com/mmcloughlin/addchain/acc/ir" - "github.com/mmcloughlin/addchain/internal/errutil" -) - -// Compile generates the fully unrolled sequence of additions. The result is -// stored in the Program field. -func Compile(p *ir.Program) error { - if p.Program != nil { - return nil - } - - p.Program = addchain.Program{} - for _, i := range p.Instructions { - var out int - var err error - - switch op := i.Op.(type) { - case ir.Add: - out, err = p.Program.Add(op.X.Index, op.Y.Index) - case ir.Double: - out, err = p.Program.Double(op.X.Index) - case ir.Shift: - out, err = p.Program.Shift(op.X.Index, op.S) - default: - return errutil.UnexpectedType(op) - } - - if err != nil { - return err - } - if out != i.Output.Index { - return errors.New("incorrect output index") - } - } - - return nil -} - -// Eval evaluates the program and places the result in the Chain field. -func Eval(p *ir.Program) error { - if p.Chain != nil { - return nil - } - - if err := Compile(p); err != nil { - return err - } - - p.Chain = p.Program.Evaluate() - return nil -} diff --git a/vendor/github.com/mmcloughlin/addchain/acc/pass/naming.go b/vendor/github.com/mmcloughlin/addchain/acc/pass/naming.go deleted file mode 100644 index e417ef1cf45..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/acc/pass/naming.go +++ /dev/null @@ -1,89 +0,0 @@ -package pass - -import ( - "fmt" - "math/big" - - "github.com/mmcloughlin/addchain/acc/ir" - "github.com/mmcloughlin/addchain/internal/bigint" - "github.com/mmcloughlin/addchain/internal/errutil" -) - -// References: -// -// [curvechains] Brian Smith. The Most Efficient Known Addition Chains for Field Element and -// Scalar Inversion for the Most Popular and Most Unpopular Elliptic Curves. 2017. -// https://briansmith.org/ecc-inversion-addition-chains-01 (accessed June 30, 2019) - -// Naming conventions described in [curvechains]. -var ( - NameByteValues = NameBinaryValues(8, "_%b") - NameXRuns = NameBinaryRuns("x%d") -) - -// ClearNames deletes all operand names. -func ClearNames(p *ir.Program) error { - if err := CanonicalizeOperands(p); err != nil { - return err - } - - for _, operand := range p.Operands { - operand.Identifier = "" - } - - return nil -} - -// NameBinaryValues assigns variable names to operands with values less than 2ᵏ. -// The identifier is determined from the format string, which should expect to -// take one *big.Int argument. -func NameBinaryValues(k int, format string) Interface { - return NameOperands(func(_ int, x *big.Int) string { - if x.BitLen() > k { - return "" - } - return fmt.Sprintf(format, x) - }) -} - -// NameBinaryRuns assigns variable names to operands with values of the form 2ⁿ -// - 1. The identifier is determined from the format string, which takes the -// length of the run as a parameter. -func NameBinaryRuns(format string) Interface { - return NameOperands(func(_ int, x *big.Int) string { - n := uint(x.BitLen()) - if !bigint.Equal(x, bigint.Ones(n)) { - return "" - } - return fmt.Sprintf(format, n) - }) -} - -// NameOperands builds a pass that names operands according to the given scheme. -func NameOperands(name func(int, *big.Int) string) Interface { - return Func(func(p *ir.Program) error { - // We need canonical operands, and we need to know the chain values. - if err := Exec(p, Func(CanonicalizeOperands), Func(Eval)); err != nil { - return err - } - - for _, operand := range p.Operands { - // Skip if it already has a name. - if operand.Identifier != "" { - continue - } - - // Fetch referenced value. - idx := operand.Index - if idx >= len(p.Chain) { - return errutil.AssertionFailure("operand index %d out of bounds", idx) - } - x := p.Chain[idx] - - // Set name. - operand.Identifier = name(idx, x) - } - - return nil - }) -} diff --git a/vendor/github.com/mmcloughlin/addchain/acc/pass/pass.go b/vendor/github.com/mmcloughlin/addchain/acc/pass/pass.go deleted file mode 100644 index a9f1ee23d09..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/acc/pass/pass.go +++ /dev/null @@ -1,117 +0,0 @@ -// Package pass implements analysis and processing passes on acc programs. -package pass - -import ( - "fmt" - - "github.com/mmcloughlin/addchain/acc/ir" - "github.com/mmcloughlin/addchain/internal/errutil" -) - -// Interface for a processing pass. -type Interface interface { - Execute(*ir.Program) error -} - -// Func adapts a function to the pass Interface. -type Func func(*ir.Program) error - -// Execute calls p. -func (f Func) Execute(p *ir.Program) error { - return f(p) -} - -// Concat returns a pass that executes the given passes in order, stopping on -// the first error. -func Concat(passes ...Interface) Interface { - return Func(func(p *ir.Program) error { - for _, pass := range passes { - if err := pass.Execute(p); err != nil { - return err - } - } - return nil - }) -} - -// Exec is a convenience for executing a list of passes on p. -func Exec(p *ir.Program, passes ...Interface) error { - return Concat(passes...).Execute(p) -} - -// CanonicalizeOperands ensures there is only one Operand object for each -// operand index in the program. In particular, this ensures there are not -// conflicting names for the same index. Populates the Operands field of the -// program. -func CanonicalizeOperands(p *ir.Program) error { - if p.Operands != nil { - return nil - } - - p.Operands = map[int]*ir.Operand{} - - // First pass through determines canonical operand for each index. - for _, i := range p.Instructions { - for _, operand := range i.Operands() { - // Look for an existing operand object for this index. - existing, found := p.Operands[operand.Index] - if !found { - p.Operands[operand.Index] = operand - continue - } - - if existing == operand { - continue - } - - // They're different objects. Check for a name conflict. - if existing.Identifier != "" && operand.Identifier != "" && existing.Identifier != operand.Identifier { - return fmt.Errorf("identifier conflict: index %d named %q and %q", operand.Index, operand.Identifier, existing.Identifier) - } - - if operand.Identifier != "" { - existing.Identifier = operand.Identifier - } - } - } - - // Second pass through replaces all operands with the canonical version. - for _, i := range p.Instructions { - switch op := i.Op.(type) { - case ir.Add: - i.Op = ir.Add{ - X: p.Operands[op.X.Index], - Y: p.Operands[op.Y.Index], - } - case ir.Double: - i.Op = ir.Double{ - X: p.Operands[op.X.Index], - } - case ir.Shift: - i.Op = ir.Shift{ - X: p.Operands[op.X.Index], - S: op.S, - } - default: - return errutil.UnexpectedType(op) - } - } - - return nil -} - -// ReadCounts computes how many times each index is read in the program. This -// populates the ReadCount field of the program. -func ReadCounts(p *ir.Program) error { - if p.ReadCount != nil { - return nil - } - - p.ReadCount = map[int]int{} - for _, i := range p.Instructions { - for _, input := range i.Op.Inputs() { - p.ReadCount[input.Index]++ - } - } - return nil -} diff --git a/vendor/github.com/mmcloughlin/addchain/acc/pass/validation.go b/vendor/github.com/mmcloughlin/addchain/acc/pass/validation.go deleted file mode 100644 index e93ba63c34d..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/acc/pass/validation.go +++ /dev/null @@ -1,28 +0,0 @@ -package pass - -import ( - "fmt" - - "github.com/mmcloughlin/addchain/acc/ir" -) - -// Validate is a pass to sanity check an intermediate representation program. -var Validate = Func(CheckDanglingInputs) - -// CheckDanglingInputs looks for program inputs that have no instruction -// outputting them. Note this can happen and still be technically correct. For -// example a shift instruction produces many intermediate results, and one of -// these can later be referenced. The resulting program is still correct, but -// undesirable. -func CheckDanglingInputs(p *ir.Program) error { - outputset := map[int]bool{0: true} - for _, i := range p.Instructions { - for _, input := range i.Op.Inputs() { - if !outputset[input.Index] { - return fmt.Errorf("no output instruction for input index %d", input.Index) - } - } - outputset[i.Output.Index] = true - } - return nil -} diff --git a/vendor/github.com/mmcloughlin/addchain/acc/printer/printer.go b/vendor/github.com/mmcloughlin/addchain/acc/printer/printer.go deleted file mode 100644 index 96e8baa9f02..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/acc/printer/printer.go +++ /dev/null @@ -1,131 +0,0 @@ -// Package printer implements printing of acc AST nodes. -package printer - -import ( - "bytes" - "io" - "os" - - "github.com/mmcloughlin/addchain/acc/ast" - "github.com/mmcloughlin/addchain/internal/errutil" - "github.com/mmcloughlin/addchain/internal/print" -) - -// String prints the AST and returns resulting string. -func String(n interface{}) (string, error) { - b, err := Bytes(n) - if err != nil { - return "", err - } - return string(b), nil -} - -// Bytes prints the AST and returns resulting bytes. -func Bytes(n interface{}) ([]byte, error) { - var buf bytes.Buffer - if err := Fprint(&buf, n); err != nil { - return nil, err - } - return buf.Bytes(), nil -} - -// Print an AST node to standard out. -func Print(n interface{}) error { - return Fprint(os.Stdout, n) -} - -// Fprint writes the AST node n to w. -func Fprint(w io.Writer, n interface{}) error { - p := newprinter(w) - p.node(n) - p.Flush() - return p.Error() -} - -type printer struct { - *print.TabWriter -} - -func newprinter(w io.Writer) *printer { - return &printer{ - TabWriter: print.NewTabWriter(w, 1, 4, 1, ' ', 0), - } -} - -func (p *printer) node(n interface{}) { - switch n := n.(type) { - case *ast.Chain: - for _, stmt := range n.Statements { - p.statement(stmt) - } - case ast.Statement: - p.statement(n) - case ast.Expr: - p.expr(n, nil) - default: - p.SetError(errutil.UnexpectedType(n)) - } -} - -func (p *printer) statement(stmt ast.Statement) { - if len(stmt.Name) > 0 { - p.Printf("%s\t=\t", stmt.Name) - } else { - p.Printf("return\t\t") - } - p.expr(stmt.Expr, nil) - p.NL() -} - -func (p *printer) expr(e, parent ast.Expr) { - // Parens required if the precence of this operator is less than its parent. - if parent != nil && e.Precedence() < parent.Precedence() { - p.Printf("(") - p.expr(e, nil) - p.Printf(")") - return - } - - switch e := e.(type) { - case ast.Operand: - p.operand(e) - case ast.Identifier: - p.identifier(e) - case ast.Add: - p.add(e) - case ast.Double: - p.double(e) - case ast.Shift: - p.shift(e) - default: - p.SetError(errutil.UnexpectedType(e)) - } -} - -func (p *printer) add(a ast.Add) { - p.expr(a.X, a) - p.Printf(" + ") - p.expr(a.Y, a) -} - -func (p *printer) double(d ast.Double) { - p.Printf("2*") - p.expr(d.X, d) -} - -func (p *printer) shift(s ast.Shift) { - p.expr(s.X, s) - p.Printf(" << %d", s.S) -} - -func (p *printer) identifier(name ast.Identifier) { - p.Printf("%s", name) -} - -func (p *printer) operand(op ast.Operand) { - if op == 0 { - p.Printf("1") - } else { - p.Printf("[%d]", op) - } -} diff --git a/vendor/github.com/mmcloughlin/addchain/acc/translate.go b/vendor/github.com/mmcloughlin/addchain/acc/translate.go deleted file mode 100644 index 91bfcf17e46..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/acc/translate.go +++ /dev/null @@ -1,139 +0,0 @@ -package acc - -import ( - "fmt" - - "github.com/mmcloughlin/addchain/acc/ast" - "github.com/mmcloughlin/addchain/acc/ir" - "github.com/mmcloughlin/addchain/internal/errutil" -) - -// Translate converts an abstract syntax tree to an intermediate representation. -func Translate(c *ast.Chain) (*ir.Program, error) { - s := newstate() - for _, stmt := range c.Statements { - if err := s.statement(stmt); err != nil { - return nil, err - } - } - return s.prog, nil -} - -type state struct { - prog *ir.Program - n int - variable map[ast.Identifier]*ir.Operand -} - -func newstate() *state { - return &state{ - prog: &ir.Program{}, - n: 1, - variable: map[ast.Identifier]*ir.Operand{}, - } -} - -func (s *state) statement(stmt ast.Statement) error { - out, err := s.expr(stmt.Expr) - if err != nil { - return err - } - if err := s.define(stmt.Name, out); err != nil { - return err - } - return nil -} - -func (s *state) expr(expr ast.Expr) (*ir.Operand, error) { - switch e := expr.(type) { - case ast.Operand: - return &ir.Operand{Index: int(e)}, nil - case ast.Identifier: - return s.lookup(e) - case ast.Add: - return s.add(e) - case ast.Double: - return s.double(e) - case ast.Shift: - return s.shift(e) - default: - return nil, errutil.UnexpectedType(e) - } -} - -func (s *state) add(a ast.Add) (*ir.Operand, error) { - x, err := s.expr(a.X) - if err != nil { - return nil, err - } - - y, err := s.expr(a.Y) - if err != nil { - return nil, err - } - - if x.Index > y.Index { - x, y = y, x - } - - out := ir.Index(s.n) - inst := &ir.Instruction{ - Output: out, - Op: ir.Add{X: x, Y: y}, - } - s.prog.AddInstruction(inst) - s.n++ - - return out, nil -} - -func (s *state) double(d ast.Double) (*ir.Operand, error) { - x, err := s.expr(d.X) - if err != nil { - return nil, err - } - - out := ir.Index(s.n) - inst := &ir.Instruction{ - Output: out, - Op: ir.Double{X: x}, - } - s.prog.AddInstruction(inst) - s.n++ - - return out, nil -} - -func (s *state) shift(sh ast.Shift) (*ir.Operand, error) { - x, err := s.expr(sh.X) - if err != nil { - return nil, err - } - - s.n += int(sh.S) - out := ir.Index(s.n - 1) - inst := &ir.Instruction{ - Output: out, - Op: ir.Shift{X: x, S: sh.S}, - } - s.prog.AddInstruction(inst) - - return out, nil -} - -func (s *state) define(name ast.Identifier, op *ir.Operand) error { - if _, found := s.variable[name]; found { - return fmt.Errorf("cannot redefine %q", name) - } - op.Identifier = string(name) - s.variable[name] = op - return nil -} - -func (s state) lookup(name ast.Identifier) (*ir.Operand, error) { - operand, ok := s.variable[name] - if !ok { - return nil, fmt.Errorf("variable %q undefined", name) - } - return operand, nil -} diff --git a/vendor/github.com/mmcloughlin/addchain/alg/alg.go b/vendor/github.com/mmcloughlin/addchain/alg/alg.go deleted file mode 100644 index 0555dacb0d3..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/alg/alg.go +++ /dev/null @@ -1,43 +0,0 @@ -// Package alg provides base types for addition chain and addition sequence search algorithms. -package alg - -import ( - "math/big" - - "github.com/mmcloughlin/addchain" -) - -// ChainAlgorithm is a method of generating an addition chain for a target integer. -type ChainAlgorithm interface { - // FindChain generates an addition chain ending at target. - FindChain(target *big.Int) (addchain.Chain, error) - - // String returns a name for the algorithm. - String() string -} - -// SequenceAlgorithm is a method of generating an addition sequence for a set of -// target values. -type SequenceAlgorithm interface { - // FindSequence generates an addition chain containing every element of targets. - FindSequence(targets []*big.Int) (addchain.Chain, error) - - // String returns a name for the algorithm. - String() string -} - -// AsChainAlgorithm adapts a sequence algorithm to a chain algorithm. The -// resulting algorithm calls the sequence algorithm with a singleton list -// containing the target. -func AsChainAlgorithm(s SequenceAlgorithm) ChainAlgorithm { - return asChainAlgorithm{s} -} - -type asChainAlgorithm struct { - SequenceAlgorithm -} - -// FindChain calls FindSequence with a singleton list containing the target. -func (a asChainAlgorithm) FindChain(target *big.Int) (addchain.Chain, error) { - return a.FindSequence([]*big.Int{target}) -} diff --git a/vendor/github.com/mmcloughlin/addchain/alg/contfrac/contfrac.go b/vendor/github.com/mmcloughlin/addchain/alg/contfrac/contfrac.go deleted file mode 100644 index 3c31a538356..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/alg/contfrac/contfrac.go +++ /dev/null @@ -1,262 +0,0 @@ -// Package contfrac implements addition sequence algorithms based on continued-fraction expansions. -package contfrac - -import ( - "fmt" - "math/big" - - "github.com/mmcloughlin/addchain" - "github.com/mmcloughlin/addchain/internal/bigint" - "github.com/mmcloughlin/addchain/internal/bigints" -) - -// References: -// -// [contfrac] F Bergeron, J Berstel, S Brlek and C Duboc. Addition chains using continued -// fractions. Journal of Algorithms. 1989. -// http://www-igm.univ-mlv.fr/~berstel/Articles/1989AdditionChainDuboc.pdf -// [efficientcompaddchain] Bergeron, F., Berstel, J. and Brlek, S. Efficient computation of addition -// chains. Journal de theorie des nombres de Bordeaux. 1994. -// http://www.numdam.org/item/JTNB_1994__6_1_21_0 -// [gencontfrac] Amadou Tall and Ali Yassin Sanghare. Efficient computation of -// addition-subtraction chains using generalized continued Fractions. Cryptology -// ePrint Archive, Report 2013/466. 2013. https://eprint.iacr.org/2013/466 -// [hehcc:exp] Christophe Doche. Exponentiation. Handbook of Elliptic and Hyperelliptic Curve -// Cryptography, chapter 9. 2006. -// http://koclab.cs.ucsb.edu/teaching/ecc/eccPapers/Doche-ch09.pdf - -// Strategy is a method of choosing the auxiliary integer k in the continued -// fraction method outlined in [efficientcompaddchain]. -type Strategy interface { - // K returns values of k to try given n. - K(n *big.Int) []*big.Int - - // Singleton returns whether every call to K will return one value of k. This - // determines whether the resulting continued fractions sequence algorithm will - // be logarithmic, and therefore suitable for large inputs. - Singleton() bool - - // String returns a name for the strategy. - String() string -} - -// Strategies lists all available continued fraction strategies. -var Strategies = []Strategy{ - BinaryStrategy{}, - CoBinaryStrategy{}, - DichotomicStrategy{}, - SqrtStrategy{}, - TotalStrategy{}, - DyadicStrategy{}, - FermatStrategy{}, -} - -// Algorithm uses the continued fractions method for finding an addition chain -// [contfrac] [efficientcompaddchain]. -type Algorithm struct { - strategy Strategy -} - -// NewAlgorithm builds a continued fractions addition sequence algorithm using -// the provided strategy for selecting the auziallary integer k. -func NewAlgorithm(s Strategy) Algorithm { - return Algorithm{ - strategy: s, - } -} - -func (a Algorithm) String() string { - return fmt.Sprintf("continued_fractions(%s)", a.strategy) -} - -// FindSequence applies the continued fractions method to build a chain -// containing targets. -func (a Algorithm) FindSequence(targets []*big.Int) (addchain.Chain, error) { - bigints.Sort(targets) - return a.chain(targets), nil -} - -func (a Algorithm) minchain(n *big.Int) addchain.Chain { - if bigint.IsPow2(n) { - return bigint.Pow2UpTo(n) - } - - if bigint.EqualInt64(n, 3) { - return bigints.Int64s(1, 2, 3) - } - - var min addchain.Chain - for _, k := range a.strategy.K(n) { - c := a.chain([]*big.Int{k, n}) - if min == nil || len(c) < len(min) { - min = c - } - } - - return min -} - -// chain produces a continued fraction chain for the given values. The slice ns -// must be in ascending order. -func (a Algorithm) chain(ns []*big.Int) addchain.Chain { - k := len(ns) - if k == 1 || ns[k-2].Cmp(bigint.One()) <= 0 { - return a.minchain(ns[k-1]) - } - - q, r := new(big.Int), new(big.Int) - q.DivMod(ns[k-1], ns[k-2], r) - - cq := a.minchain(q) - remaining := bigints.Clone(ns[:k-1]) - - if bigint.IsZero(r) { - return addchain.Product(a.chain(remaining), cq) - } - - remaining = bigints.InsertSortedUnique(remaining, r) - return addchain.Plus(addchain.Product(a.chain(remaining), cq), r) -} - -// BinaryStrategy implements the binary strategy, which just sets k = floor(n/2). See [efficientcompaddchain] page 26. -// Since this is a singleton strategy it gives rise to a logarithmic sequence algoirithm that may not be optimal. -type BinaryStrategy struct{} - -func (BinaryStrategy) String() string { return "binary" } - -// Singleton returns true, since the binary strategy returns a single proposal -// for k. -func (BinaryStrategy) Singleton() bool { return true } - -// K returns floor(n/2). -func (BinaryStrategy) K(n *big.Int) []*big.Int { - k := new(big.Int).Rsh(n, 1) - return []*big.Int{k} -} - -// CoBinaryStrategy implements the co-binary strategy, also referred to as the -// "modified-binary" strategy. See [efficientcompaddchain] page 26 or -// [gencontfrac] page 6. Since this is a singleton strategy it gives rise to a -// logarithmic sequence algorithm that may not be optimal. -type CoBinaryStrategy struct{} - -func (CoBinaryStrategy) String() string { return "co_binary" } - -// Singleton returns true, since the co-binary strategy returns a single -// proposal for k. -func (CoBinaryStrategy) Singleton() bool { return true } - -// K returns floor(n/2) when n is even, or floor((n+1)/2) when n is odd. -func (CoBinaryStrategy) K(n *big.Int) []*big.Int { - k := bigint.Clone(n) - if k.Bit(0) == 1 { - k.Add(k, bigint.One()) - } - k.Rsh(k, 1) - return []*big.Int{k} -} - -// TotalStrategy returns all possible values of k less than n. This will result -// in the optimal continued fraction chain at a complexity of O(n² log²(n)). -// Note that the optimal continued fraction chain is not necessarily the optimal -// chain. Must not be used for large inputs. -type TotalStrategy struct{} - -func (TotalStrategy) String() string { return "total" } - -// Singleton returns false, since the total strategy returns more than once k. -func (TotalStrategy) Singleton() bool { return false } - -// K returns {2,, 3, ..., n-1}. -func (TotalStrategy) K(n *big.Int) []*big.Int { - ks := []*big.Int{} - k := big.NewInt(2) - one := bigint.One() - for k.Cmp(n) < 0 { - ks = append(ks, bigint.Clone(k)) - k.Add(k, one) - } - return ks -} - -// DyadicStrategy implements the Dyadic Strategy, defined in -// [efficientcompaddchain] page 28. This gives rise to a sequence algorithm with -// complexity O(n*log³(n)). Must not be used for large inputs. -type DyadicStrategy struct{} - -func (DyadicStrategy) String() string { return "dyadic" } - -// Singleton returns false, since the dyadic strategy returns more than once k. -func (DyadicStrategy) Singleton() bool { return false } - -// K returns floor( n / 2ʲ ) for all j. -func (DyadicStrategy) K(n *big.Int) []*big.Int { - ks := []*big.Int{} - k := new(big.Int).Rsh(n, 1) - one := bigint.One() - for k.Cmp(one) > 0 { - ks = append(ks, bigint.Clone(k)) - k.Rsh(k, 1) - } - return ks -} - -// FermatStrategy implements Fermat's Strategy, defined in -// [efficientcompaddchain] page 28. This returns a set of possible k of size -// O(log(log(n))), giving rise to a faster algorithm than the Dyadic strategy. -// This has been shown to be near optimal for small inputs. Must not be used for -// large inputs. -type FermatStrategy struct{} - -func (FermatStrategy) String() string { return "fermat" } - -// Singleton returns false, since Fermat's strategy returns more than once k. -func (FermatStrategy) Singleton() bool { return false } - -// K returns floor( n / 2^(2^j) ) for all j. -func (FermatStrategy) K(n *big.Int) []*big.Int { - ks := []*big.Int{} - k := new(big.Int).Rsh(n, 1) - one := bigint.One() - s := uint(1) - for k.Cmp(one) > 0 { - ks = append(ks, bigint.Clone(k)) - k.Rsh(k, s) - s *= 2 - } - return ks -} - -// DichotomicStrategy is a singleton strategy, defined in -// [efficientcompaddchain] page 28. This gives rise to a logarithmic sequence -// algorithm, but the result is not necessarily optimal. -type DichotomicStrategy struct{} - -func (DichotomicStrategy) String() string { return "dichotomic" } - -// Singleton returns true, since the dichotomic strategy suggests just one k. -func (DichotomicStrategy) Singleton() bool { return true } - -// K returns only one suggestion for k, namely floor( n / 2ʰ ) where h = log2(n)/2. -func (DichotomicStrategy) K(n *big.Int) []*big.Int { - l := n.BitLen() - h := uint(l) / 2 - k := new(big.Int).Div(n, bigint.Pow2(h)) - return []*big.Int{k} -} - -// SqrtStrategy chooses k to be floor(sqrt(n)). See [gencontfrac] page 6. Since -// this is a singleton strategy, it gives rise to a logarithmic sequence -// algorithm that's not necessarily optimal. -type SqrtStrategy struct{} - -func (SqrtStrategy) String() string { return "sqrt" } - -// Singleton returns true, since the square root strategy suggests just one k. -func (SqrtStrategy) Singleton() bool { return false } - -// K returns floor(sqrt(n)). -func (SqrtStrategy) K(n *big.Int) []*big.Int { - sqrt := new(big.Int).Sqrt(n) - return []*big.Int{sqrt} -} diff --git a/vendor/github.com/mmcloughlin/addchain/alg/dict/dict.go b/vendor/github.com/mmcloughlin/addchain/alg/dict/dict.go deleted file mode 100644 index 08a1fa0e0fe..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/alg/dict/dict.go +++ /dev/null @@ -1,434 +0,0 @@ -// Package dict implements dictionary and run-length addition chain algorithms. -package dict - -import ( - "errors" - "fmt" - "math/big" - "sort" - - "github.com/mmcloughlin/addchain" - "github.com/mmcloughlin/addchain/alg" - "github.com/mmcloughlin/addchain/internal/bigint" - "github.com/mmcloughlin/addchain/internal/bigints" - "github.com/mmcloughlin/addchain/internal/bigvector" -) - -// References: -// -// [braueraddsubchains] Martin Otto. Brauer addition-subtraction chains. PhD thesis, Universitat -// Paderborn. 2001. -// http://www.martin-otto.de/publications/docs/2001_MartinOtto_Diplom_BrauerAddition-SubtractionChains.pdf -// [genshortchains] Kunihiro, Noboru and Yamamoto, Hirosuke. New Methods for Generating Short -// Addition Chains. IEICE Transactions on Fundamentals of Electronics -// Communications and Computer Sciences. 2000. -// https://pdfs.semanticscholar.org/b398/d10faca35af9ce5a6026458b251fd0a5640c.pdf -// [hehcc:exp] Christophe Doche. Exponentiation. Handbook of Elliptic and Hyperelliptic Curve -// Cryptography, chapter 9. 2006. -// http://koclab.cs.ucsb.edu/teaching/ecc/eccPapers/Doche-ch09.pdf - -// Term represents the integer D * 2ᴱ. -type Term struct { - D *big.Int - E uint -} - -// Int converts the term to an integer. -func (t Term) Int() *big.Int { - return new(big.Int).Lsh(t.D, t.E) -} - -// Sum is the representation of an integer as a sum of dictionary terms. See -// [hehcc:exp] definition 9.34. -type Sum []Term - -// Int computes the dictionary sum as an integer. -func (s Sum) Int() *big.Int { - x := bigint.Zero() - for _, t := range s { - x.Add(x, t.Int()) - } - return x -} - -// SortByExponent sorts terms in ascending order of the exponent E. -func (s Sum) SortByExponent() { - sort.Slice(s, func(i, j int) bool { return s[i].E < s[j].E }) -} - -// Dictionary returns the distinct D values in the terms of this sum. The values -// are returned in ascending order. -func (s Sum) Dictionary() []*big.Int { - dict := make([]*big.Int, 0, len(s)) - for _, t := range s { - dict = append(dict, t.D) - } - bigints.Sort(dict) - return bigints.Unique(dict) -} - -// Decomposer is a method of breaking an integer into a dictionary sum. -type Decomposer interface { - Decompose(x *big.Int) Sum - String() string -} - -// FixedWindow breaks integers into k-bit windows. -type FixedWindow struct { - K uint // Window size. -} - -func (w FixedWindow) String() string { return fmt.Sprintf("fixed_window(%d)", w.K) } - -// Decompose represents x in terms of k-bit windows from left to right. -func (w FixedWindow) Decompose(x *big.Int) Sum { - sum := Sum{} - h := x.BitLen() - for h > 0 { - l := max(h-int(w.K), 0) - d := bigint.Extract(x, uint(l), uint(h)) - if bigint.IsNonZero(d) { - sum = append(sum, Term{D: d, E: uint(l)}) - } - h = l - } - sum.SortByExponent() - return sum -} - -// SlidingWindow breaks integers into k-bit windows, skipping runs of zeros -// where possible. See [hehcc:exp] section 9.1.3 or [braueraddsubchains] section -// 1.2.3. -type SlidingWindow struct { - K uint // Window size. -} - -func (w SlidingWindow) String() string { return fmt.Sprintf("sliding_window(%d)", w.K) } - -// Decompose represents x in base 2ᵏ. -func (w SlidingWindow) Decompose(x *big.Int) Sum { - sum := Sum{} - h := x.BitLen() - 1 - for h >= 0 { - // Find first 1. - for h >= 0 && x.Bit(h) == 0 { - h-- - } - - if h < 0 { - break - } - - // Look down k positions. - l := max(h-int(w.K)+1, 0) - - // Advance to the next 1. - for x.Bit(l) == 0 { - l++ - } - - sum = append(sum, Term{ - D: bigint.Extract(x, uint(l), uint(h+1)), - E: uint(l), - }) - - h = l - 1 - } - sum.SortByExponent() - return sum -} - -// RunLength decomposes integers in to runs of 1s up to a maximal length. See -// [genshortchains] Section 3.1. -type RunLength struct { - T uint // Maximal run length. Zero means no limit. -} - -func (r RunLength) String() string { return fmt.Sprintf("run_length(%d)", r.T) } - -// Decompose breaks x into runs of 1 bits. -func (r RunLength) Decompose(x *big.Int) Sum { - sum := Sum{} - i := x.BitLen() - 1 - for i >= 0 { - // Find first 1. - for i >= 0 && x.Bit(i) == 0 { - i-- - } - - if i < 0 { - break - } - - // Look for the end of the run. - s := i - for i >= 0 && x.Bit(i) == 1 && (r.T == 0 || uint(s-i) < r.T) { - i-- - } - - // We have a run from s to i+1. - sum = append(sum, Term{ - D: bigint.Ones(uint(s - i)), - E: uint(i + 1), - }) - } - sum.SortByExponent() - return sum -} - -// Hybrid is a mix of the sliding window and run length decomposition methods, -// similar to the "Hybrid Method" of [genshortchains] Section 3.3. -type Hybrid struct { - K uint // Window size. - T uint // Maximal run length. Zero means no limit. -} - -func (h Hybrid) String() string { return fmt.Sprintf("hybrid(%d,%d)", h.K, h.T) } - -// Decompose breaks x into k-bit sliding windows or runs of 1s up to length T. -func (h Hybrid) Decompose(x *big.Int) Sum { - sum := Sum{} - - // Clone since we'll be modifying it. - y := bigint.Clone(x) - - // Process runs of length at least K. - i := y.BitLen() - 1 - for i >= 0 { - // Find first 1. - for i >= 0 && y.Bit(i) == 0 { - i-- - } - - if i < 0 { - break - } - - // Look for the end of the run. - s := i - for i >= 0 && y.Bit(i) == 1 && (h.T == 0 || uint(s-i) < h.T) { - i-- - } - - // We have a run from s to i+1. Skip it if its short. - n := uint(s - i) - if n <= h.K { - continue - } - - // Add it to the sum and remove it from the integer. - sum = append(sum, Term{ - D: bigint.Ones(n), - E: uint(i + 1), - }) - - y.Xor(y, bigint.Mask(uint(i+1), uint(s+1))) - } - - // Process what remains with a sliding window. - w := SlidingWindow{K: h.K} - rem := w.Decompose(y) - - sum = append(sum, rem...) - sum.SortByExponent() - - return sum -} - -// Algorithm implements a general dictionary-based chain construction algorithm, -// as in [braueraddsubchains] Algorithm 1.26. This operates in three stages: -// decompose the target into a sum of dictionray terms, use a sequence algorithm -// to generate the dictionary, then construct the target from the dictionary -// terms. -type Algorithm struct { - decomp Decomposer - seqalg alg.SequenceAlgorithm -} - -// NewAlgorithm builds a dictionary algorithm that breaks up integers using the -// decomposer d and uses the sequence algorithm s to generate dictionary -// entries. -func NewAlgorithm(d Decomposer, a alg.SequenceAlgorithm) *Algorithm { - return &Algorithm{ - decomp: d, - seqalg: a, - } -} - -func (a Algorithm) String() string { - return fmt.Sprintf("dictionary(%s,%s)", a.decomp, a.seqalg) -} - -// FindChain builds an addition chain producing n. This works by using the -// configured Decomposer to represent n as a sum of dictionary terms, then -// delegating to the SequenceAlgorithm to build a chain producing the -// dictionary, and finally using the dictionary terms to construct n. See -// [genshortchains] Section 2 for a full description. -func (a Algorithm) FindChain(n *big.Int) (addchain.Chain, error) { - // Decompose the target. - sum := a.decomp.Decompose(n) - sum.SortByExponent() - - // Extract dictionary. - dict := sum.Dictionary() - - // Use the sequence algorithm to produce a chain for each element of the dictionary. - c, err := a.seqalg.FindSequence(dict) - if err != nil { - return nil, err - } - - // Reduce. - sum, c, err = primitive(sum, c) - if err != nil { - return nil, err - } - - // Build chain for n out of the dictionary. - dc := dictsumchain(sum) - c = append(c, dc...) - bigints.Sort(c) - c = addchain.Chain(bigints.Unique(c)) - - return c, nil -} - -// dictsumchain builds a chain for the integer represented by sum, assuming that -// all the terms of the sum are already present. Therefore this is intended to -// be appended to a chain that already contains the dictionary terms. -func dictsumchain(sum Sum) addchain.Chain { - c := addchain.Chain{} - k := len(sum) - 1 - cur := bigint.Clone(sum[k].D) - for ; k > 0; k-- { - // Shift until the next exponent. - for i := sum[k].E; i > sum[k-1].E; i-- { - cur.Lsh(cur, 1) - c.AppendClone(cur) - } - - // Add in the dictionary term at this position. - cur.Add(cur, sum[k-1].D) - c.AppendClone(cur) - } - - for i := sum[0].E; i > 0; i-- { - cur.Lsh(cur, 1) - c.AppendClone(cur) - } - - return c -} - -// primitive removes terms from the dictionary that are only required once. -// -// The general structure of dictionary based algorithm is to decompose the -// target into a sum of dictionary terms, then create a chain for the -// dictionary, and then create the target from that. In a case where a -// dictionary term is only required once in the target, this can cause extra -// work. In such a case, we will spend operations on creating the dictionary -// term independently, and then later add it into the result. Since it is only -// needed once, we can effectively construct the dictionary term "on the fly" as -// we build up the final target. -// -// This function looks for such opportunities. If it finds them it will produce -// an alternative dictionary sum that replaces that term with a sum of smaller -// terms. -func primitive(sum Sum, c addchain.Chain) (Sum, addchain.Chain, error) { - // This optimization cannot apply if the sum has only one term. - if len(sum) == 1 { - return sum, c, nil - } - - n := len(c) - - // We'll need a mapping from chain elements to where they appear in the chain. - idx := map[string]int{} - for i, x := range c { - idx[x.String()] = i - } - - // Build program for the chain. - p, err := c.Program() - if err != nil { - return nil, nil, err - } - - // How many times is each index read during construction, and during its use in the dictionary chain. - reads := p.ReadCounts() - - for _, t := range sum { - i := idx[t.D.String()] - reads[i]++ - } - - // Now, the primitive dictionary elements are those that are read at least twice, and their dependencies. - deps := p.Dependencies() - primitive := make([]bool, n) - - for i, numreads := range reads { - if numreads < 2 { - continue - } - primitive[i] = true - for _, j := range bigint.BitsSet(deps[i]) { - primitive[j] = true - } - } - - // Express every position in the chain as a linear combination of dictionary - // terms that are used more than once. - vc := []bigvector.Vector{bigvector.NewBasis(n, 0)} - for i, op := range p { - var next bigvector.Vector - if primitive[i+1] { - next = bigvector.NewBasis(n, i+1) - } else { - next = bigvector.Add(vc[op.I], vc[op.J]) - } - vc = append(vc, next) - } - - // Now express the target sum in terms that are used more than once. - v := bigvector.New(n) - for _, t := range sum { - i := idx[t.D.String()] - v = bigvector.Add(v, bigvector.Lsh(vc[i], t.E)) - } - - // Rebuild this into a dictionary sum. - out := Sum{} - for i := 0; i < v.Len(); i++ { - for _, e := range bigint.BitsSet(v.Idx(i)) { - out = append(out, Term{ - D: c[i], - E: uint(e), - }) - } - } - - out.SortByExponent() - - // We should have not changed the sum. - if !bigint.Equal(out.Int(), sum.Int()) { - return nil, nil, errors.New("reconstruction does not match") - } - - // Prune any elements of the chain that are used only once. - pruned := addchain.Chain{} - for i, x := range c { - if primitive[i] { - pruned = append(pruned, x) - } - } - - return out, pruned, nil -} - -// max returns the maximum of a and b. -func max(a, b int) int { - if a > b { - return a - } - return b -} diff --git a/vendor/github.com/mmcloughlin/addchain/alg/dict/runs.go b/vendor/github.com/mmcloughlin/addchain/alg/dict/runs.go deleted file mode 100644 index 5277be47643..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/alg/dict/runs.go +++ /dev/null @@ -1,108 +0,0 @@ -package dict - -import ( - "errors" - "fmt" - "math/big" - - "github.com/mmcloughlin/addchain" - "github.com/mmcloughlin/addchain/alg" - "github.com/mmcloughlin/addchain/internal/bigint" - "github.com/mmcloughlin/addchain/internal/bigints" -) - -// RunsAlgorithm is a custom variant of the dictionary approach that decomposes -// a target into runs of ones. It leverages the observation that building a -// dictionary consisting of runs of 1s of lengths l₁, l₂, ..., l_k can itself -// be reduced to first finding an addition chain for the run lengths. Then from -// this chain we can build a chain for the runs themselves. -type RunsAlgorithm struct { - seqalg alg.SequenceAlgorithm -} - -// NewRunsAlgorithm constructs a RunsAlgorithm using the given sequence -// algorithm to generate addition sequences for run lengths. Note that since run -// lengths are far smaller than the integers themselves, this sequence algorithm -// does not need to be able to handle large integers. -func NewRunsAlgorithm(a alg.SequenceAlgorithm) *RunsAlgorithm { - return &RunsAlgorithm{ - seqalg: a, - } -} - -func (a RunsAlgorithm) String() string { - return fmt.Sprintf("runs(%s)", a.seqalg) -} - -// FindChain uses the run lengths method to find a chain for n. -func (a RunsAlgorithm) FindChain(n *big.Int) (addchain.Chain, error) { - // Find the runs in n. - d := RunLength{T: 0} - sum := d.Decompose(n) - runs := sum.Dictionary() - - // Treat the run lengths themselves as a sequence to be solved. - lengths := []*big.Int{} - for _, run := range runs { - length := int64(run.BitLen()) - lengths = append(lengths, big.NewInt(length)) - } - - // Delegate to the sequence algorithm for a solution. - lc, err := a.seqalg.FindSequence(lengths) - if err != nil { - return nil, err - } - - // Build a dictionary chain from this. - c, err := RunsChain(lc) - if err != nil { - return nil, err - } - - // Reduce. - sum, c, err = primitive(sum, c) - if err != nil { - return nil, err - } - - // Build chain for n out of the dictionary. - dc := dictsumchain(sum) - c = append(c, dc...) - bigints.Sort(c) - c = addchain.Chain(bigints.Unique(c)) - - return c, nil -} - -// RunsChain takes a chain for the run lengths and generates a chain for the -// runs themselves. That is, if the provided chain is l₁, l₂, ..., l_k then -// the result will contain r(l₁), r(l₂), ..., r(l_k) where r(n) = 2ⁿ - 1. -func RunsChain(lc addchain.Chain) (addchain.Chain, error) { - p, err := lc.Program() - if err != nil { - return nil, err - } - - c := addchain.New() - s := map[uint]uint{} // current largest shift of each run length - for _, op := range p { - a, b := bigint.MinMax(lc[op.I], lc[op.J]) - if !a.IsUint64() || !b.IsUint64() { - return nil, errors.New("values in lengths chain are far too large") - } - - la := uint(a.Uint64()) - lb := uint(b.Uint64()) - - rb := bigint.Ones(lb) - for ; s[lb] < la; s[lb]++ { - shift := new(big.Int).Lsh(rb, s[lb]+1) - c = append(c, shift) - } - - c = append(c, bigint.Ones(la+lb)) - } - - return c, nil -} diff --git a/vendor/github.com/mmcloughlin/addchain/alg/ensemble/ensemble.go b/vendor/github.com/mmcloughlin/addchain/alg/ensemble/ensemble.go deleted file mode 100644 index f84a2626753..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/alg/ensemble/ensemble.go +++ /dev/null @@ -1,71 +0,0 @@ -// Package ensemble provides a collection of addition chain algorithms intended -// for target integers of cryptographic interest. -package ensemble - -import ( - "github.com/mmcloughlin/addchain/alg" - "github.com/mmcloughlin/addchain/alg/contfrac" - "github.com/mmcloughlin/addchain/alg/dict" - "github.com/mmcloughlin/addchain/alg/heuristic" - "github.com/mmcloughlin/addchain/alg/opt" -) - -// Ensemble is a convenience for building an ensemble of chain algorithms intended for large integers. -func Ensemble() []alg.ChainAlgorithm { - // Choose sequence algorithms. - seqalgs := []alg.SequenceAlgorithm{ - heuristic.NewAlgorithm(heuristic.UseFirst( - heuristic.Halving{}, - heuristic.DeltaLargest{}, - )), - heuristic.NewAlgorithm(heuristic.UseFirst( - heuristic.Halving{}, - heuristic.Approximation{}, - )), - } - - for _, strategy := range contfrac.Strategies { - if strategy.Singleton() { - seqalgs = append(seqalgs, contfrac.NewAlgorithm(strategy)) - } - } - - // Build decomposers. - decomposers := []dict.Decomposer{} - for k := uint(4); k <= 128; k *= 2 { - decomposers = append(decomposers, dict.SlidingWindow{K: k}) - } - - decomposers = append(decomposers, dict.RunLength{T: 0}) - for t := uint(16); t <= 128; t *= 2 { - decomposers = append(decomposers, dict.RunLength{T: t}) - } - - for k := uint(2); k <= 8; k++ { - decomposers = append(decomposers, dict.Hybrid{K: k, T: 0}) - for t := uint(16); t <= 64; t *= 2 { - decomposers = append(decomposers, dict.Hybrid{K: k, T: t}) - } - } - - // Build dictionary algorithms for every combination. - as := []alg.ChainAlgorithm{} - for _, decomp := range decomposers { - for _, seqalg := range seqalgs { - a := dict.NewAlgorithm(decomp, seqalg) - as = append(as, a) - } - } - - // Add the runs algorithms. - for _, seqalg := range seqalgs { - as = append(as, dict.NewRunsAlgorithm(seqalg)) - } - - // Wrap in an optimization layer. - for i, a := range as { - as[i] = opt.Algorithm{Algorithm: a} - } - - return as -} diff --git a/vendor/github.com/mmcloughlin/addchain/alg/exec/exec.go b/vendor/github.com/mmcloughlin/addchain/alg/exec/exec.go deleted file mode 100644 index 731aa29e176..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/alg/exec/exec.go +++ /dev/null @@ -1,99 +0,0 @@ -// Package exec implements addition chain algorithm execution. -package exec - -import ( - "errors" - "io/ioutil" - "log" - "math/big" - "runtime" - - "github.com/mmcloughlin/addchain" - "github.com/mmcloughlin/addchain/alg" - "github.com/mmcloughlin/addchain/internal/bigint" -) - -// Result from applying an algorithm to a target. -type Result struct { - Target *big.Int - Algorithm alg.ChainAlgorithm - Err error - Chain addchain.Chain - Program addchain.Program -} - -// Execute the algorithm on the target number n. -func Execute(n *big.Int, a alg.ChainAlgorithm) Result { - r := Result{ - Target: n, - Algorithm: a, - } - - r.Chain, r.Err = a.FindChain(n) - if r.Err != nil { - return r - } - - // Note this also performs validation. - r.Program, r.Err = r.Chain.Program() - if r.Err != nil { - return r - } - - // Still, verify that it produced what we wanted. - if !bigint.Equal(r.Chain.End(), n) { - r.Err = errors.New("did not produce the required value") - } - - return r -} - -// Parallel executes multiple algorithms in parallel. -type Parallel struct { - limit int - logger *log.Logger -} - -// NewParallel builds a new parallel executor. -func NewParallel() *Parallel { - return &Parallel{ - limit: runtime.NumCPU(), - logger: log.New(ioutil.Discard, "", 0), - } -} - -// SetConcurrency sets the number of algorithms that may be run in parallel. -func (p *Parallel) SetConcurrency(limit int) { - p.limit = limit -} - -// SetLogger sets logging output. -func (p *Parallel) SetLogger(l *log.Logger) { - p.logger = l -} - -// Execute all algorithms against the provided target. -func (p Parallel) Execute(n *big.Int, as []alg.ChainAlgorithm) []Result { - rs := make([]Result, len(as)) - - // Use buffered channel to limit concurrency. - type token struct{} - sem := make(chan token, p.limit) - - for i, a := range as { - sem <- token{} - go func(i int, a alg.ChainAlgorithm) { - p.logger.Printf("start: %s", a) - rs[i] = Execute(n, a) - p.logger.Printf("done: %s", a) - <-sem - }(i, a) - } - - // Wait for completion. - for i := 0; i < p.limit; i++ { - sem <- token{} - } - - return rs -} diff --git a/vendor/github.com/mmcloughlin/addchain/alg/heuristic/heuristic.go b/vendor/github.com/mmcloughlin/addchain/alg/heuristic/heuristic.go deleted file mode 100644 index 94abb6400a6..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/alg/heuristic/heuristic.go +++ /dev/null @@ -1,234 +0,0 @@ -// Package heuristic implements heuristic-based addition sequence algorithms -// with the Bos-Coster Makesequence structure. -package heuristic - -import ( - "errors" - "fmt" - "math/big" - "strings" - - "github.com/mmcloughlin/addchain" - "github.com/mmcloughlin/addchain/internal/bigint" - "github.com/mmcloughlin/addchain/internal/bigints" -) - -// References: -// -// [boscoster] Bos, Jurjen and Coster, Matthijs. Addition Chain Heuristics. In Advances in -// Cryptology --- CRYPTO' 89 Proceedings, pages 400--407. 1990. -// https://link.springer.com/content/pdf/10.1007/0-387-34805-0_37.pdf -// [github:kwantam/addchain] Riad S. Wahby. kwantam/addchain. Github Repository. Apache License, Version 2.0. -// 2018. https://github.com/kwantam/addchain -// [hehcc:exp] Christophe Doche. Exponentiation. Handbook of Elliptic and Hyperelliptic Curve -// Cryptography, chapter 9. 2006. -// http://koclab.cs.ucsb.edu/teaching/ecc/eccPapers/Doche-ch09.pdf -// [modboscoster] Ayan Nandy. Modifications of Bos and Coster’s Heuristics in search of a -// shorter addition chain for faster exponentiation. Masters thesis, Indian -// Statistical Institute Kolkata. 2011. -// http://library.isical.ac.in:8080/jspui/bitstream/10263/6441/1/DISS-285.pdf -// [mpnt] F. L. Ţiplea, S. Iftene, C. Hriţcu, I. Goriac, R. Gordân and E. Erbiceanu. -// MpNT: A Multi-Precision Number Theory Package, Number Theoretical Algorithms -// (I). Technical Report TR03-02, Faculty of Computer Science, "Alexandru Ioan -// Cuza" University, Iasi. 2003. https://profs.info.uaic.ro/~tr/tr03-02.pdf -// [speedsubgroup] Stam, Martijn. Speeding up subgroup cryptosystems. PhD thesis, Technische -// Universiteit Eindhoven. 2003. https://cr.yp.to/bib/2003/stam-thesis.pdf - -// Heuristic suggests insertions given a current protosequence. -type Heuristic interface { - // Suggest insertions given a target and protosequence f. Protosequence must - // contain sorted distinct integers. - Suggest(f []*big.Int, target *big.Int) []*big.Int - - // String returns a name for the heuristic. - String() string -} - -// Algorithm searches for an addition sequence using a heuristic at each step. -// This implements the framework given in [mpnt], page 63, with the heuristic -// playing the role of the "newnumbers" function. -type Algorithm struct { - heuristic Heuristic -} - -// NewAlgorithm builds a heuristic algorithm. -func NewAlgorithm(h Heuristic) *Algorithm { - return &Algorithm{ - heuristic: h, - } -} - -func (h Algorithm) String() string { - return fmt.Sprintf("heuristic(%v)", h.heuristic) -} - -// FindSequence searches for an addition sequence for the given targets. -func (h Algorithm) FindSequence(targets []*big.Int) (addchain.Chain, error) { - // Skip the special case when targets is just {1}. - if len(targets) == 1 && bigint.EqualInt64(targets[0], 1) { - return targets, nil - } - - // Initialize protosequence. - leader := bigints.Int64s(1, 2) - proto := append(leader, targets...) - bigints.Sort(proto) - proto = bigints.Unique(proto) - c := []*big.Int{} - - for len(proto) > 2 { - // Pop the target element. - top := len(proto) - 1 - target := proto[top] - proto = proto[:top] - c = bigints.InsertSortedUnique(c, target) - - // Apply heuristic. - insert := h.heuristic.Suggest(proto, target) - if insert == nil { - return nil, errors.New("failed to find sequence") - } - - // Update protosequence. - proto = bigints.MergeUnique(proto, insert) - } - - // Prepare the chain to return. - c = bigints.MergeUnique(leader, c) - - return addchain.Chain(c), nil -} - -// DeltaLargest implements the simple heuristic of adding the delta between the -// largest two entries in the protosequence. -type DeltaLargest struct{} - -func (DeltaLargest) String() string { return "delta_largest" } - -// Suggest proposes inserting target-max(f). -func (DeltaLargest) Suggest(f []*big.Int, target *big.Int) []*big.Int { - n := len(f) - delta := new(big.Int).Sub(target, f[n-1]) - if delta.Sign() <= 0 { - panic("delta must be positive") - } - return []*big.Int{delta} -} - -// Approximation is the "Approximation" heuristic from [boscoster]. -type Approximation struct{} - -func (Approximation) String() string { return "approximation" } - -// Suggest applies the "Approximation" heuristic. This heuristic looks for two -// elements a, b in the list that sum to something close to the target element -// f. That is, we look for f-(a+b) = epsilon where a ⩽ b and epsilon is a -// "small" positive value. -func (Approximation) Suggest(f []*big.Int, target *big.Int) []*big.Int { - delta := new(big.Int) - insert := new(big.Int) - mindelta := new(big.Int) - best := new(big.Int) - first := true - - // Leverage the fact that f contains sorted distinct integers to apply a - // linear algorithm, similar to the 2-SUM problem. Maintain left and right - // pointers and adjust them based on whether the sum is above or below the - // target. - for l, r := 0, len(f)-1; l <= r; { - a, b := f[l], f[r] - - // Compute the delta f-(a+b). - delta.Add(a, b) - delta.Sub(target, delta) - if delta.Sign() < 0 { - // Sum exceeds target, decrement r for smaller b value. - r-- - continue - } - - // Proposed insertion is a+delta. - insert.Add(a, delta) - - // If it's actually in the sequence already, use it. - if bigints.ContainsSorted(insert, f) { - return []*big.Int{insert} - } - - // Keep it if its the closest we've seen. - if first || delta.Cmp(mindelta) < 0 { - mindelta.Set(delta) - best.Set(insert) - first = false - } - - // Advance to next a value. - l++ - } - - return []*big.Int{best} -} - -// Halving is the "Halving" heuristic from [boscoster]. -type Halving struct{} - -func (Halving) String() string { return "halving" } - -// Suggest applies when the target is at least twice as big as the next largest. -// If so it will return a sequence of doublings to insert. Otherwise it will -// return nil. -func (Halving) Suggest(f []*big.Int, target *big.Int) []*big.Int { - n := len(f) - max, next := target, f[n-1] - - // Check the condition f / f₁ ⩾ 2ᵘ - r := new(big.Int).Div(max, next) - if r.BitLen() < 2 { - return nil - } - u := r.BitLen() - 1 - - // Compute k = floor( f / 2ᵘ ). - k := new(big.Int).Rsh(max, uint(u)) - - // Proposal to insert: - // Delta d = f - k*2ᵘ - // Sequence k, 2*k, ..., k*2ᵘ - kshifts := []*big.Int{} - for e := 0; e <= u; e++ { - kshift := new(big.Int).Lsh(k, uint(e)) - kshifts = append(kshifts, kshift) - } - d := new(big.Int).Sub(max, kshifts[u]) - if bigint.IsZero(d) { - return kshifts[:u] - } - - return bigints.InsertSortedUnique(kshifts, d) -} - -// UseFirst builds a compositite heuristic that will make the first non-nil -// suggestion from the sub-heuristics. -func UseFirst(heuristics ...Heuristic) Heuristic { - return useFirst(heuristics) -} - -type useFirst []Heuristic - -func (h useFirst) String() string { - names := []string{} - for _, sub := range h { - names = append(names, sub.String()) - } - return "use_first(" + strings.Join(names, ",") + ")" -} - -// Suggest delegates to each sub-heuristic in turn and returns the first non-nil suggestion. -func (h useFirst) Suggest(f []*big.Int, target *big.Int) []*big.Int { - for _, heuristic := range h { - if insert := heuristic.Suggest(f, target); insert != nil { - return insert - } - } - return nil -} diff --git a/vendor/github.com/mmcloughlin/addchain/alg/opt/opt.go b/vendor/github.com/mmcloughlin/addchain/alg/opt/opt.go deleted file mode 100644 index bf28cb9062a..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/alg/opt/opt.go +++ /dev/null @@ -1,101 +0,0 @@ -// Package opt implements generic optimizations that remove redundancy from addition chains. -package opt - -import ( - "fmt" - "math/big" - - "github.com/mmcloughlin/addchain" - "github.com/mmcloughlin/addchain/alg" -) - -// Algorithm applies chain optimization to the result of a wrapped algorithm. -type Algorithm struct { - Algorithm alg.ChainAlgorithm -} - -func (a Algorithm) String() string { - return fmt.Sprintf("opt(%s)", a.Algorithm) -} - -// FindChain delegates to the wrapped algorithm, then runs Optimize on the result. -func (a Algorithm) FindChain(n *big.Int) (addchain.Chain, error) { - c, err := a.Algorithm.FindChain(n) - if err != nil { - return nil, err - } - - opt, err := Optimize(c) - if err != nil { - return nil, err - } - - return opt, nil -} - -// Optimize aims to remove redundancy from an addition chain. -func Optimize(c addchain.Chain) (addchain.Chain, error) { - // Build program for c with all possible options at each step. - ops := make([][]addchain.Op, len(c)) - for k := 1; k < len(c); k++ { - ops[k] = c.Ops(k) - } - - // Count how many times each index is used where it is the only available Op. - counts := make([]int, len(c)) - for k := 1; k < len(c); k++ { - if len(ops[k]) != 1 { - continue - } - for _, i := range ops[k][0].Operands() { - counts[i]++ - } - } - - // Now, try to remove the positions which are never the only available op. - remove := []int{} - for k := 1; k < len(c)-1; k++ { - if counts[k] > 0 { - continue - } - - // Prune places k is used. - for l := k + 1; l < len(c); l++ { - ops[l] = pruneuses(ops[l], k) - - // If this list now only has one element, the operands in it are now - // indispensable. - if len(ops[l]) == 1 { - for _, i := range ops[l][0].Operands() { - counts[i]++ - } - } - } - - // Mark k for deletion. - remove = append(remove, k) - } - - // Perform removals. - pruned := addchain.Chain{} - for i, x := range c { - if len(remove) > 0 && remove[0] == i { - remove = remove[1:] - continue - } - pruned = append(pruned, x) - } - - return pruned, nil -} - -// pruneuses removes any uses of i from the list of operations. -func pruneuses(ops []addchain.Op, i int) []addchain.Op { - filtered := ops[:0] - for _, op := range ops { - if !op.Uses(i) { - filtered = append(filtered, op) - } - } - return filtered -} diff --git a/vendor/github.com/mmcloughlin/addchain/chain.go b/vendor/github.com/mmcloughlin/addchain/chain.go deleted file mode 100644 index 3d41657ebc0..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/chain.go +++ /dev/null @@ -1,194 +0,0 @@ -// Package addchain provides addition chain types and operations on them. -package addchain - -import ( - "errors" - "fmt" - "math/big" - - "github.com/mmcloughlin/addchain/internal/bigint" - "github.com/mmcloughlin/addchain/internal/bigints" -) - -// References: -// -// [efficientcompaddchain] Bergeron, F., Berstel, J. and Brlek, S. Efficient computation of addition -// chains. Journal de theorie des nombres de Bordeaux. 1994. -// http://www.numdam.org/item/JTNB_1994__6_1_21_0 -// [knuth] Knuth, Donald E. Evaluation of Powers. The Art of Computer Programming, Volume 2 -// (Third Edition): Seminumerical Algorithms, chapter 4.6.3. 1997. -// https://www-cs-faculty.stanford.edu/~knuth/taocp.html - -// Chain is an addition chain. -type Chain []*big.Int - -// New constructs the minimal chain {1}. -func New() Chain { - return Chain{big.NewInt(1)} -} - -// Int64s builds a chain from the given int64 values. -func Int64s(xs ...int64) Chain { - return Chain(bigints.Int64s(xs...)) -} - -// Clone the chain. -func (c Chain) Clone() Chain { - return bigints.Clone(c) -} - -// AppendClone appends a copy of x to c. -func (c *Chain) AppendClone(x *big.Int) { - *c = append(*c, bigint.Clone(x)) -} - -// End returns the last element of the chain. -func (c Chain) End() *big.Int { - return c[len(c)-1] -} - -// Ops returns all operations that produce the kth position. This could be empty -// for an invalid chain. -func (c Chain) Ops(k int) []Op { - ops := []Op{} - s := new(big.Int) - - // If the prefix is ascending this can be done in linear time. - if c[:k].IsAscending() { - for l, r := 0, k-1; l <= r; { - s.Add(c[l], c[r]) - cmp := s.Cmp(c[k]) - if cmp == 0 { - ops = append(ops, Op{l, r}) - } - if cmp <= 0 { - l++ - } else { - r-- - } - } - return ops - } - - // Fallback to quadratic. - for i := 0; i < k; i++ { - for j := i; j < k; j++ { - s.Add(c[i], c[j]) - if s.Cmp(c[k]) == 0 { - ops = append(ops, Op{i, j}) - } - } - } - - return ops -} - -// Op returns an Op that produces the kth position. -func (c Chain) Op(k int) (Op, error) { - ops := c.Ops(k) - if len(ops) == 0 { - return Op{}, fmt.Errorf("position %d is not the sum of previous entries", k) - } - return ops[0], nil -} - -// Program produces a program that generates the chain. -func (c Chain) Program() (Program, error) { - // Sanity checks. - if len(c) == 0 { - return nil, errors.New("chain empty") - } - - if c[0].Cmp(big.NewInt(1)) != 0 { - return nil, errors.New("chain must start with 1") - } - - if bigints.Contains(bigint.Zero(), c) { - return nil, errors.New("chain contains zero") - } - - for i := 0; i < len(c); i++ { - for j := i + 1; j < len(c); j++ { - if bigint.Equal(c[i], c[j]) { - return nil, fmt.Errorf("chain contains duplicate: %v at positions %d and %d", c[i], i, j) - } - } - } - - // Produce the program. - p := Program{} - for k := 1; k < len(c); k++ { - op, err := c.Op(k) - if err != nil { - return nil, err - } - p = append(p, op) - } - - return p, nil -} - -// Validate checks that c is in fact an addition chain. -func (c Chain) Validate() error { - _, err := c.Program() - return err -} - -// Produces checks that c is a valid chain ending with target. -func (c Chain) Produces(target *big.Int) error { - if err := c.Validate(); err != nil { - return err - } - if c.End().Cmp(target) != 0 { - return errors.New("chain does not end with target") - } - return nil -} - -// Superset checks that c is a valid chain containing all the targets. -func (c Chain) Superset(targets []*big.Int) error { - if err := c.Validate(); err != nil { - return err - } - for _, target := range targets { - if !bigints.Contains(target, c) { - return fmt.Errorf("chain does not contain %v", target) - } - } - return nil -} - -// IsAscending reports whether the chain is ascending, that is if it's in sorted -// order without repeats, as defined in [knuth] Section 4.6.3 formula (11). -// Does not fully validate the chain, only that it is ascending. -func (c Chain) IsAscending() bool { - if len(c) == 0 || !bigint.EqualInt64(c[0], 1) { - return false - } - for i := 1; i < len(c); i++ { - if c[i-1].Cmp(c[i]) >= 0 { - return false - } - } - return true -} - -// Product computes the product of two addition chains. The is the "o times" -// operator defined in [efficientcompaddchain] Section 2. -func Product(a, b Chain) Chain { - c := a.Clone() - last := c.End() - for _, x := range b[1:] { - y := new(big.Int).Mul(last, x) - c = append(c, y) - } - return c -} - -// Plus adds x to the addition chain. This is the "o plus" operator defined in -// [efficientcompaddchain] Section 2. -func Plus(a Chain, x *big.Int) Chain { - c := a.Clone() - y := new(big.Int).Add(c.End(), x) - return append(c, y) -} diff --git a/vendor/github.com/mmcloughlin/addchain/codecov.yml b/vendor/github.com/mmcloughlin/addchain/codecov.yml deleted file mode 100644 index 35cde5cd5e8..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/codecov.yml +++ /dev/null @@ -1,4 +0,0 @@ -coverage: - status: - project: off - patch: off diff --git a/vendor/github.com/mmcloughlin/addchain/install.sh b/vendor/github.com/mmcloughlin/addchain/install.sh deleted file mode 100644 index 6ea84cbc9e9..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/install.sh +++ /dev/null @@ -1,378 +0,0 @@ -#!/bin/sh -set -e -# Code generated by godownloader. DO NOT EDIT. -# - -usage() { - this=$1 - cat </dev/null -} -echoerr() { - echo "$@" 1>&2 -} -log_prefix() { - echo "$0" -} -_logp=6 -log_set_priority() { - _logp="$1" -} -log_priority() { - if test -z "$1"; then - echo "$_logp" - return - fi - [ "$1" -le "$_logp" ] -} -log_tag() { - case $1 in - 0) echo "emerg" ;; - 1) echo "alert" ;; - 2) echo "crit" ;; - 3) echo "err" ;; - 4) echo "warning" ;; - 5) echo "notice" ;; - 6) echo "info" ;; - 7) echo "debug" ;; - *) echo "$1" ;; - esac -} -log_debug() { - log_priority 7 || return 0 - echoerr "$(log_prefix)" "$(log_tag 7)" "$@" -} -log_info() { - log_priority 6 || return 0 - echoerr "$(log_prefix)" "$(log_tag 6)" "$@" -} -log_err() { - log_priority 3 || return 0 - echoerr "$(log_prefix)" "$(log_tag 3)" "$@" -} -log_crit() { - log_priority 2 || return 0 - echoerr "$(log_prefix)" "$(log_tag 2)" "$@" -} -uname_os() { - os=$(uname -s | tr '[:upper:]' '[:lower:]') - case "$os" in - cygwin_nt*) os="windows" ;; - mingw*) os="windows" ;; - msys_nt*) os="windows" ;; - esac - echo "$os" -} -uname_arch() { - arch=$(uname -m) - case $arch in - x86_64) arch="amd64" ;; - x86) arch="386" ;; - i686) arch="386" ;; - i386) arch="386" ;; - aarch64) arch="arm64" ;; - armv5*) arch="armv5" ;; - armv6*) arch="armv6" ;; - armv7*) arch="armv7" ;; - esac - echo ${arch} -} -uname_os_check() { - os=$(uname_os) - case "$os" in - darwin) return 0 ;; - dragonfly) return 0 ;; - freebsd) return 0 ;; - linux) return 0 ;; - android) return 0 ;; - nacl) return 0 ;; - netbsd) return 0 ;; - openbsd) return 0 ;; - plan9) return 0 ;; - solaris) return 0 ;; - windows) return 0 ;; - esac - log_crit "uname_os_check '$(uname -s)' got converted to '$os' which is not a GOOS value. Please file bug at https://github.com/client9/shlib" - return 1 -} -uname_arch_check() { - arch=$(uname_arch) - case "$arch" in - 386) return 0 ;; - amd64) return 0 ;; - arm64) return 0 ;; - armv5) return 0 ;; - armv6) return 0 ;; - armv7) return 0 ;; - ppc64) return 0 ;; - ppc64le) return 0 ;; - mips) return 0 ;; - mipsle) return 0 ;; - mips64) return 0 ;; - mips64le) return 0 ;; - s390x) return 0 ;; - amd64p32) return 0 ;; - esac - log_crit "uname_arch_check '$(uname -m)' got converted to '$arch' which is not a GOARCH value. Please file bug report at https://github.com/client9/shlib" - return 1 -} -untar() { - tarball=$1 - case "${tarball}" in - *.tar.gz | *.tgz) tar --no-same-owner -xzf "${tarball}" ;; - *.tar) tar --no-same-owner -xf "${tarball}" ;; - *.zip) unzip "${tarball}" ;; - *) - log_err "untar unknown archive format for ${tarball}" - return 1 - ;; - esac -} -http_download_curl() { - local_file=$1 - source_url=$2 - header=$3 - if [ -z "$header" ]; then - code=$(curl -w '%{http_code}' -sL -o "$local_file" "$source_url") - else - code=$(curl -w '%{http_code}' -sL -H "$header" -o "$local_file" "$source_url") - fi - if [ "$code" != "200" ]; then - log_debug "http_download_curl received HTTP status $code" - return 1 - fi - return 0 -} -http_download_wget() { - local_file=$1 - source_url=$2 - header=$3 - if [ -z "$header" ]; then - wget -q -O "$local_file" "$source_url" - else - wget -q --header "$header" -O "$local_file" "$source_url" - fi -} -http_download() { - log_debug "http_download $2" - if is_command curl; then - http_download_curl "$@" - return - elif is_command wget; then - http_download_wget "$@" - return - fi - log_crit "http_download unable to find wget or curl" - return 1 -} -http_copy() { - tmp=$(mktemp) - http_download "${tmp}" "$1" "$2" || return 1 - body=$(cat "$tmp") - rm -f "${tmp}" - echo "$body" -} -github_release() { - owner_repo=$1 - version=$2 - test -z "$version" && version="latest" - giturl="https://github.com/${owner_repo}/releases/${version}" - json=$(http_copy "$giturl" "Accept:application/json") - test -z "$json" && return 1 - version=$(echo "$json" | tr -s '\n' ' ' | sed 's/.*"tag_name":"//' | sed 's/".*//') - test -z "$version" && return 1 - echo "$version" -} -hash_sha256() { - TARGET=${1:-/dev/stdin} - if is_command gsha256sum; then - hash=$(gsha256sum "$TARGET") || return 1 - echo "$hash" | cut -d ' ' -f 1 - elif is_command sha256sum; then - hash=$(sha256sum "$TARGET") || return 1 - echo "$hash" | cut -d ' ' -f 1 - elif is_command shasum; then - hash=$(shasum -a 256 "$TARGET" 2>/dev/null) || return 1 - echo "$hash" | cut -d ' ' -f 1 - elif is_command openssl; then - hash=$(openssl -dst openssl dgst -sha256 "$TARGET") || return 1 - echo "$hash" | cut -d ' ' -f a - else - log_crit "hash_sha256 unable to find command to compute sha-256 hash" - return 1 - fi -} -hash_sha256_verify() { - TARGET=$1 - checksums=$2 - if [ -z "$checksums" ]; then - log_err "hash_sha256_verify checksum file not specified in arg2" - return 1 - fi - BASENAME=${TARGET##*/} - want=$(grep "${BASENAME}" "${checksums}" 2>/dev/null | tr '\t' ' ' | cut -d ' ' -f 1) - if [ -z "$want" ]; then - log_err "hash_sha256_verify unable to find checksum for '${TARGET}' in '${checksums}'" - return 1 - fi - got=$(hash_sha256 "$TARGET") - if [ "$want" != "$got" ]; then - log_err "hash_sha256_verify checksum for '$TARGET' did not verify ${want} vs $got" - return 1 - fi -} -cat /dev/null <= 0 -} - -// ContainsSorted reports whether n is in xs, which is assumed to be sorted. -func ContainsSorted(n *big.Int, xs []*big.Int) bool { - i := sort.Search(len(xs), func(i int) bool { return xs[i].Cmp(n) >= 0 }) - return i < len(xs) && bigint.Equal(xs[i], n) -} - -// Clone a list of integers. -func Clone(xs []*big.Int) []*big.Int { - return append([]*big.Int{}, xs...) -} - -// Unique removes consecutive duplicates. -func Unique(xs []*big.Int) []*big.Int { - if len(xs) == 0 { - return []*big.Int{} - } - u := make([]*big.Int, 1, len(xs)) - u[0] = xs[0] - for _, x := range xs[1:] { - last := u[len(u)-1] - if !bigint.Equal(x, last) { - u = append(u, x) - } - } - return u -} - -// InsertSortedUnique inserts an integer into a slice of sorted distinct -// integers. -func InsertSortedUnique(xs []*big.Int, x *big.Int) []*big.Int { - return MergeUnique([]*big.Int{x}, xs) -} - -// MergeUnique merges two slices of sorted distinct integers. Elements in both -// slices are deduplicated. -func MergeUnique(xs, ys []*big.Int) []*big.Int { - r := make([]*big.Int, 0, len(xs)+len(ys)) - - for len(xs) > 0 && len(ys) > 0 { - switch xs[0].Cmp(ys[0]) { - case -1: - r = append(r, xs[0]) - xs = xs[1:] - case 0: - r = append(r, xs[0]) - xs = xs[1:] - ys = ys[1:] - case 1: - r = append(r, ys[0]) - ys = ys[1:] - } - } - - r = append(r, xs...) - r = append(r, ys...) - - return r -} diff --git a/vendor/github.com/mmcloughlin/addchain/internal/bigvector/bigvector.go b/vendor/github.com/mmcloughlin/addchain/internal/bigvector/bigvector.go deleted file mode 100644 index bac75bd5f8c..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/internal/bigvector/bigvector.go +++ /dev/null @@ -1,86 +0,0 @@ -// Package bigvector implements operations on vectors of immutable -// multi-precision integers. -package bigvector - -import ( - "math/big" - - "github.com/mmcloughlin/addchain/internal/bigint" -) - -// Vector of immutable multi-precision integers. -type Vector interface { - // Len returns vector length. - Len() int - - // Idx returns integer at index i. Returned integer must not be written to. - Idx(i int) *big.Int -} - -// New constructs an n-dimensional zero vector. -func New(n int) Vector { - return make(vector, n) -} - -type vector []big.Int - -func (v vector) Len() int { return len(v) } -func (v vector) Idx(i int) *big.Int { return &v[i] } - -// NewBasis constructs an n-dimensional basis vector with a 1 in position i. -func NewBasis(n, i int) Vector { - return basis{n: n, i: i} -} - -// Basis implementation saves allocations by returning pre-allocated zero and -// one integers based on the index requested. -var ( - zero = bigint.Zero() - one = bigint.One() -) - -type basis struct { - n int - i int -} - -func (b basis) Len() int { return b.n } - -func (b basis) Idx(i int) *big.Int { - switch { - case i >= b.n: - panic("bigvector: index out of range") - case i == b.i: - return one - default: - return zero - } -} - -// Add vectors. -func Add(u, v Vector) Vector { - assertsamelen(u, v) - n := u.Len() - w := make(vector, n) - for i := 0; i < n; i++ { - w[i].Add(u.Idx(i), v.Idx(i)) - } - return w -} - -// Lsh left shifts every element of the vector v. -func Lsh(v Vector, s uint) Vector { - n := v.Len() - w := make(vector, n) - for i := 0; i < n; i++ { - w[i].Lsh(v.Idx(i), s) - } - return w -} - -// assertsamelen panics if u and v are different lengths. -func assertsamelen(u, v Vector) { - if u.Len() != v.Len() { - panic("bigvector: length mismatch") - } -} diff --git a/vendor/github.com/mmcloughlin/addchain/internal/container/heap/heap.go b/vendor/github.com/mmcloughlin/addchain/internal/container/heap/heap.go deleted file mode 100644 index 9d396f50e28..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/internal/container/heap/heap.go +++ /dev/null @@ -1,55 +0,0 @@ -// Package heap implements a heap on specific types. -package heap - -import "container/heap" - -// MinInts is a min-heap of integers. -type MinInts struct { - h *intheap -} - -// NewMinInts builds an empty integer min-heap. -func NewMinInts() *MinInts { - return &MinInts{ - h: &intheap{}, - } -} - -// Empty returns whether the heap is empty. -func (h *MinInts) Empty() bool { - return h.Len() == 0 -} - -// Len returns the number of elements in the heap. -func (h *MinInts) Len() int { - return h.h.Len() -} - -// Push x onto the heap. -func (h *MinInts) Push(x int) { - heap.Push(h.h, x) -} - -// Pop the min element from the heap. -func (h *MinInts) Pop() int { - return heap.Pop(h.h).(int) -} - -type intheap struct { - x []int -} - -func (h intheap) Len() int { return len(h.x) } -func (h intheap) Less(i, j int) bool { return h.x[i] < h.x[j] } -func (h intheap) Swap(i, j int) { h.x[i], h.x[j] = h.x[j], h.x[i] } - -func (h *intheap) Push(x interface{}) { - h.x = append(h.x, x.(int)) -} - -func (h *intheap) Pop() interface{} { - n := len(h.x) - x := h.x[n-1] - h.x = h.x[:n-1] - return x -} diff --git a/vendor/github.com/mmcloughlin/addchain/internal/errutil/errutil.go b/vendor/github.com/mmcloughlin/addchain/internal/errutil/errutil.go deleted file mode 100644 index 364724118ce..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/internal/errutil/errutil.go +++ /dev/null @@ -1,28 +0,0 @@ -// Package errutil implements common error types and helper functions. -package errutil - -import ( - "fmt" - "io" -) - -// AssertionFailure is used for an error resulting from the failure of an -// expected invariant. -func AssertionFailure(format string, args ...interface{}) error { - return fmt.Errorf("assertion failure: "+format, args...) -} - -// UnexpectedType builds an error for an unexpected type, typically in a type switch. -func UnexpectedType(t interface{}) error { - return AssertionFailure("unexpected type %T", t) -} - -// CheckClose closes c. If an error occurs it will be written to the error -// pointer errp, if it doesn't already reference an error. This is intended to -// allow you to properly check errors when defering a close call. In this case -// the error pointer should be the address of a named error return. -func CheckClose(errp *error, c io.Closer) { - if err := c.Close(); err != nil && *errp == nil { - *errp = err - } -} diff --git a/vendor/github.com/mmcloughlin/addchain/internal/print/printer.go b/vendor/github.com/mmcloughlin/addchain/internal/print/printer.go deleted file mode 100644 index 39bd4924977..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/internal/print/printer.go +++ /dev/null @@ -1,104 +0,0 @@ -// Package print provides helpers for structured output printing. -package print - -import ( - "fmt" - "io" - "strings" - "text/tabwriter" -) - -// DefaultIndent is the default string for one level of indentation. -const DefaultIndent = "\t" - -// Printer provides convenience methods for structured output printing. -// Specifically it stores any errors encountered so error checking does not have -// to be done on every print call. Also provides helpers for managing indentation. -type Printer struct { - out io.Writer - level int // current indentation level - indent string // indentation string - pending bool // if there's a pending indentation - err error // saved error from printing -} - -// New builds a printer writing to w. -func New(w io.Writer) Printer { - return Printer{ - out: w, - indent: DefaultIndent, - } -} - -// SetIndentString configures the string used for one level of indentation. -func (p *Printer) SetIndentString(indent string) { - p.indent = indent -} - -// Indent by one level. -func (p *Printer) Indent() { - p.level++ -} - -// Dedent by one level. -func (p *Printer) Dedent() { - p.level-- -} - -// Linef prints a formatted line. -func (p *Printer) Linef(format string, args ...interface{}) { - p.Printf(format, args...) - p.NL() -} - -// NL prints a newline. -func (p *Printer) NL() { - p.Printf("\n") - p.pending = true -} - -// Printf prints formatted output. -func (p *Printer) Printf(format string, args ...interface{}) { - if p.err != nil { - return - } - if p.pending { - indent := strings.Repeat(p.indent, p.level) - format = indent + format - p.pending = false - } - _, err := fmt.Fprintf(p.out, format, args...) - p.SetError(err) -} - -// Error returns the first error that occurred so far, if any. -func (p *Printer) Error() error { - return p.err -} - -// SetError records a possible error. -func (p *Printer) SetError(err error) { - if p.err == nil { - p.err = err - } -} - -// TabWriter provides tabwriter.Writer functionality with the Printer interface. -type TabWriter struct { - tw *tabwriter.Writer - Printer -} - -// NewTabWriter builds a TabWriter. Arguments are the same as for tabwriter.NewWriter. -func NewTabWriter(w io.Writer, minwidth, tabwidth, padding int, padchar byte, flags uint) *TabWriter { - tw := tabwriter.NewWriter(w, minwidth, tabwidth, padding, padchar, flags) - return &TabWriter{ - tw: tw, - Printer: New(tw), - } -} - -// Flush the tabwriter. -func (p *TabWriter) Flush() { - p.SetError(p.tw.Flush()) -} diff --git a/vendor/github.com/mmcloughlin/addchain/logo.svg b/vendor/github.com/mmcloughlin/addchain/logo.svg deleted file mode 100644 index 0ab26295c04..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/logo.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/vendor/github.com/mmcloughlin/addchain/meta/cite.go b/vendor/github.com/mmcloughlin/addchain/meta/cite.go deleted file mode 100644 index bfaae04c759..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/meta/cite.go +++ /dev/null @@ -1,61 +0,0 @@ -package meta - -import ( - "bytes" - "errors" - "fmt" - "io" - "strconv" - "strings" - - "github.com/mmcloughlin/addchain/internal/print" -) - -// CheckCitable checks whether a citation can be generated for this built -// version. -func (p *Properties) CheckCitable() error { - if !p.IsRelease() { - return errors.New("cannot cite non-release version") - } - return nil -} - -// WriteCitation writes BibTeX citation for the most recent release to the given -// writer. -func (p *Properties) WriteCitation(w io.Writer) error { - // Determine release time. - date, err := p.ReleaseTime() - if err != nil { - return fmt.Errorf("release date: %w", err) - } - - // Use tabwriter for field alignment. - tw := print.NewTabWriter(w, 1, 4, 1, ' ', 0) - - field := func(key, value string) { tw.Linef(" %s\t=\t%s,", key, value) } - str := func(key, value string) { field(key, "{"+value+"}") } - - tw.Linef("@misc{%s,", p.Name) - str("title", p.Title()) - str("author", "Michael B. McLoughlin") - field("year", strconv.Itoa(date.Year())) - field("month", strings.ToLower(date.Month().String()[:3])) - str("howpublished", "Repository \\url{"+p.RepositoryURL()+"}") - str("version", p.ReleaseVersion) - str("license", "BSD 3-Clause License") - str("doi", p.DOI) - str("url", p.DOIURL()) - tw.Linef("}") - tw.Flush() - - return tw.Error() -} - -// Citation returns a BibTeX citation for the most recent release. -func (p *Properties) Citation() (string, error) { - buf := bytes.NewBuffer(nil) - if err := p.WriteCitation(buf); err != nil { - return "", err - } - return buf.String(), nil -} diff --git a/vendor/github.com/mmcloughlin/addchain/meta/meta.go b/vendor/github.com/mmcloughlin/addchain/meta/meta.go deleted file mode 100644 index da8b0e2a982..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/meta/meta.go +++ /dev/null @@ -1,101 +0,0 @@ -// Package meta defines properties about this project. -package meta - -import ( - "fmt" - "path" - "time" -) - -// VersionTagPrefix is the prefix used on Git tags corresponding to semantic -// version releases. -const VersionTagPrefix = "v" - -// Properties about this software package. -type Properties struct { - // Name is the project name. - Name string - - // FullName is the "owner/name" identifier for the project. - FullName string - - // Description is the concise project headline. - Description string - - // BuildVersion is the version that was built. Typically populated at build - // time and will typically be empty for non-release builds. - BuildVersion string - - // ReleaseVersion is the version of the most recent release. - ReleaseVersion string - - // ReleaseDate is the date of the most recent release. (RFC3339 date format.) - ReleaseDate string - - // ConceptDOI is the DOI for all versions. - ConceptDOI string - - // DOI for the most recent release. - DOI string - - // ZenodoID is the Zenodo deposit ID for the most recent release. - ZenodoID string -} - -// Meta defines specific properties for the current version of this software. -var Meta = &Properties{ - Name: "addchain", - FullName: "mmcloughlin/addchain", - Description: "Cryptographic Addition Chain Generation in Go", - BuildVersion: buildversion, - ReleaseVersion: releaseversion, - ReleaseDate: releasedate, - ConceptDOI: conceptdoi, - DOI: doi, - ZenodoID: zenodoid, -} - -// Title is a full project title, suitable for a citation. -func (p *Properties) Title() string { - return fmt.Sprintf("%s: %s", p.Name, p.Description) -} - -// IsRelease reports whether the built version is a release. -func (p *Properties) IsRelease() bool { - return p.BuildVersion == p.ReleaseVersion -} - -// ReleaseTag returns the release tag corresponding to the most recent release. -func (p *Properties) ReleaseTag() string { - return VersionTagPrefix + p.ReleaseVersion -} - -// Module returns the Go module path. -func (p *Properties) Module() string { - return path.Join("github.com", p.FullName) -} - -// RepositoryURL returns a URL to the hosted repository. -func (p *Properties) RepositoryURL() string { - return "https://" + p.Module() -} - -// ReleaseURL returns the URL to the release page. -func (p *Properties) ReleaseURL() string { - return fmt.Sprintf("%s/releases/tag/%s", p.RepositoryURL(), p.ReleaseTag()) -} - -// ReleaseTime returns the release date as a time object. -func (p *Properties) ReleaseTime() (time.Time, error) { - return time.Parse("2006-01-02", p.ReleaseDate) -} - -// DOIURL returns the DOI URL corresponding to the most recent release. -func (p *Properties) DOIURL() string { return doiurl(p.DOI) } - -// ConceptDOIURL returns the DOI URL corresponding to the most recent release. -func (p *Properties) ConceptDOIURL() string { return doiurl(p.ConceptDOI) } - -func doiurl(doi string) string { - return "https://doi.org/" + doi -} diff --git a/vendor/github.com/mmcloughlin/addchain/meta/vars.go b/vendor/github.com/mmcloughlin/addchain/meta/vars.go deleted file mode 100644 index a034e8cd06c..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/meta/vars.go +++ /dev/null @@ -1,10 +0,0 @@ -package meta - -var ( - buildversion = "" - releaseversion = "0.4.0" - releasedate = "2021-10-30" - conceptdoi = "10.5281/zenodo.4625263" - doi = "10.5281/zenodo.5622943" - zenodoid = "5622943" -) diff --git a/vendor/github.com/mmcloughlin/addchain/program.go b/vendor/github.com/mmcloughlin/addchain/program.go deleted file mode 100644 index 6449910b068..00000000000 --- a/vendor/github.com/mmcloughlin/addchain/program.go +++ /dev/null @@ -1,133 +0,0 @@ -package addchain - -import ( - "fmt" - "math/big" - - "github.com/mmcloughlin/addchain/internal/bigint" -) - -// Op is an instruction to add positions I and J in a chain. -type Op struct{ I, J int } - -// IsDouble returns whether this operation is a doubling. -func (o Op) IsDouble() bool { return o.I == o.J } - -// Operands returns the indicies used in this operation. This will contain one -// or two entries depending on whether this is a doubling. -func (o Op) Operands() []int { - if o.IsDouble() { - return []int{o.I} - } - return []int{o.I, o.J} -} - -// Uses reports whether the given index is one of the operands. -func (o Op) Uses(i int) bool { - return o.I == i || o.J == i -} - -// Program is a sequence of operations. -type Program []Op - -// Shift appends a sequence of operations that bitwise shift index i left by s, -// equivalent to s double operations. Returns the index of the result. -func (p *Program) Shift(i int, s uint) (int, error) { - for ; s > 0; s-- { - next, err := p.Double(i) - if err != nil { - return 0, err - } - i = next - } - return i, nil -} - -// Double appends an operation that doubles index i. Returns the index of the -// result. -func (p *Program) Double(i int) (int, error) { - return p.Add(i, i) -} - -// Add appends an operation that adds indices i and j. Returns the index of the -// result. -func (p *Program) Add(i, j int) (int, error) { - if err := p.boundscheck(i); err != nil { - return 0, err - } - if err := p.boundscheck(j); err != nil { - return 0, err - } - *p = append(*p, Op{i, j}) - return len(*p), nil -} - -// boundscheck returns an error if i is out of bounds. -func (p Program) boundscheck(i int) error { - // Note the corresponding chain is one longer than the program. - n := len(p) - switch { - case i < 0: - return fmt.Errorf("negative index %d", i) - case i > n: - return fmt.Errorf("index %d out of bounds", i) - } - return nil -} - -// Doubles returns the number of doubles in the program. -func (p Program) Doubles() int { - doubles, _ := p.Count() - return doubles -} - -// Adds returns the number of adds in the program. -func (p Program) Adds() int { - _, adds := p.Count() - return adds -} - -// Count returns the number of doubles and adds in the program. -func (p Program) Count() (doubles, adds int) { - for _, op := range p { - if op.IsDouble() { - doubles++ - } else { - adds++ - } - } - return -} - -// Evaluate executes the program and returns the resulting chain. -func (p Program) Evaluate() Chain { - c := New() - for _, op := range p { - sum := new(big.Int).Add(c[op.I], c[op.J]) - c = append(c, sum) - } - return c -} - -// ReadCounts returns how many times each index is read in the program. -func (p Program) ReadCounts() []int { - reads := make([]int, len(p)+1) - for _, op := range p { - for _, i := range op.Operands() { - reads[i]++ - } - } - return reads -} - -// Dependencies returns an array of bitsets where each bitset contains the set -// of indicies that contributed to that position. -func (p Program) Dependencies() []*big.Int { - bitsets := []*big.Int{bigint.One()} - for i, op := range p { - bitset := new(big.Int).Or(bitsets[op.I], bitsets[op.J]) - bitset.SetBit(bitset, i+1, 1) - bitsets = append(bitsets, bitset) - } - return bitsets -} diff --git a/vendor/github.com/spf13/cobra/.golangci.yml b/vendor/github.com/spf13/cobra/.golangci.yml index 0d6e61793a7..2c8f4808c1a 100644 --- a/vendor/github.com/spf13/cobra/.golangci.yml +++ b/vendor/github.com/spf13/cobra/.golangci.yml @@ -1,3 +1,17 @@ +# Copyright 2013-2023 The Cobra Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + run: deadline: 5m @@ -5,44 +19,39 @@ linters: disable-all: true enable: #- bodyclose - - deadcode + # - deadcode ! deprecated since v1.49.0; replaced by 'unused' #- depguard #- dogsled #- dupl - errcheck #- exhaustive #- funlen - - gas #- gochecknoinits - goconst - #- gocritic + - gocritic #- gocyclo - #- gofmt + - gofmt - goimports - - golint #- gomnd #- goprintffuncname - #- gosec - #- gosimple + - gosec + - gosimple - govet - ineffassign - - interfacer #- lll - - maligned - - megacheck - #- misspell + - misspell #- nakedret #- noctx - #- nolintlint + - nolintlint #- rowserrcheck #- scopelint - #- staticcheck - - structcheck - #- stylecheck + - staticcheck + #- structcheck ! deprecated since v1.49.0; replaced by 'unused' + - stylecheck #- typecheck - unconvert #- unparam - #- unused - - varcheck + - unused + # - varcheck ! deprecated since v1.49.0; replaced by 'unused' #- whitespace fast: false diff --git a/vendor/github.com/spf13/cobra/Makefile b/vendor/github.com/spf13/cobra/Makefile index 443ef1a987a..0da8d7aa08a 100644 --- a/vendor/github.com/spf13/cobra/Makefile +++ b/vendor/github.com/spf13/cobra/Makefile @@ -5,10 +5,6 @@ ifeq (, $(shell which golangci-lint)) $(warning "could not find golangci-lint in $(PATH), run: curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh") endif -ifeq (, $(shell which richgo)) -$(warning "could not find richgo in $(PATH), run: go get github.com/kyoh86/richgo") -endif - .PHONY: fmt lint test install_deps clean default: all @@ -25,6 +21,10 @@ lint: test: install_deps $(info ******************** running tests ********************) + go test -v ./... + +richtest: install_deps + $(info ******************** running tests with kyoh86/richgo ********************) richgo test -v ./... install_deps: diff --git a/vendor/github.com/spf13/cobra/README.md b/vendor/github.com/spf13/cobra/README.md index 2bf15208229..6444f4b7f6f 100644 --- a/vendor/github.com/spf13/cobra/README.md +++ b/vendor/github.com/spf13/cobra/README.md @@ -1,12 +1,12 @@ -![cobra logo](https://cloud.githubusercontent.com/assets/173412/10886352/ad566232-814f-11e5-9cd0-aa101788c117.png) +![cobra logo](assets/CobraMain.png) Cobra is a library for creating powerful modern CLI applications. Cobra is used in many Go projects such as [Kubernetes](https://kubernetes.io/), -[Hugo](https://gohugo.io), and [Github CLI](https://github.com/cli/cli) to -name a few. [This list](./projects_using_cobra.md) contains a more extensive list of projects using Cobra. +[Hugo](https://gohugo.io), and [GitHub CLI](https://github.com/cli/cli) to +name a few. [This list](site/content/projects_using_cobra.md) contains a more extensive list of projects using Cobra. -[![](https://img.shields.io/github/workflow/status/spf13/cobra/Test?longCache=tru&label=Test&logo=github%20actions&logoColor=fff)](https://github.com/spf13/cobra/actions?query=workflow%3ATest) +[![](https://img.shields.io/github/actions/workflow/status/spf13/cobra/test.yml?branch=main&longCache=true&label=Test&logo=github%20actions&logoColor=fff)](https://github.com/spf13/cobra/actions?query=workflow%3ATest) [![Go Reference](https://pkg.go.dev/badge/github.com/spf13/cobra.svg)](https://pkg.go.dev/github.com/spf13/cobra) [![Go Report Card](https://goreportcard.com/badge/github.com/spf13/cobra)](https://goreportcard.com/report/github.com/spf13/cobra) [![Slack](https://img.shields.io/badge/Slack-cobra-brightgreen)](https://gophers.slack.com/archives/CD3LP1199) @@ -23,6 +23,7 @@ Cobra provides: * Global, local and cascading flags * Intelligent suggestions (`app srver`... did you mean `app server`?) * Automatic help generation for commands and flags +* Grouping help for subcommands * Automatic help flag recognition of `-h`, `--help`, etc. * Automatically generated shell autocomplete for your application (bash, zsh, fish, powershell) * Automatically generated man pages for your application @@ -40,9 +41,9 @@ The best applications read like sentences when used, and as a result, users intuitively know how to interact with them. The pattern to follow is -`APPNAME VERB NOUN --ADJECTIVE.` +`APPNAME VERB NOUN --ADJECTIVE` or -`APPNAME COMMAND ARG --FLAG` +`APPNAME COMMAND ARG --FLAG`. A few good real world examples may better illustrate this point. @@ -79,7 +80,7 @@ which maintains the same interface while adding POSIX compliance. # Installing Using Cobra is easy. First, use `go get` to install the latest version -of the library. +of the library. ``` go get -u github.com/spf13/cobra@latest @@ -104,8 +105,8 @@ go install github.com/spf13/cobra-cli@latest For complete details on using the Cobra-CLI generator, please read [The Cobra Generator README](https://github.com/spf13/cobra-cli/blob/main/README.md) -For complete details on using the Cobra library, please read the [The Cobra User Guide](user_guide.md). +For complete details on using the Cobra library, please read the [The Cobra User Guide](site/content/user_guide.md). # License -Cobra is released under the Apache 2.0 license. See [LICENSE.txt](https://github.com/spf13/cobra/blob/master/LICENSE.txt) +Cobra is released under the Apache 2.0 license. See [LICENSE.txt](LICENSE.txt) diff --git a/vendor/github.com/spf13/cobra/active_help.go b/vendor/github.com/spf13/cobra/active_help.go index 0c631913d45..25c30e3ccc3 100644 --- a/vendor/github.com/spf13/cobra/active_help.go +++ b/vendor/github.com/spf13/cobra/active_help.go @@ -1,17 +1,30 @@ +// Copyright 2013-2023 The Cobra Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package cobra import ( "fmt" "os" - "strings" ) const ( activeHelpMarker = "_activeHelp_ " // The below values should not be changed: programs will be using them explicitly // in their user documentation, and users will be using them explicitly. - activeHelpEnvVarSuffix = "_ACTIVE_HELP" - activeHelpGlobalEnvVar = "COBRA_ACTIVE_HELP" + activeHelpEnvVarSuffix = "ACTIVE_HELP" + activeHelpGlobalEnvVar = configEnvVarGlobalPrefix + "_" + activeHelpEnvVarSuffix activeHelpGlobalDisable = "0" ) @@ -28,7 +41,7 @@ func AppendActiveHelp(compArray []string, activeHelpStr string) []string { // GetActiveHelpConfig returns the value of the ActiveHelp environment variable // _ACTIVE_HELP where is the name of the root command in upper -// case, with all - replaced by _. +// case, with all non-ASCII-alphanumeric characters replaced by `_`. // It will always return "0" if the global environment variable COBRA_ACTIVE_HELP // is set to "0". func GetActiveHelpConfig(cmd *Command) string { @@ -41,9 +54,7 @@ func GetActiveHelpConfig(cmd *Command) string { // activeHelpEnvVar returns the name of the program-specific ActiveHelp environment // variable. It has the format _ACTIVE_HELP where is the name of the -// root command in upper case, with all - replaced by _. +// root command in upper case, with all non-ASCII-alphanumeric characters replaced by `_`. func activeHelpEnvVar(name string) string { - // This format should not be changed: users will be using it explicitly. - activeHelpEnvVar := strings.ToUpper(fmt.Sprintf("%s%s", name, activeHelpEnvVarSuffix)) - return strings.ReplaceAll(activeHelpEnvVar, "-", "_") + return configEnvVar(name, activeHelpEnvVarSuffix) } diff --git a/vendor/github.com/spf13/cobra/active_help.md b/vendor/github.com/spf13/cobra/active_help.md deleted file mode 100644 index 5e7f59af380..00000000000 --- a/vendor/github.com/spf13/cobra/active_help.md +++ /dev/null @@ -1,157 +0,0 @@ -# Active Help - -Active Help is a framework provided by Cobra which allows a program to define messages (hints, warnings, etc) that will be printed during program usage. It aims to make it easier for your users to learn how to use your program. If configured by the program, Active Help is printed when the user triggers shell completion. - -For example, -``` -bash-5.1$ helm repo add [tab] -You must choose a name for the repo you are adding. - -bash-5.1$ bin/helm package [tab] -Please specify the path to the chart to package - -bash-5.1$ bin/helm package [tab][tab] -bin/ internal/ scripts/ pkg/ testdata/ -``` - -**Hint**: A good place to use Active Help messages is when the normal completion system does not provide any suggestions. In such cases, Active Help nicely supplements the normal shell completions to guide the user in knowing what is expected by the program. -## Supported shells - -Active Help is currently only supported for the following shells: -- Bash (using [bash completion V2](shell_completions.md#bash-completion-v2) only). Note that bash 4.4 or higher is required for the prompt to appear when an Active Help message is printed. -- Zsh - -## Adding Active Help messages - -As Active Help uses the shell completion system, the implementation of Active Help messages is done by enhancing custom dynamic completions. If you are not familiar with dynamic completions, please refer to [Shell Completions](shell_completions.md). - -Adding Active Help is done through the use of the `cobra.AppendActiveHelp(...)` function, where the program repeatedly adds Active Help messages to the list of completions. Keep reading for details. - -### Active Help for nouns - -Adding Active Help when completing a noun is done within the `ValidArgsFunction(...)` of a command. Please notice the use of `cobra.AppendActiveHelp(...)` in the following example: - -```go -cmd := &cobra.Command{ - Use: "add [NAME] [URL]", - Short: "add a chart repository", - Args: require.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - return addRepo(args) - }, - ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - var comps []string - if len(args) == 0 { - comps = cobra.AppendActiveHelp(comps, "You must choose a name for the repo you are adding") - } else if len(args) == 1 { - comps = cobra.AppendActiveHelp(comps, "You must specify the URL for the repo you are adding") - } else { - comps = cobra.AppendActiveHelp(comps, "This command does not take any more arguments") - } - return comps, cobra.ShellCompDirectiveNoFileComp - }, -} -``` -The example above defines the completions (none, in this specific example) as well as the Active Help messages for the `helm repo add` command. It yields the following behavior: -``` -bash-5.1$ helm repo add [tab] -You must choose a name for the repo you are adding - -bash-5.1$ helm repo add grafana [tab] -You must specify the URL for the repo you are adding - -bash-5.1$ helm repo add grafana https://grafana.github.io/helm-charts [tab] -This command does not take any more arguments -``` -**Hint**: As can be seen in the above example, a good place to use Active Help messages is when the normal completion system does not provide any suggestions. In such cases, Active Help nicely supplements the normal shell completions. - -### Active Help for flags - -Providing Active Help for flags is done in the same fashion as for nouns, but using the completion function registered for the flag. For example: -```go -_ = cmd.RegisterFlagCompletionFunc("version", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - if len(args) != 2 { - return cobra.AppendActiveHelp(nil, "You must first specify the chart to install before the --version flag can be completed"), cobra.ShellCompDirectiveNoFileComp - } - return compVersionFlag(args[1], toComplete) - }) -``` -The example above prints an Active Help message when not enough information was given by the user to complete the `--version` flag. -``` -bash-5.1$ bin/helm install myrelease --version 2.0.[tab] -You must first specify the chart to install before the --version flag can be completed - -bash-5.1$ bin/helm install myrelease bitnami/solr --version 2.0.[tab][tab] -2.0.1 2.0.2 2.0.3 -``` - -## User control of Active Help - -You may want to allow your users to disable Active Help or choose between different levels of Active Help. It is entirely up to the program to define the type of configurability of Active Help that it wants to offer, if any. -Allowing to configure Active Help is entirely optional; you can use Active Help in your program without doing anything about Active Help configuration. - -The way to configure Active Help is to use the program's Active Help environment -variable. That variable is named `_ACTIVE_HELP` where `` is the name of your -program in uppercase with any `-` replaced by an `_`. The variable should be set by the user to whatever -Active Help configuration values are supported by the program. - -For example, say `helm` has chosen to support three levels for Active Help: `on`, `off`, `local`. Then a user -would set the desired behavior to `local` by doing `export HELM_ACTIVE_HELP=local` in their shell. - -For simplicity, when in `cmd.ValidArgsFunction(...)` or a flag's completion function, the program should read the -Active Help configuration using the `cobra.GetActiveHelpConfig(cmd)` function and select what Active Help messages -should or should not be added (instead of reading the environment variable directly). - -For example: -```go -ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - activeHelpLevel := cobra.GetActiveHelpConfig(cmd) - - var comps []string - if len(args) == 0 { - if activeHelpLevel != "off" { - comps = cobra.AppendActiveHelp(comps, "You must choose a name for the repo you are adding") - } - } else if len(args) == 1 { - if activeHelpLevel != "off" { - comps = cobra.AppendActiveHelp(comps, "You must specify the URL for the repo you are adding") - } - } else { - if activeHelpLevel == "local" { - comps = cobra.AppendActiveHelp(comps, "This command does not take any more arguments") - } - } - return comps, cobra.ShellCompDirectiveNoFileComp -}, -``` -**Note 1**: If the `_ACTIVE_HELP` environment variable is set to the string "0", Cobra will automatically disable all Active Help output (even if some output was specified by the program using the `cobra.AppendActiveHelp(...)` function). Using "0" can simplify your code in situations where you want to blindly disable Active Help without having to call `cobra.GetActiveHelpConfig(cmd)` explicitly. - -**Note 2**: If a user wants to disable Active Help for every single program based on Cobra, she can set the environment variable `COBRA_ACTIVE_HELP` to "0". In this case `cobra.GetActiveHelpConfig(cmd)` will return "0" no matter what the variable `_ACTIVE_HELP` is set to. - -**Note 3**: If the user does not set `_ACTIVE_HELP` or `COBRA_ACTIVE_HELP` (which will be a common case), the default value for the Active Help configuration returned by `cobra.GetActiveHelpConfig(cmd)` will be the empty string. -## Active Help with Cobra's default completion command - -Cobra provides a default `completion` command for programs that wish to use it. -When using the default `completion` command, Active Help is configurable in the same -fashion as described above using environment variables. You may wish to document this in more -details for your users. - -## Debugging Active Help - -Debugging your Active Help code is done in the same way as debugging your dynamic completion code, which is with Cobra's hidden `__complete` command. Please refer to [debugging shell completion](shell_completions.md#debugging) for details. - -When debugging with the `__complete` command, if you want to specify different Active Help configurations, you should use the active help environment variable. That variable is named `_ACTIVE_HELP` where any `-` is replaced by an `_`. For example, we can test deactivating some Active Help as shown below: -``` -$ HELM_ACTIVE_HELP=1 bin/helm __complete install wordpress bitnami/h -bitnami/haproxy -bitnami/harbor -_activeHelp_ WARNING: cannot re-use a name that is still in use -:0 -Completion ended with directive: ShellCompDirectiveDefault - -$ HELM_ACTIVE_HELP=0 bin/helm __complete install wordpress bitnami/h -bitnami/haproxy -bitnami/harbor -:0 -Completion ended with directive: ShellCompDirectiveDefault -``` diff --git a/vendor/github.com/spf13/cobra/args.go b/vendor/github.com/spf13/cobra/args.go index 20a022b3084..ed1e70ceaa4 100644 --- a/vendor/github.com/spf13/cobra/args.go +++ b/vendor/github.com/spf13/cobra/args.go @@ -1,3 +1,17 @@ +// Copyright 2013-2023 The Cobra Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package cobra import ( @@ -7,7 +21,7 @@ import ( type PositionalArgs func(cmd *Command, args []string) error -// Legacy arg validation has the following behaviour: +// legacyArgs validation has the following behaviour: // - root commands with no subcommands can take arbitrary arguments // - root commands with subcommands will do subcommand validity checking // - subcommands will always accept arbitrary arguments @@ -32,16 +46,16 @@ func NoArgs(cmd *Command, args []string) error { return nil } -// OnlyValidArgs returns an error if any args are not in the list of ValidArgs. +// OnlyValidArgs returns an error if there are any positional args that are not in +// the `ValidArgs` field of `Command` func OnlyValidArgs(cmd *Command, args []string) error { if len(cmd.ValidArgs) > 0 { // Remove any description that may be included in ValidArgs. // A description is following a tab character. - var validArgs []string + validArgs := make([]string, 0, len(cmd.ValidArgs)) for _, v := range cmd.ValidArgs { - validArgs = append(validArgs, strings.Split(v, "\t")[0]) + validArgs = append(validArgs, strings.SplitN(v, "\t", 2)[0]) } - for _, v := range args { if !stringInSlice(v, validArgs) { return fmt.Errorf("invalid argument %q for %q%s", v, cmd.CommandPath(), cmd.findSuggestions(args[0])) @@ -86,18 +100,6 @@ func ExactArgs(n int) PositionalArgs { } } -// ExactValidArgs returns an error if -// there are not exactly N positional args OR -// there are any positional args that are not in the `ValidArgs` field of `Command` -func ExactValidArgs(n int) PositionalArgs { - return func(cmd *Command, args []string) error { - if err := ExactArgs(n)(cmd, args); err != nil { - return err - } - return OnlyValidArgs(cmd, args) - } -} - // RangeArgs returns an error if the number of args is not within the expected range. func RangeArgs(min int, max int) PositionalArgs { return func(cmd *Command, args []string) error { @@ -119,3 +121,11 @@ func MatchAll(pargs ...PositionalArgs) PositionalArgs { return nil } } + +// ExactValidArgs returns an error if there are not exactly N positional args OR +// there are any positional args that are not in the `ValidArgs` field of `Command` +// +// Deprecated: use MatchAll(ExactArgs(n), OnlyValidArgs) instead +func ExactValidArgs(n int) PositionalArgs { + return MatchAll(ExactArgs(n), OnlyValidArgs) +} diff --git a/vendor/github.com/spf13/cobra/bash_completions.go b/vendor/github.com/spf13/cobra/bash_completions.go index cb7e1953787..f4d198cbcbd 100644 --- a/vendor/github.com/spf13/cobra/bash_completions.go +++ b/vendor/github.com/spf13/cobra/bash_completions.go @@ -1,3 +1,17 @@ +// Copyright 2013-2023 The Cobra Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package cobra import ( @@ -71,7 +85,7 @@ __%[1]s_handle_go_custom_completion() local out requestComp lastParam lastChar comp directive args # Prepare the command to request completions for the program. - # Calling ${words[0]} instead of directly %[1]s allows to handle aliases + # Calling ${words[0]} instead of directly %[1]s allows handling aliases args=("${words[@]:1}") # Disable ActiveHelp which is not supported for bash completion v1 requestComp="%[8]s=0 ${words[0]} %[2]s ${args[*]}" @@ -518,7 +532,7 @@ func writeLocalNonPersistentFlag(buf io.StringWriter, flag *pflag.Flag) { } } -// Setup annotations for go completions for registered flags +// prepareCustomAnnotationsForFlags setup annotations for go completions for registered flags func prepareCustomAnnotationsForFlags(cmd *Command) { flagCompletionMutex.RLock() defer flagCompletionMutex.RUnlock() @@ -583,19 +597,16 @@ func writeRequiredFlag(buf io.StringWriter, cmd *Command) { if nonCompletableFlag(flag) { return } - for key := range flag.Annotations { - switch key { - case BashCompOneRequiredFlag: - format := " must_have_one_flag+=(\"--%s" - if flag.Value.Type() != "bool" { - format += "=" - } - format += cbn - WriteStringAndCheck(buf, fmt.Sprintf(format, flag.Name)) - - if len(flag.Shorthand) > 0 { - WriteStringAndCheck(buf, fmt.Sprintf(" must_have_one_flag+=(\"-%s"+cbn, flag.Shorthand)) - } + if _, ok := flag.Annotations[BashCompOneRequiredFlag]; ok { + format := " must_have_one_flag+=(\"--%s" + if flag.Value.Type() != "bool" { + format += "=" + } + format += cbn + WriteStringAndCheck(buf, fmt.Sprintf(format, flag.Name)) + + if len(flag.Shorthand) > 0 { + WriteStringAndCheck(buf, fmt.Sprintf(" must_have_one_flag+=(\"-%s"+cbn, flag.Shorthand)) } } }) @@ -607,7 +618,7 @@ func writeRequiredNouns(buf io.StringWriter, cmd *Command) { for _, value := range cmd.ValidArgs { // Remove any description that may be included following a tab character. // Descriptions are not supported by bash completion. - value = strings.Split(value, "\t")[0] + value = strings.SplitN(value, "\t", 2)[0] WriteStringAndCheck(buf, fmt.Sprintf(" must_have_one_noun+=(%q)\n", value)) } if cmd.ValidArgsFunction != nil { diff --git a/vendor/github.com/spf13/cobra/bash_completions.md b/vendor/github.com/spf13/cobra/bash_completions.md deleted file mode 100644 index 52919b2fa6d..00000000000 --- a/vendor/github.com/spf13/cobra/bash_completions.md +++ /dev/null @@ -1,93 +0,0 @@ -# Generating Bash Completions For Your cobra.Command - -Please refer to [Shell Completions](shell_completions.md) for details. - -## Bash legacy dynamic completions - -For backward compatibility, Cobra still supports its legacy dynamic completion solution (described below). Unlike the `ValidArgsFunction` solution, the legacy solution will only work for Bash shell-completion and not for other shells. This legacy solution can be used along-side `ValidArgsFunction` and `RegisterFlagCompletionFunc()`, as long as both solutions are not used for the same command. This provides a path to gradually migrate from the legacy solution to the new solution. - -**Note**: Cobra's default `completion` command uses bash completion V2. If you are currently using Cobra's legacy dynamic completion solution, you should not use the default `completion` command but continue using your own. - -The legacy solution allows you to inject bash functions into the bash completion script. Those bash functions are responsible for providing the completion choices for your own completions. - -Some code that works in kubernetes: - -```bash -const ( - bash_completion_func = `__kubectl_parse_get() -{ - local kubectl_output out - if kubectl_output=$(kubectl get --no-headers "$1" 2>/dev/null); then - out=($(echo "${kubectl_output}" | awk '{print $1}')) - COMPREPLY=( $( compgen -W "${out[*]}" -- "$cur" ) ) - fi -} - -__kubectl_get_resource() -{ - if [[ ${#nouns[@]} -eq 0 ]]; then - return 1 - fi - __kubectl_parse_get ${nouns[${#nouns[@]} -1]} - if [[ $? -eq 0 ]]; then - return 0 - fi -} - -__kubectl_custom_func() { - case ${last_command} in - kubectl_get | kubectl_describe | kubectl_delete | kubectl_stop) - __kubectl_get_resource - return - ;; - *) - ;; - esac -} -`) -``` - -And then I set that in my command definition: - -```go -cmds := &cobra.Command{ - Use: "kubectl", - Short: "kubectl controls the Kubernetes cluster manager", - Long: `kubectl controls the Kubernetes cluster manager. - -Find more information at https://github.com/GoogleCloudPlatform/kubernetes.`, - Run: runHelp, - BashCompletionFunction: bash_completion_func, -} -``` - -The `BashCompletionFunction` option is really only valid/useful on the root command. Doing the above will cause `__kubectl_custom_func()` (`___custom_func()`) to be called when the built in processor was unable to find a solution. In the case of kubernetes a valid command might look something like `kubectl get pod [mypod]`. If you type `kubectl get pod [tab][tab]` the `__kubectl_customc_func()` will run because the cobra.Command only understood "kubectl" and "get." `__kubectl_custom_func()` will see that the cobra.Command is "kubectl_get" and will thus call another helper `__kubectl_get_resource()`. `__kubectl_get_resource` will look at the 'nouns' collected. In our example the only noun will be `pod`. So it will call `__kubectl_parse_get pod`. `__kubectl_parse_get` will actually call out to kubernetes and get any pods. It will then set `COMPREPLY` to valid pods! - -Similarly, for flags: - -```go - annotation := make(map[string][]string) - annotation[cobra.BashCompCustom] = []string{"__kubectl_get_namespaces"} - - flag := &pflag.Flag{ - Name: "namespace", - Usage: usage, - Annotations: annotation, - } - cmd.Flags().AddFlag(flag) -``` - -In addition add the `__kubectl_get_namespaces` implementation in the `BashCompletionFunction` -value, e.g.: - -```bash -__kubectl_get_namespaces() -{ - local template - template="{{ range .items }}{{ .metadata.name }} {{ end }}" - local kubectl_out - if kubectl_out=$(kubectl get -o template --template="${template}" namespace 2>/dev/null); then - COMPREPLY=( $( compgen -W "${kubectl_out}[*]" -- "$cur" ) ) - fi -} -``` diff --git a/vendor/github.com/spf13/cobra/bash_completionsV2.go b/vendor/github.com/spf13/cobra/bash_completionsV2.go index 767bf031200..1cce5c329c2 100644 --- a/vendor/github.com/spf13/cobra/bash_completionsV2.go +++ b/vendor/github.com/spf13/cobra/bash_completionsV2.go @@ -1,3 +1,17 @@ +// Copyright 2013-2023 The Cobra Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package cobra import ( @@ -24,7 +38,7 @@ func genBashComp(buf io.StringWriter, name string, includeDesc bool) { __%[1]s_debug() { - if [[ -n ${BASH_COMP_DEBUG_FILE:-} ]]; then + if [[ -n ${BASH_COMP_DEBUG_FILE-} ]]; then echo "$*" >> "${BASH_COMP_DEBUG_FILE}" fi } @@ -43,7 +57,7 @@ __%[1]s_get_completion_results() { local requestComp lastParam lastChar args # Prepare the command to request completions for the program. - # Calling ${words[0]} instead of directly %[1]s allows to handle aliases + # Calling ${words[0]} instead of directly %[1]s allows handling aliases args=("${words[@]:1}") requestComp="${words[0]} %[2]s ${args[*]}" @@ -51,7 +65,7 @@ __%[1]s_get_completion_results() { lastChar=${lastParam:$((${#lastParam}-1)):1} __%[1]s_debug "lastParam ${lastParam}, lastChar ${lastChar}" - if [ -z "${cur}" ] && [ "${lastChar}" != "=" ]; then + if [[ -z ${cur} && ${lastChar} != = ]]; then # If the last parameter is complete (there is a space following it) # We add an extra empty parameter so we can indicate this to the go method. __%[1]s_debug "Adding extra empty parameter" @@ -61,7 +75,7 @@ __%[1]s_get_completion_results() { # When completing a flag with an = (e.g., %[1]s -n=) # bash focuses on the part after the =, so we need to remove # the flag part from $cur - if [[ "${cur}" == -*=* ]]; then + if [[ ${cur} == -*=* ]]; then cur="${cur#*=}" fi @@ -73,7 +87,7 @@ __%[1]s_get_completion_results() { directive=${out##*:} # Remove the directive out=${out%%:*} - if [ "${directive}" = "${out}" ]; then + if [[ ${directive} == "${out}" ]]; then # There is not directive specified directive=0 fi @@ -87,22 +101,36 @@ __%[1]s_process_completion_results() { local shellCompDirectiveNoFileComp=%[5]d local shellCompDirectiveFilterFileExt=%[6]d local shellCompDirectiveFilterDirs=%[7]d + local shellCompDirectiveKeepOrder=%[8]d - if [ $((directive & shellCompDirectiveError)) -ne 0 ]; then + if (((directive & shellCompDirectiveError) != 0)); then # Error code. No completion. __%[1]s_debug "Received error from custom completion go code" return else - if [ $((directive & shellCompDirectiveNoSpace)) -ne 0 ]; then - if [[ $(type -t compopt) = "builtin" ]]; then + if (((directive & shellCompDirectiveNoSpace) != 0)); then + if [[ $(type -t compopt) == builtin ]]; then __%[1]s_debug "Activating no space" compopt -o nospace else __%[1]s_debug "No space directive not supported in this version of bash" fi fi - if [ $((directive & shellCompDirectiveNoFileComp)) -ne 0 ]; then - if [[ $(type -t compopt) = "builtin" ]]; then + if (((directive & shellCompDirectiveKeepOrder) != 0)); then + if [[ $(type -t compopt) == builtin ]]; then + # no sort isn't supported for bash less than < 4.4 + if [[ ${BASH_VERSINFO[0]} -lt 4 || ( ${BASH_VERSINFO[0]} -eq 4 && ${BASH_VERSINFO[1]} -lt 4 ) ]]; then + __%[1]s_debug "No sort directive not supported in this version of bash" + else + __%[1]s_debug "Activating keep order" + compopt -o nosort + fi + else + __%[1]s_debug "No sort directive not supported in this version of bash" + fi + fi + if (((directive & shellCompDirectiveNoFileComp) != 0)); then + if [[ $(type -t compopt) == builtin ]]; then __%[1]s_debug "Activating no file completion" compopt +o default else @@ -116,7 +144,7 @@ __%[1]s_process_completion_results() { local activeHelp=() __%[1]s_extract_activeHelp - if [ $((directive & shellCompDirectiveFilterFileExt)) -ne 0 ]; then + if (((directive & shellCompDirectiveFilterFileExt) != 0)); then # File extension filtering local fullFilter filter filteringCmd @@ -129,13 +157,12 @@ __%[1]s_process_completion_results() { filteringCmd="_filedir $fullFilter" __%[1]s_debug "File filtering command: $filteringCmd" $filteringCmd - elif [ $((directive & shellCompDirectiveFilterDirs)) -ne 0 ]; then + elif (((directive & shellCompDirectiveFilterDirs) != 0)); then # File completion for directories only - # Use printf to strip any trailing newline local subdir - subdir=$(printf "%%s" "${completions[0]}") - if [ -n "$subdir" ]; then + subdir=${completions[0]} + if [[ -n $subdir ]]; then __%[1]s_debug "Listing directories in $subdir" pushd "$subdir" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&1 || return else @@ -150,7 +177,7 @@ __%[1]s_process_completion_results() { __%[1]s_handle_special_char "$cur" = # Print the activeHelp statements before we finish - if [ ${#activeHelp} -ne 0 ]; then + if ((${#activeHelp[*]} != 0)); then printf "\n"; printf "%%s\n" "${activeHelp[@]}" printf "\n" @@ -170,21 +197,21 @@ __%[1]s_process_completion_results() { # Separate activeHelp lines from real completions. # Fills the $activeHelp and $completions arrays. __%[1]s_extract_activeHelp() { - local activeHelpMarker="%[8]s" + local activeHelpMarker="%[9]s" local endIndex=${#activeHelpMarker} while IFS='' read -r comp; do - if [ "${comp:0:endIndex}" = "$activeHelpMarker" ]; then + if [[ ${comp:0:endIndex} == $activeHelpMarker ]]; then comp=${comp:endIndex} __%[1]s_debug "ActiveHelp found: $comp" - if [ -n "$comp" ]; then + if [[ -n $comp ]]; then activeHelp+=("$comp") fi else # Not an activeHelp line but a normal completion completions+=("$comp") fi - done < <(printf "%%s\n" "${out}") + done <<<"${out}" } __%[1]s_handle_completion_types() { @@ -240,7 +267,7 @@ __%[1]s_handle_standard_completion_case() { done < <(printf "%%s\n" "${completions[@]}") # If there is a single completion left, remove the description text - if [ ${#COMPREPLY[*]} -eq 1 ]; then + if ((${#COMPREPLY[*]} == 1)); then __%[1]s_debug "COMPREPLY[0]: ${COMPREPLY[0]}" comp="${COMPREPLY[0]%%%%$tab*}" __%[1]s_debug "Removed description from single completion, which is now: ${comp}" @@ -257,8 +284,8 @@ __%[1]s_handle_special_char() if [[ "$comp" == *${char}* && "$COMP_WORDBREAKS" == *${char}* ]]; then local word=${comp%%"${comp##*${char}}"} local idx=${#COMPREPLY[*]} - while [[ $((--idx)) -ge 0 ]]; do - COMPREPLY[$idx]=${COMPREPLY[$idx]#"$word"} + while ((--idx >= 0)); do + COMPREPLY[idx]=${COMPREPLY[idx]#"$word"} done fi } @@ -284,7 +311,7 @@ __%[1]s_format_comp_descriptions() # Make sure we can fit a description of at least 8 characters # if we are to align the descriptions. - if [[ $maxdesclength -gt 8 ]]; then + if ((maxdesclength > 8)); then # Add the proper number of spaces to align the descriptions for ((i = ${#comp} ; i < longest ; i++)); do comp+=" " @@ -296,8 +323,8 @@ __%[1]s_format_comp_descriptions() # If there is enough space for any description text, # truncate the descriptions that are too long for the shell width - if [ $maxdesclength -gt 0 ]; then - if [ ${#desc} -gt $maxdesclength ]; then + if ((maxdesclength > 0)); then + if ((${#desc} > maxdesclength)); then desc=${desc:0:$(( maxdesclength - 1 ))} desc+="…" fi @@ -318,9 +345,9 @@ __start_%[1]s() # Call _init_completion from the bash-completion package # to prepare the arguments properly if declare -F _init_completion >/dev/null 2>&1; then - _init_completion -n "=:" || return + _init_completion -n =: || return else - __%[1]s_init_completion -n "=:" || return + __%[1]s_init_completion -n =: || return fi __%[1]s_debug @@ -347,7 +374,7 @@ fi # ex: ts=4 sw=4 et filetype=sh `, name, compCmd, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, - ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, + ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveKeepOrder, activeHelpMarker)) } diff --git a/vendor/github.com/spf13/cobra/cobra.go b/vendor/github.com/spf13/cobra/cobra.go index d6cbfd71985..e0b0947b04c 100644 --- a/vendor/github.com/spf13/cobra/cobra.go +++ b/vendor/github.com/spf13/cobra/cobra.go @@ -1,9 +1,10 @@ -// Copyright © 2013 Steve Francia . +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 +// +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -39,15 +40,30 @@ var templateFuncs = template.FuncMap{ } var initializers []func() +var finalizers []func() + +const ( + defaultPrefixMatching = false + defaultCommandSorting = true + defaultCaseInsensitive = false + defaultTraverseRunHooks = false +) -// EnablePrefixMatching allows to set automatic prefix matching. Automatic prefix matching can be a dangerous thing +// EnablePrefixMatching allows setting automatic prefix matching. Automatic prefix matching can be a dangerous thing // to automatically enable in CLI tools. // Set this to true to enable it. -var EnablePrefixMatching = false +var EnablePrefixMatching = defaultPrefixMatching // EnableCommandSorting controls sorting of the slice of commands, which is turned on by default. // To disable sorting, set it to false. -var EnableCommandSorting = true +var EnableCommandSorting = defaultCommandSorting + +// EnableCaseInsensitive allows case-insensitive commands names. (case sensitive by default) +var EnableCaseInsensitive = defaultCaseInsensitive + +// EnableTraverseRunHooks executes persistent pre-run and post-run hooks from all parents. +// By default this is disabled, which means only the first run hook to be found is executed. +var EnableTraverseRunHooks = defaultTraverseRunHooks // MousetrapHelpText enables an information splash screen on Windows // if the CLI is started from explorer.exe. @@ -84,6 +100,12 @@ func OnInitialize(y ...func()) { initializers = append(initializers, y...) } +// OnFinalize sets the passed functions to be run when each command's +// Execute method is terminated. +func OnFinalize(y ...func()) { + finalizers = append(finalizers, y...) +} + // FIXME Gt is unused by cobra and should be removed in a version 2. It exists only for compatibility with users of cobra. // Gt takes two types and checks whether the first type is greater than the second. In case of types Arrays, Chans, @@ -150,8 +172,8 @@ func appendIfNotPresent(s, stringToAppend string) string { // rpad adds padding to the right of a string. func rpad(s string, padding int) string { - template := fmt.Sprintf("%%-%ds", padding) - return fmt.Sprintf(template, s) + formattedString := fmt.Sprintf("%%-%ds", padding) + return fmt.Sprintf(formattedString, s) } // tmpl executes the given template text on data, writing the result to w. @@ -171,8 +193,6 @@ func ld(s, t string, ignoreCase bool) int { d := make([][]int, len(s)+1) for i := range d { d[i] = make([]int, len(t)+1) - } - for i := range d { d[i][0] = i } for j := range d[0] { diff --git a/vendor/github.com/spf13/cobra/command.go b/vendor/github.com/spf13/cobra/command.go index 675bb1340af..54748fc67eb 100644 --- a/vendor/github.com/spf13/cobra/command.go +++ b/vendor/github.com/spf13/cobra/command.go @@ -1,9 +1,10 @@ -// Copyright © 2013 Steve Francia . +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 +// +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -29,16 +30,27 @@ import ( flag "github.com/spf13/pflag" ) +const ( + FlagSetByCobraAnnotation = "cobra_annotation_flag_set_by_cobra" + CommandDisplayNameAnnotation = "cobra_annotation_command_display_name" +) + // FParseErrWhitelist configures Flag parse errors to be ignored type FParseErrWhitelist flag.ParseErrorsWhitelist +// Group Structure to manage groups for commands +type Group struct { + ID string + Title string +} + // Command is just that, a command for your application. // E.g. 'go run ...' - 'run' is the command. Cobra requires // you to define the usage and description as part of your command // definition to ensure usability. type Command struct { // Use is the one-line usage message. - // Recommended syntax is as follow: + // Recommended syntax is as follows: // [ ] identifies an optional argument. Arguments that are not enclosed in brackets are required. // ... indicates that you can specify multiple values for the previous argument. // | indicates mutually exclusive information. You can use the argument to the left of the separator or the @@ -58,6 +70,9 @@ type Command struct { // Short is the short description shown in the 'help' output. Short string + // The group id under which this subcommand is grouped in the 'help' output of its parent. + GroupID string + // Long is the long message shown in the 'help ' output. Long string @@ -87,7 +102,7 @@ type Command struct { Deprecated string // Annotations are key/value pairs that can be used by applications to identify or - // group commands. + // group commands or set special options. Annotations map[string]string // Version defines the version for this command. If this value is non-empty and the command does not @@ -103,6 +118,8 @@ type Command struct { // * PostRun() // * PersistentPostRun() // All functions get the same args, the arguments after the command name. + // The *PreRun and *PostRun functions will only be executed if the Run function of the current + // command has been declared. // // PersistentPreRun: children of this command will inherit and execute. PersistentPreRun func(cmd *Command, args []string) @@ -125,6 +142,9 @@ type Command struct { // PersistentPostRunE: PersistentPostRun but returns an error. PersistentPostRunE func(cmd *Command, args []string) error + // groups for subcommands + commandgroups []*Group + // args is actual args parsed from flags. args []string // flagErrorBuf contains all error messages from pflag. @@ -134,8 +154,10 @@ type Command struct { // pflags contains persistent flags. pflags *flag.FlagSet // lflags contains local flags. + // This field does not represent internal state, it's used as a cache to optimise LocalFlags function call lflags *flag.FlagSet // iflags contains inherited flags. + // This field does not represent internal state, it's used as a cache to optimise InheritedFlags function call iflags *flag.FlagSet // parentsPflags is all persistent flags of cmd's parents. parentsPflags *flag.FlagSet @@ -157,9 +179,18 @@ type Command struct { // helpCommand is command with usage 'help'. If it's not defined by user, // cobra uses default help command. helpCommand *Command + // helpCommandGroupID is the group id for the helpCommand + helpCommandGroupID string + + // completionCommandGroupID is the group id for the completion command + completionCommandGroupID string + // versionTemplate is the version template defined by user. versionTemplate string + // errPrefix is the error message prefix defined by user. + errPrefix string + // inReader is a reader defined by the user that replaces stdin inReader io.Reader // outWriter is a writer defined by the user that replaces stdout @@ -236,8 +267,8 @@ func (c *Command) Context() context.Context { return c.ctx } -// SetContext sets context for the command. It is set to context.Background by default and will be overwritten by -// Command.ExecuteContext or Command.ExecuteContextC +// SetContext sets context for the command. This context will be overwritten by +// Command.ExecuteContext or Command.ExecuteContextC. func (c *Command) SetContext(ctx context.Context) { c.ctx = ctx } @@ -300,6 +331,21 @@ func (c *Command) SetHelpCommand(cmd *Command) { c.helpCommand = cmd } +// SetHelpCommandGroupID sets the group id of the help command. +func (c *Command) SetHelpCommandGroupID(groupID string) { + if c.helpCommand != nil { + c.helpCommand.GroupID = groupID + } + // helpCommandGroupID is used if no helpCommand is defined by the user + c.helpCommandGroupID = groupID +} + +// SetCompletionCommandGroupID sets the group id of the completion command. +func (c *Command) SetCompletionCommandGroupID(groupID string) { + // completionCommandGroupID is used if no completion command is defined by the user + c.Root().completionCommandGroupID = groupID +} + // SetHelpTemplate sets help template to be used. Application can use it to set custom template. func (c *Command) SetHelpTemplate(s string) { c.helpTemplate = s @@ -310,6 +356,11 @@ func (c *Command) SetVersionTemplate(s string) { c.versionTemplate = s } +// SetErrPrefix sets error message prefix to be used. Application can use it to set custom prefix. +func (c *Command) SetErrPrefix(s string) { + c.errPrefix = s +} + // SetGlobalNormalizationFunc sets a normalization function to all flag sets and also to child commands. // The user should not have a cyclic dependency on commands. func (c *Command) SetGlobalNormalizationFunc(n func(f *flag.FlagSet, name string) flag.NormalizedName) { @@ -508,10 +559,16 @@ Aliases: {{.NameAndAliases}}{{end}}{{if .HasExample}} Examples: -{{.Example}}{{end}}{{if .HasAvailableSubCommands}} +{{.Example}}{{end}}{{if .HasAvailableSubCommands}}{{$cmds := .Commands}}{{if eq (len .Groups) 0}} + +Available Commands:{{range $cmds}}{{if (or .IsAvailableCommand (eq .Name "help"))}} + {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{else}}{{range $group := .Groups}} + +{{.Title}}{{range $cmds}}{{if (and (eq .GroupID $group.ID) (or .IsAvailableCommand (eq .Name "help")))}} + {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if not .AllChildCommandsHaveGroup}} -Available Commands:{{range .Commands}}{{if (or .IsAvailableCommand (eq .Name "help"))}} - {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}} +Additional Commands:{{range $cmds}}{{if (and (eq .GroupID "") (or .IsAvailableCommand (eq .Name "help")))}} + {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}} Flags: {{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}} @@ -553,6 +610,18 @@ func (c *Command) VersionTemplate() string { ` } +// ErrPrefix return error message prefix for the command +func (c *Command) ErrPrefix() string { + if c.errPrefix != "" { + return c.errPrefix + } + + if c.HasParent() { + return c.parent.ErrPrefix() + } + return "Error:" +} + func hasNoOptDefVal(name string, fs *flag.FlagSet) bool { flag := fs.Lookup(name) if flag == nil { @@ -613,20 +682,44 @@ Loop: // argsMinusFirstX removes only the first x from args. Otherwise, commands that look like // openshift admin policy add-role-to-user admin my-user, lose the admin argument (arg[4]). -func argsMinusFirstX(args []string, x string) []string { - for i, y := range args { - if x == y { - ret := []string{} - ret = append(ret, args[:i]...) - ret = append(ret, args[i+1:]...) - return ret +// Special care needs to be taken not to remove a flag value. +func (c *Command) argsMinusFirstX(args []string, x string) []string { + if len(args) == 0 { + return args + } + c.mergePersistentFlags() + flags := c.Flags() + +Loop: + for pos := 0; pos < len(args); pos++ { + s := args[pos] + switch { + case s == "--": + // -- means we have reached the end of the parseable args. Break out of the loop now. + break Loop + case strings.HasPrefix(s, "--") && !strings.Contains(s, "=") && !hasNoOptDefVal(s[2:], flags): + fallthrough + case strings.HasPrefix(s, "-") && !strings.Contains(s, "=") && len(s) == 2 && !shortHasNoOptDefVal(s[1:], flags): + // This is a flag without a default value, and an equal sign is not used. Increment pos in order to skip + // over the next arg, because that is the value of this flag. + pos++ + continue + case !strings.HasPrefix(s, "-"): + // This is not a flag or a flag value. Check to see if it matches what we're looking for, and if so, + // return the args, excluding the one at this position. + if s == x { + ret := make([]string, 0, len(args)-1) + ret = append(ret, args[:pos]...) + ret = append(ret, args[pos+1:]...) + return ret + } } } return args } func isFlagArg(arg string) bool { - return ((len(arg) >= 3 && arg[1] == '-') || + return ((len(arg) >= 3 && arg[0:2] == "--") || (len(arg) >= 2 && arg[0] == '-' && arg[1] != '-')) } @@ -644,7 +737,7 @@ func (c *Command) Find(args []string) (*Command, []string, error) { cmd := c.findNext(nextSubCmd) if cmd != nil { - return innerfind(cmd, argsMinusFirstX(innerArgs, nextSubCmd)) + return innerfind(cmd, c.argsMinusFirstX(innerArgs, nextSubCmd)) } return c, innerArgs } @@ -663,20 +756,20 @@ func (c *Command) findSuggestions(arg string) string { if c.SuggestionsMinimumDistance <= 0 { c.SuggestionsMinimumDistance = 2 } - suggestionsString := "" + var sb strings.Builder if suggestions := c.SuggestionsFor(arg); len(suggestions) > 0 { - suggestionsString += "\n\nDid you mean this?\n" + sb.WriteString("\n\nDid you mean this?\n") for _, s := range suggestions { - suggestionsString += fmt.Sprintf("\t%v\n", s) + _, _ = fmt.Fprintf(&sb, "\t%v\n", s) } } - return suggestionsString + return sb.String() } func (c *Command) findNext(next string) *Command { matches := make([]*Command, 0) for _, cmd := range c.commands { - if cmd.Name() == next || cmd.HasAlias(next) { + if commandNameMatches(cmd.Name(), next) || cmd.HasAlias(next) { cmd.commandCalledAs.name = next return cmd } @@ -686,7 +779,9 @@ func (c *Command) findNext(next string) *Command { } if len(matches) == 1 { - return matches[0] + // Temporarily disable gosec G602, which produces a false positive. + // See https://github.com/securego/gosec/issues/1005. + return matches[0] // #nosec G602 } return nil @@ -780,7 +875,7 @@ func (c *Command) ArgsLenAtDash() int { func (c *Command) execute(a []string) (err error) { if c == nil { - return fmt.Errorf("Called Execute() on a nil Command") + return fmt.Errorf("called Execute() on a nil Command") } if len(c.Deprecated) > 0 { @@ -833,6 +928,8 @@ func (c *Command) execute(a []string) (err error) { c.preRun() + defer c.postRun() + argWoFlags := c.Flags().Args() if c.DisableFlagParsing { argWoFlags = a @@ -842,15 +939,31 @@ func (c *Command) execute(a []string) (err error) { return err } + parents := make([]*Command, 0, 5) for p := c; p != nil; p = p.Parent() { + if EnableTraverseRunHooks { + // When EnableTraverseRunHooks is set: + // - Execute all persistent pre-runs from the root parent till this command. + // - Execute all persistent post-runs from this command till the root parent. + parents = append([]*Command{p}, parents...) + } else { + // Otherwise, execute only the first found persistent hook. + parents = append(parents, p) + } + } + for _, p := range parents { if p.PersistentPreRunE != nil { if err := p.PersistentPreRunE(c, argWoFlags); err != nil { return err } - break + if !EnableTraverseRunHooks { + break + } } else if p.PersistentPreRun != nil { p.PersistentPreRun(c, argWoFlags) - break + if !EnableTraverseRunHooks { + break + } } } if c.PreRunE != nil { @@ -861,10 +974,10 @@ func (c *Command) execute(a []string) (err error) { c.PreRun(c, argWoFlags) } - if err := c.validateRequiredFlags(); err != nil { + if err := c.ValidateRequiredFlags(); err != nil { return err } - if err := c.validateFlagGroups(); err != nil { + if err := c.ValidateFlagGroups(); err != nil { return err } @@ -887,10 +1000,14 @@ func (c *Command) execute(a []string) (err error) { if err := p.PersistentPostRunE(c, argWoFlags); err != nil { return err } - break + if !EnableTraverseRunHooks { + break + } } else if p.PersistentPostRun != nil { p.PersistentPostRun(c, argWoFlags) - break + if !EnableTraverseRunHooks { + break + } } } @@ -903,6 +1020,12 @@ func (c *Command) preRun() { } } +func (c *Command) postRun() { + for _, x := range finalizers { + x() + } +} + // ExecuteContext is the same as Execute(), but sets the ctx on the command. // Retrieve ctx by calling cmd.Context() inside your *Run lifecycle or ValidArgs // functions. @@ -946,7 +1069,11 @@ func (c *Command) ExecuteC() (cmd *Command, err error) { // initialize help at the last point to allow for user overriding c.InitDefaultHelpCmd() // initialize completion at the last point to allow for user overriding - c.initDefaultCompletionCmd() + c.InitDefaultCompletionCmd() + + // Now that all commands have been created, let's make sure all groups + // are properly created also + c.checkCommandGroups() args := c.args @@ -970,7 +1097,7 @@ func (c *Command) ExecuteC() (cmd *Command, err error) { c = cmd } if !c.SilenceErrors { - c.PrintErrln("Error:", err.Error()) + c.PrintErrln(c.ErrPrefix(), err.Error()) c.PrintErrf("Run '%v --help' for usage.\n", c.CommandPath()) } return c, err @@ -999,7 +1126,7 @@ func (c *Command) ExecuteC() (cmd *Command, err error) { // If root command has SilenceErrors flagged, // all subcommands should respect it if !cmd.SilenceErrors && !c.SilenceErrors { - c.PrintErrln("Error:", err.Error()) + c.PrintErrln(cmd.ErrPrefix(), err.Error()) } // If root command has SilenceUsage flagged, @@ -1018,7 +1145,8 @@ func (c *Command) ValidateArgs(args []string) error { return c.Args(c, args) } -func (c *Command) validateRequiredFlags() error { +// ValidateRequiredFlags validates all required flags are present and returns an error otherwise +func (c *Command) ValidateRequiredFlags() error { if c.DisableFlagParsing { return nil } @@ -1041,6 +1169,19 @@ func (c *Command) validateRequiredFlags() error { return nil } +// checkCommandGroups checks if a command has been added to a group that does not exists. +// If so, we panic because it indicates a coding error that should be corrected. +func (c *Command) checkCommandGroups() { + for _, sub := range c.commands { + // if Group is not defined let the developer know right away + if sub.GroupID != "" && !c.ContainsGroup(sub.GroupID) { + panic(fmt.Sprintf("group id '%s' is not defined for subcommand '%s'", sub.GroupID, sub.CommandPath())) + } + + sub.checkCommandGroups() + } +} + // InitDefaultHelpFlag adds default help flag to c. // It is called automatically by executing the c or by calling help and usage. // If c already has help flag, it will do nothing. @@ -1048,12 +1189,14 @@ func (c *Command) InitDefaultHelpFlag() { c.mergePersistentFlags() if c.Flags().Lookup("help") == nil { usage := "help for " - if c.Name() == "" { + name := c.displayName() + if name == "" { usage += "this command" } else { - usage += c.Name() + usage += name } c.Flags().BoolP("help", "h", false, usage) + _ = c.Flags().SetAnnotation("help", FlagSetByCobraAnnotation, []string{"true"}) } } @@ -1079,6 +1222,7 @@ func (c *Command) InitDefaultVersionFlag() { } else { c.Flags().Bool("version", false, usage) } + _ = c.Flags().SetAnnotation("version", FlagSetByCobraAnnotation, []string{"true"}) } } @@ -1095,7 +1239,7 @@ func (c *Command) InitDefaultHelpCmd() { Use: "help [command]", Short: "Help about any command", Long: `Help provides help for any command in the application. -Simply type ` + c.Name() + ` help [path to command] for full details.`, +Simply type ` + c.displayName() + ` help [path to command] for full details.`, ValidArgsFunction: func(c *Command, args []string, toComplete string) ([]string, ShellCompDirective) { var completions []string cmd, _, e := c.Root().Find(args) @@ -1121,10 +1265,12 @@ Simply type ` + c.Name() + ` help [path to command] for full details.`, c.Printf("Unknown help topic %#q\n", args) CheckErr(c.Root().Usage()) } else { - cmd.InitDefaultHelpFlag() // make possible 'help' flag to be shown + cmd.InitDefaultHelpFlag() // make possible 'help' flag to be shown + cmd.InitDefaultVersionFlag() // make possible 'version' flag to be shown CheckErr(cmd.Help()) } }, + GroupID: c.helpCommandGroupID, } } c.RemoveCommand(c.helpCommand) @@ -1185,6 +1331,36 @@ func (c *Command) AddCommand(cmds ...*Command) { } } +// Groups returns a slice of child command groups. +func (c *Command) Groups() []*Group { + return c.commandgroups +} + +// AllChildCommandsHaveGroup returns if all subcommands are assigned to a group +func (c *Command) AllChildCommandsHaveGroup() bool { + for _, sub := range c.commands { + if (sub.IsAvailableCommand() || sub == c.helpCommand) && sub.GroupID == "" { + return false + } + } + return true +} + +// ContainsGroup return if groupID exists in the list of command groups. +func (c *Command) ContainsGroup(groupID string) bool { + for _, x := range c.commandgroups { + if x.ID == groupID { + return true + } + } + return false +} + +// AddGroup adds one or more command groups to this parent command. +func (c *Command) AddGroup(groups ...*Group) { + c.commandgroups = append(c.commandgroups, groups...) +} + // RemoveCommand removes one or more commands from a parent command. func (c *Command) RemoveCommand(cmds ...*Command) { commands := []*Command{} @@ -1254,16 +1430,24 @@ func (c *Command) CommandPath() string { if c.HasParent() { return c.Parent().CommandPath() + " " + c.Name() } + return c.displayName() +} + +func (c *Command) displayName() string { + if displayName, ok := c.Annotations[CommandDisplayNameAnnotation]; ok { + return displayName + } return c.Name() } // UseLine puts out the full usage for a given command (including parents). func (c *Command) UseLine() string { var useline string + use := strings.Replace(c.Use, c.Name(), c.displayName(), 1) if c.HasParent() { - useline = c.parent.CommandPath() + " " + c.Use + useline = c.parent.CommandPath() + " " + use } else { - useline = c.Use + useline = use } if c.DisableFlagsInUseLine { return useline @@ -1328,7 +1512,7 @@ func (c *Command) Name() string { // HasAlias determines if a given string is an alias of the command. func (c *Command) HasAlias(s string) bool { for _, a := range c.Aliases { - if a == s { + if commandNameMatches(a, s) { return true } } @@ -1465,7 +1649,7 @@ func (c *Command) GlobalNormalizationFunc() func(f *flag.FlagSet, name string) f // to this command (local and persistent declared here and by all parents). func (c *Command) Flags() *flag.FlagSet { if c.flags == nil { - c.flags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + c.flags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) if c.flagErrorBuf == nil { c.flagErrorBuf = new(bytes.Buffer) } @@ -1476,10 +1660,11 @@ func (c *Command) Flags() *flag.FlagSet { } // LocalNonPersistentFlags are flags specific to this command which will NOT persist to subcommands. +// This function does not modify the flags of the current command, it's purpose is to return the current state. func (c *Command) LocalNonPersistentFlags() *flag.FlagSet { persistentFlags := c.PersistentFlags() - out := flag.NewFlagSet(c.Name(), flag.ContinueOnError) + out := flag.NewFlagSet(c.displayName(), flag.ContinueOnError) c.LocalFlags().VisitAll(func(f *flag.Flag) { if persistentFlags.Lookup(f.Name) == nil { out.AddFlag(f) @@ -1489,11 +1674,12 @@ func (c *Command) LocalNonPersistentFlags() *flag.FlagSet { } // LocalFlags returns the local FlagSet specifically set in the current command. +// This function does not modify the flags of the current command, it's purpose is to return the current state. func (c *Command) LocalFlags() *flag.FlagSet { c.mergePersistentFlags() if c.lflags == nil { - c.lflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + c.lflags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) if c.flagErrorBuf == nil { c.flagErrorBuf = new(bytes.Buffer) } @@ -1505,7 +1691,8 @@ func (c *Command) LocalFlags() *flag.FlagSet { } addToLocal := func(f *flag.Flag) { - if c.lflags.Lookup(f.Name) == nil && c.parentsPflags.Lookup(f.Name) == nil { + // Add the flag if it is not a parent PFlag, or it shadows a parent PFlag + if c.lflags.Lookup(f.Name) == nil && f != c.parentsPflags.Lookup(f.Name) { c.lflags.AddFlag(f) } } @@ -1515,11 +1702,12 @@ func (c *Command) LocalFlags() *flag.FlagSet { } // InheritedFlags returns all flags which were inherited from parent commands. +// This function does not modify the flags of the current command, it's purpose is to return the current state. func (c *Command) InheritedFlags() *flag.FlagSet { c.mergePersistentFlags() if c.iflags == nil { - c.iflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + c.iflags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) if c.flagErrorBuf == nil { c.flagErrorBuf = new(bytes.Buffer) } @@ -1540,6 +1728,7 @@ func (c *Command) InheritedFlags() *flag.FlagSet { } // NonInheritedFlags returns all flags which were not inherited from parent commands. +// This function does not modify the flags of the current command, it's purpose is to return the current state. func (c *Command) NonInheritedFlags() *flag.FlagSet { return c.LocalFlags() } @@ -1547,7 +1736,7 @@ func (c *Command) NonInheritedFlags() *flag.FlagSet { // PersistentFlags returns the persistent FlagSet specifically set in the current command. func (c *Command) PersistentFlags() *flag.FlagSet { if c.pflags == nil { - c.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + c.pflags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) if c.flagErrorBuf == nil { c.flagErrorBuf = new(bytes.Buffer) } @@ -1560,9 +1749,9 @@ func (c *Command) PersistentFlags() *flag.FlagSet { func (c *Command) ResetFlags() { c.flagErrorBuf = new(bytes.Buffer) c.flagErrorBuf.Reset() - c.flags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + c.flags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) c.flags.SetOutput(c.flagErrorBuf) - c.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + c.pflags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) c.pflags.SetOutput(c.flagErrorBuf) c.lflags = nil @@ -1679,7 +1868,7 @@ func (c *Command) mergePersistentFlags() { // If c.parentsPflags == nil, it makes new. func (c *Command) updateParentsPflags() { if c.parentsPflags == nil { - c.parentsPflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + c.parentsPflags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) c.parentsPflags.SetOutput(c.flagErrorBuf) c.parentsPflags.SortFlags = false } @@ -1694,3 +1883,14 @@ func (c *Command) updateParentsPflags() { c.parentsPflags.AddFlagSet(parent.PersistentFlags()) }) } + +// commandNameMatches checks if two command names are equal +// taking into account case sensitivity according to +// EnableCaseInsensitive global configuration. +func commandNameMatches(s string, t string) bool { + if EnableCaseInsensitive { + return strings.EqualFold(s, t) + } + + return s == t +} diff --git a/vendor/github.com/spf13/cobra/command_notwin.go b/vendor/github.com/spf13/cobra/command_notwin.go index bb5dad90b7f..307f0c127fd 100644 --- a/vendor/github.com/spf13/cobra/command_notwin.go +++ b/vendor/github.com/spf13/cobra/command_notwin.go @@ -1,3 +1,17 @@ +// Copyright 2013-2023 The Cobra Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + //go:build !windows // +build !windows diff --git a/vendor/github.com/spf13/cobra/command_win.go b/vendor/github.com/spf13/cobra/command_win.go index a84f5a82aab..adbef395c25 100644 --- a/vendor/github.com/spf13/cobra/command_win.go +++ b/vendor/github.com/spf13/cobra/command_win.go @@ -1,3 +1,17 @@ +// Copyright 2013-2023 The Cobra Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + //go:build windows // +build windows diff --git a/vendor/github.com/spf13/cobra/completions.go b/vendor/github.com/spf13/cobra/completions.go index 2c24839988c..c0c08b05721 100644 --- a/vendor/github.com/spf13/cobra/completions.go +++ b/vendor/github.com/spf13/cobra/completions.go @@ -1,8 +1,24 @@ +// Copyright 2013-2023 The Cobra Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package cobra import ( "fmt" "os" + "regexp" + "strconv" "strings" "sync" @@ -63,6 +79,10 @@ const ( // obtain the same behavior but only for flags. ShellCompDirectiveFilterDirs + // ShellCompDirectiveKeepOrder indicates that the shell should preserve the order + // in which the completions are provided + ShellCompDirectiveKeepOrder + // =========================================================================== // All directives using iota should be above this one. @@ -127,6 +147,20 @@ func (c *Command) RegisterFlagCompletionFunc(flagName string, f func(cmd *Comman return nil } +// GetFlagCompletionFunc returns the completion function for the given flag of the command, if available. +func (c *Command) GetFlagCompletionFunc(flagName string) (func(*Command, []string, string) ([]string, ShellCompDirective), bool) { + flag := c.Flag(flagName) + if flag == nil { + return nil, false + } + + flagCompletionMutex.RLock() + defer flagCompletionMutex.RUnlock() + + completionFunc, exists := flagCompletionFunctions[flag] + return completionFunc, exists +} + // Returns a string listing the different directive enabled in the specified parameter func (d ShellCompDirective) string() string { var directives []string @@ -145,6 +179,9 @@ func (d ShellCompDirective) string() string { if d&ShellCompDirectiveFilterDirs != 0 { directives = append(directives, "ShellCompDirectiveFilterDirs") } + if d&ShellCompDirectiveKeepOrder != 0 { + directives = append(directives, "ShellCompDirectiveKeepOrder") + } if len(directives) == 0 { directives = append(directives, "ShellCompDirectiveDefault") } @@ -155,7 +192,7 @@ func (d ShellCompDirective) string() string { return strings.Join(directives, ", ") } -// Adds a special hidden command that can be used to request custom completions. +// initCompleteCmd adds a special hidden command that can be used to request custom completions. func (c *Command) initCompleteCmd(args []string) { completeCmd := &Command{ Use: fmt.Sprintf("%s [command-line]", ShellCompRequestCmd), @@ -176,24 +213,29 @@ func (c *Command) initCompleteCmd(args []string) { // 2- Even without completions, we need to print the directive } - noDescriptions := (cmd.CalledAs() == ShellCompNoDescRequestCmd) + noDescriptions := cmd.CalledAs() == ShellCompNoDescRequestCmd + if !noDescriptions { + if doDescriptions, err := strconv.ParseBool(getEnvConfig(cmd, configEnvVarSuffixDescriptions)); err == nil { + noDescriptions = !doDescriptions + } + } + noActiveHelp := GetActiveHelpConfig(finalCmd) == activeHelpGlobalDisable + out := finalCmd.OutOrStdout() for _, comp := range completions { - if GetActiveHelpConfig(finalCmd) == activeHelpGlobalDisable { - // Remove all activeHelp entries in this case - if strings.HasPrefix(comp, activeHelpMarker) { - continue - } + if noActiveHelp && strings.HasPrefix(comp, activeHelpMarker) { + // Remove all activeHelp entries if it's disabled. + continue } if noDescriptions { // Remove any description that may be included following a tab character. - comp = strings.Split(comp, "\t")[0] + comp = strings.SplitN(comp, "\t", 2)[0] } // Make sure we only write the first line to the output. // This is needed if a description contains a linebreak. // Otherwise the shell scripts will interpret the other lines as new flags // and could therefore provide a wrong completion. - comp = strings.Split(comp, "\n")[0] + comp = strings.SplitN(comp, "\n", 2)[0] // Finally trim the completion. This is especially important to get rid // of a trailing tab when there are no description following it. @@ -202,14 +244,14 @@ func (c *Command) initCompleteCmd(args []string) { // although there is no description). comp = strings.TrimSpace(comp) - // Print each possible completion to stdout for the completion script to consume. - fmt.Fprintln(finalCmd.OutOrStdout(), comp) + // Print each possible completion to the output for the completion script to consume. + fmt.Fprintln(out, comp) } // As the last printout, print the completion directive for the completion script to parse. // The directive integer must be that last character following a single colon (:). // The completion script expects : - fmt.Fprintf(finalCmd.OutOrStdout(), ":%d\n", directive) + fmt.Fprintf(out, ":%d\n", directive) // Print some helpful info to stderr for the user to understand. // Output from stderr must be ignored by the completion script. @@ -256,10 +298,20 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi } if err != nil { // Unable to find the real command. E.g., someInvalidCmd - return c, []string{}, ShellCompDirectiveDefault, fmt.Errorf("Unable to find a command for arguments: %v", trimmedArgs) + return c, []string{}, ShellCompDirectiveDefault, fmt.Errorf("unable to find a command for arguments: %v", trimmedArgs) } finalCmd.ctx = c.ctx + // These flags are normally added when `execute()` is called on `finalCmd`, + // however, when doing completion, we don't call `finalCmd.execute()`. + // Let's add the --help and --version flag ourselves but only if the finalCmd + // has not disabled flag parsing; if flag parsing is disabled, it is up to the + // finalCmd itself to handle the completion of *all* flags. + if !finalCmd.DisableFlagParsing { + finalCmd.InitDefaultHelpFlag() + finalCmd.InitDefaultVersionFlag() + } + // Check if we are doing flag value completion before parsing the flags. // This is important because if we are completing a flag value, we need to also // remove the flag name argument from the list of finalArgs or else the parsing @@ -292,6 +344,12 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi } } + // Look for the --help or --version flags. If they are present, + // there should be no further completions. + if helpOrVersionFlagPresent(finalCmd) { + return finalCmd, []string{}, ShellCompDirectiveNoFileComp, nil + } + // We only remove the flags from the arguments if DisableFlagParsing is not set. // This is important for commands which have requested to do their own flag completion. if !finalCmd.DisableFlagParsing { @@ -356,6 +414,11 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi finalCmd.InheritedFlags().VisitAll(func(flag *pflag.Flag) { doCompleteFlags(flag) }) + // Try to complete non-inherited flags even if DisableFlagParsing==true. + // This allows programs to tell Cobra about flags for completion even + // if the actual parsing of flags is not done by Cobra. + // For instance, Helm uses this to provide flag name completion for + // some of its plugins. finalCmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) { doCompleteFlags(flag) }) @@ -463,6 +526,18 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi return finalCmd, completions, directive, nil } +func helpOrVersionFlagPresent(cmd *Command) bool { + if versionFlag := cmd.Flags().Lookup("version"); versionFlag != nil && + len(versionFlag.Annotations[FlagSetByCobraAnnotation]) > 0 && versionFlag.Changed { + return true + } + if helpFlag := cmd.Flags().Lookup("help"); helpFlag != nil && + len(helpFlag.Annotations[FlagSetByCobraAnnotation]) > 0 && helpFlag.Changed { + return true + } + return false +} + func getFlagNameCompletions(flag *pflag.Flag, toComplete string) []string { if nonCompletableFlag(flag) { return []string{} @@ -607,12 +682,12 @@ func checkIfFlagCompletion(finalCmd *Command, args []string, lastArg string) (*p return flag, trimmedArgs, lastArg, nil } -// initDefaultCompletionCmd adds a default 'completion' command to c. +// InitDefaultCompletionCmd adds a default 'completion' command to c. // This function will do nothing if any of the following is true: // 1- the feature has been explicitly disabled by the program, // 2- c has no subcommands (to avoid creating one), // 3- c already has a 'completion' command provided by the program. -func (c *Command) initDefaultCompletionCmd() { +func (c *Command) InitDefaultCompletionCmd() { if c.CompletionOptions.DisableDefaultCmd || !c.HasSubCommands() { return } @@ -635,6 +710,7 @@ See each sub-command's help for details on how to use the generated script. Args: NoArgs, ValidArgsFunction: NoFileCompletions, Hidden: c.CompletionOptions.HiddenDefaultCmd, + GroupID: c.completionCommandGroupID, } c.AddCommand(completionCmd) @@ -688,7 +764,7 @@ to enable it. You can execute the following once: To load completions in your current shell session: - source <(%[1]s completion zsh); compdef _%[1]s %[1]s + source <(%[1]s completion zsh) To load completions for every new session, execute once: @@ -830,3 +906,34 @@ func CompError(msg string) { func CompErrorln(msg string) { CompError(fmt.Sprintf("%s\n", msg)) } + +// These values should not be changed: users will be using them explicitly. +const ( + configEnvVarGlobalPrefix = "COBRA" + configEnvVarSuffixDescriptions = "COMPLETION_DESCRIPTIONS" +) + +var configEnvVarPrefixSubstRegexp = regexp.MustCompile(`[^A-Z0-9_]`) + +// configEnvVar returns the name of the program-specific configuration environment +// variable. It has the format _ where is the name of the +// root command in upper case, with all non-ASCII-alphanumeric characters replaced by `_`. +func configEnvVar(name, suffix string) string { + // This format should not be changed: users will be using it explicitly. + v := strings.ToUpper(fmt.Sprintf("%s_%s", name, suffix)) + v = configEnvVarPrefixSubstRegexp.ReplaceAllString(v, "_") + return v +} + +// getEnvConfig returns the value of the configuration environment variable +// _ where is the name of the root command in upper +// case, with all non-ASCII-alphanumeric characters replaced by `_`. +// If the value is empty or not set, the value of the environment variable +// COBRA_ is returned instead. +func getEnvConfig(cmd *Command, suffix string) string { + v := os.Getenv(configEnvVar(cmd.Root().Name(), suffix)) + if v == "" { + v = os.Getenv(configEnvVar(configEnvVarGlobalPrefix, suffix)) + } + return v +} diff --git a/vendor/github.com/spf13/cobra/fish_completions.go b/vendor/github.com/spf13/cobra/fish_completions.go index 005ee6be73e..12d61b69111 100644 --- a/vendor/github.com/spf13/cobra/fish_completions.go +++ b/vendor/github.com/spf13/cobra/fish_completions.go @@ -1,3 +1,17 @@ +// Copyright 2013-2023 The Cobra Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package cobra import ( @@ -39,7 +53,7 @@ function __%[1]s_perform_completion __%[1]s_debug "last arg: $lastArg" # Disable ActiveHelp which is not supported for fish shell - set -l requestComp "%[9]s=0 $args[1] %[3]s $args[2..-1] $lastArg" + set -l requestComp "%[10]s=0 $args[1] %[3]s $args[2..-1] $lastArg" __%[1]s_debug "Calling $requestComp" set -l results (eval $requestComp 2> /dev/null) @@ -75,6 +89,60 @@ function __%[1]s_perform_completion printf "%%s\n" "$directiveLine" end +# this function limits calls to __%[1]s_perform_completion, by caching the result behind $__%[1]s_perform_completion_once_result +function __%[1]s_perform_completion_once + __%[1]s_debug "Starting __%[1]s_perform_completion_once" + + if test -n "$__%[1]s_perform_completion_once_result" + __%[1]s_debug "Seems like a valid result already exists, skipping __%[1]s_perform_completion" + return 0 + end + + set --global __%[1]s_perform_completion_once_result (__%[1]s_perform_completion) + if test -z "$__%[1]s_perform_completion_once_result" + __%[1]s_debug "No completions, probably due to a failure" + return 1 + end + + __%[1]s_debug "Performed completions and set __%[1]s_perform_completion_once_result" + return 0 +end + +# this function is used to clear the $__%[1]s_perform_completion_once_result variable after completions are run +function __%[1]s_clear_perform_completion_once_result + __%[1]s_debug "" + __%[1]s_debug "========= clearing previously set __%[1]s_perform_completion_once_result variable ==========" + set --erase __%[1]s_perform_completion_once_result + __%[1]s_debug "Successfully erased the variable __%[1]s_perform_completion_once_result" +end + +function __%[1]s_requires_order_preservation + __%[1]s_debug "" + __%[1]s_debug "========= checking if order preservation is required ==========" + + __%[1]s_perform_completion_once + if test -z "$__%[1]s_perform_completion_once_result" + __%[1]s_debug "Error determining if order preservation is required" + return 1 + end + + set -l directive (string sub --start 2 $__%[1]s_perform_completion_once_result[-1]) + __%[1]s_debug "Directive is: $directive" + + set -l shellCompDirectiveKeepOrder %[9]d + set -l keeporder (math (math --scale 0 $directive / $shellCompDirectiveKeepOrder) %% 2) + __%[1]s_debug "Keeporder is: $keeporder" + + if test $keeporder -ne 0 + __%[1]s_debug "This does require order preservation" + return 0 + end + + __%[1]s_debug "This doesn't require order preservation" + return 1 +end + + # This function does two things: # - Obtain the completions and store them in the global __%[1]s_comp_results # - Return false if file completion should be performed @@ -85,17 +153,17 @@ function __%[1]s_prepare_completions # Start fresh set --erase __%[1]s_comp_results - set -l results (__%[1]s_perform_completion) - __%[1]s_debug "Completion results: $results" + __%[1]s_perform_completion_once + __%[1]s_debug "Completion results: $__%[1]s_perform_completion_once_result" - if test -z "$results" + if test -z "$__%[1]s_perform_completion_once_result" __%[1]s_debug "No completion, probably due to a failure" # Might as well do file completion, in case it helps return 1 end - set -l directive (string sub --start 2 $results[-1]) - set --global __%[1]s_comp_results $results[1..-2] + set -l directive (string sub --start 2 $__%[1]s_perform_completion_once_result[-1]) + set --global __%[1]s_comp_results $__%[1]s_perform_completion_once_result[1..-2] __%[1]s_debug "Completions are: $__%[1]s_comp_results" __%[1]s_debug "Directive is: $directive" @@ -191,13 +259,17 @@ end # Remove any pre-existing completions for the program since we will be handling all of them. complete -c %[2]s -e +# this will get called after the two calls below and clear the $__%[1]s_perform_completion_once_result global +complete -c %[2]s -n '__%[1]s_clear_perform_completion_once_result' # The call to __%[1]s_prepare_completions will setup __%[1]s_comp_results # which provides the program's completion choices. -complete -c %[2]s -n '__%[1]s_prepare_completions' -f -a '$__%[1]s_comp_results' - +# If this doesn't require order preservation, we don't use the -k flag +complete -c %[2]s -n 'not __%[1]s_requires_order_preservation && __%[1]s_prepare_completions' -f -a '$__%[1]s_comp_results' +# otherwise we use the -k flag +complete -k -c %[2]s -n '__%[1]s_requires_order_preservation && __%[1]s_prepare_completions' -f -a '$__%[1]s_comp_results' `, nameForVar, name, compCmd, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, - ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, activeHelpEnvVar(name))) + ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveKeepOrder, activeHelpEnvVar(name))) } // GenFishCompletion generates fish completion file and writes to the passed writer. diff --git a/vendor/github.com/spf13/cobra/fish_completions.md b/vendor/github.com/spf13/cobra/fish_completions.md deleted file mode 100644 index 19b2ed1293a..00000000000 --- a/vendor/github.com/spf13/cobra/fish_completions.md +++ /dev/null @@ -1,4 +0,0 @@ -## Generating Fish Completions For Your cobra.Command - -Please refer to [Shell Completions](shell_completions.md) for details. - diff --git a/vendor/github.com/spf13/cobra/flag_groups.go b/vendor/github.com/spf13/cobra/flag_groups.go index dc78431194c..560612fd338 100644 --- a/vendor/github.com/spf13/cobra/flag_groups.go +++ b/vendor/github.com/spf13/cobra/flag_groups.go @@ -1,9 +1,10 @@ -// Copyright © 2022 Steve Francia . +// Copyright 2013-2023 The Cobra Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 +// +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -22,8 +23,9 @@ import ( ) const ( - requiredAsGroup = "cobra_annotation_required_if_others_set" - mutuallyExclusive = "cobra_annotation_mutually_exclusive" + requiredAsGroupAnnotation = "cobra_annotation_required_if_others_set" + oneRequiredAnnotation = "cobra_annotation_one_required" + mutuallyExclusiveAnnotation = "cobra_annotation_mutually_exclusive" ) // MarkFlagsRequiredTogether marks the given flags with annotations so that Cobra errors @@ -35,7 +37,23 @@ func (c *Command) MarkFlagsRequiredTogether(flagNames ...string) { if f == nil { panic(fmt.Sprintf("Failed to find flag %q and mark it as being required in a flag group", v)) } - if err := c.Flags().SetAnnotation(v, requiredAsGroup, append(f.Annotations[requiredAsGroup], strings.Join(flagNames, " "))); err != nil { + if err := c.Flags().SetAnnotation(v, requiredAsGroupAnnotation, append(f.Annotations[requiredAsGroupAnnotation], strings.Join(flagNames, " "))); err != nil { + // Only errs if the flag isn't found. + panic(err) + } + } +} + +// MarkFlagsOneRequired marks the given flags with annotations so that Cobra errors +// if the command is invoked without at least one flag from the given set of flags. +func (c *Command) MarkFlagsOneRequired(flagNames ...string) { + c.mergePersistentFlags() + for _, v := range flagNames { + f := c.Flags().Lookup(v) + if f == nil { + panic(fmt.Sprintf("Failed to find flag %q and mark it as being in a one-required flag group", v)) + } + if err := c.Flags().SetAnnotation(v, oneRequiredAnnotation, append(f.Annotations[oneRequiredAnnotation], strings.Join(flagNames, " "))); err != nil { // Only errs if the flag isn't found. panic(err) } @@ -52,15 +70,15 @@ func (c *Command) MarkFlagsMutuallyExclusive(flagNames ...string) { panic(fmt.Sprintf("Failed to find flag %q and mark it as being in a mutually exclusive flag group", v)) } // Each time this is called is a single new entry; this allows it to be a member of multiple groups if needed. - if err := c.Flags().SetAnnotation(v, mutuallyExclusive, append(f.Annotations[mutuallyExclusive], strings.Join(flagNames, " "))); err != nil { + if err := c.Flags().SetAnnotation(v, mutuallyExclusiveAnnotation, append(f.Annotations[mutuallyExclusiveAnnotation], strings.Join(flagNames, " "))); err != nil { panic(err) } } } -// validateFlagGroups validates the mutuallyExclusive/requiredAsGroup logic and returns the +// ValidateFlagGroups validates the mutuallyExclusive/oneRequired/requiredAsGroup logic and returns the // first error encountered. -func (c *Command) validateFlagGroups() error { +func (c *Command) ValidateFlagGroups() error { if c.DisableFlagParsing { return nil } @@ -70,15 +88,20 @@ func (c *Command) validateFlagGroups() error { // groupStatus format is the list of flags as a unique ID, // then a map of each flag name and whether it is set or not. groupStatus := map[string]map[string]bool{} + oneRequiredGroupStatus := map[string]map[string]bool{} mutuallyExclusiveGroupStatus := map[string]map[string]bool{} flags.VisitAll(func(pflag *flag.Flag) { - processFlagForGroupAnnotation(flags, pflag, requiredAsGroup, groupStatus) - processFlagForGroupAnnotation(flags, pflag, mutuallyExclusive, mutuallyExclusiveGroupStatus) + processFlagForGroupAnnotation(flags, pflag, requiredAsGroupAnnotation, groupStatus) + processFlagForGroupAnnotation(flags, pflag, oneRequiredAnnotation, oneRequiredGroupStatus) + processFlagForGroupAnnotation(flags, pflag, mutuallyExclusiveAnnotation, mutuallyExclusiveGroupStatus) }) if err := validateRequiredFlagGroups(groupStatus); err != nil { return err } + if err := validateOneRequiredFlagGroups(oneRequiredGroupStatus); err != nil { + return err + } if err := validateExclusiveFlagGroups(mutuallyExclusiveGroupStatus); err != nil { return err } @@ -107,7 +130,7 @@ func processFlagForGroupAnnotation(flags *flag.FlagSet, pflag *flag.Flag, annota continue } - groupStatus[group] = map[string]bool{} + groupStatus[group] = make(map[string]bool, len(flagnames)) for _, name := range flagnames { groupStatus[group][name] = false } @@ -141,6 +164,27 @@ func validateRequiredFlagGroups(data map[string]map[string]bool) error { return nil } +func validateOneRequiredFlagGroups(data map[string]map[string]bool) error { + keys := sortedKeys(data) + for _, flagList := range keys { + flagnameAndStatus := data[flagList] + var set []string + for flagname, isSet := range flagnameAndStatus { + if isSet { + set = append(set, flagname) + } + } + if len(set) >= 1 { + continue + } + + // Sort values, so they can be tested/scripted against consistently. + sort.Strings(set) + return fmt.Errorf("at least one of the flags in the group [%v] is required", flagList) + } + return nil +} + func validateExclusiveFlagGroups(data map[string]map[string]bool) error { keys := sortedKeys(data) for _, flagList := range keys { @@ -175,6 +219,7 @@ func sortedKeys(m map[string]map[string]bool) []string { // enforceFlagGroupsForCompletion will do the following: // - when a flag in a group is present, other flags in the group will be marked required +// - when none of the flags in a one-required group are present, all flags in the group will be marked required // - when a flag in a mutually exclusive group is present, other flags in the group will be marked as hidden // This allows the standard completion logic to behave appropriately for flag groups func (c *Command) enforceFlagGroupsForCompletion() { @@ -184,10 +229,12 @@ func (c *Command) enforceFlagGroupsForCompletion() { flags := c.Flags() groupStatus := map[string]map[string]bool{} + oneRequiredGroupStatus := map[string]map[string]bool{} mutuallyExclusiveGroupStatus := map[string]map[string]bool{} c.Flags().VisitAll(func(pflag *flag.Flag) { - processFlagForGroupAnnotation(flags, pflag, requiredAsGroup, groupStatus) - processFlagForGroupAnnotation(flags, pflag, mutuallyExclusive, mutuallyExclusiveGroupStatus) + processFlagForGroupAnnotation(flags, pflag, requiredAsGroupAnnotation, groupStatus) + processFlagForGroupAnnotation(flags, pflag, oneRequiredAnnotation, oneRequiredGroupStatus) + processFlagForGroupAnnotation(flags, pflag, mutuallyExclusiveAnnotation, mutuallyExclusiveGroupStatus) }) // If a flag that is part of a group is present, we make all the other flags @@ -203,6 +250,26 @@ func (c *Command) enforceFlagGroupsForCompletion() { } } + // If none of the flags of a one-required group are present, we make all the flags + // of that group required so that the shell completion suggests them automatically + for flagList, flagnameAndStatus := range oneRequiredGroupStatus { + isSet := false + + for _, isSet = range flagnameAndStatus { + if isSet { + break + } + } + + // None of the flags of the group are set, mark all flags in the group + // as required + if !isSet { + for _, fName := range strings.Split(flagList, " ") { + _ = c.MarkFlagRequired(fName) + } + } + } + // If a flag that is mutually exclusive to others is present, we hide the other // flags of that group so the shell completion does not suggest them for flagList, flagnameAndStatus := range mutuallyExclusiveGroupStatus { diff --git a/vendor/github.com/spf13/cobra/powershell_completions.go b/vendor/github.com/spf13/cobra/powershell_completions.go index 379e7c088af..a830b7bcad2 100644 --- a/vendor/github.com/spf13/cobra/powershell_completions.go +++ b/vendor/github.com/spf13/cobra/powershell_completions.go @@ -1,3 +1,17 @@ +// Copyright 2013-2023 The Cobra Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + // The generated scripts require PowerShell v5.0+ (which comes Windows 10, but // can be downloaded separately for windows 7 or 8.1). @@ -8,9 +22,15 @@ import ( "fmt" "io" "os" + "strings" ) func genPowerShellComp(buf io.StringWriter, name string, includeDesc bool) { + // Variables should not contain a '-' or ':' character + nameForVar := name + nameForVar = strings.ReplaceAll(nameForVar, "-", "_") + nameForVar = strings.ReplaceAll(nameForVar, ":", "_") + compCmd := ShellCompRequestCmd if !includeDesc { compCmd = ShellCompNoDescRequestCmd @@ -27,7 +47,7 @@ filter __%[1]s_escapeStringWithSpecialChars { `+" $_ -replace '\\s|#|@|\\$|;|,|''|\\{|\\}|\\(|\\)|\"|`|\\||<|>|&','`$&'"+` } -Register-ArgumentCompleter -CommandName '%[1]s' -ScriptBlock { +[scriptblock]${__%[2]sCompleterBlock} = { param( $WordToComplete, $CommandAst, @@ -52,17 +72,18 @@ Register-ArgumentCompleter -CommandName '%[1]s' -ScriptBlock { } __%[1]s_debug "Truncated command: $Command" - $ShellCompDirectiveError=%[3]d - $ShellCompDirectiveNoSpace=%[4]d - $ShellCompDirectiveNoFileComp=%[5]d - $ShellCompDirectiveFilterFileExt=%[6]d - $ShellCompDirectiveFilterDirs=%[7]d + $ShellCompDirectiveError=%[4]d + $ShellCompDirectiveNoSpace=%[5]d + $ShellCompDirectiveNoFileComp=%[6]d + $ShellCompDirectiveFilterFileExt=%[7]d + $ShellCompDirectiveFilterDirs=%[8]d + $ShellCompDirectiveKeepOrder=%[9]d # Prepare the command to request completions for the program. # Split the command at the first space to separate the program and arguments. $Program,$Arguments = $Command.Split(" ",2) - $RequestComp="$Program %[2]s $Arguments" + $RequestComp="$Program %[3]s $Arguments" __%[1]s_debug "RequestComp: $RequestComp" # we cannot use $WordToComplete because it @@ -86,13 +107,22 @@ Register-ArgumentCompleter -CommandName '%[1]s' -ScriptBlock { # If the last parameter is complete (there is a space following it) # We add an extra empty parameter so we can indicate this to the go method. __%[1]s_debug "Adding extra empty parameter" -`+" # We need to use `\"`\" to pass an empty argument a \"\" or '' does not work!!!"+` -`+" $RequestComp=\"$RequestComp\" + ' `\"`\"'"+` + # PowerShell 7.2+ changed the way how the arguments are passed to executables, + # so for pre-7.2 or when Legacy argument passing is enabled we need to use +`+" # `\"`\" to pass an empty argument, a \"\" or '' does not work!!!"+` + if ($PSVersionTable.PsVersion -lt [version]'7.2.0' -or + ($PSVersionTable.PsVersion -lt [version]'7.3.0' -and -not [ExperimentalFeature]::IsEnabled("PSNativeCommandArgumentPassing")) -or + (($PSVersionTable.PsVersion -ge [version]'7.3.0' -or [ExperimentalFeature]::IsEnabled("PSNativeCommandArgumentPassing")) -and + $PSNativeCommandArgumentPassing -eq 'Legacy')) { +`+" $RequestComp=\"$RequestComp\" + ' `\"`\"'"+` + } else { + $RequestComp="$RequestComp" + ' ""' + } } __%[1]s_debug "Calling $RequestComp" # First disable ActiveHelp which is not supported for Powershell - $env:%[8]s=0 + ${env:%[10]s}=0 #call the command store the output in $out and redirect stderr and stdout to null # $Out is an array contains each line per element @@ -117,7 +147,7 @@ Register-ArgumentCompleter -CommandName '%[1]s' -ScriptBlock { } $Longest = 0 - $Values = $Out | ForEach-Object { + [Array]$Values = $Out | ForEach-Object { #Split the output in name and description `+" $Name, $Description = $_.Split(\"`t\",2)"+` __%[1]s_debug "Name: $Name Description: $Description" @@ -162,6 +192,11 @@ Register-ArgumentCompleter -CommandName '%[1]s' -ScriptBlock { } } + # we sort the values in ascending order by name if keep order isn't passed + if (($Directive -band $ShellCompDirectiveKeepOrder) -eq 0 ) { + $Values = $Values | Sort-Object -Property Name + } + if (($Directive -band $ShellCompDirectiveNoFileComp) -ne 0 ) { __%[1]s_debug "ShellCompDirectiveNoFileComp is called" @@ -243,9 +278,11 @@ Register-ArgumentCompleter -CommandName '%[1]s' -ScriptBlock { } } -`, name, compCmd, + +Register-ArgumentCompleter -CommandName '%[1]s' -ScriptBlock ${__%[2]sCompleterBlock} +`, name, nameForVar, compCmd, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, - ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, activeHelpEnvVar(name))) + ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveKeepOrder, activeHelpEnvVar(name))) } func (c *Command) genPowerShellCompletion(w io.Writer, includeDesc bool) error { diff --git a/vendor/github.com/spf13/cobra/powershell_completions.md b/vendor/github.com/spf13/cobra/powershell_completions.md deleted file mode 100644 index c449f1e5c0f..00000000000 --- a/vendor/github.com/spf13/cobra/powershell_completions.md +++ /dev/null @@ -1,3 +0,0 @@ -# Generating PowerShell Completions For Your Own cobra.Command - -Please refer to [Shell Completions](shell_completions.md#powershell-completions) for details. diff --git a/vendor/github.com/spf13/cobra/projects_using_cobra.md b/vendor/github.com/spf13/cobra/projects_using_cobra.md deleted file mode 100644 index ac680118eff..00000000000 --- a/vendor/github.com/spf13/cobra/projects_using_cobra.md +++ /dev/null @@ -1,54 +0,0 @@ -## Projects using Cobra - -- [Arduino CLI](https://github.com/arduino/arduino-cli) -- [Bleve](https://blevesearch.com/) -- [CockroachDB](https://www.cockroachlabs.com/) -- [Cosmos SDK](https://github.com/cosmos/cosmos-sdk) -- [Datree](https://github.com/datreeio/datree) -- [Delve](https://github.com/derekparker/delve) -- [Docker (distribution)](https://github.com/docker/distribution) -- [Etcd](https://etcd.io/) -- [Gardener](https://github.com/gardener/gardenctl) -- [Giant Swarm's gsctl](https://github.com/giantswarm/gsctl) -- [Git Bump](https://github.com/erdaltsksn/git-bump) -- [Github CLI](https://github.com/cli/cli) -- [GitHub Labeler](https://github.com/erdaltsksn/gh-label) -- [Golangci-lint](https://golangci-lint.run) -- [GopherJS](https://github.com/gopherjs/gopherjs) -- [GoReleaser](https://goreleaser.com) -- [Helm](https://helm.sh) -- [Hugo](https://gohugo.io) -- [Infracost](https://github.com/infracost/infracost) -- [Istio](https://istio.io) -- [Kool](https://github.com/kool-dev/kool) -- [Kubernetes](https://kubernetes.io/) -- [Kubescape](https://github.com/armosec/kubescape) -- [Linkerd](https://linkerd.io/) -- [Mattermost-server](https://github.com/mattermost/mattermost-server) -- [Mercure](https://mercure.rocks/) -- [Meroxa CLI](https://github.com/meroxa/cli) -- [Metal Stack CLI](https://github.com/metal-stack/metalctl) -- [Moby (former Docker)](https://github.com/moby/moby) -- [Moldy](https://github.com/Moldy-Community/moldy) -- [Multi-gitter](https://github.com/lindell/multi-gitter) -- [Nanobox](https://github.com/nanobox-io/nanobox)/[Nanopack](https://github.com/nanopack) -- [nFPM](https://nfpm.goreleaser.com) -- [OpenShift](https://www.openshift.com/) -- [Ory Hydra](https://github.com/ory/hydra) -- [Ory Kratos](https://github.com/ory/kratos) -- [Pixie](https://github.com/pixie-io/pixie) -- [Polygon Edge](https://github.com/0xPolygon/polygon-edge) -- [Pouch](https://github.com/alibaba/pouch) -- [ProjectAtomic (enterprise)](https://www.projectatomic.io/) -- [Prototool](https://github.com/uber/prototool) -- [Pulumi](https://www.pulumi.com) -- [QRcp](https://github.com/claudiodangelis/qrcp) -- [Random](https://github.com/erdaltsksn/random) -- [Rclone](https://rclone.org/) -- [Scaleway CLI](https://github.com/scaleway/scaleway-cli) -- [Skaffold](https://skaffold.dev/) -- [Tendermint](https://github.com/tendermint/tendermint) -- [Twitch CLI](https://github.com/twitchdev/twitch-cli) -- [UpCloud CLI (`upctl`)](https://github.com/UpCloudLtd/upcloud-cli) -- VMware's [Tanzu Community Edition](https://github.com/vmware-tanzu/community-edition) & [Tanzu Framework](https://github.com/vmware-tanzu/tanzu-framework) -- [Werf](https://werf.io/) diff --git a/vendor/github.com/spf13/cobra/shell_completions.go b/vendor/github.com/spf13/cobra/shell_completions.go index d99bf91e5f9..b035742d399 100644 --- a/vendor/github.com/spf13/cobra/shell_completions.go +++ b/vendor/github.com/spf13/cobra/shell_completions.go @@ -1,3 +1,17 @@ +// Copyright 2013-2023 The Cobra Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package cobra import ( diff --git a/vendor/github.com/spf13/cobra/shell_completions.md b/vendor/github.com/spf13/cobra/shell_completions.md deleted file mode 100644 index 1e2058ed625..00000000000 --- a/vendor/github.com/spf13/cobra/shell_completions.md +++ /dev/null @@ -1,548 +0,0 @@ -# Generating shell completions - -Cobra can generate shell completions for multiple shells. -The currently supported shells are: -- Bash -- Zsh -- fish -- PowerShell - -Cobra will automatically provide your program with a fully functional `completion` command, -similarly to how it provides the `help` command. - -## Creating your own completion command - -If you do not wish to use the default `completion` command, you can choose to -provide your own, which will take precedence over the default one. (This also provides -backwards-compatibility with programs that already have their own `completion` command.) - -If you are using the `cobra-cli` generator, -which can be found at [spf13/cobra-cli](https://github.com/spf13/cobra-cli), -you can create a completion command by running - -```bash -cobra-cli add completion -``` -and then modifying the generated `cmd/completion.go` file to look something like this -(writing the shell script to stdout allows the most flexible use): - -```go -var completionCmd = &cobra.Command{ - Use: "completion [bash|zsh|fish|powershell]", - Short: "Generate completion script", - Long: fmt.Sprintf(`To load completions: - -Bash: - - $ source <(%[1]s completion bash) - - # To load completions for each session, execute once: - # Linux: - $ %[1]s completion bash > /etc/bash_completion.d/%[1]s - # macOS: - $ %[1]s completion bash > $(brew --prefix)/etc/bash_completion.d/%[1]s - -Zsh: - - # If shell completion is not already enabled in your environment, - # you will need to enable it. You can execute the following once: - - $ echo "autoload -U compinit; compinit" >> ~/.zshrc - - # To load completions for each session, execute once: - $ %[1]s completion zsh > "${fpath[1]}/_%[1]s" - - # You will need to start a new shell for this setup to take effect. - -fish: - - $ %[1]s completion fish | source - - # To load completions for each session, execute once: - $ %[1]s completion fish > ~/.config/fish/completions/%[1]s.fish - -PowerShell: - - PS> %[1]s completion powershell | Out-String | Invoke-Expression - - # To load completions for every new session, run: - PS> %[1]s completion powershell > %[1]s.ps1 - # and source this file from your PowerShell profile. -`,cmd.Root().Name()), - DisableFlagsInUseLine: true, - ValidArgs: []string{"bash", "zsh", "fish", "powershell"}, - Args: cobra.ExactValidArgs(1), - Run: func(cmd *cobra.Command, args []string) { - switch args[0] { - case "bash": - cmd.Root().GenBashCompletion(os.Stdout) - case "zsh": - cmd.Root().GenZshCompletion(os.Stdout) - case "fish": - cmd.Root().GenFishCompletion(os.Stdout, true) - case "powershell": - cmd.Root().GenPowerShellCompletionWithDesc(os.Stdout) - } - }, -} -``` - -**Note:** The cobra generator may include messages printed to stdout, for example, if the config file is loaded; this will break the auto-completion script so must be removed. - -## Adapting the default completion command - -Cobra provides a few options for the default `completion` command. To configure such options you must set -the `CompletionOptions` field on the *root* command. - -To tell Cobra *not* to provide the default `completion` command: -``` -rootCmd.CompletionOptions.DisableDefaultCmd = true -``` - -To tell Cobra *not* to provide the user with the `--no-descriptions` flag to the completion sub-commands: -``` -rootCmd.CompletionOptions.DisableNoDescFlag = true -``` - -To tell Cobra to completely disable descriptions for completions: -``` -rootCmd.CompletionOptions.DisableDescriptions = true -``` - -# Customizing completions - -The generated completion scripts will automatically handle completing commands and flags. However, you can make your completions much more powerful by providing information to complete your program's nouns and flag values. - -## Completion of nouns - -### Static completion of nouns - -Cobra allows you to provide a pre-defined list of completion choices for your nouns using the `ValidArgs` field. -For example, if you want `kubectl get [tab][tab]` to show a list of valid "nouns" you have to set them. -Some simplified code from `kubectl get` looks like: - -```go -validArgs = []string{ "pod", "node", "service", "replicationcontroller" } - -cmd := &cobra.Command{ - Use: "get [(-o|--output=)json|yaml|template|...] (RESOURCE [NAME] | RESOURCE/NAME ...)", - Short: "Display one or many resources", - Long: get_long, - Example: get_example, - Run: func(cmd *cobra.Command, args []string) { - cobra.CheckErr(RunGet(f, out, cmd, args)) - }, - ValidArgs: validArgs, -} -``` - -Notice we put the `ValidArgs` field on the `get` sub-command. Doing so will give results like: - -```bash -$ kubectl get [tab][tab] -node pod replicationcontroller service -``` - -#### Aliases for nouns - -If your nouns have aliases, you can define them alongside `ValidArgs` using `ArgAliases`: - -```go -argAliases = []string { "pods", "nodes", "services", "svc", "replicationcontrollers", "rc" } - -cmd := &cobra.Command{ - ... - ValidArgs: validArgs, - ArgAliases: argAliases -} -``` - -The aliases are not shown to the user on tab completion, but they are accepted as valid nouns by -the completion algorithm if entered manually, e.g. in: - -```bash -$ kubectl get rc [tab][tab] -backend frontend database -``` - -Note that without declaring `rc` as an alias, the completion algorithm would not know to show the list of -replication controllers following `rc`. - -### Dynamic completion of nouns - -In some cases it is not possible to provide a list of completions in advance. Instead, the list of completions must be determined at execution-time. In a similar fashion as for static completions, you can use the `ValidArgsFunction` field to provide a Go function that Cobra will execute when it needs the list of completion choices for the nouns of a command. Note that either `ValidArgs` or `ValidArgsFunction` can be used for a single cobra command, but not both. -Simplified code from `helm status` looks like: - -```go -cmd := &cobra.Command{ - Use: "status RELEASE_NAME", - Short: "Display the status of the named release", - Long: status_long, - RunE: func(cmd *cobra.Command, args []string) { - RunGet(args[0]) - }, - ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - if len(args) != 0 { - return nil, cobra.ShellCompDirectiveNoFileComp - } - return getReleasesFromCluster(toComplete), cobra.ShellCompDirectiveNoFileComp - }, -} -``` -Where `getReleasesFromCluster()` is a Go function that obtains the list of current Helm releases running on the Kubernetes cluster. -Notice we put the `ValidArgsFunction` on the `status` sub-command. Let's assume the Helm releases on the cluster are: `harbor`, `notary`, `rook` and `thanos` then this dynamic completion will give results like: - -```bash -$ helm status [tab][tab] -harbor notary rook thanos -``` -You may have noticed the use of `cobra.ShellCompDirective`. These directives are bit fields allowing to control some shell completion behaviors for your particular completion. You can combine them with the bit-or operator such as `cobra.ShellCompDirectiveNoSpace | cobra.ShellCompDirectiveNoFileComp` -```go -// Indicates that the shell will perform its default behavior after completions -// have been provided (this implies none of the other directives). -ShellCompDirectiveDefault - -// Indicates an error occurred and completions should be ignored. -ShellCompDirectiveError - -// Indicates that the shell should not add a space after the completion, -// even if there is a single completion provided. -ShellCompDirectiveNoSpace - -// Indicates that the shell should not provide file completion even when -// no completion is provided. -ShellCompDirectiveNoFileComp - -// Indicates that the returned completions should be used as file extension filters. -// For example, to complete only files of the form *.json or *.yaml: -// return []string{"yaml", "json"}, ShellCompDirectiveFilterFileExt -// For flags, using MarkFlagFilename() and MarkPersistentFlagFilename() -// is a shortcut to using this directive explicitly. -// -ShellCompDirectiveFilterFileExt - -// Indicates that only directory names should be provided in file completion. -// For example: -// return nil, ShellCompDirectiveFilterDirs -// For flags, using MarkFlagDirname() is a shortcut to using this directive explicitly. -// -// To request directory names within another directory, the returned completions -// should specify a single directory name within which to search. For example, -// to complete directories within "themes/": -// return []string{"themes"}, ShellCompDirectiveFilterDirs -// -ShellCompDirectiveFilterDirs -``` - -***Note***: When using the `ValidArgsFunction`, Cobra will call your registered function after having parsed all flags and arguments provided in the command-line. You therefore don't need to do this parsing yourself. For example, when a user calls `helm status --namespace my-rook-ns [tab][tab]`, Cobra will call your registered `ValidArgsFunction` after having parsed the `--namespace` flag, as it would have done when calling the `RunE` function. - -#### Debugging - -Cobra achieves dynamic completion through the use of a hidden command called by the completion script. To debug your Go completion code, you can call this hidden command directly: -```bash -$ helm __complete status har -harbor -:4 -Completion ended with directive: ShellCompDirectiveNoFileComp # This is on stderr -``` -***Important:*** If the noun to complete is empty (when the user has not yet typed any letters of that noun), you must pass an empty parameter to the `__complete` command: -```bash -$ helm __complete status "" -harbor -notary -rook -thanos -:4 -Completion ended with directive: ShellCompDirectiveNoFileComp # This is on stderr -``` -Calling the `__complete` command directly allows you to run the Go debugger to troubleshoot your code. You can also add printouts to your code; Cobra provides the following functions to use for printouts in Go completion code: -```go -// Prints to the completion script debug file (if BASH_COMP_DEBUG_FILE -// is set to a file path) and optionally prints to stderr. -cobra.CompDebug(msg string, printToStdErr bool) { -cobra.CompDebugln(msg string, printToStdErr bool) - -// Prints to the completion script debug file (if BASH_COMP_DEBUG_FILE -// is set to a file path) and to stderr. -cobra.CompError(msg string) -cobra.CompErrorln(msg string) -``` -***Important:*** You should **not** leave traces that print directly to stdout in your completion code as they will be interpreted as completion choices by the completion script. Instead, use the cobra-provided debugging traces functions mentioned above. - -## Completions for flags - -### Mark flags as required - -Most of the time completions will only show sub-commands. But if a flag is required to make a sub-command work, you probably want it to show up when the user types [tab][tab]. You can mark a flag as 'Required' like so: - -```go -cmd.MarkFlagRequired("pod") -cmd.MarkFlagRequired("container") -``` - -and you'll get something like - -```bash -$ kubectl exec [tab][tab] --c --container= -p --pod= -``` - -### Specify dynamic flag completion - -As for nouns, Cobra provides a way of defining dynamic completion of flags. To provide a Go function that Cobra will execute when it needs the list of completion choices for a flag, you must register the function using the `command.RegisterFlagCompletionFunc()` function. - -```go -flagName := "output" -cmd.RegisterFlagCompletionFunc(flagName, func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return []string{"json", "table", "yaml"}, cobra.ShellCompDirectiveDefault -}) -``` -Notice that calling `RegisterFlagCompletionFunc()` is done through the `command` with which the flag is associated. In our example this dynamic completion will give results like so: - -```bash -$ helm status --output [tab][tab] -json table yaml -``` - -#### Debugging - -You can also easily debug your Go completion code for flags: -```bash -$ helm __complete status --output "" -json -table -yaml -:4 -Completion ended with directive: ShellCompDirectiveNoFileComp # This is on stderr -``` -***Important:*** You should **not** leave traces that print to stdout in your completion code as they will be interpreted as completion choices by the completion script. Instead, use the cobra-provided debugging traces functions mentioned further above. - -### Specify valid filename extensions for flags that take a filename - -To limit completions of flag values to file names with certain extensions you can either use the different `MarkFlagFilename()` functions or a combination of `RegisterFlagCompletionFunc()` and `ShellCompDirectiveFilterFileExt`, like so: -```go -flagName := "output" -cmd.MarkFlagFilename(flagName, "yaml", "json") -``` -or -```go -flagName := "output" -cmd.RegisterFlagCompletionFunc(flagName, func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return []string{"yaml", "json"}, ShellCompDirectiveFilterFileExt}) -``` - -### Limit flag completions to directory names - -To limit completions of flag values to directory names you can either use the `MarkFlagDirname()` functions or a combination of `RegisterFlagCompletionFunc()` and `ShellCompDirectiveFilterDirs`, like so: -```go -flagName := "output" -cmd.MarkFlagDirname(flagName) -``` -or -```go -flagName := "output" -cmd.RegisterFlagCompletionFunc(flagName, func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return nil, cobra.ShellCompDirectiveFilterDirs -}) -``` -To limit completions of flag values to directory names *within another directory* you can use a combination of `RegisterFlagCompletionFunc()` and `ShellCompDirectiveFilterDirs` like so: -```go -flagName := "output" -cmd.RegisterFlagCompletionFunc(flagName, func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return []string{"themes"}, cobra.ShellCompDirectiveFilterDirs -}) -``` -### Descriptions for completions - -Cobra provides support for completion descriptions. Such descriptions are supported for each shell -(however, for bash, it is only available in the [completion V2 version](#bash-completion-v2)). -For commands and flags, Cobra will provide the descriptions automatically, based on usage information. -For example, using zsh: -``` -$ helm s[tab] -search -- search for a keyword in charts -show -- show information of a chart -status -- displays the status of the named release -``` -while using fish: -``` -$ helm s[tab] -search (search for a keyword in charts) show (show information of a chart) status (displays the status of the named release) -``` - -Cobra allows you to add descriptions to your own completions. Simply add the description text after each completion, following a `\t` separator. This technique applies to completions returned by `ValidArgs`, `ValidArgsFunction` and `RegisterFlagCompletionFunc()`. For example: -```go -ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return []string{"harbor\tAn image registry", "thanos\tLong-term metrics"}, cobra.ShellCompDirectiveNoFileComp -}} -``` -or -```go -ValidArgs: []string{"bash\tCompletions for bash", "zsh\tCompletions for zsh"} -``` -## Bash completions - -### Dependencies - -The bash completion script generated by Cobra requires the `bash_completion` package. You should update the help text of your completion command to show how to install the `bash_completion` package ([Kubectl docs](https://kubernetes.io/docs/tasks/tools/install-kubectl/#enabling-shell-autocompletion)) - -### Aliases - -You can also configure `bash` aliases for your program and they will also support completions. - -```bash -alias aliasname=origcommand -complete -o default -F __start_origcommand aliasname - -# and now when you run `aliasname` completion will make -# suggestions as it did for `origcommand`. - -$ aliasname -completion firstcommand secondcommand -``` -### Bash legacy dynamic completions - -For backward compatibility, Cobra still supports its bash legacy dynamic completion solution. -Please refer to [Bash Completions](bash_completions.md) for details. - -### Bash completion V2 - -Cobra provides two versions for bash completion. The original bash completion (which started it all!) can be used by calling -`GenBashCompletion()` or `GenBashCompletionFile()`. - -A new V2 bash completion version is also available. This version can be used by calling `GenBashCompletionV2()` or -`GenBashCompletionFileV2()`. The V2 version does **not** support the legacy dynamic completion -(see [Bash Completions](bash_completions.md)) but instead works only with the Go dynamic completion -solution described in this document. -Unless your program already uses the legacy dynamic completion solution, it is recommended that you use the bash -completion V2 solution which provides the following extra features: -- Supports completion descriptions (like the other shells) -- Small completion script of less than 300 lines (v1 generates scripts of thousands of lines; `kubectl` for example has a bash v1 completion script of over 13K lines) -- Streamlined user experience thanks to a completion behavior aligned with the other shells - -`Bash` completion V2 supports descriptions for completions. When calling `GenBashCompletionV2()` or `GenBashCompletionFileV2()` -you must provide these functions with a parameter indicating if the completions should be annotated with a description; Cobra -will provide the description automatically based on usage information. You can choose to make this option configurable by -your users. - -``` -# With descriptions -$ helm s[tab][tab] -search (search for a keyword in charts) status (display the status of the named release) -show (show information of a chart) - -# Without descriptions -$ helm s[tab][tab] -search show status -``` -**Note**: Cobra's default `completion` command uses bash completion V2. If for some reason you need to use bash completion V1, you will need to implement your own `completion` command. -## Zsh completions - -Cobra supports native zsh completion generated from the root `cobra.Command`. -The generated completion script should be put somewhere in your `$fpath` and be named -`_`. You will need to start a new shell for the completions to become available. - -Zsh supports descriptions for completions. Cobra will provide the description automatically, -based on usage information. Cobra provides a way to completely disable such descriptions by -using `GenZshCompletionNoDesc()` or `GenZshCompletionFileNoDesc()`. You can choose to make -this a configurable option to your users. -``` -# With descriptions -$ helm s[tab] -search -- search for a keyword in charts -show -- show information of a chart -status -- displays the status of the named release - -# Without descriptions -$ helm s[tab] -search show status -``` -*Note*: Because of backward-compatibility requirements, we were forced to have a different API to disable completion descriptions between `zsh` and `fish`. - -### Limitations - -* Custom completions implemented in Bash scripting (legacy) are not supported and will be ignored for `zsh` (including the use of the `BashCompCustom` flag annotation). - * You should instead use `ValidArgsFunction` and `RegisterFlagCompletionFunc()` which are portable to the different shells (`bash`, `zsh`, `fish`, `powershell`). -* The function `MarkFlagCustom()` is not supported and will be ignored for `zsh`. - * You should instead use `RegisterFlagCompletionFunc()`. - -### Zsh completions standardization - -Cobra 1.1 standardized its zsh completion support to align it with its other shell completions. Although the API was kept backward-compatible, some small changes in behavior were introduced. -Please refer to [Zsh Completions](zsh_completions.md) for details. - -## fish completions - -Cobra supports native fish completions generated from the root `cobra.Command`. You can use the `command.GenFishCompletion()` or `command.GenFishCompletionFile()` functions. You must provide these functions with a parameter indicating if the completions should be annotated with a description; Cobra will provide the description automatically based on usage information. You can choose to make this option configurable by your users. -``` -# With descriptions -$ helm s[tab] -search (search for a keyword in charts) show (show information of a chart) status (displays the status of the named release) - -# Without descriptions -$ helm s[tab] -search show status -``` -*Note*: Because of backward-compatibility requirements, we were forced to have a different API to disable completion descriptions between `zsh` and `fish`. - -### Limitations - -* Custom completions implemented in bash scripting (legacy) are not supported and will be ignored for `fish` (including the use of the `BashCompCustom` flag annotation). - * You should instead use `ValidArgsFunction` and `RegisterFlagCompletionFunc()` which are portable to the different shells (`bash`, `zsh`, `fish`, `powershell`). -* The function `MarkFlagCustom()` is not supported and will be ignored for `fish`. - * You should instead use `RegisterFlagCompletionFunc()`. -* The following flag completion annotations are not supported and will be ignored for `fish`: - * `BashCompFilenameExt` (filtering by file extension) - * `BashCompSubdirsInDir` (filtering by directory) -* The functions corresponding to the above annotations are consequently not supported and will be ignored for `fish`: - * `MarkFlagFilename()` and `MarkPersistentFlagFilename()` (filtering by file extension) - * `MarkFlagDirname()` and `MarkPersistentFlagDirname()` (filtering by directory) -* Similarly, the following completion directives are not supported and will be ignored for `fish`: - * `ShellCompDirectiveFilterFileExt` (filtering by file extension) - * `ShellCompDirectiveFilterDirs` (filtering by directory) - -## PowerShell completions - -Cobra supports native PowerShell completions generated from the root `cobra.Command`. You can use the `command.GenPowerShellCompletion()` or `command.GenPowerShellCompletionFile()` functions. To include descriptions use `command.GenPowerShellCompletionWithDesc()` and `command.GenPowerShellCompletionFileWithDesc()`. Cobra will provide the description automatically based on usage information. You can choose to make this option configurable by your users. - -The script is designed to support all three PowerShell completion modes: - -* TabCompleteNext (default windows style - on each key press the next option is displayed) -* Complete (works like bash) -* MenuComplete (works like zsh) - -You set the mode with `Set-PSReadLineKeyHandler -Key Tab -Function `. Descriptions are only displayed when using the `Complete` or `MenuComplete` mode. - -Users need PowerShell version 5.0 or above, which comes with Windows 10 and can be downloaded separately for Windows 7 or 8.1. They can then write the completions to a file and source this file from their PowerShell profile, which is referenced by the `$Profile` environment variable. See `Get-Help about_Profiles` for more info about PowerShell profiles. - -``` -# With descriptions and Mode 'Complete' -$ helm s[tab] -search (search for a keyword in charts) show (show information of a chart) status (displays the status of the named release) - -# With descriptions and Mode 'MenuComplete' The description of the current selected value will be displayed below the suggestions. -$ helm s[tab] -search show status - -search for a keyword in charts - -# Without descriptions -$ helm s[tab] -search show status -``` - -### Limitations - -* Custom completions implemented in bash scripting (legacy) are not supported and will be ignored for `powershell` (including the use of the `BashCompCustom` flag annotation). - * You should instead use `ValidArgsFunction` and `RegisterFlagCompletionFunc()` which are portable to the different shells (`bash`, `zsh`, `fish`, `powershell`). -* The function `MarkFlagCustom()` is not supported and will be ignored for `powershell`. - * You should instead use `RegisterFlagCompletionFunc()`. -* The following flag completion annotations are not supported and will be ignored for `powershell`: - * `BashCompFilenameExt` (filtering by file extension) - * `BashCompSubdirsInDir` (filtering by directory) -* The functions corresponding to the above annotations are consequently not supported and will be ignored for `powershell`: - * `MarkFlagFilename()` and `MarkPersistentFlagFilename()` (filtering by file extension) - * `MarkFlagDirname()` and `MarkPersistentFlagDirname()` (filtering by directory) -* Similarly, the following completion directives are not supported and will be ignored for `powershell`: - * `ShellCompDirectiveFilterFileExt` (filtering by file extension) - * `ShellCompDirectiveFilterDirs` (filtering by directory) diff --git a/vendor/github.com/spf13/cobra/user_guide.md b/vendor/github.com/spf13/cobra/user_guide.md deleted file mode 100644 index 5a7acf88e69..00000000000 --- a/vendor/github.com/spf13/cobra/user_guide.md +++ /dev/null @@ -1,666 +0,0 @@ -# User Guide - -While you are welcome to provide your own organization, typically a Cobra-based -application will follow the following organizational structure: - -``` - ▾ appName/ - ▾ cmd/ - add.go - your.go - commands.go - here.go - main.go -``` - -In a Cobra app, typically the main.go file is very bare. It serves one purpose: initializing Cobra. - -```go -package main - -import ( - "{pathToYourApp}/cmd" -) - -func main() { - cmd.Execute() -} -``` - -## Using the Cobra Generator - -Cobra-CLI is its own program that will create your application and add any -commands you want. It's the easiest way to incorporate Cobra into your application. - -For complete details on using the Cobra generator, please refer to [The Cobra-CLI Generator README](https://github.com/spf13/cobra-cli/blob/main/README.md) - -## Using the Cobra Library - -To manually implement Cobra you need to create a bare main.go file and a rootCmd file. -You will optionally provide additional commands as you see fit. - -### Create rootCmd - -Cobra doesn't require any special constructors. Simply create your commands. - -Ideally you place this in app/cmd/root.go: - -```go -var rootCmd = &cobra.Command{ - Use: "hugo", - Short: "Hugo is a very fast static site generator", - Long: `A Fast and Flexible Static Site Generator built with - love by spf13 and friends in Go. - Complete documentation is available at https://gohugo.io/documentation/`, - Run: func(cmd *cobra.Command, args []string) { - // Do Stuff Here - }, -} - -func Execute() { - if err := rootCmd.Execute(); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } -} -``` - -You will additionally define flags and handle configuration in your init() function. - -For example cmd/root.go: - -```go -package cmd - -import ( - "fmt" - "os" - - "github.com/spf13/cobra" - "github.com/spf13/viper" -) - -var ( - // Used for flags. - cfgFile string - userLicense string - - rootCmd = &cobra.Command{ - Use: "cobra-cli", - Short: "A generator for Cobra based Applications", - Long: `Cobra is a CLI library for Go that empowers applications. -This application is a tool to generate the needed files -to quickly create a Cobra application.`, - } -) - -// Execute executes the root command. -func Execute() error { - return rootCmd.Execute() -} - -func init() { - cobra.OnInitialize(initConfig) - - rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)") - rootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "author name for copyright attribution") - rootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "name of license for the project") - rootCmd.PersistentFlags().Bool("viper", true, "use Viper for configuration") - viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author")) - viper.BindPFlag("useViper", rootCmd.PersistentFlags().Lookup("viper")) - viper.SetDefault("author", "NAME HERE ") - viper.SetDefault("license", "apache") - - rootCmd.AddCommand(addCmd) - rootCmd.AddCommand(initCmd) -} - -func initConfig() { - if cfgFile != "" { - // Use config file from the flag. - viper.SetConfigFile(cfgFile) - } else { - // Find home directory. - home, err := os.UserHomeDir() - cobra.CheckErr(err) - - // Search config in home directory with name ".cobra" (without extension). - viper.AddConfigPath(home) - viper.SetConfigType("yaml") - viper.SetConfigName(".cobra") - } - - viper.AutomaticEnv() - - if err := viper.ReadInConfig(); err == nil { - fmt.Println("Using config file:", viper.ConfigFileUsed()) - } -} -``` - -### Create your main.go - -With the root command you need to have your main function execute it. -Execute should be run on the root for clarity, though it can be called on any command. - -In a Cobra app, typically the main.go file is very bare. It serves one purpose: to initialize Cobra. - -```go -package main - -import ( - "{pathToYourApp}/cmd" -) - -func main() { - cmd.Execute() -} -``` - -### Create additional commands - -Additional commands can be defined and typically are each given their own file -inside of the cmd/ directory. - -If you wanted to create a version command you would create cmd/version.go and -populate it with the following: - -```go -package cmd - -import ( - "fmt" - - "github.com/spf13/cobra" -) - -func init() { - rootCmd.AddCommand(versionCmd) -} - -var versionCmd = &cobra.Command{ - Use: "version", - Short: "Print the version number of Hugo", - Long: `All software has versions. This is Hugo's`, - Run: func(cmd *cobra.Command, args []string) { - fmt.Println("Hugo Static Site Generator v0.9 -- HEAD") - }, -} -``` - -### Returning and handling errors - -If you wish to return an error to the caller of a command, `RunE` can be used. - -```go -package cmd - -import ( - "fmt" - - "github.com/spf13/cobra" -) - -func init() { - rootCmd.AddCommand(tryCmd) -} - -var tryCmd = &cobra.Command{ - Use: "try", - Short: "Try and possibly fail at something", - RunE: func(cmd *cobra.Command, args []string) error { - if err := someFunc(); err != nil { - return err - } - return nil - }, -} -``` - -The error can then be caught at the execute function call. - -## Working with Flags - -Flags provide modifiers to control how the action command operates. - -### Assign flags to a command - -Since the flags are defined and used in different locations, we need to -define a variable outside with the correct scope to assign the flag to -work with. - -```go -var Verbose bool -var Source string -``` - -There are two different approaches to assign a flag. - -### Persistent Flags - -A flag can be 'persistent', meaning that this flag will be available to the -command it's assigned to as well as every command under that command. For -global flags, assign a flag as a persistent flag on the root. - -```go -rootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output") -``` - -### Local Flags - -A flag can also be assigned locally, which will only apply to that specific command. - -```go -localCmd.Flags().StringVarP(&Source, "source", "s", "", "Source directory to read from") -``` - -### Local Flag on Parent Commands - -By default, Cobra only parses local flags on the target command, and any local flags on -parent commands are ignored. By enabling `Command.TraverseChildren`, Cobra will -parse local flags on each command before executing the target command. - -```go -command := cobra.Command{ - Use: "print [OPTIONS] [COMMANDS]", - TraverseChildren: true, -} -``` - -### Bind Flags with Config - -You can also bind your flags with [viper](https://github.com/spf13/viper): -```go -var author string - -func init() { - rootCmd.PersistentFlags().StringVar(&author, "author", "YOUR NAME", "Author name for copyright attribution") - viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author")) -} -``` - -In this example, the persistent flag `author` is bound with `viper`. -**Note**: the variable `author` will not be set to the value from config, -when the `--author` flag is provided by user. - -More in [viper documentation](https://github.com/spf13/viper#working-with-flags). - -### Required flags - -Flags are optional by default. If instead you wish your command to report an error -when a flag has not been set, mark it as required: -```go -rootCmd.Flags().StringVarP(&Region, "region", "r", "", "AWS region (required)") -rootCmd.MarkFlagRequired("region") -``` - -Or, for persistent flags: -```go -rootCmd.PersistentFlags().StringVarP(&Region, "region", "r", "", "AWS region (required)") -rootCmd.MarkPersistentFlagRequired("region") -``` - -### Flag Groups - -If you have different flags that must be provided together (e.g. if they provide the `--username` flag they MUST provide the `--password` flag as well) then -Cobra can enforce that requirement: -```go -rootCmd.Flags().StringVarP(&u, "username", "u", "", "Username (required if password is set)") -rootCmd.Flags().StringVarP(&pw, "password", "p", "", "Password (required if username is set)") -rootCmd.MarkFlagsRequiredTogether("username", "password") -``` - -You can also prevent different flags from being provided together if they represent mutually -exclusive options such as specifying an output format as either `--json` or `--yaml` but never both: -```go -rootCmd.Flags().BoolVar(&u, "json", false, "Output in JSON") -rootCmd.Flags().BoolVar(&pw, "yaml", false, "Output in YAML") -rootCmd.MarkFlagsMutuallyExclusive("json", "yaml") -``` - -In both of these cases: - - both local and persistent flags can be used - - **NOTE:** the group is only enforced on commands where every flag is defined - - a flag may appear in multiple groups - - a group may contain any number of flags - -## Positional and Custom Arguments - -Validation of positional arguments can be specified using the `Args` field of `Command`. -If `Args` is undefined or `nil`, it defaults to `ArbitraryArgs`. - -The following validators are built in: - -- `NoArgs` - the command will report an error if there are any positional args. -- `ArbitraryArgs` - the command will accept any args. -- `OnlyValidArgs` - the command will report an error if there are any positional args that are not in the `ValidArgs` field of `Command`. -- `MinimumNArgs(int)` - the command will report an error if there are not at least N positional args. -- `MaximumNArgs(int)` - the command will report an error if there are more than N positional args. -- `ExactArgs(int)` - the command will report an error if there are not exactly N positional args. -- `ExactValidArgs(int)` - the command will report an error if there are not exactly N positional args OR if there are any positional args that are not in the `ValidArgs` field of `Command` -- `RangeArgs(min, max)` - the command will report an error if the number of args is not between the minimum and maximum number of expected args. -- `MatchAll(pargs ...PositionalArgs)` - enables combining existing checks with arbitrary other checks (e.g. you want to check the ExactArgs length along with other qualities). - -An example of setting the custom validator: - -```go -var cmd = &cobra.Command{ - Short: "hello", - Args: func(cmd *cobra.Command, args []string) error { - if len(args) < 1 { - return errors.New("requires a color argument") - } - if myapp.IsValidColor(args[0]) { - return nil - } - return fmt.Errorf("invalid color specified: %s", args[0]) - }, - Run: func(cmd *cobra.Command, args []string) { - fmt.Println("Hello, World!") - }, -} -``` - -## Example - -In the example below, we have defined three commands. Two are at the top level -and one (cmdTimes) is a child of one of the top commands. In this case the root -is not executable, meaning that a subcommand is required. This is accomplished -by not providing a 'Run' for the 'rootCmd'. - -We have only defined one flag for a single command. - -More documentation about flags is available at https://github.com/spf13/pflag - -```go -package main - -import ( - "fmt" - "strings" - - "github.com/spf13/cobra" -) - -func main() { - var echoTimes int - - var cmdPrint = &cobra.Command{ - Use: "print [string to print]", - Short: "Print anything to the screen", - Long: `print is for printing anything back to the screen. -For many years people have printed back to the screen.`, - Args: cobra.MinimumNArgs(1), - Run: func(cmd *cobra.Command, args []string) { - fmt.Println("Print: " + strings.Join(args, " ")) - }, - } - - var cmdEcho = &cobra.Command{ - Use: "echo [string to echo]", - Short: "Echo anything to the screen", - Long: `echo is for echoing anything back. -Echo works a lot like print, except it has a child command.`, - Args: cobra.MinimumNArgs(1), - Run: func(cmd *cobra.Command, args []string) { - fmt.Println("Echo: " + strings.Join(args, " ")) - }, - } - - var cmdTimes = &cobra.Command{ - Use: "times [string to echo]", - Short: "Echo anything to the screen more times", - Long: `echo things multiple times back to the user by providing -a count and a string.`, - Args: cobra.MinimumNArgs(1), - Run: func(cmd *cobra.Command, args []string) { - for i := 0; i < echoTimes; i++ { - fmt.Println("Echo: " + strings.Join(args, " ")) - } - }, - } - - cmdTimes.Flags().IntVarP(&echoTimes, "times", "t", 1, "times to echo the input") - - var rootCmd = &cobra.Command{Use: "app"} - rootCmd.AddCommand(cmdPrint, cmdEcho) - cmdEcho.AddCommand(cmdTimes) - rootCmd.Execute() -} -``` - -For a more complete example of a larger application, please checkout [Hugo](https://gohugo.io/). - -## Help Command - -Cobra automatically adds a help command to your application when you have subcommands. -This will be called when a user runs 'app help'. Additionally, help will also -support all other commands as input. Say, for instance, you have a command called -'create' without any additional configuration; Cobra will work when 'app help -create' is called. Every command will automatically have the '--help' flag added. - -### Example - -The following output is automatically generated by Cobra. Nothing beyond the -command and flag definitions are needed. - - $ cobra help - - Cobra is a CLI library for Go that empowers applications. - This application is a tool to generate the needed files - to quickly create a Cobra application. - - Usage: - cobra [command] - - Available Commands: - add Add a command to a Cobra Application - help Help about any command - init Initialize a Cobra Application - - Flags: - -a, --author string author name for copyright attribution (default "YOUR NAME") - --config string config file (default is $HOME/.cobra.yaml) - -h, --help help for cobra - -l, --license string name of license for the project - --viper use Viper for configuration (default true) - - Use "cobra [command] --help" for more information about a command. - - -Help is just a command like any other. There is no special logic or behavior -around it. In fact, you can provide your own if you want. - -### Defining your own help - -You can provide your own Help command or your own template for the default command to use -with following functions: - -```go -cmd.SetHelpCommand(cmd *Command) -cmd.SetHelpFunc(f func(*Command, []string)) -cmd.SetHelpTemplate(s string) -``` - -The latter two will also apply to any children commands. - -## Usage Message - -When the user provides an invalid flag or invalid command, Cobra responds by -showing the user the 'usage'. - -### Example -You may recognize this from the help above. That's because the default help -embeds the usage as part of its output. - - $ cobra --invalid - Error: unknown flag: --invalid - Usage: - cobra [command] - - Available Commands: - add Add a command to a Cobra Application - help Help about any command - init Initialize a Cobra Application - - Flags: - -a, --author string author name for copyright attribution (default "YOUR NAME") - --config string config file (default is $HOME/.cobra.yaml) - -h, --help help for cobra - -l, --license string name of license for the project - --viper use Viper for configuration (default true) - - Use "cobra [command] --help" for more information about a command. - -### Defining your own usage -You can provide your own usage function or template for Cobra to use. -Like help, the function and template are overridable through public methods: - -```go -cmd.SetUsageFunc(f func(*Command) error) -cmd.SetUsageTemplate(s string) -``` - -## Version Flag - -Cobra adds a top-level '--version' flag if the Version field is set on the root command. -Running an application with the '--version' flag will print the version to stdout using -the version template. The template can be customized using the -`cmd.SetVersionTemplate(s string)` function. - -## PreRun and PostRun Hooks - -It is possible to run functions before or after the main `Run` function of your command. The `PersistentPreRun` and `PreRun` functions will be executed before `Run`. `PersistentPostRun` and `PostRun` will be executed after `Run`. The `Persistent*Run` functions will be inherited by children if they do not declare their own. These functions are run in the following order: - -- `PersistentPreRun` -- `PreRun` -- `Run` -- `PostRun` -- `PersistentPostRun` - -An example of two commands which use all of these features is below. When the subcommand is executed, it will run the root command's `PersistentPreRun` but not the root command's `PersistentPostRun`: - -```go -package main - -import ( - "fmt" - - "github.com/spf13/cobra" -) - -func main() { - - var rootCmd = &cobra.Command{ - Use: "root [sub]", - Short: "My root command", - PersistentPreRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd PersistentPreRun with args: %v\n", args) - }, - PreRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd PreRun with args: %v\n", args) - }, - Run: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd Run with args: %v\n", args) - }, - PostRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd PostRun with args: %v\n", args) - }, - PersistentPostRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd PersistentPostRun with args: %v\n", args) - }, - } - - var subCmd = &cobra.Command{ - Use: "sub [no options!]", - Short: "My subcommand", - PreRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside subCmd PreRun with args: %v\n", args) - }, - Run: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside subCmd Run with args: %v\n", args) - }, - PostRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside subCmd PostRun with args: %v\n", args) - }, - PersistentPostRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside subCmd PersistentPostRun with args: %v\n", args) - }, - } - - rootCmd.AddCommand(subCmd) - - rootCmd.SetArgs([]string{""}) - rootCmd.Execute() - fmt.Println() - rootCmd.SetArgs([]string{"sub", "arg1", "arg2"}) - rootCmd.Execute() -} -``` - -Output: -``` -Inside rootCmd PersistentPreRun with args: [] -Inside rootCmd PreRun with args: [] -Inside rootCmd Run with args: [] -Inside rootCmd PostRun with args: [] -Inside rootCmd PersistentPostRun with args: [] - -Inside rootCmd PersistentPreRun with args: [arg1 arg2] -Inside subCmd PreRun with args: [arg1 arg2] -Inside subCmd Run with args: [arg1 arg2] -Inside subCmd PostRun with args: [arg1 arg2] -Inside subCmd PersistentPostRun with args: [arg1 arg2] -``` - -## Suggestions when "unknown command" happens - -Cobra will print automatic suggestions when "unknown command" errors happen. This allows Cobra to behave similarly to the `git` command when a typo happens. For example: - -``` -$ hugo srever -Error: unknown command "srever" for "hugo" - -Did you mean this? - server - -Run 'hugo --help' for usage. -``` - -Suggestions are automatic based on every subcommand registered and use an implementation of [Levenshtein distance](https://en.wikipedia.org/wiki/Levenshtein_distance). Every registered command that matches a minimum distance of 2 (ignoring case) will be displayed as a suggestion. - -If you need to disable suggestions or tweak the string distance in your command, use: - -```go -command.DisableSuggestions = true -``` - -or - -```go -command.SuggestionsMinimumDistance = 1 -``` - -You can also explicitly set names for which a given command will be suggested using the `SuggestFor` attribute. This allows suggestions for strings that are not close in terms of string distance, but makes sense in your set of commands and for some which you don't want aliases. Example: - -``` -$ kubectl remove -Error: unknown command "remove" for "kubectl" - -Did you mean this? - delete - -Run 'kubectl help' for usage. -``` - -## Generating documentation for your command - -Cobra can generate documentation based on subcommands, flags, etc. Read more about it in the [docs generation documentation](doc/README.md). - -## Generating shell completions - -Cobra can generate a shell-completion file for the following shells: bash, zsh, fish, PowerShell. If you add more information to your commands, these completions can be amazingly powerful and flexible. Read more about it in [Shell Completions](shell_completions.md). - -## Providing Active Help - -Cobra makes use of the shell-completion system to define a framework allowing you to provide Active Help to your users. Active Help are messages (hints, warnings, etc) printed as the program is being used. Read more about it in [Active Help](active_help.md). diff --git a/vendor/github.com/spf13/cobra/zsh_completions.go b/vendor/github.com/spf13/cobra/zsh_completions.go index 65cd94c6040..1856e4c7f68 100644 --- a/vendor/github.com/spf13/cobra/zsh_completions.go +++ b/vendor/github.com/spf13/cobra/zsh_completions.go @@ -1,3 +1,17 @@ +// Copyright 2013-2023 The Cobra Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package cobra import ( @@ -76,6 +90,7 @@ func genZshComp(buf io.StringWriter, name string, includeDesc bool) { compCmd = ShellCompNoDescRequestCmd } WriteStringAndCheck(buf, fmt.Sprintf(`#compdef %[1]s +compdef _%[1]s %[1]s # zsh completion for %-36[1]s -*- shell-script -*- @@ -94,8 +109,9 @@ _%[1]s() local shellCompDirectiveNoFileComp=%[5]d local shellCompDirectiveFilterFileExt=%[6]d local shellCompDirectiveFilterDirs=%[7]d + local shellCompDirectiveKeepOrder=%[8]d - local lastParam lastChar flagPrefix requestComp out directive comp lastComp noSpace + local lastParam lastChar flagPrefix requestComp out directive comp lastComp noSpace keepOrder local -a completions __%[1]s_debug "\n========= starting completion logic ==========" @@ -163,7 +179,7 @@ _%[1]s() return fi - local activeHelpMarker="%[8]s" + local activeHelpMarker="%[9]s" local endIndex=${#activeHelpMarker} local startIndex=$((${#activeHelpMarker}+1)) local hasActiveHelp=0 @@ -213,6 +229,11 @@ _%[1]s() noSpace="-S ''" fi + if [ $((directive & shellCompDirectiveKeepOrder)) -ne 0 ]; then + __%[1]s_debug "Activating keep order." + keepOrder="-V" + fi + if [ $((directive & shellCompDirectiveFilterFileExt)) -ne 0 ]; then # File extension filtering local filteringCmd @@ -248,7 +269,7 @@ _%[1]s() return $result else __%[1]s_debug "Calling _describe" - if eval _describe "completions" completions $flagPrefix $noSpace; then + if eval _describe $keepOrder "completions" completions $flagPrefix $noSpace; then __%[1]s_debug "_describe found some completions" # Return the success of having called _describe @@ -282,6 +303,6 @@ if [ "$funcstack[1]" = "_%[1]s" ]; then fi `, name, compCmd, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, - ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, + ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveKeepOrder, activeHelpMarker)) } diff --git a/vendor/github.com/spf13/cobra/zsh_completions.md b/vendor/github.com/spf13/cobra/zsh_completions.md deleted file mode 100644 index 7cff61787f4..00000000000 --- a/vendor/github.com/spf13/cobra/zsh_completions.md +++ /dev/null @@ -1,48 +0,0 @@ -## Generating Zsh Completion For Your cobra.Command - -Please refer to [Shell Completions](shell_completions.md) for details. - -## Zsh completions standardization - -Cobra 1.1 standardized its zsh completion support to align it with its other shell completions. Although the API was kept backwards-compatible, some small changes in behavior were introduced. - -### Deprecation summary - -See further below for more details on these deprecations. - -* `cmd.MarkZshCompPositionalArgumentFile(pos, []string{})` is no longer needed. It is therefore **deprecated** and silently ignored. -* `cmd.MarkZshCompPositionalArgumentFile(pos, glob[])` is **deprecated** and silently ignored. - * Instead use `ValidArgsFunction` with `ShellCompDirectiveFilterFileExt`. -* `cmd.MarkZshCompPositionalArgumentWords()` is **deprecated** and silently ignored. - * Instead use `ValidArgsFunction`. - -### Behavioral changes - -**Noun completion** -|Old behavior|New behavior| -|---|---| -|No file completion by default (opposite of bash)|File completion by default; use `ValidArgsFunction` with `ShellCompDirectiveNoFileComp` to turn off file completion on a per-argument basis| -|Completion of flag names without the `-` prefix having been typed|Flag names are only completed if the user has typed the first `-`| -`cmd.MarkZshCompPositionalArgumentFile(pos, []string{})` used to turn on file completion on a per-argument position basis|File completion for all arguments by default; `cmd.MarkZshCompPositionalArgumentFile()` is **deprecated** and silently ignored| -|`cmd.MarkZshCompPositionalArgumentFile(pos, glob[])` used to turn on file completion **with glob filtering** on a per-argument position basis (zsh-specific)|`cmd.MarkZshCompPositionalArgumentFile()` is **deprecated** and silently ignored; use `ValidArgsFunction` with `ShellCompDirectiveFilterFileExt` for file **extension** filtering (not full glob filtering)| -|`cmd.MarkZshCompPositionalArgumentWords(pos, words[])` used to provide completion choices on a per-argument position basis (zsh-specific)|`cmd.MarkZshCompPositionalArgumentWords()` is **deprecated** and silently ignored; use `ValidArgsFunction` to achieve the same behavior| - -**Flag-value completion** - -|Old behavior|New behavior| -|---|---| -|No file completion by default (opposite of bash)|File completion by default; use `RegisterFlagCompletionFunc()` with `ShellCompDirectiveNoFileComp` to turn off file completion| -|`cmd.MarkFlagFilename(flag, []string{})` and similar used to turn on file completion|File completion by default; `cmd.MarkFlagFilename(flag, []string{})` no longer needed in this context and silently ignored| -|`cmd.MarkFlagFilename(flag, glob[])` used to turn on file completion **with glob filtering** (syntax of `[]string{"*.yaml", "*.yml"}` incompatible with bash)|Will continue to work, however, support for bash syntax is added and should be used instead so as to work for all shells (`[]string{"yaml", "yml"}`)| -|`cmd.MarkFlagDirname(flag)` only completes directories (zsh-specific)|Has been added for all shells| -|Completion of a flag name does not repeat, unless flag is of type `*Array` or `*Slice` (not supported by bash)|Retained for `zsh` and added to `fish`| -|Completion of a flag name does not provide the `=` form (unlike bash)|Retained for `zsh` and added to `fish`| - -**Improvements** - -* Custom completion support (`ValidArgsFunction` and `RegisterFlagCompletionFunc()`) -* File completion by default if no other completions found -* Handling of required flags -* File extension filtering no longer mutually exclusive with bash usage -* Completion of directory names *within* another directory -* Support for `=` form of flags diff --git a/vendor/github.com/spf13/pflag/.editorconfig b/vendor/github.com/spf13/pflag/.editorconfig new file mode 100644 index 00000000000..4492e9f9fe1 --- /dev/null +++ b/vendor/github.com/spf13/pflag/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +[*.go] +indent_style = tab diff --git a/vendor/github.com/spf13/pflag/.golangci.yaml b/vendor/github.com/spf13/pflag/.golangci.yaml new file mode 100644 index 00000000000..b274f248451 --- /dev/null +++ b/vendor/github.com/spf13/pflag/.golangci.yaml @@ -0,0 +1,4 @@ +linters: + disable-all: true + enable: + - nolintlint diff --git a/vendor/github.com/spf13/pflag/flag.go b/vendor/github.com/spf13/pflag/flag.go index 24a5036e95b..7c058de3744 100644 --- a/vendor/github.com/spf13/pflag/flag.go +++ b/vendor/github.com/spf13/pflag/flag.go @@ -160,7 +160,7 @@ type FlagSet struct { args []string // arguments after flags argsLenAtDash int // len(args) when a '--' was located when parsing, or -1 if no -- errorHandling ErrorHandling - output io.Writer // nil means stderr; use out() accessor + output io.Writer // nil means stderr; use Output() accessor interspersed bool // allow interspersed option/non-option args normalizeNameFunc func(f *FlagSet, name string) NormalizedName @@ -255,13 +255,20 @@ func (f *FlagSet) normalizeFlagName(name string) NormalizedName { return n(f, name) } -func (f *FlagSet) out() io.Writer { +// Output returns the destination for usage and error messages. os.Stderr is returned if +// output was not set or was set to nil. +func (f *FlagSet) Output() io.Writer { if f.output == nil { return os.Stderr } return f.output } +// Name returns the name of the flag set. +func (f *FlagSet) Name() string { + return f.name +} + // SetOutput sets the destination for usage and error messages. // If output is nil, os.Stderr is used. func (f *FlagSet) SetOutput(output io.Writer) { @@ -358,7 +365,7 @@ func (f *FlagSet) ShorthandLookup(name string) *Flag { } if len(name) > 1 { msg := fmt.Sprintf("can not look up shorthand which is more than one ASCII character: %q", name) - fmt.Fprintf(f.out(), msg) + fmt.Fprintf(f.Output(), msg) panic(msg) } c := name[0] @@ -482,7 +489,7 @@ func (f *FlagSet) Set(name, value string) error { } if flag.Deprecated != "" { - fmt.Fprintf(f.out(), "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated) + fmt.Fprintf(f.Output(), "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated) } return nil } @@ -523,7 +530,7 @@ func Set(name, value string) error { // otherwise, the default values of all defined flags in the set. func (f *FlagSet) PrintDefaults() { usages := f.FlagUsages() - fmt.Fprint(f.out(), usages) + fmt.Fprint(f.Output(), usages) } // defaultIsZeroValue returns true if the default value for this flag represents @@ -758,7 +765,7 @@ func PrintDefaults() { // defaultUsage is the default function to print a usage message. func defaultUsage(f *FlagSet) { - fmt.Fprintf(f.out(), "Usage of %s:\n", f.name) + fmt.Fprintf(f.Output(), "Usage of %s:\n", f.name) f.PrintDefaults() } @@ -844,7 +851,7 @@ func (f *FlagSet) AddFlag(flag *Flag) { _, alreadyThere := f.formal[normalizedFlagName] if alreadyThere { msg := fmt.Sprintf("%s flag redefined: %s", f.name, flag.Name) - fmt.Fprintln(f.out(), msg) + fmt.Fprintln(f.Output(), msg) panic(msg) // Happens only if flags are declared with identical names } if f.formal == nil { @@ -860,7 +867,7 @@ func (f *FlagSet) AddFlag(flag *Flag) { } if len(flag.Shorthand) > 1 { msg := fmt.Sprintf("%q shorthand is more than one ASCII character", flag.Shorthand) - fmt.Fprintf(f.out(), msg) + fmt.Fprintf(f.Output(), msg) panic(msg) } if f.shorthands == nil { @@ -870,7 +877,7 @@ func (f *FlagSet) AddFlag(flag *Flag) { used, alreadyThere := f.shorthands[c] if alreadyThere { msg := fmt.Sprintf("unable to redefine %q shorthand in %q flagset: it's already used for %q flag", c, f.name, used.Name) - fmt.Fprintf(f.out(), msg) + fmt.Fprintf(f.Output(), msg) panic(msg) } f.shorthands[c] = flag @@ -909,7 +916,7 @@ func VarP(value Value, name, shorthand, usage string) { func (f *FlagSet) failf(format string, a ...interface{}) error { err := fmt.Errorf(format, a...) if f.errorHandling != ContinueOnError { - fmt.Fprintln(f.out(), err) + fmt.Fprintln(f.Output(), err) f.usage() } return err @@ -1060,7 +1067,7 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse } if flag.ShorthandDeprecated != "" { - fmt.Fprintf(f.out(), "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated) + fmt.Fprintf(f.Output(), "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated) } err = fn(flag, value) diff --git a/vendor/github.com/spf13/pflag/ip.go b/vendor/github.com/spf13/pflag/ip.go index 3d414ba69fe..06b8bcb5721 100644 --- a/vendor/github.com/spf13/pflag/ip.go +++ b/vendor/github.com/spf13/pflag/ip.go @@ -16,6 +16,9 @@ func newIPValue(val net.IP, p *net.IP) *ipValue { func (i *ipValue) String() string { return net.IP(*i).String() } func (i *ipValue) Set(s string) error { + if s == "" { + return nil + } ip := net.ParseIP(strings.TrimSpace(s)) if ip == nil { return fmt.Errorf("failed to parse IP: %q", s) diff --git a/vendor/github.com/spf13/pflag/ipnet_slice.go b/vendor/github.com/spf13/pflag/ipnet_slice.go new file mode 100644 index 00000000000..6b541aa8798 --- /dev/null +++ b/vendor/github.com/spf13/pflag/ipnet_slice.go @@ -0,0 +1,147 @@ +package pflag + +import ( + "fmt" + "io" + "net" + "strings" +) + +// -- ipNetSlice Value +type ipNetSliceValue struct { + value *[]net.IPNet + changed bool +} + +func newIPNetSliceValue(val []net.IPNet, p *[]net.IPNet) *ipNetSliceValue { + ipnsv := new(ipNetSliceValue) + ipnsv.value = p + *ipnsv.value = val + return ipnsv +} + +// Set converts, and assigns, the comma-separated IPNet argument string representation as the []net.IPNet value of this flag. +// If Set is called on a flag that already has a []net.IPNet assigned, the newly converted values will be appended. +func (s *ipNetSliceValue) Set(val string) error { + + // remove all quote characters + rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "") + + // read flag arguments with CSV parser + ipNetStrSlice, err := readAsCSV(rmQuote.Replace(val)) + if err != nil && err != io.EOF { + return err + } + + // parse ip values into slice + out := make([]net.IPNet, 0, len(ipNetStrSlice)) + for _, ipNetStr := range ipNetStrSlice { + _, n, err := net.ParseCIDR(strings.TrimSpace(ipNetStr)) + if err != nil { + return fmt.Errorf("invalid string being converted to CIDR: %s", ipNetStr) + } + out = append(out, *n) + } + + if !s.changed { + *s.value = out + } else { + *s.value = append(*s.value, out...) + } + + s.changed = true + + return nil +} + +// Type returns a string that uniquely represents this flag's type. +func (s *ipNetSliceValue) Type() string { + return "ipNetSlice" +} + +// String defines a "native" format for this net.IPNet slice flag value. +func (s *ipNetSliceValue) String() string { + + ipNetStrSlice := make([]string, len(*s.value)) + for i, n := range *s.value { + ipNetStrSlice[i] = n.String() + } + + out, _ := writeAsCSV(ipNetStrSlice) + return "[" + out + "]" +} + +func ipNetSliceConv(val string) (interface{}, error) { + val = strings.Trim(val, "[]") + // Emtpy string would cause a slice with one (empty) entry + if len(val) == 0 { + return []net.IPNet{}, nil + } + ss := strings.Split(val, ",") + out := make([]net.IPNet, len(ss)) + for i, sval := range ss { + _, n, err := net.ParseCIDR(strings.TrimSpace(sval)) + if err != nil { + return nil, fmt.Errorf("invalid string being converted to CIDR: %s", sval) + } + out[i] = *n + } + return out, nil +} + +// GetIPNetSlice returns the []net.IPNet value of a flag with the given name +func (f *FlagSet) GetIPNetSlice(name string) ([]net.IPNet, error) { + val, err := f.getFlagType(name, "ipNetSlice", ipNetSliceConv) + if err != nil { + return []net.IPNet{}, err + } + return val.([]net.IPNet), nil +} + +// IPNetSliceVar defines a ipNetSlice flag with specified name, default value, and usage string. +// The argument p points to a []net.IPNet variable in which to store the value of the flag. +func (f *FlagSet) IPNetSliceVar(p *[]net.IPNet, name string, value []net.IPNet, usage string) { + f.VarP(newIPNetSliceValue(value, p), name, "", usage) +} + +// IPNetSliceVarP is like IPNetSliceVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) IPNetSliceVarP(p *[]net.IPNet, name, shorthand string, value []net.IPNet, usage string) { + f.VarP(newIPNetSliceValue(value, p), name, shorthand, usage) +} + +// IPNetSliceVar defines a []net.IPNet flag with specified name, default value, and usage string. +// The argument p points to a []net.IPNet variable in which to store the value of the flag. +func IPNetSliceVar(p *[]net.IPNet, name string, value []net.IPNet, usage string) { + CommandLine.VarP(newIPNetSliceValue(value, p), name, "", usage) +} + +// IPNetSliceVarP is like IPNetSliceVar, but accepts a shorthand letter that can be used after a single dash. +func IPNetSliceVarP(p *[]net.IPNet, name, shorthand string, value []net.IPNet, usage string) { + CommandLine.VarP(newIPNetSliceValue(value, p), name, shorthand, usage) +} + +// IPNetSlice defines a []net.IPNet flag with specified name, default value, and usage string. +// The return value is the address of a []net.IPNet variable that stores the value of that flag. +func (f *FlagSet) IPNetSlice(name string, value []net.IPNet, usage string) *[]net.IPNet { + p := []net.IPNet{} + f.IPNetSliceVarP(&p, name, "", value, usage) + return &p +} + +// IPNetSliceP is like IPNetSlice, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) IPNetSliceP(name, shorthand string, value []net.IPNet, usage string) *[]net.IPNet { + p := []net.IPNet{} + f.IPNetSliceVarP(&p, name, shorthand, value, usage) + return &p +} + +// IPNetSlice defines a []net.IPNet flag with specified name, default value, and usage string. +// The return value is the address of a []net.IP variable that stores the value of the flag. +func IPNetSlice(name string, value []net.IPNet, usage string) *[]net.IPNet { + return CommandLine.IPNetSliceP(name, "", value, usage) +} + +// IPNetSliceP is like IPNetSlice, but accepts a shorthand letter that can be used after a single dash. +func IPNetSliceP(name, shorthand string, value []net.IPNet, usage string) *[]net.IPNet { + return CommandLine.IPNetSliceP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/string_array.go b/vendor/github.com/spf13/pflag/string_array.go index 4894af81802..d1ff0a96ba0 100644 --- a/vendor/github.com/spf13/pflag/string_array.go +++ b/vendor/github.com/spf13/pflag/string_array.go @@ -31,11 +31,7 @@ func (s *stringArrayValue) Append(val string) error { func (s *stringArrayValue) Replace(val []string) error { out := make([]string, len(val)) for i, d := range val { - var err error out[i] = d - if err != nil { - return err - } } *s.value = out return nil diff --git a/vendor/modules.txt b/vendor/modules.txt index 456674863a0..29206827c2a 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -70,7 +70,7 @@ github.com/alecthomas/units # github.com/beorn7/perks v1.0.1 ## explicit; go 1.11 github.com/beorn7/perks/quantile -# github.com/bits-and-blooms/bitset v1.13.0 +# github.com/bits-and-blooms/bitset v1.20.0 ## explicit; go 1.16 github.com/bits-and-blooms/bitset # github.com/cespare/xxhash/v2 v2.3.0 @@ -79,30 +79,30 @@ github.com/cespare/xxhash/v2 # github.com/cheggaaa/pb v1.0.29 ## explicit; go 1.12 github.com/cheggaaa/pb -# github.com/consensys/bavard v0.1.13 -## explicit; go 1.15 -github.com/consensys/bavard -# github.com/consensys/gnark-crypto v0.12.1 -## explicit; go 1.18 +# github.com/consensys/gnark-crypto v0.18.1 +## explicit; go 1.23.0 github.com/consensys/gnark-crypto/ecc github.com/consensys/gnark-crypto/ecc/bls12-377 github.com/consensys/gnark-crypto/ecc/bls12-377/fp github.com/consensys/gnark-crypto/ecc/bls12-377/fr +github.com/consensys/gnark-crypto/ecc/bls12-377/hash_to_curve github.com/consensys/gnark-crypto/ecc/bls12-377/internal/fptower github.com/consensys/gnark-crypto/ecc/bls12-381 github.com/consensys/gnark-crypto/ecc/bls12-381/fp github.com/consensys/gnark-crypto/ecc/bls12-381/fr +github.com/consensys/gnark-crypto/ecc/bls12-381/hash_to_curve github.com/consensys/gnark-crypto/ecc/bls12-381/internal/fptower github.com/consensys/gnark-crypto/ecc/bn254 github.com/consensys/gnark-crypto/ecc/bn254/fp github.com/consensys/gnark-crypto/ecc/bn254/fr +github.com/consensys/gnark-crypto/ecc/bn254/hash_to_curve github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower -github.com/consensys/gnark-crypto/field/generator/config -github.com/consensys/gnark-crypto/field/generator/internal/addchain +github.com/consensys/gnark-crypto/field/asm/element_4w +github.com/consensys/gnark-crypto/field/asm/element_6w github.com/consensys/gnark-crypto/field/hash github.com/consensys/gnark-crypto/field/pool -github.com/consensys/gnark-crypto/internal/generator/config github.com/consensys/gnark-crypto/internal/parallel +github.com/consensys/gnark-crypto/utils/cpu # github.com/containerd/log v0.1.0 ## explicit; go 1.20 github.com/containerd/log @@ -282,8 +282,8 @@ github.com/hyperledger/fabric-protos-go/orderer/smartbft github.com/hyperledger/fabric-protos-go/peer github.com/hyperledger/fabric-protos-go/peer/lifecycle github.com/hyperledger/fabric-protos-go/transientstore -# github.com/inconshreveable/mousetrap v1.0.0 -## explicit +# github.com/inconshreveable/mousetrap v1.1.0 +## explicit; go 1.18 github.com/inconshreveable/mousetrap # github.com/kilic/bls12-381 v0.1.0 ## explicit; go 1.13 @@ -315,30 +315,6 @@ github.com/miekg/pkcs11 # github.com/mitchellh/mapstructure v1.4.3 ## explicit; go 1.14 github.com/mitchellh/mapstructure -# github.com/mmcloughlin/addchain v0.4.0 -## explicit; go 1.16 -github.com/mmcloughlin/addchain -github.com/mmcloughlin/addchain/acc -github.com/mmcloughlin/addchain/acc/ast -github.com/mmcloughlin/addchain/acc/ir -github.com/mmcloughlin/addchain/acc/parse -github.com/mmcloughlin/addchain/acc/parse/internal/parser -github.com/mmcloughlin/addchain/acc/pass -github.com/mmcloughlin/addchain/acc/printer -github.com/mmcloughlin/addchain/alg -github.com/mmcloughlin/addchain/alg/contfrac -github.com/mmcloughlin/addchain/alg/dict -github.com/mmcloughlin/addchain/alg/ensemble -github.com/mmcloughlin/addchain/alg/exec -github.com/mmcloughlin/addchain/alg/heuristic -github.com/mmcloughlin/addchain/alg/opt -github.com/mmcloughlin/addchain/internal/bigint -github.com/mmcloughlin/addchain/internal/bigints -github.com/mmcloughlin/addchain/internal/bigvector -github.com/mmcloughlin/addchain/internal/container/heap -github.com/mmcloughlin/addchain/internal/errutil -github.com/mmcloughlin/addchain/internal/print -github.com/mmcloughlin/addchain/meta # github.com/moby/docker-image-spec v1.3.1 ## explicit; go 1.18 github.com/moby/docker-image-spec/specs-go/v1 @@ -458,13 +434,13 @@ github.com/spf13/afero/mem # github.com/spf13/cast v1.3.1 ## explicit github.com/spf13/cast -# github.com/spf13/cobra v1.5.0 +# github.com/spf13/cobra v1.8.1 ## explicit; go 1.15 github.com/spf13/cobra # github.com/spf13/jwalterweatherman v1.1.0 ## explicit github.com/spf13/jwalterweatherman -# github.com/spf13/pflag v1.0.5 +# github.com/spf13/pflag v1.0.6 ## explicit; go 1.12 github.com/spf13/pflag # github.com/spf13/viper v1.7.0 @@ -743,9 +719,5 @@ gopkg.in/yaml.v2 gopkg.in/yaml.v3 # gotest.tools/v3 v3.5.0 ## explicit; go 1.17 -# rsc.io/tmplfunc v0.0.3 -## explicit; go 1.17 -rsc.io/tmplfunc -rsc.io/tmplfunc/internal/parse # github.com/hyperledger/fabric-config => github.com/scientificideas/fabric-config v0.1.1-0.20220421194734-201061bc5f26 # github.com/hyperledger/fabric-protos-go => github.com/scientificideas/fabric-protos-go v0.0.0-20221126151030-78861c4f6e73 diff --git a/vendor/rsc.io/tmplfunc/LICENSE b/vendor/rsc.io/tmplfunc/LICENSE deleted file mode 100644 index 6a66aea5eaf..00000000000 --- a/vendor/rsc.io/tmplfunc/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/rsc.io/tmplfunc/README.md b/vendor/rsc.io/tmplfunc/README.md deleted file mode 100644 index 8e3d917c410..00000000000 --- a/vendor/rsc.io/tmplfunc/README.md +++ /dev/null @@ -1,8 +0,0 @@ -[![Documentation](https://pkg.go.dev/badge/rsc.io/tmplfunc.svg)](https://pkg.go.dev/rsc.io/tmplfunc) - -Package tmplfunc provides an extension of Go templates -in which templates can be invoked as if they were functions. - -See the [package documentation](https://pkg.go.dev/rsc.io/tmplfunc) for details. - - diff --git a/vendor/rsc.io/tmplfunc/func.go b/vendor/rsc.io/tmplfunc/func.go deleted file mode 100644 index 4366d1f4fd5..00000000000 --- a/vendor/rsc.io/tmplfunc/func.go +++ /dev/null @@ -1,205 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package tmplfunc - -import ( - "bytes" - "fmt" - "reflect" - "regexp" - "strings" - - "rsc.io/tmplfunc/internal/parse" - - htmltemplate "html/template" - texttemplate "text/template" -) - -var validNameRE = regexp.MustCompile(`\A[_\pL][_\pL\p{Nd}]*\z`) -var validArgNameRE = regexp.MustCompile(`\A[_\pL][_\pL\p{Nd}]*(\.\.\.|\?)?\z`) - -func funcs(t Template, names, texts []string) error { - var leftDelim, rightDelim string - switch t := t.(type) { - case nil: - return fmt.Errorf("tmplfunc: nil Template") - default: - return fmt.Errorf("tmplfunc: non-template type %T", t) - case *texttemplate.Template: - leftDelim = reflect.ValueOf(t).Elem().FieldByName("leftDelim").String() - rightDelim = reflect.ValueOf(t).Elem().FieldByName("rightDelim").String() - case *htmltemplate.Template: - leftDelim = reflect.ValueOf(t).Elem().FieldByName("text").Elem().FieldByName("leftDelim").String() - rightDelim = reflect.ValueOf(t).Elem().FieldByName("text").Elem().FieldByName("rightDelim").String() - } - - trees := make(map[string]*parse.Tree) - for i, text := range texts { - t := parse.New(names[i], nil) - t.Mode = parse.SkipFuncCheck - _, err := t.Parse(text, leftDelim, rightDelim, trees) - if err != nil { - return err - } - } - - // Install functions for named templates as appropriate. - funcs := make(map[string]interface{}) - for name := range trees { - if err := addFunc(t, name, funcs); err != nil { - return err - } - } - - switch t := t.(type) { - case *texttemplate.Template: - t.Funcs(funcs) - case *htmltemplate.Template: - t.Funcs(funcs) - } - - return nil -} - -// Funcs installs functions for all the templates in the set containing t. -// After using t.Clone it is necessary to call Funcs on the result to arrange -// for the functions to invoke the cloned templates and not the originals. -func Funcs(t Template) error { - funcs := make(map[string]interface{}) - switch t := t.(type) { - case *texttemplate.Template: - for _, t1 := range t.Templates() { - if err := addFunc(t, t1.Name(), funcs); err != nil { - return err - } - } - t.Funcs(funcs) - case *htmltemplate.Template: - for _, t1 := range t.Templates() { - if err := addFunc(t, t1.Name(), funcs); err != nil { - return err - } - } - t.Funcs(funcs) - } - return nil -} - -func addFunc(t Template, name string, funcs map[string]interface{}) error { - fn, bundle, err := bundler(name) - if err != nil { - return err - } - if fn == "" { - return nil - } - switch t := t.(type) { - case *texttemplate.Template: - funcs[fn] = func(args ...interface{}) (string, error) { - t := t.Lookup(name) - if t == nil { - return "", fmt.Errorf("lost template %q", name) - } - arg, err := bundle(args) - if err != nil { - return "", err - } - var buf bytes.Buffer - err = t.Execute(&buf, arg) - if err != nil { - return "", err - } - return buf.String(), nil - } - case *htmltemplate.Template: - funcs[fn] = func(args ...interface{}) (htmltemplate.HTML, error) { - t := t.Lookup(name) - if t == nil { - return "", fmt.Errorf("lost template %q", name) - } - arg, err := bundle(args) - if err != nil { - return "", err - } - var buf bytes.Buffer - err = t.Execute(&buf, arg) - if err != nil { - return "", err - } - return htmltemplate.HTML(buf.String()), nil - } - } - return nil -} - -func bundler(name string) (fn string, bundle func(args []interface{}) (interface{}, error), err error) { - f := strings.Fields(name) - if len(f) == 0 || !validNameRE.MatchString(f[0]) { - return "", nil, nil - } - - fn = f[0] - if len(f) == 1 { - bundle = func(args []interface{}) (interface{}, error) { - if len(args) == 0 { - return nil, nil - } - if len(args) == 1 { - return args[0], nil - } - return nil, fmt.Errorf("too many arguments in call to template %s", fn) - } - } else { - sawQ := false - for i, argName := range f[1:] { - if !validArgNameRE.MatchString(argName) { - return "", nil, fmt.Errorf("invalid template name %q: invalid argument name %s", name, argName) - } - if strings.HasSuffix(argName, "...") { - if i != len(f)-2 { - return "", nil, fmt.Errorf("invalid template name %q: %s is not last argument", name, argName) - } - break - } - if strings.HasSuffix(argName, "?") { - sawQ = true - continue - } - if sawQ { - return "", nil, fmt.Errorf("invalid template name %q: required %s after optional %s", name, argName, f[i]) - } - } - - bundle = func(args []interface{}) (interface{}, error) { - m := make(map[string]interface{}) - for _, argName := range f[1:] { - if strings.HasSuffix(argName, "...") { - m[strings.TrimSuffix(argName, "...")] = args - args = nil - break - } - if strings.HasSuffix(argName, "?") { - prefix := strings.TrimSuffix(argName, "?") - if len(args) == 0 { - m[prefix] = nil - } else { - m[prefix], args = args[0], args[1:] - } - continue - } - if len(args) == 0 { - return nil, fmt.Errorf("too few arguments in call to template %s", fn) - } - m[argName], args = args[0], args[1:] - } - if len(args) > 0 { - return nil, fmt.Errorf("too many arguments in call to template %s", fn) - } - return m, nil - } - } - - return fn, bundle, nil -} diff --git a/vendor/rsc.io/tmplfunc/internal/parse/lex.go b/vendor/rsc.io/tmplfunc/internal/parse/lex.go deleted file mode 100644 index 6784071b111..00000000000 --- a/vendor/rsc.io/tmplfunc/internal/parse/lex.go +++ /dev/null @@ -1,671 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package parse - -import ( - "fmt" - "strings" - "unicode" - "unicode/utf8" -) - -// item represents a token or text string returned from the scanner. -type item struct { - typ itemType // The type of this item. - pos Pos // The starting position, in bytes, of this item in the input string. - val string // The value of this item. - line int // The line number at the start of this item. -} - -func (i item) String() string { - switch { - case i.typ == itemEOF: - return "EOF" - case i.typ == itemError: - return i.val - case i.typ > itemKeyword: - return fmt.Sprintf("<%s>", i.val) - case len(i.val) > 10: - return fmt.Sprintf("%.10q...", i.val) - } - return fmt.Sprintf("%q", i.val) -} - -// itemType identifies the type of lex items. -type itemType int - -const ( - itemError itemType = iota // error occurred; value is text of error - itemBool // boolean constant - itemChar // printable ASCII character; grab bag for comma etc. - itemCharConstant // character constant - itemComment // comment text - itemComplex // complex constant (1+2i); imaginary is just a number - itemAssign // equals ('=') introducing an assignment - itemDeclare // colon-equals (':=') introducing a declaration - itemEOF - itemField // alphanumeric identifier starting with '.' - itemIdentifier // alphanumeric identifier not starting with '.' - itemLeftDelim // left action delimiter - itemLeftParen // '(' inside action - itemNumber // simple number, including imaginary - itemPipe // pipe symbol - itemRawString // raw quoted string (includes quotes) - itemRightDelim // right action delimiter - itemRightParen // ')' inside action - itemSpace // run of spaces separating arguments - itemString // quoted string (includes quotes) - itemText // plain text - itemVariable // variable starting with '$', such as '$' or '$1' or '$hello' - // Keywords appear after all the rest. - itemKeyword // used only to delimit the keywords - itemBlock // block keyword - itemDot // the cursor, spelled '.' - itemDefine // define keyword - itemElse // else keyword - itemEnd // end keyword - itemIf // if keyword - itemNil // the untyped nil constant, easiest to treat as a keyword - itemRange // range keyword - itemTemplate // template keyword - itemWith // with keyword -) - -var key = map[string]itemType{ - ".": itemDot, - "block": itemBlock, - "define": itemDefine, - "else": itemElse, - "end": itemEnd, - "if": itemIf, - "range": itemRange, - "nil": itemNil, - "template": itemTemplate, - "with": itemWith, -} - -const eof = -1 - -// Trimming spaces. -// If the action begins "{{- " rather than "{{", then all space/tab/newlines -// preceding the action are trimmed; conversely if it ends " -}}" the -// leading spaces are trimmed. This is done entirely in the lexer; the -// parser never sees it happen. We require an ASCII space (' ', \t, \r, \n) -// to be present to avoid ambiguity with things like "{{-3}}". It reads -// better with the space present anyway. For simplicity, only ASCII -// does the job. -const ( - spaceChars = " \t\r\n" // These are the space characters defined by Go itself. - trimMarker = '-' // Attached to left/right delimiter, trims trailing spaces from preceding/following text. - trimMarkerLen = Pos(1 + 1) // marker plus space before or after -) - -// stateFn represents the state of the scanner as a function that returns the next state. -type stateFn func(*lexer) stateFn - -// lexer holds the state of the scanner. -type lexer struct { - name string // the name of the input; used only for error reports - input string // the string being scanned - leftDelim string // start of action - rightDelim string // end of action - emitComment bool // emit itemComment tokens. - pos Pos // current position in the input - start Pos // start position of this item - width Pos // width of last rune read from input - items chan item // channel of scanned items - parenDepth int // nesting depth of ( ) exprs - line int // 1+number of newlines seen - startLine int // start line of this item -} - -// next returns the next rune in the input. -func (l *lexer) next() rune { - if int(l.pos) >= len(l.input) { - l.width = 0 - return eof - } - r, w := utf8.DecodeRuneInString(l.input[l.pos:]) - l.width = Pos(w) - l.pos += l.width - if r == '\n' { - l.line++ - } - return r -} - -// peek returns but does not consume the next rune in the input. -func (l *lexer) peek() rune { - r := l.next() - l.backup() - return r -} - -// backup steps back one rune. Can only be called once per call of next. -func (l *lexer) backup() { - l.pos -= l.width - // Correct newline count. - if l.width == 1 && l.input[l.pos] == '\n' { - l.line-- - } -} - -// emit passes an item back to the client. -func (l *lexer) emit(t itemType) { - l.items <- item{t, l.start, l.input[l.start:l.pos], l.startLine} - l.start = l.pos - l.startLine = l.line -} - -// ignore skips over the pending input before this point. -func (l *lexer) ignore() { - l.line += strings.Count(l.input[l.start:l.pos], "\n") - l.start = l.pos - l.startLine = l.line -} - -// accept consumes the next rune if it's from the valid set. -func (l *lexer) accept(valid string) bool { - if strings.ContainsRune(valid, l.next()) { - return true - } - l.backup() - return false -} - -// acceptRun consumes a run of runes from the valid set. -func (l *lexer) acceptRun(valid string) { - for strings.ContainsRune(valid, l.next()) { - } - l.backup() -} - -// errorf returns an error token and terminates the scan by passing -// back a nil pointer that will be the next state, terminating l.nextItem. -func (l *lexer) errorf(format string, args ...interface{}) stateFn { - l.items <- item{itemError, l.start, fmt.Sprintf(format, args...), l.startLine} - return nil -} - -// nextItem returns the next item from the input. -// Called by the parser, not in the lexing goroutine. -func (l *lexer) nextItem() item { - return <-l.items -} - -// drain drains the output so the lexing goroutine will exit. -// Called by the parser, not in the lexing goroutine. -func (l *lexer) drain() { - for range l.items { - } -} - -// lex creates a new scanner for the input string. -func lex(name, input, left, right string, emitComment bool) *lexer { - if left == "" { - left = leftDelim - } - if right == "" { - right = rightDelim - } - l := &lexer{ - name: name, - input: input, - leftDelim: left, - rightDelim: right, - emitComment: emitComment, - items: make(chan item), - line: 1, - startLine: 1, - } - go l.run() - return l -} - -// run runs the state machine for the lexer. -func (l *lexer) run() { - for state := lexText; state != nil; { - state = state(l) - } - close(l.items) -} - -// state functions - -const ( - leftDelim = "{{" - rightDelim = "}}" - leftComment = "/*" - rightComment = "*/" -) - -// lexText scans until an opening action delimiter, "{{". -func lexText(l *lexer) stateFn { - l.width = 0 - if x := strings.Index(l.input[l.pos:], l.leftDelim); x >= 0 { - ldn := Pos(len(l.leftDelim)) - l.pos += Pos(x) - trimLength := Pos(0) - if hasLeftTrimMarker(l.input[l.pos+ldn:]) { - trimLength = rightTrimLength(l.input[l.start:l.pos]) - } - l.pos -= trimLength - if l.pos > l.start { - l.line += strings.Count(l.input[l.start:l.pos], "\n") - l.emit(itemText) - } - l.pos += trimLength - l.ignore() - return lexLeftDelim - } - l.pos = Pos(len(l.input)) - // Correctly reached EOF. - if l.pos > l.start { - l.line += strings.Count(l.input[l.start:l.pos], "\n") - l.emit(itemText) - } - l.emit(itemEOF) - return nil -} - -// rightTrimLength returns the length of the spaces at the end of the string. -func rightTrimLength(s string) Pos { - return Pos(len(s) - len(strings.TrimRight(s, spaceChars))) -} - -// atRightDelim reports whether the lexer is at a right delimiter, possibly preceded by a trim marker. -func (l *lexer) atRightDelim() (delim, trimSpaces bool) { - if hasRightTrimMarker(l.input[l.pos:]) && strings.HasPrefix(l.input[l.pos+trimMarkerLen:], l.rightDelim) { // With trim marker. - return true, true - } - if strings.HasPrefix(l.input[l.pos:], l.rightDelim) { // Without trim marker. - return true, false - } - return false, false -} - -// leftTrimLength returns the length of the spaces at the beginning of the string. -func leftTrimLength(s string) Pos { - return Pos(len(s) - len(strings.TrimLeft(s, spaceChars))) -} - -// lexLeftDelim scans the left delimiter, which is known to be present, possibly with a trim marker. -func lexLeftDelim(l *lexer) stateFn { - l.pos += Pos(len(l.leftDelim)) - trimSpace := hasLeftTrimMarker(l.input[l.pos:]) - afterMarker := Pos(0) - if trimSpace { - afterMarker = trimMarkerLen - } - if strings.HasPrefix(l.input[l.pos+afterMarker:], leftComment) { - l.pos += afterMarker - l.ignore() - return lexComment - } - l.emit(itemLeftDelim) - l.pos += afterMarker - l.ignore() - l.parenDepth = 0 - return lexInsideAction -} - -// lexComment scans a comment. The left comment marker is known to be present. -func lexComment(l *lexer) stateFn { - l.pos += Pos(len(leftComment)) - i := strings.Index(l.input[l.pos:], rightComment) - if i < 0 { - return l.errorf("unclosed comment") - } - l.pos += Pos(i + len(rightComment)) - delim, trimSpace := l.atRightDelim() - if !delim { - return l.errorf("comment ends before closing delimiter") - } - if l.emitComment { - l.emit(itemComment) - } - if trimSpace { - l.pos += trimMarkerLen - } - l.pos += Pos(len(l.rightDelim)) - if trimSpace { - l.pos += leftTrimLength(l.input[l.pos:]) - } - l.ignore() - return lexText -} - -// lexRightDelim scans the right delimiter, which is known to be present, possibly with a trim marker. -func lexRightDelim(l *lexer) stateFn { - trimSpace := hasRightTrimMarker(l.input[l.pos:]) - if trimSpace { - l.pos += trimMarkerLen - l.ignore() - } - l.pos += Pos(len(l.rightDelim)) - l.emit(itemRightDelim) - if trimSpace { - l.pos += leftTrimLength(l.input[l.pos:]) - l.ignore() - } - return lexText -} - -// lexInsideAction scans the elements inside action delimiters. -func lexInsideAction(l *lexer) stateFn { - // Either number, quoted string, or identifier. - // Spaces separate arguments; runs of spaces turn into itemSpace. - // Pipe symbols separate and are emitted. - delim, _ := l.atRightDelim() - if delim { - if l.parenDepth == 0 { - return lexRightDelim - } - return l.errorf("unclosed left paren") - } - switch r := l.next(); { - case r == eof: - return l.errorf("unclosed action") - case isSpace(r): - l.backup() // Put space back in case we have " -}}". - return lexSpace - case r == '=': - l.emit(itemAssign) - case r == ':': - if l.next() != '=' { - return l.errorf("expected :=") - } - l.emit(itemDeclare) - case r == '|': - l.emit(itemPipe) - case r == '"': - return lexQuote - case r == '`': - return lexRawQuote - case r == '$': - return lexVariable - case r == '\'': - return lexChar - case r == '.': - // special look-ahead for ".field" so we don't break l.backup(). - if l.pos < Pos(len(l.input)) { - r := l.input[l.pos] - if r < '0' || '9' < r { - return lexField - } - } - fallthrough // '.' can start a number. - case r == '+' || r == '-' || ('0' <= r && r <= '9'): - l.backup() - return lexNumber - case isAlphaNumeric(r): - l.backup() - return lexIdentifier - case r == '(': - l.emit(itemLeftParen) - l.parenDepth++ - case r == ')': - l.emit(itemRightParen) - l.parenDepth-- - if l.parenDepth < 0 { - return l.errorf("unexpected right paren %#U", r) - } - case r <= unicode.MaxASCII && unicode.IsPrint(r): - l.emit(itemChar) - default: - return l.errorf("unrecognized character in action: %#U", r) - } - return lexInsideAction -} - -// lexSpace scans a run of space characters. -// We have not consumed the first space, which is known to be present. -// Take care if there is a trim-marked right delimiter, which starts with a space. -func lexSpace(l *lexer) stateFn { - var r rune - var numSpaces int - for { - r = l.peek() - if !isSpace(r) { - break - } - l.next() - numSpaces++ - } - // Be careful about a trim-marked closing delimiter, which has a minus - // after a space. We know there is a space, so check for the '-' that might follow. - if hasRightTrimMarker(l.input[l.pos-1:]) && strings.HasPrefix(l.input[l.pos-1+trimMarkerLen:], l.rightDelim) { - l.backup() // Before the space. - if numSpaces == 1 { - return lexRightDelim // On the delim, so go right to that. - } - } - l.emit(itemSpace) - return lexInsideAction -} - -// lexIdentifier scans an alphanumeric. -func lexIdentifier(l *lexer) stateFn { -Loop: - for { - switch r := l.next(); { - case isAlphaNumeric(r): - // absorb. - default: - l.backup() - word := l.input[l.start:l.pos] - if !l.atTerminator() { - return l.errorf("bad character %#U", r) - } - switch { - case key[word] > itemKeyword: - l.emit(key[word]) - case word[0] == '.': - l.emit(itemField) - case word == "true", word == "false": - l.emit(itemBool) - default: - l.emit(itemIdentifier) - } - break Loop - } - } - return lexInsideAction -} - -// lexField scans a field: .Alphanumeric. -// The . has been scanned. -func lexField(l *lexer) stateFn { - return lexFieldOrVariable(l, itemField) -} - -// lexVariable scans a Variable: $Alphanumeric. -// The $ has been scanned. -func lexVariable(l *lexer) stateFn { - if l.atTerminator() { // Nothing interesting follows -> "$". - l.emit(itemVariable) - return lexInsideAction - } - return lexFieldOrVariable(l, itemVariable) -} - -// lexVariable scans a field or variable: [.$]Alphanumeric. -// The . or $ has been scanned. -func lexFieldOrVariable(l *lexer, typ itemType) stateFn { - if l.atTerminator() { // Nothing interesting follows -> "." or "$". - if typ == itemVariable { - l.emit(itemVariable) - } else { - l.emit(itemDot) - } - return lexInsideAction - } - var r rune - for { - r = l.next() - if !isAlphaNumeric(r) { - l.backup() - break - } - } - if !l.atTerminator() { - return l.errorf("bad character %#U", r) - } - l.emit(typ) - return lexInsideAction -} - -// atTerminator reports whether the input is at valid termination character to -// appear after an identifier. Breaks .X.Y into two pieces. Also catches cases -// like "$x+2" not being acceptable without a space, in case we decide one -// day to implement arithmetic. -func (l *lexer) atTerminator() bool { - r := l.peek() - if isSpace(r) { - return true - } - switch r { - case eof, '.', ',', '|', ':', ')', '(': - return true - } - // Does r start the delimiter? This can be ambiguous (with delim=="//", $x/2 will - // succeed but should fail) but only in extremely rare cases caused by willfully - // bad choice of delimiter. - if rd, _ := utf8.DecodeRuneInString(l.rightDelim); rd == r { - return true - } - return false -} - -// lexChar scans a character constant. The initial quote is already -// scanned. Syntax checking is done by the parser. -func lexChar(l *lexer) stateFn { -Loop: - for { - switch l.next() { - case '\\': - if r := l.next(); r != eof && r != '\n' { - break - } - fallthrough - case eof, '\n': - return l.errorf("unterminated character constant") - case '\'': - break Loop - } - } - l.emit(itemCharConstant) - return lexInsideAction -} - -// lexNumber scans a number: decimal, octal, hex, float, or imaginary. This -// isn't a perfect number scanner - for instance it accepts "." and "0x0.2" -// and "089" - but when it's wrong the input is invalid and the parser (via -// strconv) will notice. -func lexNumber(l *lexer) stateFn { - if !l.scanNumber() { - return l.errorf("bad number syntax: %q", l.input[l.start:l.pos]) - } - if sign := l.peek(); sign == '+' || sign == '-' { - // Complex: 1+2i. No spaces, must end in 'i'. - if !l.scanNumber() || l.input[l.pos-1] != 'i' { - return l.errorf("bad number syntax: %q", l.input[l.start:l.pos]) - } - l.emit(itemComplex) - } else { - l.emit(itemNumber) - } - return lexInsideAction -} - -func (l *lexer) scanNumber() bool { - // Optional leading sign. - l.accept("+-") - // Is it hex? - digits := "0123456789_" - if l.accept("0") { - // Note: Leading 0 does not mean octal in floats. - if l.accept("xX") { - digits = "0123456789abcdefABCDEF_" - } else if l.accept("oO") { - digits = "01234567_" - } else if l.accept("bB") { - digits = "01_" - } - } - l.acceptRun(digits) - if l.accept(".") { - l.acceptRun(digits) - } - if len(digits) == 10+1 && l.accept("eE") { - l.accept("+-") - l.acceptRun("0123456789_") - } - if len(digits) == 16+6+1 && l.accept("pP") { - l.accept("+-") - l.acceptRun("0123456789_") - } - // Is it imaginary? - l.accept("i") - // Next thing mustn't be alphanumeric. - if isAlphaNumeric(l.peek()) { - l.next() - return false - } - return true -} - -// lexQuote scans a quoted string. -func lexQuote(l *lexer) stateFn { -Loop: - for { - switch l.next() { - case '\\': - if r := l.next(); r != eof && r != '\n' { - break - } - fallthrough - case eof, '\n': - return l.errorf("unterminated quoted string") - case '"': - break Loop - } - } - l.emit(itemString) - return lexInsideAction -} - -// lexRawQuote scans a raw quoted string. -func lexRawQuote(l *lexer) stateFn { -Loop: - for { - switch l.next() { - case eof: - return l.errorf("unterminated raw quoted string") - case '`': - break Loop - } - } - l.emit(itemRawString) - return lexInsideAction -} - -// isSpace reports whether r is a space character. -func isSpace(r rune) bool { - return r == ' ' || r == '\t' || r == '\r' || r == '\n' -} - -// isAlphaNumeric reports whether r is an alphabetic, digit, or underscore. -func isAlphaNumeric(r rune) bool { - return r == '_' || unicode.IsLetter(r) || unicode.IsDigit(r) -} - -func hasLeftTrimMarker(s string) bool { - return len(s) >= 2 && s[0] == trimMarker && isSpace(rune(s[1])) -} - -func hasRightTrimMarker(s string) bool { - return len(s) >= 2 && isSpace(rune(s[0])) && s[1] == trimMarker -} diff --git a/vendor/rsc.io/tmplfunc/internal/parse/node.go b/vendor/rsc.io/tmplfunc/internal/parse/node.go deleted file mode 100644 index 177482f9b26..00000000000 --- a/vendor/rsc.io/tmplfunc/internal/parse/node.go +++ /dev/null @@ -1,972 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Parse nodes. - -package parse - -import ( - "fmt" - "strconv" - "strings" -) - -var textFormat = "%s" // Changed to "%q" in tests for better error messages. - -// A Node is an element in the parse tree. The interface is trivial. -// The interface contains an unexported method so that only -// types local to this package can satisfy it. -type Node interface { - Type() NodeType - String() string - // Copy does a deep copy of the Node and all its components. - // To avoid type assertions, some XxxNodes also have specialized - // CopyXxx methods that return *XxxNode. - Copy() Node - Position() Pos // byte position of start of node in full original input string - // tree returns the containing *Tree. - // It is unexported so all implementations of Node are in this package. - tree() *Tree - // writeTo writes the String output to the builder. - writeTo(*strings.Builder) -} - -// NodeType identifies the type of a parse tree node. -type NodeType int - -// Pos represents a byte position in the original input text from which -// this template was parsed. -type Pos int - -func (p Pos) Position() Pos { - return p -} - -// Type returns itself and provides an easy default implementation -// for embedding in a Node. Embedded in all non-trivial Nodes. -func (t NodeType) Type() NodeType { - return t -} - -const ( - NodeText NodeType = iota // Plain text. - NodeAction // A non-control action such as a field evaluation. - NodeBool // A boolean constant. - NodeChain // A sequence of field accesses. - NodeCommand // An element of a pipeline. - NodeDot // The cursor, dot. - nodeElse // An else action. Not added to tree. - nodeEnd // An end action. Not added to tree. - NodeField // A field or method name. - NodeIdentifier // An identifier; always a function name. - NodeIf // An if action. - NodeList // A list of Nodes. - NodeNil // An untyped nil constant. - NodeNumber // A numerical constant. - NodePipe // A pipeline of commands. - NodeRange // A range action. - NodeString // A string constant. - NodeTemplate // A template invocation action. - NodeVariable // A $ variable. - NodeWith // A with action. - NodeComment // A comment. -) - -// Nodes. - -// ListNode holds a sequence of nodes. -type ListNode struct { - NodeType - Pos - tr *Tree - Nodes []Node // The element nodes in lexical order. -} - -func (t *Tree) newList(pos Pos) *ListNode { - return &ListNode{tr: t, NodeType: NodeList, Pos: pos} -} - -func (l *ListNode) append(n Node) { - l.Nodes = append(l.Nodes, n) -} - -func (l *ListNode) tree() *Tree { - return l.tr -} - -func (l *ListNode) String() string { - var sb strings.Builder - l.writeTo(&sb) - return sb.String() -} - -func (l *ListNode) writeTo(sb *strings.Builder) { - for _, n := range l.Nodes { - n.writeTo(sb) - } -} - -func (l *ListNode) CopyList() *ListNode { - if l == nil { - return l - } - n := l.tr.newList(l.Pos) - for _, elem := range l.Nodes { - n.append(elem.Copy()) - } - return n -} - -func (l *ListNode) Copy() Node { - return l.CopyList() -} - -// TextNode holds plain text. -type TextNode struct { - NodeType - Pos - tr *Tree - Text []byte // The text; may span newlines. -} - -func (t *Tree) newText(pos Pos, text string) *TextNode { - return &TextNode{tr: t, NodeType: NodeText, Pos: pos, Text: []byte(text)} -} - -func (t *TextNode) String() string { - return fmt.Sprintf(textFormat, t.Text) -} - -func (t *TextNode) writeTo(sb *strings.Builder) { - sb.WriteString(t.String()) -} - -func (t *TextNode) tree() *Tree { - return t.tr -} - -func (t *TextNode) Copy() Node { - return &TextNode{tr: t.tr, NodeType: NodeText, Pos: t.Pos, Text: append([]byte{}, t.Text...)} -} - -// CommentNode holds a comment. -type CommentNode struct { - NodeType - Pos - tr *Tree - Text string // Comment text. -} - -func (t *Tree) newComment(pos Pos, text string) *CommentNode { - return &CommentNode{tr: t, NodeType: NodeComment, Pos: pos, Text: text} -} - -func (c *CommentNode) String() string { - var sb strings.Builder - c.writeTo(&sb) - return sb.String() -} - -func (c *CommentNode) writeTo(sb *strings.Builder) { - sb.WriteString("{{") - sb.WriteString(c.Text) - sb.WriteString("}}") -} - -func (c *CommentNode) tree() *Tree { - return c.tr -} - -func (c *CommentNode) Copy() Node { - return &CommentNode{tr: c.tr, NodeType: NodeComment, Pos: c.Pos, Text: c.Text} -} - -// PipeNode holds a pipeline with optional declaration -type PipeNode struct { - NodeType - Pos - tr *Tree - Line int // The line number in the input. Deprecated: Kept for compatibility. - IsAssign bool // The variables are being assigned, not declared. - Decl []*VariableNode // Variables in lexical order. - Cmds []*CommandNode // The commands in lexical order. -} - -func (t *Tree) newPipeline(pos Pos, line int, vars []*VariableNode) *PipeNode { - return &PipeNode{tr: t, NodeType: NodePipe, Pos: pos, Line: line, Decl: vars} -} - -func (p *PipeNode) append(command *CommandNode) { - p.Cmds = append(p.Cmds, command) -} - -func (p *PipeNode) String() string { - var sb strings.Builder - p.writeTo(&sb) - return sb.String() -} - -func (p *PipeNode) writeTo(sb *strings.Builder) { - if len(p.Decl) > 0 { - for i, v := range p.Decl { - if i > 0 { - sb.WriteString(", ") - } - v.writeTo(sb) - } - sb.WriteString(" := ") - } - for i, c := range p.Cmds { - if i > 0 { - sb.WriteString(" | ") - } - c.writeTo(sb) - } -} - -func (p *PipeNode) tree() *Tree { - return p.tr -} - -func (p *PipeNode) CopyPipe() *PipeNode { - if p == nil { - return p - } - vars := make([]*VariableNode, len(p.Decl)) - for i, d := range p.Decl { - vars[i] = d.Copy().(*VariableNode) - } - n := p.tr.newPipeline(p.Pos, p.Line, vars) - n.IsAssign = p.IsAssign - for _, c := range p.Cmds { - n.append(c.Copy().(*CommandNode)) - } - return n -} - -func (p *PipeNode) Copy() Node { - return p.CopyPipe() -} - -// ActionNode holds an action (something bounded by delimiters). -// Control actions have their own nodes; ActionNode represents simple -// ones such as field evaluations and parenthesized pipelines. -type ActionNode struct { - NodeType - Pos - tr *Tree - Line int // The line number in the input. Deprecated: Kept for compatibility. - Pipe *PipeNode // The pipeline in the action. -} - -func (t *Tree) newAction(pos Pos, line int, pipe *PipeNode) *ActionNode { - return &ActionNode{tr: t, NodeType: NodeAction, Pos: pos, Line: line, Pipe: pipe} -} - -func (a *ActionNode) String() string { - var sb strings.Builder - a.writeTo(&sb) - return sb.String() -} - -func (a *ActionNode) writeTo(sb *strings.Builder) { - sb.WriteString("{{") - a.Pipe.writeTo(sb) - sb.WriteString("}}") -} - -func (a *ActionNode) tree() *Tree { - return a.tr -} - -func (a *ActionNode) Copy() Node { - return a.tr.newAction(a.Pos, a.Line, a.Pipe.CopyPipe()) - -} - -// CommandNode holds a command (a pipeline inside an evaluating action). -type CommandNode struct { - NodeType - Pos - tr *Tree - Args []Node // Arguments in lexical order: Identifier, field, or constant. -} - -func (t *Tree) newCommand(pos Pos) *CommandNode { - return &CommandNode{tr: t, NodeType: NodeCommand, Pos: pos} -} - -func (c *CommandNode) append(arg Node) { - c.Args = append(c.Args, arg) -} - -func (c *CommandNode) String() string { - var sb strings.Builder - c.writeTo(&sb) - return sb.String() -} - -func (c *CommandNode) writeTo(sb *strings.Builder) { - for i, arg := range c.Args { - if i > 0 { - sb.WriteByte(' ') - } - if arg, ok := arg.(*PipeNode); ok { - sb.WriteByte('(') - arg.writeTo(sb) - sb.WriteByte(')') - continue - } - arg.writeTo(sb) - } -} - -func (c *CommandNode) tree() *Tree { - return c.tr -} - -func (c *CommandNode) Copy() Node { - if c == nil { - return c - } - n := c.tr.newCommand(c.Pos) - for _, c := range c.Args { - n.append(c.Copy()) - } - return n -} - -// IdentifierNode holds an identifier. -type IdentifierNode struct { - NodeType - Pos - tr *Tree - Ident string // The identifier's name. -} - -// NewIdentifier returns a new IdentifierNode with the given identifier name. -func NewIdentifier(ident string) *IdentifierNode { - return &IdentifierNode{NodeType: NodeIdentifier, Ident: ident} -} - -// SetPos sets the position. NewIdentifier is a public method so we can't modify its signature. -// Chained for convenience. -// TODO: fix one day? -func (i *IdentifierNode) SetPos(pos Pos) *IdentifierNode { - i.Pos = pos - return i -} - -// SetTree sets the parent tree for the node. NewIdentifier is a public method so we can't modify its signature. -// Chained for convenience. -// TODO: fix one day? -func (i *IdentifierNode) SetTree(t *Tree) *IdentifierNode { - i.tr = t - return i -} - -func (i *IdentifierNode) String() string { - return i.Ident -} - -func (i *IdentifierNode) writeTo(sb *strings.Builder) { - sb.WriteString(i.String()) -} - -func (i *IdentifierNode) tree() *Tree { - return i.tr -} - -func (i *IdentifierNode) Copy() Node { - return NewIdentifier(i.Ident).SetTree(i.tr).SetPos(i.Pos) -} - -// VariableNode holds a list of variable names, possibly with chained field -// accesses. The dollar sign is part of the (first) name. -type VariableNode struct { - NodeType - Pos - tr *Tree - Ident []string // Variable name and fields in lexical order. -} - -func (t *Tree) newVariable(pos Pos, ident string) *VariableNode { - return &VariableNode{tr: t, NodeType: NodeVariable, Pos: pos, Ident: strings.Split(ident, ".")} -} - -func (v *VariableNode) String() string { - var sb strings.Builder - v.writeTo(&sb) - return sb.String() -} - -func (v *VariableNode) writeTo(sb *strings.Builder) { - for i, id := range v.Ident { - if i > 0 { - sb.WriteByte('.') - } - sb.WriteString(id) - } -} - -func (v *VariableNode) tree() *Tree { - return v.tr -} - -func (v *VariableNode) Copy() Node { - return &VariableNode{tr: v.tr, NodeType: NodeVariable, Pos: v.Pos, Ident: append([]string{}, v.Ident...)} -} - -// DotNode holds the special identifier '.'. -type DotNode struct { - NodeType - Pos - tr *Tree -} - -func (t *Tree) newDot(pos Pos) *DotNode { - return &DotNode{tr: t, NodeType: NodeDot, Pos: pos} -} - -func (d *DotNode) Type() NodeType { - // Override method on embedded NodeType for API compatibility. - // TODO: Not really a problem; could change API without effect but - // api tool complains. - return NodeDot -} - -func (d *DotNode) String() string { - return "." -} - -func (d *DotNode) writeTo(sb *strings.Builder) { - sb.WriteString(d.String()) -} - -func (d *DotNode) tree() *Tree { - return d.tr -} - -func (d *DotNode) Copy() Node { - return d.tr.newDot(d.Pos) -} - -// NilNode holds the special identifier 'nil' representing an untyped nil constant. -type NilNode struct { - NodeType - Pos - tr *Tree -} - -func (t *Tree) newNil(pos Pos) *NilNode { - return &NilNode{tr: t, NodeType: NodeNil, Pos: pos} -} - -func (n *NilNode) Type() NodeType { - // Override method on embedded NodeType for API compatibility. - // TODO: Not really a problem; could change API without effect but - // api tool complains. - return NodeNil -} - -func (n *NilNode) String() string { - return "nil" -} - -func (n *NilNode) writeTo(sb *strings.Builder) { - sb.WriteString(n.String()) -} - -func (n *NilNode) tree() *Tree { - return n.tr -} - -func (n *NilNode) Copy() Node { - return n.tr.newNil(n.Pos) -} - -// FieldNode holds a field (identifier starting with '.'). -// The names may be chained ('.x.y'). -// The period is dropped from each ident. -type FieldNode struct { - NodeType - Pos - tr *Tree - Ident []string // The identifiers in lexical order. -} - -func (t *Tree) newField(pos Pos, ident string) *FieldNode { - return &FieldNode{tr: t, NodeType: NodeField, Pos: pos, Ident: strings.Split(ident[1:], ".")} // [1:] to drop leading period -} - -func (f *FieldNode) String() string { - var sb strings.Builder - f.writeTo(&sb) - return sb.String() -} - -func (f *FieldNode) writeTo(sb *strings.Builder) { - for _, id := range f.Ident { - sb.WriteByte('.') - sb.WriteString(id) - } -} - -func (f *FieldNode) tree() *Tree { - return f.tr -} - -func (f *FieldNode) Copy() Node { - return &FieldNode{tr: f.tr, NodeType: NodeField, Pos: f.Pos, Ident: append([]string{}, f.Ident...)} -} - -// ChainNode holds a term followed by a chain of field accesses (identifier starting with '.'). -// The names may be chained ('.x.y'). -// The periods are dropped from each ident. -type ChainNode struct { - NodeType - Pos - tr *Tree - Node Node - Field []string // The identifiers in lexical order. -} - -func (t *Tree) newChain(pos Pos, node Node) *ChainNode { - return &ChainNode{tr: t, NodeType: NodeChain, Pos: pos, Node: node} -} - -// Add adds the named field (which should start with a period) to the end of the chain. -func (c *ChainNode) Add(field string) { - if len(field) == 0 || field[0] != '.' { - panic("no dot in field") - } - field = field[1:] // Remove leading dot. - if field == "" { - panic("empty field") - } - c.Field = append(c.Field, field) -} - -func (c *ChainNode) String() string { - var sb strings.Builder - c.writeTo(&sb) - return sb.String() -} - -func (c *ChainNode) writeTo(sb *strings.Builder) { - if _, ok := c.Node.(*PipeNode); ok { - sb.WriteByte('(') - c.Node.writeTo(sb) - sb.WriteByte(')') - } else { - c.Node.writeTo(sb) - } - for _, field := range c.Field { - sb.WriteByte('.') - sb.WriteString(field) - } -} - -func (c *ChainNode) tree() *Tree { - return c.tr -} - -func (c *ChainNode) Copy() Node { - return &ChainNode{tr: c.tr, NodeType: NodeChain, Pos: c.Pos, Node: c.Node, Field: append([]string{}, c.Field...)} -} - -// BoolNode holds a boolean constant. -type BoolNode struct { - NodeType - Pos - tr *Tree - True bool // The value of the boolean constant. -} - -func (t *Tree) newBool(pos Pos, true bool) *BoolNode { - return &BoolNode{tr: t, NodeType: NodeBool, Pos: pos, True: true} -} - -func (b *BoolNode) String() string { - if b.True { - return "true" - } - return "false" -} - -func (b *BoolNode) writeTo(sb *strings.Builder) { - sb.WriteString(b.String()) -} - -func (b *BoolNode) tree() *Tree { - return b.tr -} - -func (b *BoolNode) Copy() Node { - return b.tr.newBool(b.Pos, b.True) -} - -// NumberNode holds a number: signed or unsigned integer, float, or complex. -// The value is parsed and stored under all the types that can represent the value. -// This simulates in a small amount of code the behavior of Go's ideal constants. -type NumberNode struct { - NodeType - Pos - tr *Tree - IsInt bool // Number has an integral value. - IsUint bool // Number has an unsigned integral value. - IsFloat bool // Number has a floating-point value. - IsComplex bool // Number is complex. - Int64 int64 // The signed integer value. - Uint64 uint64 // The unsigned integer value. - Float64 float64 // The floating-point value. - Complex128 complex128 // The complex value. - Text string // The original textual representation from the input. -} - -func (t *Tree) newNumber(pos Pos, text string, typ itemType) (*NumberNode, error) { - n := &NumberNode{tr: t, NodeType: NodeNumber, Pos: pos, Text: text} - switch typ { - case itemCharConstant: - rune, _, tail, err := strconv.UnquoteChar(text[1:], text[0]) - if err != nil { - return nil, err - } - if tail != "'" { - return nil, fmt.Errorf("malformed character constant: %s", text) - } - n.Int64 = int64(rune) - n.IsInt = true - n.Uint64 = uint64(rune) - n.IsUint = true - n.Float64 = float64(rune) // odd but those are the rules. - n.IsFloat = true - return n, nil - case itemComplex: - // fmt.Sscan can parse the pair, so let it do the work. - if _, err := fmt.Sscan(text, &n.Complex128); err != nil { - return nil, err - } - n.IsComplex = true - n.simplifyComplex() - return n, nil - } - // Imaginary constants can only be complex unless they are zero. - if len(text) > 0 && text[len(text)-1] == 'i' { - f, err := strconv.ParseFloat(text[:len(text)-1], 64) - if err == nil { - n.IsComplex = true - n.Complex128 = complex(0, f) - n.simplifyComplex() - return n, nil - } - } - // Do integer test first so we get 0x123 etc. - u, err := strconv.ParseUint(text, 0, 64) // will fail for -0; fixed below. - if err == nil { - n.IsUint = true - n.Uint64 = u - } - i, err := strconv.ParseInt(text, 0, 64) - if err == nil { - n.IsInt = true - n.Int64 = i - if i == 0 { - n.IsUint = true // in case of -0. - n.Uint64 = u - } - } - // If an integer extraction succeeded, promote the float. - if n.IsInt { - n.IsFloat = true - n.Float64 = float64(n.Int64) - } else if n.IsUint { - n.IsFloat = true - n.Float64 = float64(n.Uint64) - } else { - f, err := strconv.ParseFloat(text, 64) - if err == nil { - // If we parsed it as a float but it looks like an integer, - // it's a huge number too large to fit in an int. Reject it. - if !strings.ContainsAny(text, ".eEpP") { - return nil, fmt.Errorf("integer overflow: %q", text) - } - n.IsFloat = true - n.Float64 = f - // If a floating-point extraction succeeded, extract the int if needed. - if !n.IsInt && float64(int64(f)) == f { - n.IsInt = true - n.Int64 = int64(f) - } - if !n.IsUint && float64(uint64(f)) == f { - n.IsUint = true - n.Uint64 = uint64(f) - } - } - } - if !n.IsInt && !n.IsUint && !n.IsFloat { - return nil, fmt.Errorf("illegal number syntax: %q", text) - } - return n, nil -} - -// simplifyComplex pulls out any other types that are represented by the complex number. -// These all require that the imaginary part be zero. -func (n *NumberNode) simplifyComplex() { - n.IsFloat = imag(n.Complex128) == 0 - if n.IsFloat { - n.Float64 = real(n.Complex128) - n.IsInt = float64(int64(n.Float64)) == n.Float64 - if n.IsInt { - n.Int64 = int64(n.Float64) - } - n.IsUint = float64(uint64(n.Float64)) == n.Float64 - if n.IsUint { - n.Uint64 = uint64(n.Float64) - } - } -} - -func (n *NumberNode) String() string { - return n.Text -} - -func (n *NumberNode) writeTo(sb *strings.Builder) { - sb.WriteString(n.String()) -} - -func (n *NumberNode) tree() *Tree { - return n.tr -} - -func (n *NumberNode) Copy() Node { - nn := new(NumberNode) - *nn = *n // Easy, fast, correct. - return nn -} - -// StringNode holds a string constant. The value has been "unquoted". -type StringNode struct { - NodeType - Pos - tr *Tree - Quoted string // The original text of the string, with quotes. - Text string // The string, after quote processing. -} - -func (t *Tree) newString(pos Pos, orig, text string) *StringNode { - return &StringNode{tr: t, NodeType: NodeString, Pos: pos, Quoted: orig, Text: text} -} - -func (s *StringNode) String() string { - return s.Quoted -} - -func (s *StringNode) writeTo(sb *strings.Builder) { - sb.WriteString(s.String()) -} - -func (s *StringNode) tree() *Tree { - return s.tr -} - -func (s *StringNode) Copy() Node { - return s.tr.newString(s.Pos, s.Quoted, s.Text) -} - -// endNode represents an {{end}} action. -// It does not appear in the final parse tree. -type endNode struct { - NodeType - Pos - tr *Tree -} - -func (t *Tree) newEnd(pos Pos) *endNode { - return &endNode{tr: t, NodeType: nodeEnd, Pos: pos} -} - -func (e *endNode) String() string { - return "{{end}}" -} - -func (e *endNode) writeTo(sb *strings.Builder) { - sb.WriteString(e.String()) -} - -func (e *endNode) tree() *Tree { - return e.tr -} - -func (e *endNode) Copy() Node { - return e.tr.newEnd(e.Pos) -} - -// elseNode represents an {{else}} action. Does not appear in the final tree. -type elseNode struct { - NodeType - Pos - tr *Tree - Line int // The line number in the input. Deprecated: Kept for compatibility. -} - -func (t *Tree) newElse(pos Pos, line int) *elseNode { - return &elseNode{tr: t, NodeType: nodeElse, Pos: pos, Line: line} -} - -func (e *elseNode) Type() NodeType { - return nodeElse -} - -func (e *elseNode) String() string { - return "{{else}}" -} - -func (e *elseNode) writeTo(sb *strings.Builder) { - sb.WriteString(e.String()) -} - -func (e *elseNode) tree() *Tree { - return e.tr -} - -func (e *elseNode) Copy() Node { - return e.tr.newElse(e.Pos, e.Line) -} - -// BranchNode is the common representation of if, range, and with. -type BranchNode struct { - NodeType - Pos - tr *Tree - Line int // The line number in the input. Deprecated: Kept for compatibility. - Pipe *PipeNode // The pipeline to be evaluated. - List *ListNode // What to execute if the value is non-empty. - ElseList *ListNode // What to execute if the value is empty (nil if absent). -} - -func (b *BranchNode) String() string { - var sb strings.Builder - b.writeTo(&sb) - return sb.String() -} - -func (b *BranchNode) writeTo(sb *strings.Builder) { - name := "" - switch b.NodeType { - case NodeIf: - name = "if" - case NodeRange: - name = "range" - case NodeWith: - name = "with" - default: - panic("unknown branch type") - } - sb.WriteString("{{") - sb.WriteString(name) - sb.WriteByte(' ') - b.Pipe.writeTo(sb) - sb.WriteString("}}") - b.List.writeTo(sb) - if b.ElseList != nil { - sb.WriteString("{{else}}") - b.ElseList.writeTo(sb) - } - sb.WriteString("{{end}}") -} - -func (b *BranchNode) tree() *Tree { - return b.tr -} - -func (b *BranchNode) Copy() Node { - switch b.NodeType { - case NodeIf: - return b.tr.newIf(b.Pos, b.Line, b.Pipe, b.List, b.ElseList) - case NodeRange: - return b.tr.newRange(b.Pos, b.Line, b.Pipe, b.List, b.ElseList) - case NodeWith: - return b.tr.newWith(b.Pos, b.Line, b.Pipe, b.List, b.ElseList) - default: - panic("unknown branch type") - } -} - -// IfNode represents an {{if}} action and its commands. -type IfNode struct { - BranchNode -} - -func (t *Tree) newIf(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *IfNode { - return &IfNode{BranchNode{tr: t, NodeType: NodeIf, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}} -} - -func (i *IfNode) Copy() Node { - return i.tr.newIf(i.Pos, i.Line, i.Pipe.CopyPipe(), i.List.CopyList(), i.ElseList.CopyList()) -} - -// RangeNode represents a {{range}} action and its commands. -type RangeNode struct { - BranchNode -} - -func (t *Tree) newRange(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *RangeNode { - return &RangeNode{BranchNode{tr: t, NodeType: NodeRange, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}} -} - -func (r *RangeNode) Copy() Node { - return r.tr.newRange(r.Pos, r.Line, r.Pipe.CopyPipe(), r.List.CopyList(), r.ElseList.CopyList()) -} - -// WithNode represents a {{with}} action and its commands. -type WithNode struct { - BranchNode -} - -func (t *Tree) newWith(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *WithNode { - return &WithNode{BranchNode{tr: t, NodeType: NodeWith, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}} -} - -func (w *WithNode) Copy() Node { - return w.tr.newWith(w.Pos, w.Line, w.Pipe.CopyPipe(), w.List.CopyList(), w.ElseList.CopyList()) -} - -// TemplateNode represents a {{template}} action. -type TemplateNode struct { - NodeType - Pos - tr *Tree - Line int // The line number in the input. Deprecated: Kept for compatibility. - Name string // The name of the template (unquoted). - Pipe *PipeNode // The command to evaluate as dot for the template. -} - -func (t *Tree) newTemplate(pos Pos, line int, name string, pipe *PipeNode) *TemplateNode { - return &TemplateNode{tr: t, NodeType: NodeTemplate, Pos: pos, Line: line, Name: name, Pipe: pipe} -} - -func (t *TemplateNode) String() string { - var sb strings.Builder - t.writeTo(&sb) - return sb.String() -} - -func (t *TemplateNode) writeTo(sb *strings.Builder) { - sb.WriteString("{{template ") - sb.WriteString(strconv.Quote(t.Name)) - if t.Pipe != nil { - sb.WriteByte(' ') - t.Pipe.writeTo(sb) - } - sb.WriteString("}}") -} - -func (t *TemplateNode) tree() *Tree { - return t.tr -} - -func (t *TemplateNode) Copy() Node { - return t.tr.newTemplate(t.Pos, t.Line, t.Name, t.Pipe.CopyPipe()) -} diff --git a/vendor/rsc.io/tmplfunc/internal/parse/parse.go b/vendor/rsc.io/tmplfunc/internal/parse/parse.go deleted file mode 100644 index 1a63961c13e..00000000000 --- a/vendor/rsc.io/tmplfunc/internal/parse/parse.go +++ /dev/null @@ -1,756 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package parse builds parse trees for templates as defined by text/template -// and html/template. Clients should use those packages to construct templates -// rather than this one, which provides shared internal data structures not -// intended for general use. -package parse - -import ( - "bytes" - "fmt" - "runtime" - "strconv" - "strings" -) - -// Tree is the representation of a single parsed template. -type Tree struct { - Name string // name of the template represented by the tree. - ParseName string // name of the top-level template during parsing, for error messages. - Root *ListNode // top-level root of the tree. - Mode Mode // parsing mode. - text string // text parsed to create the template (or its parent) - // Parsing only; cleared after parse. - funcs []map[string]interface{} - lex *lexer - token [3]item // three-token lookahead for parser. - peekCount int - vars []string // variables defined at the moment. - treeSet map[string]*Tree - actionLine int // line of left delim starting action - mode Mode -} - -// A mode value is a set of flags (or 0). Modes control parser behavior. -type Mode uint - -const ( - ParseComments Mode = 1 << iota // parse comments and add them to AST - SkipFuncCheck // do not check that functions are defined -) - -// Copy returns a copy of the Tree. Any parsing state is discarded. -func (t *Tree) Copy() *Tree { - if t == nil { - return nil - } - return &Tree{ - Name: t.Name, - ParseName: t.ParseName, - Root: t.Root.CopyList(), - text: t.text, - } -} - -// Parse returns a map from template name to parse.Tree, created by parsing the -// templates described in the argument string. The top-level template will be -// given the specified name. If an error is encountered, parsing stops and an -// empty map is returned with the error. -func Parse(name, text, leftDelim, rightDelim string, funcs ...map[string]interface{}) (map[string]*Tree, error) { - treeSet := make(map[string]*Tree) - t := New(name) - t.text = text - _, err := t.Parse(text, leftDelim, rightDelim, treeSet, funcs...) - return treeSet, err -} - -// next returns the next token. -func (t *Tree) next() item { - if t.peekCount > 0 { - t.peekCount-- - } else { - t.token[0] = t.lex.nextItem() - } - return t.token[t.peekCount] -} - -// backup backs the input stream up one token. -func (t *Tree) backup() { - t.peekCount++ -} - -// backup2 backs the input stream up two tokens. -// The zeroth token is already there. -func (t *Tree) backup2(t1 item) { - t.token[1] = t1 - t.peekCount = 2 -} - -// backup3 backs the input stream up three tokens -// The zeroth token is already there. -func (t *Tree) backup3(t2, t1 item) { // Reverse order: we're pushing back. - t.token[1] = t1 - t.token[2] = t2 - t.peekCount = 3 -} - -// peek returns but does not consume the next token. -func (t *Tree) peek() item { - if t.peekCount > 0 { - return t.token[t.peekCount-1] - } - t.peekCount = 1 - t.token[0] = t.lex.nextItem() - return t.token[0] -} - -// nextNonSpace returns the next non-space token. -func (t *Tree) nextNonSpace() (token item) { - for { - token = t.next() - if token.typ != itemSpace { - break - } - } - return token -} - -// peekNonSpace returns but does not consume the next non-space token. -func (t *Tree) peekNonSpace() item { - token := t.nextNonSpace() - t.backup() - return token -} - -// Parsing. - -// New allocates a new parse tree with the given name. -func New(name string, funcs ...map[string]interface{}) *Tree { - return &Tree{ - Name: name, - funcs: funcs, - } -} - -// ErrorContext returns a textual representation of the location of the node in the input text. -// The receiver is only used when the node does not have a pointer to the tree inside, -// which can occur in old code. -func (t *Tree) ErrorContext(n Node) (location, context string) { - pos := int(n.Position()) - tree := n.tree() - if tree == nil { - tree = t - } - text := tree.text[:pos] - byteNum := strings.LastIndex(text, "\n") - if byteNum == -1 { - byteNum = pos // On first line. - } else { - byteNum++ // After the newline. - byteNum = pos - byteNum - } - lineNum := 1 + strings.Count(text, "\n") - context = n.String() - return fmt.Sprintf("%s:%d:%d", tree.ParseName, lineNum, byteNum), context -} - -// errorf formats the error and terminates processing. -func (t *Tree) errorf(format string, args ...interface{}) { - t.Root = nil - format = fmt.Sprintf("template: %s:%d: %s", t.ParseName, t.token[0].line, format) - panic(fmt.Errorf(format, args...)) -} - -// error terminates processing. -func (t *Tree) error(err error) { - t.errorf("%s", err) -} - -// expect consumes the next token and guarantees it has the required type. -func (t *Tree) expect(expected itemType, context string) item { - token := t.nextNonSpace() - if token.typ != expected { - t.unexpected(token, context) - } - return token -} - -// expectOneOf consumes the next token and guarantees it has one of the required types. -func (t *Tree) expectOneOf(expected1, expected2 itemType, context string) item { - token := t.nextNonSpace() - if token.typ != expected1 && token.typ != expected2 { - t.unexpected(token, context) - } - return token -} - -// unexpected complains about the token and terminates processing. -func (t *Tree) unexpected(token item, context string) { - if token.typ == itemError { - extra := "" - if t.actionLine != 0 && t.actionLine != token.line { - extra = fmt.Sprintf(" in action started at %s:%d", t.ParseName, t.actionLine) - if strings.HasSuffix(token.val, " action") { - extra = extra[len(" in action"):] // avoid "action in action" - } - } - t.errorf("%s%s", token, extra) - } - t.errorf("unexpected %s in %s", token, context) -} - -// recover is the handler that turns panics into returns from the top level of Parse. -func (t *Tree) recover(errp *error) { - e := recover() - if e != nil { - if _, ok := e.(runtime.Error); ok { - panic(e) - } - if t != nil { - t.lex.drain() - t.stopParse() - } - *errp = e.(error) - } -} - -// startParse initializes the parser, using the lexer. -func (t *Tree) startParse(funcs []map[string]interface{}, lex *lexer, treeSet map[string]*Tree) { - t.Root = nil - t.lex = lex - t.vars = []string{"$"} - t.funcs = funcs - t.treeSet = treeSet -} - -// stopParse terminates parsing. -func (t *Tree) stopParse() { - t.lex = nil - t.vars = nil - t.funcs = nil - t.treeSet = nil -} - -// Parse parses the template definition string to construct a representation of -// the template for execution. If either action delimiter string is empty, the -// default ("{{" or "}}") is used. Embedded template definitions are added to -// the treeSet map. -func (t *Tree) Parse(text, leftDelim, rightDelim string, treeSet map[string]*Tree, funcs ...map[string]interface{}) (tree *Tree, err error) { - defer t.recover(&err) - t.ParseName = t.Name - emitComment := t.Mode&ParseComments != 0 - t.startParse(funcs, lex(t.Name, text, leftDelim, rightDelim, emitComment), treeSet) - t.text = text - t.parse() - t.add() - t.stopParse() - return t, nil -} - -// add adds tree to t.treeSet. -func (t *Tree) add() { - tree := t.treeSet[t.Name] - if tree == nil || IsEmptyTree(tree.Root) { - t.treeSet[t.Name] = t - return - } - if !IsEmptyTree(t.Root) { - t.errorf("template: multiple definition of template %q", t.Name) - } -} - -// IsEmptyTree reports whether this tree (node) is empty of everything but space or comments. -func IsEmptyTree(n Node) bool { - switch n := n.(type) { - case nil: - return true - case *ActionNode: - case *CommentNode: - return true - case *IfNode: - case *ListNode: - for _, node := range n.Nodes { - if !IsEmptyTree(node) { - return false - } - } - return true - case *RangeNode: - case *TemplateNode: - case *TextNode: - return len(bytes.TrimSpace(n.Text)) == 0 - case *WithNode: - default: - panic("unknown node: " + n.String()) - } - return false -} - -// parse is the top-level parser for a template, essentially the same -// as itemList except it also parses {{define}} actions. -// It runs to EOF. -func (t *Tree) parse() { - t.Root = t.newList(t.peek().pos) - for t.peek().typ != itemEOF { - if t.peek().typ == itemLeftDelim { - delim := t.next() - if t.nextNonSpace().typ == itemDefine { - newT := New("definition") // name will be updated once we know it. - newT.text = t.text - newT.Mode = t.Mode - newT.ParseName = t.ParseName - newT.startParse(t.funcs, t.lex, t.treeSet) - newT.parseDefinition() - continue - } - t.backup2(delim) - } - switch n := t.textOrAction(); n.Type() { - case nodeEnd, nodeElse: - t.errorf("unexpected %s", n) - default: - t.Root.append(n) - } - } -} - -// parseDefinition parses a {{define}} ... {{end}} template definition and -// installs the definition in t.treeSet. The "define" keyword has already -// been scanned. -func (t *Tree) parseDefinition() { - const context = "define clause" - name := t.expectOneOf(itemString, itemRawString, context) - var err error - t.Name, err = strconv.Unquote(name.val) - if err != nil { - t.error(err) - } - t.expect(itemRightDelim, context) - var end Node - t.Root, end = t.itemList() - if end.Type() != nodeEnd { - t.errorf("unexpected %s in %s", end, context) - } - t.add() - t.stopParse() -} - -// itemList: -// textOrAction* -// Terminates at {{end}} or {{else}}, returned separately. -func (t *Tree) itemList() (list *ListNode, next Node) { - list = t.newList(t.peekNonSpace().pos) - for t.peekNonSpace().typ != itemEOF { - n := t.textOrAction() - switch n.Type() { - case nodeEnd, nodeElse: - return list, n - } - list.append(n) - } - t.errorf("unexpected EOF") - return -} - -// textOrAction: -// text | comment | action -func (t *Tree) textOrAction() Node { - switch token := t.nextNonSpace(); token.typ { - case itemText: - return t.newText(token.pos, token.val) - case itemLeftDelim: - t.actionLine = token.line - defer t.clearActionLine() - return t.action() - case itemComment: - return t.newComment(token.pos, token.val) - default: - t.unexpected(token, "input") - } - return nil -} - -func (t *Tree) clearActionLine() { - t.actionLine = 0 -} - -// Action: -// control -// command ("|" command)* -// Left delim is past. Now get actions. -// First word could be a keyword such as range. -func (t *Tree) action() (n Node) { - switch token := t.nextNonSpace(); token.typ { - case itemBlock: - return t.blockControl() - case itemElse: - return t.elseControl() - case itemEnd: - return t.endControl() - case itemIf: - return t.ifControl() - case itemRange: - return t.rangeControl() - case itemTemplate: - return t.templateControl() - case itemWith: - return t.withControl() - } - t.backup() - token := t.peek() - // Do not pop variables; they persist until "end". - return t.newAction(token.pos, token.line, t.pipeline("command", itemRightDelim)) -} - -// Pipeline: -// declarations? command ('|' command)* -func (t *Tree) pipeline(context string, end itemType) (pipe *PipeNode) { - token := t.peekNonSpace() - pipe = t.newPipeline(token.pos, token.line, nil) - // Are there declarations or assignments? -decls: - if v := t.peekNonSpace(); v.typ == itemVariable { - t.next() - // Since space is a token, we need 3-token look-ahead here in the worst case: - // in "$x foo" we need to read "foo" (as opposed to ":=") to know that $x is an - // argument variable rather than a declaration. So remember the token - // adjacent to the variable so we can push it back if necessary. - tokenAfterVariable := t.peek() - next := t.peekNonSpace() - switch { - case next.typ == itemAssign, next.typ == itemDeclare: - pipe.IsAssign = next.typ == itemAssign - t.nextNonSpace() - pipe.Decl = append(pipe.Decl, t.newVariable(v.pos, v.val)) - t.vars = append(t.vars, v.val) - case next.typ == itemChar && next.val == ",": - t.nextNonSpace() - pipe.Decl = append(pipe.Decl, t.newVariable(v.pos, v.val)) - t.vars = append(t.vars, v.val) - if context == "range" && len(pipe.Decl) < 2 { - switch t.peekNonSpace().typ { - case itemVariable, itemRightDelim, itemRightParen: - // second initialized variable in a range pipeline - goto decls - default: - t.errorf("range can only initialize variables") - } - } - t.errorf("too many declarations in %s", context) - case tokenAfterVariable.typ == itemSpace: - t.backup3(v, tokenAfterVariable) - default: - t.backup2(v) - } - } - for { - switch token := t.nextNonSpace(); token.typ { - case end: - // At this point, the pipeline is complete - t.checkPipeline(pipe, context) - return - case itemBool, itemCharConstant, itemComplex, itemDot, itemField, itemIdentifier, - itemNumber, itemNil, itemRawString, itemString, itemVariable, itemLeftParen: - t.backup() - pipe.append(t.command()) - default: - t.unexpected(token, context) - } - } -} - -func (t *Tree) checkPipeline(pipe *PipeNode, context string) { - // Reject empty pipelines - if len(pipe.Cmds) == 0 { - t.errorf("missing value for %s", context) - } - // Only the first command of a pipeline can start with a non executable operand - for i, c := range pipe.Cmds[1:] { - switch c.Args[0].Type() { - case NodeBool, NodeDot, NodeNil, NodeNumber, NodeString: - // With A|B|C, pipeline stage 2 is B - t.errorf("non executable command in pipeline stage %d", i+2) - } - } -} - -func (t *Tree) parseControl(allowElseIf bool, context string) (pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) { - defer t.popVars(len(t.vars)) - pipe = t.pipeline(context, itemRightDelim) - var next Node - list, next = t.itemList() - switch next.Type() { - case nodeEnd: //done - case nodeElse: - if allowElseIf { - // Special case for "else if". If the "else" is followed immediately by an "if", - // the elseControl will have left the "if" token pending. Treat - // {{if a}}_{{else if b}}_{{end}} - // as - // {{if a}}_{{else}}{{if b}}_{{end}}{{end}}. - // To do this, parse the if as usual and stop at it {{end}}; the subsequent{{end}} - // is assumed. This technique works even for long if-else-if chains. - // TODO: Should we allow else-if in with and range? - if t.peek().typ == itemIf { - t.next() // Consume the "if" token. - elseList = t.newList(next.Position()) - elseList.append(t.ifControl()) - // Do not consume the next item - only one {{end}} required. - break - } - } - elseList, next = t.itemList() - if next.Type() != nodeEnd { - t.errorf("expected end; found %s", next) - } - } - return pipe.Position(), pipe.Line, pipe, list, elseList -} - -// If: -// {{if pipeline}} itemList {{end}} -// {{if pipeline}} itemList {{else}} itemList {{end}} -// If keyword is past. -func (t *Tree) ifControl() Node { - return t.newIf(t.parseControl(true, "if")) -} - -// Range: -// {{range pipeline}} itemList {{end}} -// {{range pipeline}} itemList {{else}} itemList {{end}} -// Range keyword is past. -func (t *Tree) rangeControl() Node { - return t.newRange(t.parseControl(false, "range")) -} - -// With: -// {{with pipeline}} itemList {{end}} -// {{with pipeline}} itemList {{else}} itemList {{end}} -// If keyword is past. -func (t *Tree) withControl() Node { - return t.newWith(t.parseControl(false, "with")) -} - -// End: -// {{end}} -// End keyword is past. -func (t *Tree) endControl() Node { - return t.newEnd(t.expect(itemRightDelim, "end").pos) -} - -// Else: -// {{else}} -// Else keyword is past. -func (t *Tree) elseControl() Node { - // Special case for "else if". - peek := t.peekNonSpace() - if peek.typ == itemIf { - // We see "{{else if ... " but in effect rewrite it to {{else}}{{if ... ". - return t.newElse(peek.pos, peek.line) - } - token := t.expect(itemRightDelim, "else") - return t.newElse(token.pos, token.line) -} - -// Block: -// {{block stringValue pipeline}} -// Block keyword is past. -// The name must be something that can evaluate to a string. -// The pipeline is mandatory. -func (t *Tree) blockControl() Node { - const context = "block clause" - - token := t.nextNonSpace() - name := t.parseTemplateName(token, context) - pipe := t.pipeline(context, itemRightDelim) - - block := New(name) // name will be updated once we know it. - block.text = t.text - block.Mode = t.Mode - block.ParseName = t.ParseName - block.startParse(t.funcs, t.lex, t.treeSet) - var end Node - block.Root, end = block.itemList() - if end.Type() != nodeEnd { - t.errorf("unexpected %s in %s", end, context) - } - block.add() - block.stopParse() - - return t.newTemplate(token.pos, token.line, name, pipe) -} - -// Template: -// {{template stringValue pipeline}} -// Template keyword is past. The name must be something that can evaluate -// to a string. -func (t *Tree) templateControl() Node { - const context = "template clause" - token := t.nextNonSpace() - name := t.parseTemplateName(token, context) - var pipe *PipeNode - if t.nextNonSpace().typ != itemRightDelim { - t.backup() - // Do not pop variables; they persist until "end". - pipe = t.pipeline(context, itemRightDelim) - } - return t.newTemplate(token.pos, token.line, name, pipe) -} - -func (t *Tree) parseTemplateName(token item, context string) (name string) { - switch token.typ { - case itemString, itemRawString: - s, err := strconv.Unquote(token.val) - if err != nil { - t.error(err) - } - name = s - default: - t.unexpected(token, context) - } - return -} - -// command: -// operand (space operand)* -// space-separated arguments up to a pipeline character or right delimiter. -// we consume the pipe character but leave the right delim to terminate the action. -func (t *Tree) command() *CommandNode { - cmd := t.newCommand(t.peekNonSpace().pos) - for { - t.peekNonSpace() // skip leading spaces. - operand := t.operand() - if operand != nil { - cmd.append(operand) - } - switch token := t.next(); token.typ { - case itemSpace: - continue - case itemRightDelim, itemRightParen: - t.backup() - case itemPipe: - // nothing here; break loop below - default: - t.unexpected(token, "operand") - } - break - } - if len(cmd.Args) == 0 { - t.errorf("empty command") - } - return cmd -} - -// operand: -// term .Field* -// An operand is a space-separated component of a command, -// a term possibly followed by field accesses. -// A nil return means the next item is not an operand. -func (t *Tree) operand() Node { - node := t.term() - if node == nil { - return nil - } - if t.peek().typ == itemField { - chain := t.newChain(t.peek().pos, node) - for t.peek().typ == itemField { - chain.Add(t.next().val) - } - // Compatibility with original API: If the term is of type NodeField - // or NodeVariable, just put more fields on the original. - // Otherwise, keep the Chain node. - // Obvious parsing errors involving literal values are detected here. - // More complex error cases will have to be handled at execution time. - switch node.Type() { - case NodeField: - node = t.newField(chain.Position(), chain.String()) - case NodeVariable: - node = t.newVariable(chain.Position(), chain.String()) - case NodeBool, NodeString, NodeNumber, NodeNil, NodeDot: - t.errorf("unexpected . after term %q", node.String()) - default: - node = chain - } - } - return node -} - -// term: -// literal (number, string, nil, boolean) -// function (identifier) -// . -// .Field -// $ -// '(' pipeline ')' -// A term is a simple "expression". -// A nil return means the next item is not a term. -func (t *Tree) term() Node { - switch token := t.nextNonSpace(); token.typ { - case itemIdentifier: - checkFunc := t.Mode&SkipFuncCheck == 0 - if checkFunc && !t.hasFunction(token.val) { - t.errorf("function %q not defined", token.val) - } - return NewIdentifier(token.val).SetTree(t).SetPos(token.pos) - case itemDot: - return t.newDot(token.pos) - case itemNil: - return t.newNil(token.pos) - case itemVariable: - return t.useVar(token.pos, token.val) - case itemField: - return t.newField(token.pos, token.val) - case itemBool: - return t.newBool(token.pos, token.val == "true") - case itemCharConstant, itemComplex, itemNumber: - number, err := t.newNumber(token.pos, token.val, token.typ) - if err != nil { - t.error(err) - } - return number - case itemLeftParen: - return t.pipeline("parenthesized pipeline", itemRightParen) - case itemString, itemRawString: - s, err := strconv.Unquote(token.val) - if err != nil { - t.error(err) - } - return t.newString(token.pos, token.val, s) - } - t.backup() - return nil -} - -// hasFunction reports if a function name exists in the Tree's maps. -func (t *Tree) hasFunction(name string) bool { - for _, funcMap := range t.funcs { - if funcMap == nil { - continue - } - if funcMap[name] != nil { - return true - } - } - return false -} - -// popVars trims the variable list to the specified length -func (t *Tree) popVars(n int) { - t.vars = t.vars[:n] -} - -// useVar returns a node for a variable reference. It errors if the -// variable is not defined. -func (t *Tree) useVar(pos Pos, name string) Node { - v := t.newVariable(pos, name) - for _, varName := range t.vars { - if varName == v.Ident[0] { - return v - } - } - t.errorf("undefined variable %q", v.Ident[0]) - return nil -} diff --git a/vendor/rsc.io/tmplfunc/tmpl.go b/vendor/rsc.io/tmplfunc/tmpl.go deleted file mode 100644 index a10cbc53b70..00000000000 --- a/vendor/rsc.io/tmplfunc/tmpl.go +++ /dev/null @@ -1,213 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package tmplfunc provides an extension of Go templates -// in which templates can be invoked as if they were functions. -// -// For example, after parsing -// -// {{define "link url text"}}{{.text}}{{end}} -// -// this package installs a function named link allowing the template -// to be invoked as -// -// {{link "https://golang.org" "the Go language"}} -// -// instead of the longer-form (assuming an appropriate function named dict) -// -// {{template "link" (dict "url" "https://golang.org" "text" "the Go language")}} -// -// Function Definitions -// -// The function installed for a given template depends on the name of the -// defined template, which can include not just a function name but also -// a list of parameter names. The function name and parameter names must -// consist only of letters, digits, and underscores, with a leading non-digit. -// -// If there is no parameter list, then the function is expected to take -// at most one argument, made available in the template body as “.” (dot). -// If such a function is called with no arguments, dot will be a nil interface value. -// -// If there is a parameter list, then the function requires an argument for -// each parameter, except for optional and variadic parameters, explained below. -// Inside the template, the top-level value “.” is a map[string]interface{} in which -// each parameter name is mapped to the corresponding argument value. -// A parameter x can therefore be accessed as {{(index . "x")}} or, more concisely, {{.x}}. -// -// The first special case in parameter handling is that -// a parameter can be made optional by adding a “?” suffix after its name. -// If the argument list ends before that parameter, the corresponding map entry -// will be present and set to a nil value. -// The second special case is that a parameter can be made variadic -// by adding a “...” suffix after its name. -// The corresponding map entry contains a []interface{} holding the -// zero or more arguments corresponding to that parameter. -// -// In the parameter list, required parameters must precede optional parameters, -// which must in turn precede any variadic parameter. -// -// For example, we can revise the link template given earlier to make the -// link text optional, substituting the URL when the text is omitted: -// -// {{define "link url text?"}}{{or .text .url}}{{end}} -// -// The Go home page is {{link "https://golang.org"}}. -// -// Usage -// -// This package is meant to be used with templates from either the -// text/template or html/template packages. Given a *template.Template -// variable t, substitute: -// -// t.Parse(text) -> tmplfunc.Parse(t, text) -// t.ParseFiles(list) -> tmplfunc.ParseFiles(t, list) -// t.ParseGlob(pattern) -> tmplfunc.ParseGlob(t, pattern) -// -// Parse, ParseFiles, and ParseGlob parse the new templates but also add -// functions that invoke them, named according to the function signatures. -// Templates can only invoke functions for templates that have already been -// defined or that are being defined in the same Parse, ParseFiles, or ParseGlob call. -// For example, templates in two files x.tmpl and y.tmpl can call each other -// only if ParseFiles or ParseGlob is used to parse both files in a single call. -// Otherwise, the parsing of the first file will report that calls to templates in -// the second file are calling unknown functions. -// -// When used with the html/template package, all function-invoked template -// calls are treated as invoking templates producing HTML. In order to use a -// template that produces some other kind of text fragment, the template must -// be invoked directly using the {{template "name"}} form, not as a function call. -package tmplfunc - -import ( - "fmt" - "io/ioutil" - "path/filepath" - - htmltemplate "html/template" - texttemplate "text/template" -) - -// A Template is a *template.Template, where template refers to either -// the html/template or text/template package. -type Template interface { - // Method here only to make most types that are not a *template.Template - // not implement the interface. The requirement here is to be one of the two - // template types, not just to have this single method. - DefinedTemplates() string - Name() string -} - -// Parse is like t.Parse(text), adding functions for the templates defined in text. -func Parse(t Template, text string) error { - if err := funcs(t, []string{t.Name()}, []string{text}); err != nil { - return err - } - var err error - switch t := t.(type) { - case *texttemplate.Template: - _, err = t.Parse(text) - case *htmltemplate.Template: - _, err = t.Parse(text) - } - return err -} - -// ParseFiles is like t.ParseFiles(filenames...), adding functions for the parsed templates. -func ParseFiles(t Template, filenames ...string) error { - return parseFiles(t, readFileOS, filenames...) -} - -// parseFiles is the helper for the method and function. If the argument -// template is nil, it is created from the first file. -func parseFiles(t Template, readFile func(string) (string, []byte, error), filenames ...string) error { - if len(filenames) == 0 { - // Not really a problem, but be consistent. - return fmt.Errorf("tmplfunc: no files named in call to ParseFiles") - } - - var names []string - var texts []string - for _, filename := range filenames { - name, b, err := readFile(filename) - if err != nil { - return err - } - names = append(names, name) - texts = append(texts, string(b)) - } - - err := funcs(t, names, texts) - if err != nil { - return err - } - - switch t := t.(type) { - case *texttemplate.Template: - for i, name := range names { - var tmpl *texttemplate.Template - if name == t.Name() { - tmpl = t - } else { - tmpl = t.New(name) - } - if _, err := tmpl.Parse(texts[i]); err != nil { - return err - } - } - - case *htmltemplate.Template: - for i, name := range names { - var tmpl *htmltemplate.Template - if name == t.Name() { - tmpl = t - } else { - tmpl = t.New(name) - } - if _, err := tmpl.Parse(texts[i]); err != nil { - return err - } - } - } - - return nil -} - -// ParseGlob is like t.ParseGlob(pattern), adding functions for the parsed templates. -func ParseGlob(t Template, pattern string) error { - filenames, err := filepath.Glob(pattern) - if err != nil { - return err - } - if len(filenames) == 0 { - return fmt.Errorf("tmplfunc: pattern matches no files: %#q", pattern) - } - return parseFiles(t, readFileOS, filenames...) -} - -func must(err error) { - if err != nil { - panic(err) - } -} - -// MustParse is like Parse but panics on error. -func MustParse(t Template, text string) { - must(Parse(t, text)) -} - -// MustParseFiles is like ParseFiles but panics on error. -func MustParseFiles(t Template, filenames ...string) { - must(ParseFiles(t, filenames...)) -} - -// MustParseGlob is like ParseGlob but panics on error. -func MustParseGlob(t Template, pattern string) { - must(ParseGlob(t, pattern)) -} - -func readFileOS(file string) (name string, b []byte, err error) { - name = filepath.Base(file) - b, err = ioutil.ReadFile(file) - return -}