pax_global_header00006660000000000000000000000064151430525660014521gustar00rootroot0000000000000052 comment=0e3f6fcc4061704b85de3e55a294ae62d7e55845 addchain-0.4.0/000077500000000000000000000000001514305256600132555ustar00rootroot00000000000000addchain-0.4.0/.github/000077500000000000000000000000001514305256600146155ustar00rootroot00000000000000addchain-0.4.0/.github/workflows/000077500000000000000000000000001514305256600166525ustar00rootroot00000000000000addchain-0.4.0/.github/workflows/ci.yml000066400000000000000000000036261514305256600177770ustar00rootroot00000000000000name: ci permissions: contents: read on: push: branches: - master pull_request: schedule: - cron: "33 11 * * 6" jobs: test: strategy: matrix: go-version: [1.16.x, 1.17.x] platform: [ubuntu-latest] runs-on: ${{ matrix.platform }} steps: - name: Install Go uses: actions/setup-go@37335c7bb261b353407cff977110895fa0b4f7d8 # v2.1.3 with: go-version: ${{ matrix.go-version }} - name: Checkout code uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 with: persist-credentials: false - name: Build run: go build ./... - name: Test run: go test -coverprofile=coverage.out -covermode=count ./... - name: Upload Coverage uses: codecov/codecov-action@51d810878be5422784e86451c0e7c14e5860ec47 # v2.0.2 with: token: ${{ secrets.CODECOV_TOKEN }} files: coverage.out flags: unittests lint: runs-on: ubuntu-latest steps: - name: Install Go uses: actions/setup-go@37335c7bb261b353407cff977110895fa0b4f7d8 # v2.1.3 with: go-version: 1.17.x - name: Configure Go Environment run: | echo GOPATH=${{ runner.workspace }} >> $GITHUB_ENV echo ${{ runner.workspace }}/bin >> $GITHUB_PATH - name: Checkout code uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 with: persist-credentials: false - name: Bootstrap run: ./script/bootstrap - name: Lint run: ./script/lint - name: Generate run: ./script/generate -a - name: Git Status run: | git diff test -z "$(git status --porcelain)" - name: Format run: ./script/fmt - name: Git Status run: | git diff test -z "$(git status --porcelain)" addchain-0.4.0/.github/workflows/install.yml000066400000000000000000000012301514305256600210370ustar00rootroot00000000000000name: install permissions: contents: read on: push: branches: - master pull_request: paths: - install.sh schedule: - cron: "47 18 * * *" jobs: install: strategy: matrix: platform: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.platform }} steps: - name: Checkout code uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 with: persist-credentials: false - name: Run Installer run: cat install.sh | sh -s -- -b ${{ runner.workspace }}/bin - name: Run Binary run: ${{ runner.workspace }}/bin/addchain -h addchain-0.4.0/.github/workflows/release.yml000066400000000000000000000013271514305256600210200ustar00rootroot00000000000000name: release permissions: contents: write on: push: tags: - v* jobs: release: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 with: fetch-depth: 0 persist-credentials: false - name: Set up Go uses: actions/setup-go@37335c7bb261b353407cff977110895fa0b4f7d8 # v2.1.3 with: go-version: 1.17.x - name: Run GoReleaser uses: goreleaser/goreleaser-action@5e15885530fb01d81d1f24e8a6f54ebbd0fed7eb # v2.5.0 with: version: v0.177.0 args: release --rm-dist env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} addchain-0.4.0/.github/workflows/stress.yml000066400000000000000000000021401514305256600207150ustar00rootroot00000000000000name: stress permissions: contents: read on: workflow_dispatch: schedule: - cron: "42 10 * * 3" jobs: test: strategy: matrix: go-version: [1.17.x] platform: [ubuntu-latest] runs-on: ${{ matrix.platform }} steps: - name: Install Go uses: actions/setup-go@37335c7bb261b353407cff977110895fa0b4f7d8 # v2.1.3 with: go-version: ${{ matrix.go-version }} - name: Configure Go Environment run: | echo GOPATH=${{ runner.workspace }} >> $GITHUB_ENV echo ${{ runner.workspace }}/bin >> $GITHUB_PATH - name: Checkout code uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 with: persist-credentials: false - name: Bootstrap run: ./script/bootstrap - name: Stress Test run: ./script/stress -c coverage.out - name: Upload Coverage uses: codecov/codecov-action@51d810878be5422784e86451c0e7c14e5860ec47 # v2.0.2 with: token: ${{ secrets.CODECOV_TOKEN }} files: coverage.out flags: stress addchain-0.4.0/.gitignore000066400000000000000000000000061514305256600152410ustar00rootroot00000000000000dist/ addchain-0.4.0/.golangci.yml000066400000000000000000000013221514305256600156370ustar00rootroot00000000000000linters: 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 addchain-0.4.0/.goreleaser.yml000066400000000000000000000007311514305256600162070ustar00rootroot00000000000000before: 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 addchain-0.4.0/.zenodo.json000066400000000000000000000140131514305256600155230ustar00rootroot00000000000000{ "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" ] } addchain-0.4.0/CITATION.bib000066400000000000000000000006751514305256600151550ustar00rootroot00000000000000@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}, } addchain-0.4.0/CITATION.cff000066400000000000000000000012701514305256600151470ustar00rootroot00000000000000cff-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." addchain-0.4.0/LICENSE000066400000000000000000000027661514305256600142750ustar00rootroot00000000000000BSD 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. addchain-0.4.0/README.md000066400000000000000000000455101514305256600145410ustar00rootroot00000000000000

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). addchain-0.4.0/acc/000077500000000000000000000000001514305256600140035ustar00rootroot00000000000000addchain-0.4.0/acc/acc.go000066400000000000000000000041051514305256600150600ustar00rootroot00000000000000// 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 } addchain-0.4.0/acc/acc_test.go000066400000000000000000000026611514305256600161240ustar00rootroot00000000000000package acc import ( "math/big" "strings" "testing" "github.com/mmcloughlin/addchain/internal/prime" ) func TestEvaluate(t *testing.T) { cases := []struct { Name string Lines []string Expect *big.Int }{ { Name: "add", Lines: []string{ "1 add 1", }, Expect: big.NewInt(2), }, { Name: "double", Lines: []string{ "dbl 1", }, Expect: big.NewInt(2), }, { Name: "shl", Lines: []string{ "1 shl 3", }, Expect: big.NewInt(8), }, { Name: "p25519-2", Lines: []string{ "_1 = 1", "_10 = _1 << 1", "_1001 = _10 << 2 + _1", "_1011 = _1001 + _10", "x5 = _1011 << 1 + _1001", "x10 = x5 << 5 + x5", "x20 = x10 << 10 + x10", "x40 = x20 << 20 + x20", "x50 = x40 << 10 + x10", "x100 = x50 << 50 + x50", "x200 = x100 << 100 + x100", "x250 = x200 << 50 + x50", "return x250 << 5 + _1011", }, Expect: new(big.Int).Sub( prime.P25519.Int(), big.NewInt(2), ), }, } for _, c := range cases { c := c // scopelint t.Run(c.Name, func(t *testing.T) { src := strings.Join(c.Lines, "\n") + "\n" // Load and evaluate. p, err := LoadString(src) if err != nil { t.Fatal(err) } // Report. for i, x := range p.Chain { t.Logf("[%3d] bin=%b", i, x) } if err := p.Chain.Produces(c.Expect); err != nil { t.Fatalf("chain does not produce %d: %s", c.Expect, err) } }) } } addchain-0.4.0/acc/ast/000077500000000000000000000000001514305256600145725ustar00rootroot00000000000000addchain-0.4.0/acc/ast/ast.go000066400000000000000000000025751514305256600157210ustar00rootroot00000000000000// 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 } addchain-0.4.0/acc/ast/print.go000066400000000000000000000031201514305256600162510ustar00rootroot00000000000000package 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("}") } addchain-0.4.0/acc/build.go000066400000000000000000000071051514305256600154340ustar00rootroot00000000000000package 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 } addchain-0.4.0/acc/decompile.go000066400000000000000000000023401514305256600162720ustar00rootroot00000000000000package 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 } addchain-0.4.0/acc/decompile_test.go000066400000000000000000000025021514305256600173310ustar00rootroot00000000000000package acc import ( "reflect" "testing" "github.com/mmcloughlin/addchain" "github.com/mmcloughlin/addchain/acc/ir" "github.com/mmcloughlin/addchain/acc/pass" "github.com/mmcloughlin/addchain/internal/assert" ) func TestDecompileExample(t *testing.T) { p := addchain.Program{} _, err := p.Double(0) assert.NoError(t, err) _, err = p.Add(0, 1) assert.NoError(t, err) _, err = p.Shift(1, 3) assert.NoError(t, err) _, err = p.Add(0, 5) assert.NoError(t, err) t.Log(p) expect := &ir.Program{ Instructions: []*ir.Instruction{ { Output: ir.Index(1), Op: ir.Double{ X: ir.Index(0), }, }, { Output: ir.Index(2), Op: ir.Add{ X: ir.Index(0), Y: ir.Index(1), }, }, { Output: ir.Index(5), Op: ir.Shift{ X: ir.Index(1), S: 3, }, }, { Output: ir.Index(6), Op: ir.Add{ X: ir.Index(0), Y: ir.Index(5), }, }, }, } got, err := Decompile(p) if err != nil { t.Fatal() } t.Logf("got:\n%s", got) if !reflect.DeepEqual(got, expect) { t.Logf("expect:\n%s", expect) t.Fatal("mismatch") } } func TestDecompileRandom(t *testing.T) { CheckRandom(t, func(t *testing.T, p addchain.Program) { r, err := Decompile(p) if err != nil { t.Fatal(err) } if err := pass.Validate(r); err != nil { t.Fatal(err) } }) } addchain-0.4.0/acc/ir/000077500000000000000000000000001514305256600144155ustar00rootroot00000000000000addchain-0.4.0/acc/ir/ir.go000066400000000000000000000074361514305256600153700ustar00rootroot00000000000000// 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 } addchain-0.4.0/acc/parse/000077500000000000000000000000001514305256600151155ustar00rootroot00000000000000addchain-0.4.0/acc/parse/acc.peg000066400000000000000000000044051514305256600163430ustar00rootroot00000000000000{ 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 <- !. addchain-0.4.0/acc/parse/internal/000077500000000000000000000000001514305256600167315ustar00rootroot00000000000000addchain-0.4.0/acc/parse/internal/parser/000077500000000000000000000000001514305256600202255ustar00rootroot00000000000000addchain-0.4.0/acc/parse/internal/parser/zparser.go000066400000000000000000001501161514305256600222460ustar00rootroot00000000000000// 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 } addchain-0.4.0/acc/parse/parse.go000066400000000000000000000014641514305256600165630ustar00rootroot00000000000000// 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 } addchain-0.4.0/acc/parse/parse_test.go000066400000000000000000000054061514305256600176220ustar00rootroot00000000000000package parse import ( "reflect" "testing" "github.com/mmcloughlin/addchain/acc/ast" ) func TestOperands(t *testing.T) { exprs := map[string]ast.Expr{ "1": ast.Operand(0), "[23]": ast.Operand(23), "[0x2a]": ast.Operand(0x2a), "[0644]": ast.Operand(0o644), "(1)": ast.Operand(0), "( [3] )": ast.Operand(3), "_101": ast.Identifier("_101"), "x5": ast.Identifier("x5"), "( x5)": ast.Identifier("x5"), } for expr, idx := range exprs { AssertParseResult(t, expr, idx) AssertParseResult(t, expr+"\n", idx) } } func TestExpressions(t *testing.T) { cases := []struct { Source string Expect ast.Expr }{ { Source: "1 + 1", Expect: ast.Add{X: ast.Operand(0), Y: ast.Operand(0)}, }, { Source: "1 add 1", Expect: ast.Add{X: ast.Operand(0), Y: ast.Operand(0)}, }, { Source: "1 + 1 + 1", Expect: ast.Add{ X: ast.Add{X: ast.Operand(0), Y: ast.Operand(0)}, Y: ast.Operand(0), }, }, { Source: "1 add 1 add 1", Expect: ast.Add{ X: ast.Add{X: ast.Operand(0), Y: ast.Operand(0)}, Y: ast.Operand(0), }, }, { Source: "1 << 5", Expect: ast.Shift{X: ast.Operand(0), S: 5}, }, { Source: "[3] shl 5 add 1", Expect: ast.Add{ X: ast.Shift{X: ast.Operand(3), S: 5}, Y: ast.Operand(0), }, }, { Source: "[3] << 5 + [6] << 9", Expect: ast.Add{ X: ast.Shift{X: ast.Operand(3), S: 5}, Y: ast.Shift{X: ast.Operand(6), S: 9}, }, }, { Source: "([3] + [8]) << 2", Expect: ast.Shift{ X: ast.Add{X: ast.Operand(3), Y: ast.Operand(8)}, S: 2, }, }, { Source: "2 * [3]", Expect: ast.Double{ X: ast.Operand(3), }, }, { Source: "dbl [3] add [5] << 3", Expect: ast.Add{ X: ast.Double{X: ast.Operand(3)}, Y: ast.Shift{X: ast.Operand(5), S: 3}, }, }, } for _, c := range cases { AssertParseResult(t, c.Source, c.Expect) } } func TestChains(t *testing.T) { cases := []struct { Source string Expect *ast.Chain }{ { Source: "x = 1 + 1\nreturn x<<3", Expect: &ast.Chain{ Statements: []ast.Statement{ { Name: "x", Expr: ast.Add{ X: ast.Operand(0), Y: ast.Operand(0), }, }, { Expr: ast.Shift{ X: ast.Identifier("x"), S: 3, }, }, }, }, }, } for _, c := range cases { AssertParse(t, c.Source, c.Expect) } } func AssertParseResult(t *testing.T, src string, expect ast.Expr) { t.Helper() AssertParse(t, src, &ast.Chain{ Statements: []ast.Statement{{Expr: expect}}, }) } func AssertParse(t *testing.T, src string, expect *ast.Chain) { t.Helper() t.Logf("expr=%q", src) got, err := String(src) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(expect, got) { t.Fatalf("got %#v; expected %#v", got, expect) } } addchain-0.4.0/acc/pass/000077500000000000000000000000001514305256600147515ustar00rootroot00000000000000addchain-0.4.0/acc/pass/alloc.go000066400000000000000000000046621514305256600164020ustar00rootroot00000000000000package 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) } } addchain-0.4.0/acc/pass/alloc_test.go000066400000000000000000000032721514305256600174350ustar00rootroot00000000000000package pass import ( "reflect" "strconv" "testing" "github.com/mmcloughlin/addchain/acc/ir" ) func TestAllocator(t *testing.T) { // Generate a program that will need n live variables. n := 13 p := &ir.Program{} // Create n indexes that will be used later. for i := 1; i <= n; i++ { p.AddInstruction(&ir.Instruction{ Output: ir.Index(i), Op: ir.Add{ X: ir.One, Y: ir.Index(i - 1), }, }) } // Consume the n indicies. This ensures we'll have n live variables at some // point. for i := n + 1; i <= 2*n; i++ { p.AddInstruction(&ir.Instruction{ Output: ir.Index(i), Op: ir.Add{ X: ir.Index(i - n), Y: ir.Index(i - 1), }, }) } // Execute allocation pass. t.Logf("pre:\n%s", p) a := Allocator{ Input: "in", Output: "out", Format: "tmp%d", } if err := a.Execute(p); err != nil { t.Fatal(err) } t.Logf("post:\n%s", p) // Every operand should have a name. for _, operand := range p.Operands { if operand.Identifier == "" { t.Errorf("operand %s does not have a name", operand) } } // We expect to have n-1 temporaries. Note we do not expect n, since the output // variable will be used as a temporary. expect := make([]string, n-1) for i := 0; i < n-1; i++ { expect[i] = "tmp" + strconv.Itoa(i) } if !reflect.DeepEqual(expect, p.Temporaries) { t.Fatalf("got temporaries %v; expect %v", p.Temporaries, expect) } // Confirm input and output variables are used. if p.Operands[0].Identifier != a.Input { t.Errorf("unexpected input name: got %q expect %q", p.Operands[0].Identifier, a.Input) } if p.Output().Identifier != a.Output { t.Errorf("unexpected output name: got %q expect %q", p.Output().Identifier, a.Output) } } addchain-0.4.0/acc/pass/eval.go000066400000000000000000000021161514305256600162270ustar00rootroot00000000000000package 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 } addchain-0.4.0/acc/pass/naming.go000066400000000000000000000045521514305256600165570ustar00rootroot00000000000000package 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 }) } addchain-0.4.0/acc/pass/naming_test.go000066400000000000000000000020361514305256600176110ustar00rootroot00000000000000package pass import ( "testing" "github.com/mmcloughlin/addchain/acc/ir" ) func TestNaming(t *testing.T) { p := &ir.Program{ Instructions: []*ir.Instruction{ { Output: ir.Index(1), Op: ir.Double{ X: ir.Index(0), }, }, { Output: ir.Index(2), Op: ir.Add{ X: ir.Index(0), Y: ir.Index(1), }, }, { Output: ir.Index(4), Op: ir.Shift{ X: ir.Index(2), S: 2, }, }, { Output: ir.Index(5), Op: ir.Add{ X: ir.Index(4), Y: ir.Index(2), }, }, }, } // Name 3-bit values and runs. n := Concat( NameBinaryValues(3, "_%b"), NameXRuns, ) t.Logf("pre:\n%s", p) if err := n.Execute(p); err != nil { t.Fatal(err) } t.Logf("post:\n%s", p) // Expected names. expect := map[int]string{ 0: "_1", 1: "_10", 2: "_11", 4: "", // 4-bit value that's not a run 5: "x4", } for idx, name := range expect { got := p.Operands[idx].Identifier if got != name { t.Errorf("operand %d has name %s; expected %s", idx, got, name) } } } addchain-0.4.0/acc/pass/pass.go000066400000000000000000000055041514305256600162520ustar00rootroot00000000000000// 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 } addchain-0.4.0/acc/pass/pass_test.go000066400000000000000000000045421514305256600173120ustar00rootroot00000000000000package pass import ( "reflect" "testing" "github.com/mmcloughlin/addchain/acc/ir" "github.com/mmcloughlin/addchain/internal/assert" ) func TestCanonicalizeOperands(t *testing.T) { // Index 1 is referenced multiple times from various operand types. Only one of // them has a name. Expect them to be replaced with a single version that has a // name. p := &ir.Program{ Instructions: []*ir.Instruction{ { Output: ir.Index(1), // unnamed Op: ir.Double{ X: ir.One, }, }, { Output: ir.Index(2), Op: ir.Add{ X: ir.One, Y: ir.NewOperand("a", 1), // named }, }, { Output: ir.Index(3), Op: ir.Double{ X: ir.Index(1), // unnamed }, }, { Output: ir.Index(4), Op: ir.Shift{ X: ir.Index(1), // unnamed S: 1, }, }, }, } t.Logf("pre:\n%s", p) err := CanonicalizeOperands(p) if err != nil { t.Fatal(err) } t.Logf("post:\n%s", p) // Check all operands are canonical. for _, i := range p.Instructions { for _, operand := range i.Operands() { if operand != p.Operands[operand.Index] { t.Fatal("non canonical operand found") } } } // Check that the canonical version has a name. if p.Operands[1].Identifier != "a" { t.Fatal("operand 1 should have a name") } } func TestCanonicalizeOperandsIdentifierConflict(t *testing.T) { // Construct a program with two names for index 1. p := &ir.Program{ Instructions: []*ir.Instruction{ { Output: ir.NewOperand("a", 1), Op: ir.Double{ X: ir.One, }, }, { Output: ir.NewOperand("c", 2), Op: ir.Add{ X: ir.One, Y: ir.NewOperand("b", 1), }, }, }, } err := CanonicalizeOperands(p) assert.ErrorContains(t, err, "conflict") } func TestReadCounts(t *testing.T) { p := &ir.Program{ Instructions: []*ir.Instruction{ { Output: ir.Index(1), Op: ir.Double{ X: ir.Index(0), }, }, { Output: ir.Index(2), Op: ir.Add{ X: ir.Index(0), Y: ir.Index(1), }, }, { Output: ir.Index(5), Op: ir.Shift{ X: ir.Index(1), S: 3, }, }, { Output: ir.Index(6), Op: ir.Add{ X: ir.Index(0), Y: ir.Index(5), }, }, }, } expect := map[int]int{ 0: 3, 1: 2, 5: 1, } if err := ReadCounts(p); err != nil { t.Fatal(p) } if !reflect.DeepEqual(expect, p.ReadCount) { t.FailNow() } } addchain-0.4.0/acc/pass/validation.go000066400000000000000000000015241514305256600174340ustar00rootroot00000000000000package 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 } addchain-0.4.0/acc/pass/validation_test.go000066400000000000000000000010361514305256600204710ustar00rootroot00000000000000package pass import ( "testing" "github.com/mmcloughlin/addchain/acc/ir" ) func TestCheckDanglingInputsError(t *testing.T) { // Shift instruction followed by a reference to an intermediate result. p := &ir.Program{ Instructions: []*ir.Instruction{ { Output: ir.Index(3), Op: ir.Shift{ X: ir.Index(0), S: 3, }, }, { Output: ir.Index(4), Op: ir.Add{ X: ir.Index(1), Y: ir.Index(3), }, }, }, } err := CheckDanglingInputs(p) if err == nil { t.Fatal("expected error") } } addchain-0.4.0/acc/printer/000077500000000000000000000000001514305256600154665ustar00rootroot00000000000000addchain-0.4.0/acc/printer/printer.go000066400000000000000000000046011514305256600175010ustar00rootroot00000000000000// 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) } } addchain-0.4.0/acc/roundtrip_test.go000066400000000000000000000033511514305256600174210ustar00rootroot00000000000000package acc import ( "bytes" "reflect" "testing" "github.com/mmcloughlin/addchain" "github.com/mmcloughlin/addchain/acc/parse" "github.com/mmcloughlin/addchain/acc/pass" "github.com/mmcloughlin/addchain/acc/printer" ) // The purpose of this test is to verify the full round trip from an addition // chain program to source and back. // // addchain.Chain c // | ^ // Program | | Evaluate // v | // addchain.Program p // | ^ // Decompile | | Compile // v | // ir.Program r // | ^ // Build | | Translate // v | // ast.Chain s // | ^ // Print | | Parse // v | // acc source src func TestRandomRoundTrip(t *testing.T) { CheckRandom(t, func(t *testing.T, p addchain.Program) { // Decompile into IR. r, err := Decompile(p) if err != nil { t.Fatal(err) } // Build syntax tree. s, err := Build(r) if err != nil { t.Fatal(err) } // Print to source. var src bytes.Buffer err = printer.Fprint(&src, s) if err != nil { t.Fatal(err) } // Parse back to syntax. s2, err := parse.Reader("string", &src) if err != nil { t.Fatal(err) } // Translate back to IR. r2, err := Translate(s2) if err != nil { t.Fatal(err) } // Compile back to a program. if err := pass.Compile(r2); err != nil { t.Fatal(err) } p2 := r2.Program if !reflect.DeepEqual(p, p2) { t.Logf("p:\n%v", p) t.Logf("r:\n%v", r) t.Logf("src:\n%s", src.String()) t.Logf("r2:\n%v", r2) t.Logf("p2:\n%v", p2) t.Fatal("roundtrip failure") } }) } addchain-0.4.0/acc/translate.go000066400000000000000000000050461514305256600163340ustar00rootroot00000000000000package 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 } addchain-0.4.0/acc/translate_test.go000066400000000000000000000020741514305256600173710ustar00rootroot00000000000000package acc import ( "reflect" "testing" "github.com/mmcloughlin/addchain/acc/ir" "github.com/mmcloughlin/addchain/acc/parse" ) func TestTranslateBasicOps(t *testing.T) { src := "a = 1+1\nd = 2 * 1\n1 << 42" expect := &ir.Program{ Instructions: []*ir.Instruction{ { Output: &ir.Operand{ Index: 1, Identifier: "a", }, Op: ir.Add{ X: &ir.Operand{Index: 0}, Y: &ir.Operand{Index: 0}, }, }, { Output: &ir.Operand{ Index: 2, Identifier: "d", }, Op: ir.Double{ X: &ir.Operand{Index: 0}, }, }, { Output: &ir.Operand{ Index: 44, }, Op: ir.Shift{ X: &ir.Operand{Index: 0}, S: 42, }, }, }, } AssertTranslate(t, src, expect) } func AssertTranslate(t *testing.T, src string, expect *ir.Program) { t.Helper() s, err := parse.String(src) if err != nil { t.Fatal(err) } p, err := Translate(s) if err != nil { t.Fatal(err) } t.Logf("got:\n%s", p) if !reflect.DeepEqual(p, expect) { t.Logf("expect:\n%s", expect) t.Fatal("mismatch") } } addchain-0.4.0/acc/util_test.go000066400000000000000000000016221514305256600163470ustar00rootroot00000000000000package acc import ( "testing" "github.com/mmcloughlin/addchain" "github.com/mmcloughlin/addchain/alg/contfrac" "github.com/mmcloughlin/addchain/alg/dict" "github.com/mmcloughlin/addchain/internal/test" "github.com/mmcloughlin/addchain/rand" ) // CheckRandom runs the check function against randomly generated chain programs. func CheckRandom(t *testing.T, check func(t *testing.T, p addchain.Program)) { gs := []rand.Generator{ rand.AddsGenerator{N: 10}, rand.NewSolverGenerator( 160, dict.NewAlgorithm( dict.SlidingWindow{K: 5}, contfrac.NewAlgorithm(contfrac.DichotomicStrategy{}), ), ), } for _, g := range gs { g := g // scopelint t.Run(g.String(), test.Trials(func(t *testing.T) bool { c, err := g.GenerateChain() if err != nil { t.Fatal(err) } p, err := c.Program() if err != nil { t.Fatal(err) } check(t, p) return true })) } } addchain-0.4.0/alg/000077500000000000000000000000001514305256600140205ustar00rootroot00000000000000addchain-0.4.0/alg/alg.go000066400000000000000000000024511514305256600151140ustar00rootroot00000000000000// 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}) } addchain-0.4.0/alg/algtest/000077500000000000000000000000001514305256600154635ustar00rootroot00000000000000addchain-0.4.0/alg/algtest/assert.go000066400000000000000000000023061514305256600173140ustar00rootroot00000000000000package algtest import ( "math/big" "reflect" "testing" "github.com/mmcloughlin/addchain" "github.com/mmcloughlin/addchain/alg" ) // AssertChainAlgorithmGenerates asserts that the algorithm generates the expected chain for n. func AssertChainAlgorithmGenerates(t *testing.T, a alg.ChainAlgorithm, n *big.Int, expect addchain.Chain) { c, err := a.FindChain(n) if err != nil { t.Fatal(err) } if err := c.Validate(); err != nil { t.Error(err) } if !reflect.DeepEqual(expect, c) { t.Fatalf("got %v; expect %v", c, expect) } } // AssertChainAlgorithmProduces verifies that a returns a valid chain for n. func AssertChainAlgorithmProduces(t *testing.T, a alg.ChainAlgorithm, n *big.Int) addchain.Chain { c, err := a.FindChain(n) if err != nil { t.Fatal(err) } err = c.Produces(n) if err != nil { t.Log(c) t.Fatal(err) } return c } // AssertSequenceAlgorithmProduces verifies that a returns a valid chain containing targets. func AssertSequenceAlgorithmProduces(t *testing.T, a alg.SequenceAlgorithm, targets []*big.Int) addchain.Chain { c, err := a.FindSequence(targets) if err != nil { t.Fatal(err) } err = c.Superset(targets) if err != nil { t.Log(c) t.Fatal(err) } return c } addchain-0.4.0/alg/algtest/chain.go000066400000000000000000000035221514305256600170760ustar00rootroot00000000000000package algtest import ( "math" "math/big" "math/rand" "testing" "github.com/mmcloughlin/addchain/alg" "github.com/mmcloughlin/addchain/internal/bigint" "github.com/mmcloughlin/addchain/internal/prime" "github.com/mmcloughlin/addchain/internal/test" ) // ChainAlgorithm applies a generic test suite to the algorithm a. func ChainAlgorithm(t *testing.T, a alg.ChainAlgorithm) { suite := ChainAlgorithmSuite(a) suite(t) } // ChainAlgorithmSuite builds a generic test suite function for the algorithm a. func ChainAlgorithmSuite(a alg.ChainAlgorithm) func(t *testing.T) { return func(t *testing.T) { t.Run("powers_of_two", checkPowersOfTwo(a, 100)) t.Run("binary_runs", checkBinaryRuns(a, 32)) t.Run("random_int64", checkRandomInt64s(a)) t.Run("primes", checkPrimes(a)) } } func checkPowersOfTwo(a alg.ChainAlgorithm, e uint) func(t *testing.T) { return func(t *testing.T) { n := big.NewInt(1) for i := uint(0); i <= e; i++ { AssertChainAlgorithmProduces(t, a, n) n.Lsh(n, 1) } } } func checkBinaryRuns(a alg.ChainAlgorithm, n uint) func(t *testing.T) { return func(t *testing.T) { for i := uint(1); i <= n; i++ { r := bigint.Pow2(i) r.Sub(r, bigint.One()) AssertChainAlgorithmProduces(t, a, r) } } } func checkRandomInt64s(a alg.ChainAlgorithm) func(t *testing.T) { return test.Trials(func(t *testing.T) bool { r := rand.Int63n(math.MaxInt64) n := big.NewInt(r) AssertChainAlgorithmProduces(t, a, n) return true }) } func checkPrimes(a alg.ChainAlgorithm) func(t *testing.T) { // Prepare primes in a random order. ps := []*big.Int{} for _, p := range prime.Distinguished { ps = append(ps, p.Int()) } rand.Shuffle(len(ps), func(i, j int) { ps[i], ps[j] = ps[j], ps[i] }) return test.Trials(func(t *testing.T) bool { AssertChainAlgorithmProduces(t, a, ps[0]) ps = ps[1:] return len(ps) > 0 }) } addchain-0.4.0/alg/algtest/doc.go000066400000000000000000000001031514305256600165510ustar00rootroot00000000000000// Package algtest provides algorithm test suites. package algtest addchain-0.4.0/alg/algtest/seq.go000066400000000000000000000101021514305256600165740ustar00rootroot00000000000000package algtest import ( "math/big" "testing" "github.com/mmcloughlin/addchain" "github.com/mmcloughlin/addchain/alg" "github.com/mmcloughlin/addchain/internal/bigints" ) // 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) // [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 // [pairingsfinalexp] 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 // SequenceAlgorithmSuite builds a generic suite of tests for an addition // sequence algorithm. type SequenceAlgorithmSuite struct { // Algorithm under test. Algorithm alg.SequenceAlgorithm // AcceptsLargeInputs indicates whether the algorithm can tolerate large // inputs. As a rule of thumb, set this to true if the algorithm is // logarithmic in the largest input. AcceptsLargeInputs bool } // Tests builds the test suite function. Suitable to run as a subtest with // testing.T.Run. func (s SequenceAlgorithmSuite) Tests() func(t *testing.T) { return func(t *testing.T) { t.Run("known_sequences", checkKnownSequences(s.Algorithm)) if s.AcceptsLargeInputs { t.Run("as_chain_algorithm", ChainAlgorithmSuite(alg.AsChainAlgorithm(s.Algorithm))) } } } func checkKnownSequences(a alg.SequenceAlgorithm) func(t *testing.T) { cases := []struct { Targets []*big.Int Solution addchain.Chain }{ // Example 9.39 in [hehcc:exp]. { Targets: bigints.Int64s(47, 117, 343, 499, 933, 5689), Solution: addchain.Int64s(1, 2, 4, 8, 10, 11, 18, 36, 47, 55, 91, 109, 117, 226, 343, 434, 489, 499, 933, 1422, 2844, 5688, 5689), }, // [pairingsfinalexp] page 5. { Targets: bigints.Int64s(6, 12, 18, 30, 36), Solution: addchain.Int64s(1, 2, 3, 6, 12, 18, 30, 36), }, // [pairingsfinalexp] page 8. { Targets: bigints.Int64s(4, 5, 7, 10, 15, 26, 28, 30, 55, 75, 80, 100, 108, 144), Solution: addchain.Int64s(1, 2, 4, 5, 7, 10, 15, 25, 26, 28, 30, 36, 50, 55, 75, 80, 100, 108, 144), }, // [pairingsfinalexp] page 9. { Targets: bigints.Int64s(3, 5, 7, 14, 15, 21, 25, 35, 49, 54, 62, 70, 87, 98, 112, 245, 273, 319, 343, 434, 450, 581, 609, 784, 931, 1407, 1911, 4802, 6517), Solution: addchain.Int64s(1, 2, 3, 4, 5, 7, 8, 14, 15, 16, 21, 25, 28, 35, 42, 49, 54, 62, 70, 87, 98, 112, 147, 245, 273, 294, 319, 343, 392, 434, 450, 581, 609, 784, 931, 1162, 1407, 1862, 1911, 3724, 4655, 4802, 6517), }, // Curve25519 field inversion in [curvechains]. { Targets: bigints.Int64s(1, 2, 250), Solution: bigints.Int64s(1, 2, 3, 5, 10, 20, 40, 50, 100, 200, 250), }, // P-256 field inversion in [curvechains]. { Targets: bigints.Int64s(32, 94), Solution: bigints.Int64s(1, 2, 3, 6, 12, 15, 30, 32, 64, 94), }, // P-384 field inversion in [curvechains]. { Targets: bigints.Int64s(30, 32, 255), Solution: bigints.Int64s(1, 2, 3, 6, 12, 15, 30, 32, 60, 120, 240, 255), }, // secp256k1 field inversion in [curvechains]. { Targets: bigints.Int64s(22, 223), Solution: bigints.Int64s(1, 2, 3, 6, 9, 11, 22, 44, 88, 176, 220, 223), }, } for _, c := range cases { if err := c.Solution.Superset(c.Targets); err != nil { panic(err) } } return func(t *testing.T) { for _, c := range cases { got := AssertSequenceAlgorithmProduces(t, a, c.Targets) t.Logf(" got: length=%d sequence=%v", len(got), got) t.Logf("solution: length=%d sequence=%v", len(c.Solution), c.Solution) if len(got) > len(c.Solution) { t.Logf("sub-optimal") } } } } addchain-0.4.0/alg/binary/000077500000000000000000000000001514305256600153045ustar00rootroot00000000000000addchain-0.4.0/alg/binary/binary.go000066400000000000000000000020631514305256600171200ustar00rootroot00000000000000// Package binary implements generic binary addition chain algorithms. package binary import ( "math/big" "github.com/mmcloughlin/addchain" "github.com/mmcloughlin/addchain/internal/bigint" ) // References: // // [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 // RightToLeft builds a chain algorithm for the right-to-left binary method, // akin to [hehcc:exp] Algorithm 9.2. type RightToLeft struct{} func (RightToLeft) String() string { return "binary_right_to_left" } // FindChain applies the right-to-left binary method to n. func (RightToLeft) FindChain(n *big.Int) (addchain.Chain, error) { c := addchain.Chain{} b := new(big.Int).Set(n) d := bigint.One() var x *big.Int for bigint.IsNonZero(b) { c.AppendClone(d) if b.Bit(0) == 1 { if x == nil { x = bigint.Clone(d) } else { x.Add(x, d) c.AppendClone(x) } } b.Rsh(b, 1) d.Lsh(d, 1) } return c, nil } addchain-0.4.0/alg/binary/binary_test.go000066400000000000000000000002501514305256600201530ustar00rootroot00000000000000package binary import ( "testing" "github.com/mmcloughlin/addchain/alg/algtest" ) func TestRightToLeft(t *testing.T) { algtest.ChainAlgorithm(t, RightToLeft{}) } addchain-0.4.0/alg/contfrac/000077500000000000000000000000001514305256600156175ustar00rootroot00000000000000addchain-0.4.0/alg/contfrac/contfrac.go000066400000000000000000000206571514305256600177570ustar00rootroot00000000000000// 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} } addchain-0.4.0/alg/contfrac/contfrac_test.go000066400000000000000000000016721514305256600210120ustar00rootroot00000000000000package contfrac import ( "math/big" "testing" "github.com/mmcloughlin/addchain/alg" "github.com/mmcloughlin/addchain/alg/algtest" "github.com/mmcloughlin/addchain/internal/bigints" ) func TestAlgorithms(t *testing.T) { for _, strategy := range Strategies { suite := algtest.SequenceAlgorithmSuite{ Algorithm: NewAlgorithm(strategy), AcceptsLargeInputs: strategy.Singleton(), } t.Run(suite.Algorithm.String(), suite.Tests()) } } func TestBinaryStrategy(t *testing.T) { a := alg.AsChainAlgorithm(NewAlgorithm(BinaryStrategy{})) n := big.NewInt(87) expect := bigints.Int64s(1, 2, 4, 5, 10, 20, 21, 42, 43, 86, 87) algtest.AssertChainAlgorithmGenerates(t, a, n, expect) } func TestCoBinaryStrategy(t *testing.T) { a := alg.AsChainAlgorithm(NewAlgorithm(CoBinaryStrategy{})) n := big.NewInt(87) expect := bigints.Int64s(1, 2, 3, 5, 10, 11, 21, 22, 43, 44, 87) algtest.AssertChainAlgorithmGenerates(t, a, n, expect) } addchain-0.4.0/alg/dict/000077500000000000000000000000001514305256600147435ustar00rootroot00000000000000addchain-0.4.0/alg/dict/alg_test.go000066400000000000000000000012111514305256600170670ustar00rootroot00000000000000package dict import ( "testing" "github.com/mmcloughlin/addchain/alg" "github.com/mmcloughlin/addchain/alg/algtest" "github.com/mmcloughlin/addchain/alg/contfrac" ) func TestAlgorithms(t *testing.T) { as := []alg.ChainAlgorithm{ // Dictionary-based algorithms. NewAlgorithm( SlidingWindow{K: 4}, contfrac.NewAlgorithm(contfrac.DichotomicStrategy{}), ), NewAlgorithm( FixedWindow{K: 7}, contfrac.NewAlgorithm(contfrac.BinaryStrategy{}), ), // Runs algorithm. NewRunsAlgorithm(contfrac.NewAlgorithm(contfrac.DichotomicStrategy{})), } for _, a := range as { t.Run(a.String(), algtest.ChainAlgorithmSuite(a)) } } addchain-0.4.0/alg/dict/dict.go000066400000000000000000000257311514305256600162250ustar00rootroot00000000000000// 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 } addchain-0.4.0/alg/dict/dict_test.go000066400000000000000000000114351514305256600172600ustar00rootroot00000000000000package dict import ( "math/big" "math/rand" "testing" "time" "github.com/mmcloughlin/addchain" "github.com/mmcloughlin/addchain/alg/algtest" "github.com/mmcloughlin/addchain/alg/contfrac" "github.com/mmcloughlin/addchain/internal/bigint" "github.com/mmcloughlin/addchain/internal/bigints" "github.com/mmcloughlin/addchain/internal/test" ) func TestDecomposersRandom(t *testing.T) { ds := []Decomposer{ FixedWindow{K: 2}, FixedWindow{K: 11}, FixedWindow{K: 16}, SlidingWindow{K: 2}, SlidingWindow{K: 7}, SlidingWindow{K: 12}, RunLength{T: 0}, RunLength{T: 1}, RunLength{T: 3}, RunLength{T: 7}, Hybrid{K: 4, T: 7}, Hybrid{K: 3, T: 0}, } r := rand.New(rand.NewSource(time.Now().UnixNano())) for _, d := range ds { d := d t.Run(d.String(), test.Trials(func(t *testing.T) bool { n := bigint.RandBits(r, 256) got := d.Decompose(n) if !bigint.Equal(got.Int(), n) { t.Log(got) t.Fatalf("got %v expect %v", got.Int(), n) } return true })) } } func TestFixedWindow(t *testing.T) { n := big.NewInt(0xbeef0 << 3) f := FixedWindow{K: 4} got := f.Decompose(n) expect := Sum{ {D: big.NewInt(0xf), E: 7}, {D: big.NewInt(0xe), E: 11}, {D: big.NewInt(0xe), E: 15}, {D: big.NewInt(0xb), E: 19}, } if !SumEquals(got, expect) { t.Fatalf("got %v expect %v", got, expect) } } func TestSlidingWindow(t *testing.T) { n := big.NewInt(0xf143) f := SlidingWindow{K: 4} got := f.Decompose(n) expect := Sum{ {D: big.NewInt(0x3), E: 0}, {D: big.NewInt(0x5), E: 6}, {D: big.NewInt(0xf), E: 12}, } if !SumEquals(got, expect) { t.Fatalf("got %v expect %v", got, expect) } } func TestRunLength(t *testing.T) { cases := []struct { T uint X int64 Expect Sum }{ { T: 4, X: 0xff, Expect: Sum{ {D: big.NewInt(0xf), E: 0}, {D: big.NewInt(0xf), E: 4}, }, }, { T: 0, X: 0xff, Expect: Sum{ {D: big.NewInt(0xff), E: 0}, }, }, { T: 4, X: 0xf0f0, Expect: Sum{ {D: big.NewInt(0xf), E: 4}, {D: big.NewInt(0xf), E: 12}, }, }, { T: 0, X: 0xf0f0, Expect: Sum{ {D: big.NewInt(0xf), E: 4}, {D: big.NewInt(0xf), E: 12}, }, }, { T: 3, X: 0xff, Expect: Sum{ {D: big.NewInt(0x3), E: 0}, {D: big.NewInt(0x7), E: 2}, {D: big.NewInt(0x7), E: 5}, }, }, } for _, c := range cases { d := RunLength{T: c.T} if got := d.Decompose(big.NewInt(c.X)); !SumEquals(got, c.Expect) { t.Fatalf("Decompose(%#x) = %v; expect %v", c.X, got, c.Expect) } } } func TestHybrid(t *testing.T) { n := bigint.MustBinary("11111111_11111111_000_111_000000_1_0_111111_0_11_0") f := Hybrid{K: 4, T: 8} got := f.Decompose(n) expect := Sum{ {D: big.NewInt(0x3), E: 1}, {D: big.NewInt(0x3f), E: 4}, {D: big.NewInt(0x1), E: 11}, {D: big.NewInt(0x7), E: 18}, {D: big.NewInt(0xff), E: 24}, {D: big.NewInt(0xff), E: 32}, } if !SumEquals(got, expect) { t.Fatalf("got %v expect %v", got, expect) } } func TestAlgorithm(t *testing.T) { a := NewAlgorithm( SlidingWindow{K: 4}, contfrac.NewAlgorithm(contfrac.DichotomicStrategy{}), ) n := big.NewInt(587257) c := algtest.AssertChainAlgorithmProduces(t, a, n) t.Log(c) } func TestPrimitive(t *testing.T) { // These tests are designed to verify that primitive dictionary reduction is // doing sensible things, therefore we construct a dictionary algorithm with a // decomposer that's going to have obvious results. We'll use the run length // decomposer. a := NewAlgorithm( RunLength{T: 0}, contfrac.NewAlgorithm(contfrac.TotalStrategy{}), ) // Cases are accompanied by an example of how this chain might be constructed // if dictionary reduction is working. We simply confirm that the resulting // chain is valid and at least as good as the example. cases := []struct { N *big.Int Example addchain.Chain }{ { N: bigint.MustBinary("1111_0_1_0"), Example: bigints.Int64s( 1, 2, 3, // prep 6, 12, 15, // << 2 and add 3 30, 60, 61, // << 2 and add 1 122, // << 1 ), }, { N: bigint.MustBinary("11_0_11111111_0"), Example: bigints.Int64s( 1, 2, 3, 6, 12, 15, // prepare 11 and 1111 24, 48, 96, 111, // << 5 add 1111 222, 444, 888, 1776, 1791, // << 4 add 1111 3582, // << 1 ), }, } for _, c := range cases { got := algtest.AssertChainAlgorithmProduces(t, a, c.N) if err := c.Example.Produces(c.N); err != nil { t.Fatalf("example is invalid: %s", err) } if len(got) > len(c.Example) { t.Logf(" got: %v", got) t.Logf("example: %v", c.Example) t.Errorf("suboptimal result: length %d but possible in %d", len(got), len(c.Example)) } } } func SumEquals(a, b Sum) bool { if len(a) != len(b) { return false } for i := range a { if a[i].E != b[i].E { return false } if !bigint.Equal(a[i].D, b[i].D) { return false } } return true } addchain-0.4.0/alg/dict/runs.go000066400000000000000000000055741514305256600162740ustar00rootroot00000000000000package 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 } addchain-0.4.0/alg/dict/runs_test.go000066400000000000000000000015671514305256600173310ustar00rootroot00000000000000package dict import ( "math/big" "testing" "github.com/mmcloughlin/addchain" "github.com/mmcloughlin/addchain/internal/bigint" ) func TestRunsChain(t *testing.T) { cases := []addchain.Chain{ // Basic case. addchain.Int64s(1, 2, 4, 6), // The following induces a bug in an earlier incorrect implementation. Note // that 9 and 12 are formed with 1+8 and 3+8, therfore both using 8 as the // larger of the two operands. This means that shifts of Ones(8) are required // on two occasions, causing a duplicate if you're not careful. addchain.Int64s(1, 2, 4, 8, 9, 12), } for _, lengths := range cases { runs := []*big.Int{} for _, length := range lengths { runs = append(runs, bigint.Ones(uint(length.Uint64()))) } got, err := RunsChain(lengths) if err != nil { t.Fatal(err) } if err := got.Superset(runs); err != nil { t.Fatal(err) } } } addchain-0.4.0/alg/ensemble/000077500000000000000000000000001514305256600156125ustar00rootroot00000000000000addchain-0.4.0/alg/ensemble/ensemble.go000066400000000000000000000036211514305256600177350ustar00rootroot00000000000000// 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 } addchain-0.4.0/alg/ensemble/ensemble_test.go000066400000000000000000000043161514305256600207760ustar00rootroot00000000000000package ensemble import ( "encoding/json" "io/ioutil" "reflect" "testing" "github.com/mmcloughlin/addchain/alg/exec" "github.com/mmcloughlin/addchain/internal/results" "github.com/mmcloughlin/addchain/internal/test" ) // TestResults confirms that chain lengths from every ensemble algorithm remain // unchanged. This is intended to provide confidence when making risky changes // or refactors. The results package has its own similar test, but this is // focussed on verifying that the best recorded result is still the same. // // The test uses the "golden test" technique, where we dump // known-good results into golden files and later verify that we get the same // result. func TestResults(t *testing.T) { t.Parallel() as := Ensemble() for _, c := range results.Results { c := c // scopelint t.Run(c.Slug, func(t *testing.T) { t.Parallel() // Execute. ex := exec.NewParallel() rs := ex.Execute(c.Target(), as) // Summarize results in map from algorithm name to program length. got := map[string]int{} for _, r := range rs { if r.Err != nil { t.Fatalf("error with %s: %v", r.Algorithm, r.Err) } got[r.Algorithm.String()] = len(r.Program) } // If golden, write out results data file. filename := test.GoldenName(c.Slug) if test.Golden() { t.Logf("writing golden file %s", filename) b, err := json.MarshalIndent(got, "", "\t") if err != nil { t.Fatal(err) } if err := ioutil.WriteFile(filename, b, 0644); err != nil { t.Fatalf("write golden file: %v", err) } } // Load golden file. b, err := ioutil.ReadFile(filename) if err != nil { t.Fatalf("read golden file: %v", err) } var expect map[string]int if err := json.Unmarshal(b, &expect); err != nil { t.Fatal(err) } // Verify equal. if !reflect.DeepEqual(expect, got) { t.Fatal("results do not match golden file") } }) } } func BenchmarkResults(b *testing.B) { as := Ensemble() for _, c := range results.Results { c := c // scopelint n := c.Target() b.Run(c.Slug, func(b *testing.B) { for i := 0; i < b.N; i++ { for _, a := range as { if _, err := a.FindChain(n); err != nil { b.Fatal(err) } } } }) } } addchain-0.4.0/alg/ensemble/testdata/000077500000000000000000000000001514305256600174235ustar00rootroot00000000000000addchain-0.4.0/alg/ensemble/testdata/curve25519_field.golden000066400000000000000000000353211514305256600235160ustar00rootroot00000000000000{ "opt(dictionary(hybrid(2,0),continued_fractions(binary)))": 381, "opt(dictionary(hybrid(2,0),continued_fractions(co_binary)))": 381, "opt(dictionary(hybrid(2,0),continued_fractions(dichotomic)))": 268, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,approximation))))": 381, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,delta_largest))))": 502, "opt(dictionary(hybrid(2,16),continued_fractions(binary)))": 276, "opt(dictionary(hybrid(2,16),continued_fractions(co_binary)))": 276, "opt(dictionary(hybrid(2,16),continued_fractions(dichotomic)))": 276, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,approximation))))": 276, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,delta_largest))))": 276, "opt(dictionary(hybrid(2,32),continued_fractions(binary)))": 271, "opt(dictionary(hybrid(2,32),continued_fractions(co_binary)))": 271, "opt(dictionary(hybrid(2,32),continued_fractions(dichotomic)))": 270, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,approximation))))": 271, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,delta_largest))))": 281, "opt(dictionary(hybrid(2,64),continued_fractions(binary)))": 272, "opt(dictionary(hybrid(2,64),continued_fractions(co_binary)))": 272, "opt(dictionary(hybrid(2,64),continued_fractions(dichotomic)))": 268, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,approximation))))": 272, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,delta_largest))))": 310, "opt(dictionary(hybrid(3,0),continued_fractions(binary)))": 381, "opt(dictionary(hybrid(3,0),continued_fractions(co_binary)))": 381, "opt(dictionary(hybrid(3,0),continued_fractions(dichotomic)))": 268, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,approximation))))": 341, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,delta_largest))))": 503, "opt(dictionary(hybrid(3,16),continued_fractions(binary)))": 276, "opt(dictionary(hybrid(3,16),continued_fractions(co_binary)))": 276, "opt(dictionary(hybrid(3,16),continued_fractions(dichotomic)))": 276, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,approximation))))": 277, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,delta_largest))))": 277, "opt(dictionary(hybrid(3,32),continued_fractions(binary)))": 271, "opt(dictionary(hybrid(3,32),continued_fractions(co_binary)))": 271, "opt(dictionary(hybrid(3,32),continued_fractions(dichotomic)))": 270, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,approximation))))": 271, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,delta_largest))))": 284, "opt(dictionary(hybrid(3,64),continued_fractions(binary)))": 272, "opt(dictionary(hybrid(3,64),continued_fractions(co_binary)))": 272, "opt(dictionary(hybrid(3,64),continued_fractions(dichotomic)))": 268, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,approximation))))": 273, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,delta_largest))))": 311, "opt(dictionary(hybrid(4,0),continued_fractions(binary)))": 381, "opt(dictionary(hybrid(4,0),continued_fractions(co_binary)))": 381, "opt(dictionary(hybrid(4,0),continued_fractions(dichotomic)))": 277, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,approximation))))": 320, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,delta_largest))))": 502, "opt(dictionary(hybrid(4,16),continued_fractions(binary)))": 276, "opt(dictionary(hybrid(4,16),continued_fractions(co_binary)))": 276, "opt(dictionary(hybrid(4,16),continued_fractions(dichotomic)))": 276, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,approximation))))": 276, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,delta_largest))))": 276, "opt(dictionary(hybrid(4,32),continued_fractions(binary)))": 271, "opt(dictionary(hybrid(4,32),continued_fractions(co_binary)))": 271, "opt(dictionary(hybrid(4,32),continued_fractions(dichotomic)))": 270, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,approximation))))": 271, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,delta_largest))))": 282, "opt(dictionary(hybrid(4,64),continued_fractions(binary)))": 272, "opt(dictionary(hybrid(4,64),continued_fractions(co_binary)))": 272, "opt(dictionary(hybrid(4,64),continued_fractions(dichotomic)))": 268, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,approximation))))": 272, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,delta_largest))))": 310, "opt(dictionary(hybrid(5,0),continued_fractions(binary)))": 381, "opt(dictionary(hybrid(5,0),continued_fractions(co_binary)))": 381, "opt(dictionary(hybrid(5,0),continued_fractions(dichotomic)))": 277, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,approximation))))": 320, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,delta_largest))))": 502, "opt(dictionary(hybrid(5,16),continued_fractions(binary)))": 276, "opt(dictionary(hybrid(5,16),continued_fractions(co_binary)))": 276, "opt(dictionary(hybrid(5,16),continued_fractions(dichotomic)))": 276, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,approximation))))": 276, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,delta_largest))))": 276, "opt(dictionary(hybrid(5,32),continued_fractions(binary)))": 271, "opt(dictionary(hybrid(5,32),continued_fractions(co_binary)))": 271, "opt(dictionary(hybrid(5,32),continued_fractions(dichotomic)))": 270, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,approximation))))": 271, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,delta_largest))))": 282, "opt(dictionary(hybrid(5,64),continued_fractions(binary)))": 272, "opt(dictionary(hybrid(5,64),continued_fractions(co_binary)))": 272, "opt(dictionary(hybrid(5,64),continued_fractions(dichotomic)))": 268, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,approximation))))": 272, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,delta_largest))))": 310, "opt(dictionary(hybrid(6,0),continued_fractions(binary)))": 381, "opt(dictionary(hybrid(6,0),continued_fractions(co_binary)))": 381, "opt(dictionary(hybrid(6,0),continued_fractions(dichotomic)))": 277, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,approximation))))": 320, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,delta_largest))))": 502, "opt(dictionary(hybrid(6,16),continued_fractions(binary)))": 276, "opt(dictionary(hybrid(6,16),continued_fractions(co_binary)))": 276, "opt(dictionary(hybrid(6,16),continued_fractions(dichotomic)))": 276, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,approximation))))": 276, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,delta_largest))))": 276, "opt(dictionary(hybrid(6,32),continued_fractions(binary)))": 271, "opt(dictionary(hybrid(6,32),continued_fractions(co_binary)))": 271, "opt(dictionary(hybrid(6,32),continued_fractions(dichotomic)))": 270, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,approximation))))": 271, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,delta_largest))))": 282, "opt(dictionary(hybrid(6,64),continued_fractions(binary)))": 272, "opt(dictionary(hybrid(6,64),continued_fractions(co_binary)))": 272, "opt(dictionary(hybrid(6,64),continued_fractions(dichotomic)))": 268, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,approximation))))": 272, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,delta_largest))))": 310, "opt(dictionary(hybrid(7,0),continued_fractions(binary)))": 381, "opt(dictionary(hybrid(7,0),continued_fractions(co_binary)))": 381, "opt(dictionary(hybrid(7,0),continued_fractions(dichotomic)))": 277, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,approximation))))": 320, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,delta_largest))))": 502, "opt(dictionary(hybrid(7,16),continued_fractions(binary)))": 276, "opt(dictionary(hybrid(7,16),continued_fractions(co_binary)))": 276, "opt(dictionary(hybrid(7,16),continued_fractions(dichotomic)))": 276, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,approximation))))": 276, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,delta_largest))))": 276, "opt(dictionary(hybrid(7,32),continued_fractions(binary)))": 271, "opt(dictionary(hybrid(7,32),continued_fractions(co_binary)))": 271, "opt(dictionary(hybrid(7,32),continued_fractions(dichotomic)))": 270, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,approximation))))": 271, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,delta_largest))))": 282, "opt(dictionary(hybrid(7,64),continued_fractions(binary)))": 272, "opt(dictionary(hybrid(7,64),continued_fractions(co_binary)))": 272, "opt(dictionary(hybrid(7,64),continued_fractions(dichotomic)))": 268, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,approximation))))": 272, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,delta_largest))))": 310, "opt(dictionary(hybrid(8,0),continued_fractions(binary)))": 381, "opt(dictionary(hybrid(8,0),continued_fractions(co_binary)))": 381, "opt(dictionary(hybrid(8,0),continued_fractions(dichotomic)))": 277, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,approximation))))": 320, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,delta_largest))))": 502, "opt(dictionary(hybrid(8,16),continued_fractions(binary)))": 276, "opt(dictionary(hybrid(8,16),continued_fractions(co_binary)))": 276, "opt(dictionary(hybrid(8,16),continued_fractions(dichotomic)))": 276, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,approximation))))": 276, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,delta_largest))))": 276, "opt(dictionary(hybrid(8,32),continued_fractions(binary)))": 271, "opt(dictionary(hybrid(8,32),continued_fractions(co_binary)))": 271, "opt(dictionary(hybrid(8,32),continued_fractions(dichotomic)))": 270, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,approximation))))": 271, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,delta_largest))))": 282, "opt(dictionary(hybrid(8,64),continued_fractions(binary)))": 272, "opt(dictionary(hybrid(8,64),continued_fractions(co_binary)))": 272, "opt(dictionary(hybrid(8,64),continued_fractions(dichotomic)))": 268, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,approximation))))": 272, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,delta_largest))))": 310, "opt(dictionary(run_length(0),continued_fractions(binary)))": 381, "opt(dictionary(run_length(0),continued_fractions(co_binary)))": 381, "opt(dictionary(run_length(0),continued_fractions(dichotomic)))": 268, "opt(dictionary(run_length(0),heuristic(use_first(halving,approximation))))": 381, "opt(dictionary(run_length(0),heuristic(use_first(halving,delta_largest))))": 502, "opt(dictionary(run_length(128),continued_fractions(binary)))": 281, "opt(dictionary(run_length(128),continued_fractions(co_binary)))": 281, "opt(dictionary(run_length(128),continued_fractions(dichotomic)))": 267, "opt(dictionary(run_length(128),heuristic(use_first(halving,approximation))))": 281, "opt(dictionary(run_length(128),heuristic(use_first(halving,delta_largest))))": 371, "opt(dictionary(run_length(16),continued_fractions(binary)))": 276, "opt(dictionary(run_length(16),continued_fractions(co_binary)))": 276, "opt(dictionary(run_length(16),continued_fractions(dichotomic)))": 276, "opt(dictionary(run_length(16),heuristic(use_first(halving,approximation))))": 276, "opt(dictionary(run_length(16),heuristic(use_first(halving,delta_largest))))": 276, "opt(dictionary(run_length(32),continued_fractions(binary)))": 271, "opt(dictionary(run_length(32),continued_fractions(co_binary)))": 271, "opt(dictionary(run_length(32),continued_fractions(dichotomic)))": 270, "opt(dictionary(run_length(32),heuristic(use_first(halving,approximation))))": 271, "opt(dictionary(run_length(32),heuristic(use_first(halving,delta_largest))))": 281, "opt(dictionary(run_length(64),continued_fractions(binary)))": 272, "opt(dictionary(run_length(64),continued_fractions(co_binary)))": 272, "opt(dictionary(run_length(64),continued_fractions(dichotomic)))": 268, "opt(dictionary(run_length(64),heuristic(use_first(halving,approximation))))": 272, "opt(dictionary(run_length(64),heuristic(use_first(halving,delta_largest))))": 310, "opt(dictionary(sliding_window(128),continued_fractions(binary)))": 320, "opt(dictionary(sliding_window(128),continued_fractions(co_binary)))": 320, "opt(dictionary(sliding_window(128),continued_fractions(dichotomic)))": 279, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,approximation))))": 287, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,delta_largest))))": 380, "opt(dictionary(sliding_window(16),continued_fractions(binary)))": 279, "opt(dictionary(sliding_window(16),continued_fractions(co_binary)))": 279, "opt(dictionary(sliding_window(16),continued_fractions(dichotomic)))": 277, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,approximation))))": 276, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,delta_largest))))": 280, "opt(dictionary(sliding_window(32),continued_fractions(binary)))": 278, "opt(dictionary(sliding_window(32),continued_fractions(co_binary)))": 278, "opt(dictionary(sliding_window(32),continued_fractions(dichotomic)))": 276, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,approximation))))": 273, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,delta_largest))))": 290, "opt(dictionary(sliding_window(4),continued_fractions(binary)))": 320, "opt(dictionary(sliding_window(4),continued_fractions(co_binary)))": 320, "opt(dictionary(sliding_window(4),continued_fractions(dichotomic)))": 320, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,approximation))))": 320, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,delta_largest))))": 320, "opt(dictionary(sliding_window(64),continued_fractions(binary)))": 293, "opt(dictionary(sliding_window(64),continued_fractions(co_binary)))": 293, "opt(dictionary(sliding_window(64),continued_fractions(dichotomic)))": 276, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,approximation))))": 277, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,delta_largest))))": 318, "opt(dictionary(sliding_window(8),continued_fractions(binary)))": 290, "opt(dictionary(sliding_window(8),continued_fractions(co_binary)))": 290, "opt(dictionary(sliding_window(8),continued_fractions(dichotomic)))": 290, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,approximation))))": 291, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,delta_largest))))": 291, "opt(runs(continued_fractions(binary)))": 268, "opt(runs(continued_fractions(co_binary)))": 268, "opt(runs(continued_fractions(dichotomic)))": 266, "opt(runs(heuristic(use_first(halving,approximation))))": 268, "opt(runs(heuristic(use_first(halving,delta_largest))))": 270 }addchain-0.4.0/alg/ensemble/testdata/curve25519_scalar.golden000066400000000000000000000353211514305256600237000ustar00rootroot00000000000000{ "opt(dictionary(hybrid(2,0),continued_fractions(binary)))": 289, "opt(dictionary(hybrid(2,0),continued_fractions(co_binary)))": 289, "opt(dictionary(hybrid(2,0),continued_fractions(dichotomic)))": 289, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,approximation))))": 289, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,delta_largest))))": 289, "opt(dictionary(hybrid(2,16),continued_fractions(binary)))": 289, "opt(dictionary(hybrid(2,16),continued_fractions(co_binary)))": 289, "opt(dictionary(hybrid(2,16),continued_fractions(dichotomic)))": 289, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,approximation))))": 289, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,delta_largest))))": 289, "opt(dictionary(hybrid(2,32),continued_fractions(binary)))": 289, "opt(dictionary(hybrid(2,32),continued_fractions(co_binary)))": 289, "opt(dictionary(hybrid(2,32),continued_fractions(dichotomic)))": 289, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,approximation))))": 289, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,delta_largest))))": 289, "opt(dictionary(hybrid(2,64),continued_fractions(binary)))": 289, "opt(dictionary(hybrid(2,64),continued_fractions(co_binary)))": 289, "opt(dictionary(hybrid(2,64),continued_fractions(dichotomic)))": 289, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,approximation))))": 289, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,delta_largest))))": 289, "opt(dictionary(hybrid(3,0),continued_fractions(binary)))": 287, "opt(dictionary(hybrid(3,0),continued_fractions(co_binary)))": 287, "opt(dictionary(hybrid(3,0),continued_fractions(dichotomic)))": 287, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,approximation))))": 287, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,delta_largest))))": 287, "opt(dictionary(hybrid(3,16),continued_fractions(binary)))": 287, "opt(dictionary(hybrid(3,16),continued_fractions(co_binary)))": 287, "opt(dictionary(hybrid(3,16),continued_fractions(dichotomic)))": 287, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,approximation))))": 287, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,delta_largest))))": 287, "opt(dictionary(hybrid(3,32),continued_fractions(binary)))": 287, "opt(dictionary(hybrid(3,32),continued_fractions(co_binary)))": 287, "opt(dictionary(hybrid(3,32),continued_fractions(dichotomic)))": 287, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,approximation))))": 287, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,delta_largest))))": 287, "opt(dictionary(hybrid(3,64),continued_fractions(binary)))": 287, "opt(dictionary(hybrid(3,64),continued_fractions(co_binary)))": 287, "opt(dictionary(hybrid(3,64),continued_fractions(dichotomic)))": 287, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,approximation))))": 287, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,delta_largest))))": 287, "opt(dictionary(hybrid(4,0),continued_fractions(binary)))": 283, "opt(dictionary(hybrid(4,0),continued_fractions(co_binary)))": 283, "opt(dictionary(hybrid(4,0),continued_fractions(dichotomic)))": 283, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,approximation))))": 283, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,delta_largest))))": 283, "opt(dictionary(hybrid(4,16),continued_fractions(binary)))": 283, "opt(dictionary(hybrid(4,16),continued_fractions(co_binary)))": 283, "opt(dictionary(hybrid(4,16),continued_fractions(dichotomic)))": 283, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,approximation))))": 283, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,delta_largest))))": 283, "opt(dictionary(hybrid(4,32),continued_fractions(binary)))": 283, "opt(dictionary(hybrid(4,32),continued_fractions(co_binary)))": 283, "opt(dictionary(hybrid(4,32),continued_fractions(dichotomic)))": 283, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,approximation))))": 283, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,delta_largest))))": 283, "opt(dictionary(hybrid(4,64),continued_fractions(binary)))": 283, "opt(dictionary(hybrid(4,64),continued_fractions(co_binary)))": 283, "opt(dictionary(hybrid(4,64),continued_fractions(dichotomic)))": 283, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,approximation))))": 283, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,delta_largest))))": 283, "opt(dictionary(hybrid(5,0),continued_fractions(binary)))": 285, "opt(dictionary(hybrid(5,0),continued_fractions(co_binary)))": 285, "opt(dictionary(hybrid(5,0),continued_fractions(dichotomic)))": 285, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,approximation))))": 285, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,delta_largest))))": 285, "opt(dictionary(hybrid(5,16),continued_fractions(binary)))": 285, "opt(dictionary(hybrid(5,16),continued_fractions(co_binary)))": 285, "opt(dictionary(hybrid(5,16),continued_fractions(dichotomic)))": 285, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,approximation))))": 285, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,delta_largest))))": 285, "opt(dictionary(hybrid(5,32),continued_fractions(binary)))": 285, "opt(dictionary(hybrid(5,32),continued_fractions(co_binary)))": 285, "opt(dictionary(hybrid(5,32),continued_fractions(dichotomic)))": 285, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,approximation))))": 285, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,delta_largest))))": 285, "opt(dictionary(hybrid(5,64),continued_fractions(binary)))": 285, "opt(dictionary(hybrid(5,64),continued_fractions(co_binary)))": 285, "opt(dictionary(hybrid(5,64),continued_fractions(dichotomic)))": 285, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,approximation))))": 285, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,delta_largest))))": 285, "opt(dictionary(hybrid(6,0),continued_fractions(binary)))": 285, "opt(dictionary(hybrid(6,0),continued_fractions(co_binary)))": 285, "opt(dictionary(hybrid(6,0),continued_fractions(dichotomic)))": 285, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,approximation))))": 285, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,delta_largest))))": 285, "opt(dictionary(hybrid(6,16),continued_fractions(binary)))": 285, "opt(dictionary(hybrid(6,16),continued_fractions(co_binary)))": 285, "opt(dictionary(hybrid(6,16),continued_fractions(dichotomic)))": 285, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,approximation))))": 285, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,delta_largest))))": 285, "opt(dictionary(hybrid(6,32),continued_fractions(binary)))": 285, "opt(dictionary(hybrid(6,32),continued_fractions(co_binary)))": 285, "opt(dictionary(hybrid(6,32),continued_fractions(dichotomic)))": 285, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,approximation))))": 285, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,delta_largest))))": 285, "opt(dictionary(hybrid(6,64),continued_fractions(binary)))": 285, "opt(dictionary(hybrid(6,64),continued_fractions(co_binary)))": 285, "opt(dictionary(hybrid(6,64),continued_fractions(dichotomic)))": 285, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,approximation))))": 285, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,delta_largest))))": 285, "opt(dictionary(hybrid(7,0),continued_fractions(binary)))": 284, "opt(dictionary(hybrid(7,0),continued_fractions(co_binary)))": 284, "opt(dictionary(hybrid(7,0),continued_fractions(dichotomic)))": 284, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,approximation))))": 285, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,delta_largest))))": 284, "opt(dictionary(hybrid(7,16),continued_fractions(binary)))": 284, "opt(dictionary(hybrid(7,16),continued_fractions(co_binary)))": 284, "opt(dictionary(hybrid(7,16),continued_fractions(dichotomic)))": 284, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,approximation))))": 285, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,delta_largest))))": 284, "opt(dictionary(hybrid(7,32),continued_fractions(binary)))": 284, "opt(dictionary(hybrid(7,32),continued_fractions(co_binary)))": 284, "opt(dictionary(hybrid(7,32),continued_fractions(dichotomic)))": 284, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,approximation))))": 285, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,delta_largest))))": 284, "opt(dictionary(hybrid(7,64),continued_fractions(binary)))": 284, "opt(dictionary(hybrid(7,64),continued_fractions(co_binary)))": 284, "opt(dictionary(hybrid(7,64),continued_fractions(dichotomic)))": 284, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,approximation))))": 285, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,delta_largest))))": 284, "opt(dictionary(hybrid(8,0),continued_fractions(binary)))": 283, "opt(dictionary(hybrid(8,0),continued_fractions(co_binary)))": 283, "opt(dictionary(hybrid(8,0),continued_fractions(dichotomic)))": 283, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,approximation))))": 285, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,delta_largest))))": 284, "opt(dictionary(hybrid(8,16),continued_fractions(binary)))": 283, "opt(dictionary(hybrid(8,16),continued_fractions(co_binary)))": 283, "opt(dictionary(hybrid(8,16),continued_fractions(dichotomic)))": 283, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,approximation))))": 285, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,delta_largest))))": 284, "opt(dictionary(hybrid(8,32),continued_fractions(binary)))": 283, "opt(dictionary(hybrid(8,32),continued_fractions(co_binary)))": 283, "opt(dictionary(hybrid(8,32),continued_fractions(dichotomic)))": 283, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,approximation))))": 285, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,delta_largest))))": 284, "opt(dictionary(hybrid(8,64),continued_fractions(binary)))": 283, "opt(dictionary(hybrid(8,64),continued_fractions(co_binary)))": 283, "opt(dictionary(hybrid(8,64),continued_fractions(dichotomic)))": 283, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,approximation))))": 285, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,delta_largest))))": 284, "opt(dictionary(run_length(0),continued_fractions(binary)))": 289, "opt(dictionary(run_length(0),continued_fractions(co_binary)))": 289, "opt(dictionary(run_length(0),continued_fractions(dichotomic)))": 289, "opt(dictionary(run_length(0),heuristic(use_first(halving,approximation))))": 289, "opt(dictionary(run_length(0),heuristic(use_first(halving,delta_largest))))": 289, "opt(dictionary(run_length(128),continued_fractions(binary)))": 289, "opt(dictionary(run_length(128),continued_fractions(co_binary)))": 289, "opt(dictionary(run_length(128),continued_fractions(dichotomic)))": 289, "opt(dictionary(run_length(128),heuristic(use_first(halving,approximation))))": 289, "opt(dictionary(run_length(128),heuristic(use_first(halving,delta_largest))))": 289, "opt(dictionary(run_length(16),continued_fractions(binary)))": 289, "opt(dictionary(run_length(16),continued_fractions(co_binary)))": 289, "opt(dictionary(run_length(16),continued_fractions(dichotomic)))": 289, "opt(dictionary(run_length(16),heuristic(use_first(halving,approximation))))": 289, "opt(dictionary(run_length(16),heuristic(use_first(halving,delta_largest))))": 289, "opt(dictionary(run_length(32),continued_fractions(binary)))": 289, "opt(dictionary(run_length(32),continued_fractions(co_binary)))": 289, "opt(dictionary(run_length(32),continued_fractions(dichotomic)))": 289, "opt(dictionary(run_length(32),heuristic(use_first(halving,approximation))))": 289, "opt(dictionary(run_length(32),heuristic(use_first(halving,delta_largest))))": 289, "opt(dictionary(run_length(64),continued_fractions(binary)))": 289, "opt(dictionary(run_length(64),continued_fractions(co_binary)))": 289, "opt(dictionary(run_length(64),continued_fractions(dichotomic)))": 289, "opt(dictionary(run_length(64),heuristic(use_first(halving,approximation))))": 289, "opt(dictionary(run_length(64),heuristic(use_first(halving,delta_largest))))": 289, "opt(dictionary(sliding_window(128),continued_fractions(binary)))": 324, "opt(dictionary(sliding_window(128),continued_fractions(co_binary)))": 443, "opt(dictionary(sliding_window(128),continued_fractions(dichotomic)))": 344, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,approximation))))": 324, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,delta_largest))))": 374, "opt(dictionary(sliding_window(16),continued_fractions(binary)))": 294, "opt(dictionary(sliding_window(16),continued_fractions(co_binary)))": 294, "opt(dictionary(sliding_window(16),continued_fractions(dichotomic)))": 294, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,approximation))))": 294, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,delta_largest))))": 292, "opt(dictionary(sliding_window(32),continued_fractions(binary)))": 307, "opt(dictionary(sliding_window(32),continued_fractions(co_binary)))": 307, "opt(dictionary(sliding_window(32),continued_fractions(dichotomic)))": 307, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,approximation))))": 311, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,delta_largest))))": 310, "opt(dictionary(sliding_window(4),continued_fractions(binary)))": 284, "opt(dictionary(sliding_window(4),continued_fractions(co_binary)))": 284, "opt(dictionary(sliding_window(4),continued_fractions(dichotomic)))": 284, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,approximation))))": 284, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,delta_largest))))": 284, "opt(dictionary(sliding_window(64),continued_fractions(binary)))": 345, "opt(dictionary(sliding_window(64),continued_fractions(co_binary)))": 346, "opt(dictionary(sliding_window(64),continued_fractions(dichotomic)))": 344, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,approximation))))": 345, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,delta_largest))))": 345, "opt(dictionary(sliding_window(8),continued_fractions(binary)))": 283, "opt(dictionary(sliding_window(8),continued_fractions(co_binary)))": 283, "opt(dictionary(sliding_window(8),continued_fractions(dichotomic)))": 283, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,approximation))))": 285, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,delta_largest))))": 284, "opt(runs(continued_fractions(binary)))": 289, "opt(runs(continued_fractions(co_binary)))": 289, "opt(runs(continued_fractions(dichotomic)))": 289, "opt(runs(heuristic(use_first(halving,approximation))))": 289, "opt(runs(heuristic(use_first(halving,delta_largest))))": 289 }addchain-0.4.0/alg/ensemble/testdata/goldilocks_field.golden000066400000000000000000000353211514305256600241160ustar00rootroot00000000000000{ "opt(dictionary(hybrid(2,0),continued_fractions(binary)))": 671, "opt(dictionary(hybrid(2,0),continued_fractions(co_binary)))": 671, "opt(dictionary(hybrid(2,0),continued_fractions(dichotomic)))": 462, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,approximation))))": 561, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,delta_largest))))": 668, "opt(dictionary(hybrid(2,16),continued_fractions(binary)))": 490, "opt(dictionary(hybrid(2,16),continued_fractions(co_binary)))": 490, "opt(dictionary(hybrid(2,16),continued_fractions(dichotomic)))": 482, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,approximation))))": 484, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,delta_largest))))": 487, "opt(dictionary(hybrid(2,32),continued_fractions(binary)))": 492, "opt(dictionary(hybrid(2,32),continued_fractions(co_binary)))": 492, "opt(dictionary(hybrid(2,32),continued_fractions(dichotomic)))": 470, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,approximation))))": 478, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,delta_largest))))": 489, "opt(dictionary(hybrid(2,64),continued_fractions(binary)))": 473, "opt(dictionary(hybrid(2,64),continued_fractions(co_binary)))": 473, "opt(dictionary(hybrid(2,64),continued_fractions(dichotomic)))": 465, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,approximation))))": 473, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,delta_largest))))": 487, "opt(dictionary(hybrid(3,0),continued_fractions(binary)))": 671, "opt(dictionary(hybrid(3,0),continued_fractions(co_binary)))": 671, "opt(dictionary(hybrid(3,0),continued_fractions(dichotomic)))": 462, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,approximation))))": 561, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,delta_largest))))": 668, "opt(dictionary(hybrid(3,16),continued_fractions(binary)))": 490, "opt(dictionary(hybrid(3,16),continued_fractions(co_binary)))": 490, "opt(dictionary(hybrid(3,16),continued_fractions(dichotomic)))": 482, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,approximation))))": 484, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,delta_largest))))": 487, "opt(dictionary(hybrid(3,32),continued_fractions(binary)))": 492, "opt(dictionary(hybrid(3,32),continued_fractions(co_binary)))": 492, "opt(dictionary(hybrid(3,32),continued_fractions(dichotomic)))": 470, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,approximation))))": 478, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,delta_largest))))": 489, "opt(dictionary(hybrid(3,64),continued_fractions(binary)))": 473, "opt(dictionary(hybrid(3,64),continued_fractions(co_binary)))": 473, "opt(dictionary(hybrid(3,64),continued_fractions(dichotomic)))": 465, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,approximation))))": 473, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,delta_largest))))": 487, "opt(dictionary(hybrid(4,0),continued_fractions(binary)))": 671, "opt(dictionary(hybrid(4,0),continued_fractions(co_binary)))": 671, "opt(dictionary(hybrid(4,0),continued_fractions(dichotomic)))": 462, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,approximation))))": 561, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,delta_largest))))": 668, "opt(dictionary(hybrid(4,16),continued_fractions(binary)))": 490, "opt(dictionary(hybrid(4,16),continued_fractions(co_binary)))": 490, "opt(dictionary(hybrid(4,16),continued_fractions(dichotomic)))": 482, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,approximation))))": 484, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,delta_largest))))": 487, "opt(dictionary(hybrid(4,32),continued_fractions(binary)))": 492, "opt(dictionary(hybrid(4,32),continued_fractions(co_binary)))": 492, "opt(dictionary(hybrid(4,32),continued_fractions(dichotomic)))": 470, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,approximation))))": 478, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,delta_largest))))": 489, "opt(dictionary(hybrid(4,64),continued_fractions(binary)))": 473, "opt(dictionary(hybrid(4,64),continued_fractions(co_binary)))": 473, "opt(dictionary(hybrid(4,64),continued_fractions(dichotomic)))": 465, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,approximation))))": 473, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,delta_largest))))": 487, "opt(dictionary(hybrid(5,0),continued_fractions(binary)))": 671, "opt(dictionary(hybrid(5,0),continued_fractions(co_binary)))": 671, "opt(dictionary(hybrid(5,0),continued_fractions(dichotomic)))": 462, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,approximation))))": 561, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,delta_largest))))": 668, "opt(dictionary(hybrid(5,16),continued_fractions(binary)))": 490, "opt(dictionary(hybrid(5,16),continued_fractions(co_binary)))": 490, "opt(dictionary(hybrid(5,16),continued_fractions(dichotomic)))": 482, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,approximation))))": 484, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,delta_largest))))": 487, "opt(dictionary(hybrid(5,32),continued_fractions(binary)))": 492, "opt(dictionary(hybrid(5,32),continued_fractions(co_binary)))": 492, "opt(dictionary(hybrid(5,32),continued_fractions(dichotomic)))": 470, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,approximation))))": 478, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,delta_largest))))": 489, "opt(dictionary(hybrid(5,64),continued_fractions(binary)))": 473, "opt(dictionary(hybrid(5,64),continued_fractions(co_binary)))": 473, "opt(dictionary(hybrid(5,64),continued_fractions(dichotomic)))": 465, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,approximation))))": 473, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,delta_largest))))": 487, "opt(dictionary(hybrid(6,0),continued_fractions(binary)))": 671, "opt(dictionary(hybrid(6,0),continued_fractions(co_binary)))": 671, "opt(dictionary(hybrid(6,0),continued_fractions(dichotomic)))": 462, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,approximation))))": 561, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,delta_largest))))": 668, "opt(dictionary(hybrid(6,16),continued_fractions(binary)))": 490, "opt(dictionary(hybrid(6,16),continued_fractions(co_binary)))": 490, "opt(dictionary(hybrid(6,16),continued_fractions(dichotomic)))": 482, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,approximation))))": 484, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,delta_largest))))": 487, "opt(dictionary(hybrid(6,32),continued_fractions(binary)))": 492, "opt(dictionary(hybrid(6,32),continued_fractions(co_binary)))": 492, "opt(dictionary(hybrid(6,32),continued_fractions(dichotomic)))": 470, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,approximation))))": 478, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,delta_largest))))": 489, "opt(dictionary(hybrid(6,64),continued_fractions(binary)))": 473, "opt(dictionary(hybrid(6,64),continued_fractions(co_binary)))": 473, "opt(dictionary(hybrid(6,64),continued_fractions(dichotomic)))": 465, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,approximation))))": 473, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,delta_largest))))": 487, "opt(dictionary(hybrid(7,0),continued_fractions(binary)))": 671, "opt(dictionary(hybrid(7,0),continued_fractions(co_binary)))": 671, "opt(dictionary(hybrid(7,0),continued_fractions(dichotomic)))": 462, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,approximation))))": 561, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,delta_largest))))": 668, "opt(dictionary(hybrid(7,16),continued_fractions(binary)))": 490, "opt(dictionary(hybrid(7,16),continued_fractions(co_binary)))": 490, "opt(dictionary(hybrid(7,16),continued_fractions(dichotomic)))": 482, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,approximation))))": 484, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,delta_largest))))": 487, "opt(dictionary(hybrid(7,32),continued_fractions(binary)))": 492, "opt(dictionary(hybrid(7,32),continued_fractions(co_binary)))": 492, "opt(dictionary(hybrid(7,32),continued_fractions(dichotomic)))": 470, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,approximation))))": 478, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,delta_largest))))": 489, "opt(dictionary(hybrid(7,64),continued_fractions(binary)))": 473, "opt(dictionary(hybrid(7,64),continued_fractions(co_binary)))": 473, "opt(dictionary(hybrid(7,64),continued_fractions(dichotomic)))": 465, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,approximation))))": 473, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,delta_largest))))": 487, "opt(dictionary(hybrid(8,0),continued_fractions(binary)))": 671, "opt(dictionary(hybrid(8,0),continued_fractions(co_binary)))": 671, "opt(dictionary(hybrid(8,0),continued_fractions(dichotomic)))": 462, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,approximation))))": 561, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,delta_largest))))": 668, "opt(dictionary(hybrid(8,16),continued_fractions(binary)))": 490, "opt(dictionary(hybrid(8,16),continued_fractions(co_binary)))": 490, "opt(dictionary(hybrid(8,16),continued_fractions(dichotomic)))": 482, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,approximation))))": 484, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,delta_largest))))": 487, "opt(dictionary(hybrid(8,32),continued_fractions(binary)))": 492, "opt(dictionary(hybrid(8,32),continued_fractions(co_binary)))": 492, "opt(dictionary(hybrid(8,32),continued_fractions(dichotomic)))": 470, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,approximation))))": 478, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,delta_largest))))": 489, "opt(dictionary(hybrid(8,64),continued_fractions(binary)))": 473, "opt(dictionary(hybrid(8,64),continued_fractions(co_binary)))": 473, "opt(dictionary(hybrid(8,64),continued_fractions(dichotomic)))": 465, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,approximation))))": 473, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,delta_largest))))": 487, "opt(dictionary(run_length(0),continued_fractions(binary)))": 671, "opt(dictionary(run_length(0),continued_fractions(co_binary)))": 671, "opt(dictionary(run_length(0),continued_fractions(dichotomic)))": 462, "opt(dictionary(run_length(0),heuristic(use_first(halving,approximation))))": 561, "opt(dictionary(run_length(0),heuristic(use_first(halving,delta_largest))))": 668, "opt(dictionary(run_length(128),continued_fractions(binary)))": 464, "opt(dictionary(run_length(128),continued_fractions(co_binary)))": 464, "opt(dictionary(run_length(128),continued_fractions(dichotomic)))": 463, "opt(dictionary(run_length(128),heuristic(use_first(halving,approximation))))": 464, "opt(dictionary(run_length(128),heuristic(use_first(halving,delta_largest))))": 502, "opt(dictionary(run_length(16),continued_fractions(binary)))": 490, "opt(dictionary(run_length(16),continued_fractions(co_binary)))": 490, "opt(dictionary(run_length(16),continued_fractions(dichotomic)))": 482, "opt(dictionary(run_length(16),heuristic(use_first(halving,approximation))))": 484, "opt(dictionary(run_length(16),heuristic(use_first(halving,delta_largest))))": 487, "opt(dictionary(run_length(32),continued_fractions(binary)))": 492, "opt(dictionary(run_length(32),continued_fractions(co_binary)))": 492, "opt(dictionary(run_length(32),continued_fractions(dichotomic)))": 470, "opt(dictionary(run_length(32),heuristic(use_first(halving,approximation))))": 478, "opt(dictionary(run_length(32),heuristic(use_first(halving,delta_largest))))": 489, "opt(dictionary(run_length(64),continued_fractions(binary)))": 473, "opt(dictionary(run_length(64),continued_fractions(co_binary)))": 473, "opt(dictionary(run_length(64),continued_fractions(dichotomic)))": 465, "opt(dictionary(run_length(64),heuristic(use_first(halving,approximation))))": 473, "opt(dictionary(run_length(64),heuristic(use_first(halving,delta_largest))))": 487, "opt(dictionary(sliding_window(128),continued_fractions(binary)))": 515, "opt(dictionary(sliding_window(128),continued_fractions(co_binary)))": 515, "opt(dictionary(sliding_window(128),continued_fractions(dichotomic)))": 468, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,approximation))))": 472, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,delta_largest))))": 484, "opt(dictionary(sliding_window(16),continued_fractions(binary)))": 489, "opt(dictionary(sliding_window(16),continued_fractions(co_binary)))": 489, "opt(dictionary(sliding_window(16),continued_fractions(dichotomic)))": 481, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,approximation))))": 483, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,delta_largest))))": 486, "opt(dictionary(sliding_window(32),continued_fractions(binary)))": 491, "opt(dictionary(sliding_window(32),continued_fractions(co_binary)))": 491, "opt(dictionary(sliding_window(32),continued_fractions(dichotomic)))": 469, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,approximation))))": 477, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,delta_largest))))": 488, "opt(dictionary(sliding_window(4),continued_fractions(binary)))": 561, "opt(dictionary(sliding_window(4),continued_fractions(co_binary)))": 561, "opt(dictionary(sliding_window(4),continued_fractions(dichotomic)))": 561, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,approximation))))": 561, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,delta_largest))))": 561, "opt(dictionary(sliding_window(64),continued_fractions(binary)))": 487, "opt(dictionary(sliding_window(64),continued_fractions(co_binary)))": 487, "opt(dictionary(sliding_window(64),continued_fractions(dichotomic)))": 465, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,approximation))))": 473, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,delta_largest))))": 487, "opt(dictionary(sliding_window(8),continued_fractions(binary)))": 509, "opt(dictionary(sliding_window(8),continued_fractions(co_binary)))": 509, "opt(dictionary(sliding_window(8),continued_fractions(dichotomic)))": 507, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,approximation))))": 507, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,delta_largest))))": 507, "opt(runs(continued_fractions(binary)))": 462, "opt(runs(continued_fractions(co_binary)))": 462, "opt(runs(continued_fractions(dichotomic)))": 461, "opt(runs(heuristic(use_first(halving,approximation))))": 460, "opt(runs(heuristic(use_first(halving,delta_largest))))": 461 }addchain-0.4.0/alg/ensemble/testdata/p192_field.golden000066400000000000000000000353211514305256600224570ustar00rootroot00000000000000{ "opt(dictionary(hybrid(2,0),continued_fractions(binary)))": 217, "opt(dictionary(hybrid(2,0),continued_fractions(co_binary)))": 217, "opt(dictionary(hybrid(2,0),continued_fractions(dichotomic)))": 203, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,approximation))))": 217, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,delta_largest))))": 257, "opt(dictionary(hybrid(2,16),continued_fractions(binary)))": 218, "opt(dictionary(hybrid(2,16),continued_fractions(co_binary)))": 218, "opt(dictionary(hybrid(2,16),continued_fractions(dichotomic)))": 210, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,approximation))))": 212, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,delta_largest))))": 215, "opt(dictionary(hybrid(2,32),continued_fractions(binary)))": 228, "opt(dictionary(hybrid(2,32),continued_fractions(co_binary)))": 228, "opt(dictionary(hybrid(2,32),continued_fractions(dichotomic)))": 206, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,approximation))))": 214, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,delta_largest))))": 225, "opt(dictionary(hybrid(2,64),continued_fractions(binary)))": 257, "opt(dictionary(hybrid(2,64),continued_fractions(co_binary)))": 257, "opt(dictionary(hybrid(2,64),continued_fractions(dichotomic)))": 205, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,approximation))))": 227, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,delta_largest))))": 254, "opt(dictionary(hybrid(3,0),continued_fractions(binary)))": 217, "opt(dictionary(hybrid(3,0),continued_fractions(co_binary)))": 217, "opt(dictionary(hybrid(3,0),continued_fractions(dichotomic)))": 203, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,approximation))))": 217, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,delta_largest))))": 257, "opt(dictionary(hybrid(3,16),continued_fractions(binary)))": 218, "opt(dictionary(hybrid(3,16),continued_fractions(co_binary)))": 218, "opt(dictionary(hybrid(3,16),continued_fractions(dichotomic)))": 210, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,approximation))))": 212, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,delta_largest))))": 215, "opt(dictionary(hybrid(3,32),continued_fractions(binary)))": 228, "opt(dictionary(hybrid(3,32),continued_fractions(co_binary)))": 228, "opt(dictionary(hybrid(3,32),continued_fractions(dichotomic)))": 206, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,approximation))))": 214, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,delta_largest))))": 225, "opt(dictionary(hybrid(3,64),continued_fractions(binary)))": 257, "opt(dictionary(hybrid(3,64),continued_fractions(co_binary)))": 257, "opt(dictionary(hybrid(3,64),continued_fractions(dichotomic)))": 205, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,approximation))))": 227, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,delta_largest))))": 254, "opt(dictionary(hybrid(4,0),continued_fractions(binary)))": 217, "opt(dictionary(hybrid(4,0),continued_fractions(co_binary)))": 217, "opt(dictionary(hybrid(4,0),continued_fractions(dichotomic)))": 203, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,approximation))))": 217, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,delta_largest))))": 257, "opt(dictionary(hybrid(4,16),continued_fractions(binary)))": 218, "opt(dictionary(hybrid(4,16),continued_fractions(co_binary)))": 218, "opt(dictionary(hybrid(4,16),continued_fractions(dichotomic)))": 210, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,approximation))))": 212, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,delta_largest))))": 215, "opt(dictionary(hybrid(4,32),continued_fractions(binary)))": 228, "opt(dictionary(hybrid(4,32),continued_fractions(co_binary)))": 228, "opt(dictionary(hybrid(4,32),continued_fractions(dichotomic)))": 206, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,approximation))))": 214, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,delta_largest))))": 225, "opt(dictionary(hybrid(4,64),continued_fractions(binary)))": 257, "opt(dictionary(hybrid(4,64),continued_fractions(co_binary)))": 257, "opt(dictionary(hybrid(4,64),continued_fractions(dichotomic)))": 205, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,approximation))))": 227, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,delta_largest))))": 254, "opt(dictionary(hybrid(5,0),continued_fractions(binary)))": 217, "opt(dictionary(hybrid(5,0),continued_fractions(co_binary)))": 217, "opt(dictionary(hybrid(5,0),continued_fractions(dichotomic)))": 203, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,approximation))))": 217, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,delta_largest))))": 257, "opt(dictionary(hybrid(5,16),continued_fractions(binary)))": 218, "opt(dictionary(hybrid(5,16),continued_fractions(co_binary)))": 218, "opt(dictionary(hybrid(5,16),continued_fractions(dichotomic)))": 210, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,approximation))))": 212, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,delta_largest))))": 215, "opt(dictionary(hybrid(5,32),continued_fractions(binary)))": 228, "opt(dictionary(hybrid(5,32),continued_fractions(co_binary)))": 228, "opt(dictionary(hybrid(5,32),continued_fractions(dichotomic)))": 206, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,approximation))))": 214, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,delta_largest))))": 225, "opt(dictionary(hybrid(5,64),continued_fractions(binary)))": 257, "opt(dictionary(hybrid(5,64),continued_fractions(co_binary)))": 257, "opt(dictionary(hybrid(5,64),continued_fractions(dichotomic)))": 205, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,approximation))))": 227, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,delta_largest))))": 254, "opt(dictionary(hybrid(6,0),continued_fractions(binary)))": 217, "opt(dictionary(hybrid(6,0),continued_fractions(co_binary)))": 217, "opt(dictionary(hybrid(6,0),continued_fractions(dichotomic)))": 203, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,approximation))))": 217, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,delta_largest))))": 257, "opt(dictionary(hybrid(6,16),continued_fractions(binary)))": 218, "opt(dictionary(hybrid(6,16),continued_fractions(co_binary)))": 218, "opt(dictionary(hybrid(6,16),continued_fractions(dichotomic)))": 210, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,approximation))))": 212, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,delta_largest))))": 215, "opt(dictionary(hybrid(6,32),continued_fractions(binary)))": 228, "opt(dictionary(hybrid(6,32),continued_fractions(co_binary)))": 228, "opt(dictionary(hybrid(6,32),continued_fractions(dichotomic)))": 206, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,approximation))))": 214, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,delta_largest))))": 225, "opt(dictionary(hybrid(6,64),continued_fractions(binary)))": 257, "opt(dictionary(hybrid(6,64),continued_fractions(co_binary)))": 257, "opt(dictionary(hybrid(6,64),continued_fractions(dichotomic)))": 205, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,approximation))))": 227, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,delta_largest))))": 254, "opt(dictionary(hybrid(7,0),continued_fractions(binary)))": 217, "opt(dictionary(hybrid(7,0),continued_fractions(co_binary)))": 217, "opt(dictionary(hybrid(7,0),continued_fractions(dichotomic)))": 203, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,approximation))))": 217, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,delta_largest))))": 257, "opt(dictionary(hybrid(7,16),continued_fractions(binary)))": 218, "opt(dictionary(hybrid(7,16),continued_fractions(co_binary)))": 218, "opt(dictionary(hybrid(7,16),continued_fractions(dichotomic)))": 210, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,approximation))))": 212, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,delta_largest))))": 215, "opt(dictionary(hybrid(7,32),continued_fractions(binary)))": 228, "opt(dictionary(hybrid(7,32),continued_fractions(co_binary)))": 228, "opt(dictionary(hybrid(7,32),continued_fractions(dichotomic)))": 206, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,approximation))))": 214, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,delta_largest))))": 225, "opt(dictionary(hybrid(7,64),continued_fractions(binary)))": 257, "opt(dictionary(hybrid(7,64),continued_fractions(co_binary)))": 257, "opt(dictionary(hybrid(7,64),continued_fractions(dichotomic)))": 205, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,approximation))))": 227, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,delta_largest))))": 254, "opt(dictionary(hybrid(8,0),continued_fractions(binary)))": 217, "opt(dictionary(hybrid(8,0),continued_fractions(co_binary)))": 217, "opt(dictionary(hybrid(8,0),continued_fractions(dichotomic)))": 203, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,approximation))))": 217, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,delta_largest))))": 257, "opt(dictionary(hybrid(8,16),continued_fractions(binary)))": 218, "opt(dictionary(hybrid(8,16),continued_fractions(co_binary)))": 218, "opt(dictionary(hybrid(8,16),continued_fractions(dichotomic)))": 210, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,approximation))))": 212, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,delta_largest))))": 215, "opt(dictionary(hybrid(8,32),continued_fractions(binary)))": 228, "opt(dictionary(hybrid(8,32),continued_fractions(co_binary)))": 228, "opt(dictionary(hybrid(8,32),continued_fractions(dichotomic)))": 206, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,approximation))))": 214, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,delta_largest))))": 225, "opt(dictionary(hybrid(8,64),continued_fractions(binary)))": 257, "opt(dictionary(hybrid(8,64),continued_fractions(co_binary)))": 257, "opt(dictionary(hybrid(8,64),continued_fractions(dichotomic)))": 205, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,approximation))))": 227, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,delta_largest))))": 254, "opt(dictionary(run_length(0),continued_fractions(binary)))": 217, "opt(dictionary(run_length(0),continued_fractions(co_binary)))": 217, "opt(dictionary(run_length(0),continued_fractions(dichotomic)))": 203, "opt(dictionary(run_length(0),heuristic(use_first(halving,approximation))))": 217, "opt(dictionary(run_length(0),heuristic(use_first(halving,delta_largest))))": 257, "opt(dictionary(run_length(128),continued_fractions(binary)))": 217, "opt(dictionary(run_length(128),continued_fractions(co_binary)))": 217, "opt(dictionary(run_length(128),continued_fractions(dichotomic)))": 203, "opt(dictionary(run_length(128),heuristic(use_first(halving,approximation))))": 217, "opt(dictionary(run_length(128),heuristic(use_first(halving,delta_largest))))": 257, "opt(dictionary(run_length(16),continued_fractions(binary)))": 218, "opt(dictionary(run_length(16),continued_fractions(co_binary)))": 218, "opt(dictionary(run_length(16),continued_fractions(dichotomic)))": 210, "opt(dictionary(run_length(16),heuristic(use_first(halving,approximation))))": 212, "opt(dictionary(run_length(16),heuristic(use_first(halving,delta_largest))))": 215, "opt(dictionary(run_length(32),continued_fractions(binary)))": 228, "opt(dictionary(run_length(32),continued_fractions(co_binary)))": 228, "opt(dictionary(run_length(32),continued_fractions(dichotomic)))": 206, "opt(dictionary(run_length(32),heuristic(use_first(halving,approximation))))": 214, "opt(dictionary(run_length(32),heuristic(use_first(halving,delta_largest))))": 225, "opt(dictionary(run_length(64),continued_fractions(binary)))": 257, "opt(dictionary(run_length(64),continued_fractions(co_binary)))": 257, "opt(dictionary(run_length(64),continued_fractions(dichotomic)))": 205, "opt(dictionary(run_length(64),heuristic(use_first(halving,approximation))))": 227, "opt(dictionary(run_length(64),heuristic(use_first(halving,delta_largest))))": 254, "opt(dictionary(sliding_window(128),continued_fractions(binary)))": 217, "opt(dictionary(sliding_window(128),continued_fractions(co_binary)))": 217, "opt(dictionary(sliding_window(128),continued_fractions(dichotomic)))": 205, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,approximation))))": 226, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,delta_largest))))": 253, "opt(dictionary(sliding_window(16),continued_fractions(binary)))": 217, "opt(dictionary(sliding_window(16),continued_fractions(co_binary)))": 217, "opt(dictionary(sliding_window(16),continued_fractions(dichotomic)))": 209, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,approximation))))": 211, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,delta_largest))))": 214, "opt(dictionary(sliding_window(32),continued_fractions(binary)))": 227, "opt(dictionary(sliding_window(32),continued_fractions(co_binary)))": 227, "opt(dictionary(sliding_window(32),continued_fractions(dichotomic)))": 205, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,approximation))))": 213, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,delta_largest))))": 224, "opt(dictionary(sliding_window(4),continued_fractions(binary)))": 241, "opt(dictionary(sliding_window(4),continued_fractions(co_binary)))": 241, "opt(dictionary(sliding_window(4),continued_fractions(dichotomic)))": 241, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,approximation))))": 241, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,delta_largest))))": 241, "opt(dictionary(sliding_window(64),continued_fractions(binary)))": 256, "opt(dictionary(sliding_window(64),continued_fractions(co_binary)))": 256, "opt(dictionary(sliding_window(64),continued_fractions(dichotomic)))": 204, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,approximation))))": 226, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,delta_largest))))": 253, "opt(dictionary(sliding_window(8),continued_fractions(binary)))": 221, "opt(dictionary(sliding_window(8),continued_fractions(co_binary)))": 221, "opt(dictionary(sliding_window(8),continued_fractions(dichotomic)))": 219, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,approximation))))": 219, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,delta_largest))))": 219, "opt(runs(continued_fractions(binary)))": 203, "opt(runs(continued_fractions(co_binary)))": 203, "opt(runs(continued_fractions(dichotomic)))": 203, "opt(runs(heuristic(use_first(halving,approximation))))": 204, "opt(runs(heuristic(use_first(halving,delta_largest))))": 206 }addchain-0.4.0/alg/ensemble/testdata/p2213_field.golden000066400000000000000000000353211514305256600225330ustar00rootroot00000000000000{ "opt(dictionary(hybrid(2,0),continued_fractions(binary)))": 330, "opt(dictionary(hybrid(2,0),continued_fractions(co_binary)))": 330, "opt(dictionary(hybrid(2,0),continued_fractions(dichotomic)))": 232, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,approximation))))": 330, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,delta_largest))))": 435, "opt(dictionary(hybrid(2,16),continued_fractions(binary)))": 239, "opt(dictionary(hybrid(2,16),continued_fractions(co_binary)))": 239, "opt(dictionary(hybrid(2,16),continued_fractions(dichotomic)))": 239, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,approximation))))": 239, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,delta_largest))))": 239, "opt(dictionary(hybrid(2,32),continued_fractions(binary)))": 235, "opt(dictionary(hybrid(2,32),continued_fractions(co_binary)))": 235, "opt(dictionary(hybrid(2,32),continued_fractions(dichotomic)))": 234, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,approximation))))": 235, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,delta_largest))))": 245, "opt(dictionary(hybrid(2,64),continued_fractions(binary)))": 234, "opt(dictionary(hybrid(2,64),continued_fractions(co_binary)))": 234, "opt(dictionary(hybrid(2,64),continued_fractions(dichotomic)))": 232, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,approximation))))": 234, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,delta_largest))))": 248, "opt(dictionary(hybrid(3,0),continued_fractions(binary)))": 330, "opt(dictionary(hybrid(3,0),continued_fractions(co_binary)))": 330, "opt(dictionary(hybrid(3,0),continued_fractions(dichotomic)))": 232, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,approximation))))": 330, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,delta_largest))))": 435, "opt(dictionary(hybrid(3,16),continued_fractions(binary)))": 239, "opt(dictionary(hybrid(3,16),continued_fractions(co_binary)))": 239, "opt(dictionary(hybrid(3,16),continued_fractions(dichotomic)))": 239, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,approximation))))": 239, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,delta_largest))))": 239, "opt(dictionary(hybrid(3,32),continued_fractions(binary)))": 235, "opt(dictionary(hybrid(3,32),continued_fractions(co_binary)))": 235, "opt(dictionary(hybrid(3,32),continued_fractions(dichotomic)))": 234, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,approximation))))": 235, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,delta_largest))))": 245, "opt(dictionary(hybrid(3,64),continued_fractions(binary)))": 234, "opt(dictionary(hybrid(3,64),continued_fractions(co_binary)))": 234, "opt(dictionary(hybrid(3,64),continued_fractions(dichotomic)))": 232, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,approximation))))": 234, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,delta_largest))))": 248, "opt(dictionary(hybrid(4,0),continued_fractions(binary)))": 330, "opt(dictionary(hybrid(4,0),continued_fractions(co_binary)))": 330, "opt(dictionary(hybrid(4,0),continued_fractions(dichotomic)))": 232, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,approximation))))": 330, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,delta_largest))))": 435, "opt(dictionary(hybrid(4,16),continued_fractions(binary)))": 239, "opt(dictionary(hybrid(4,16),continued_fractions(co_binary)))": 239, "opt(dictionary(hybrid(4,16),continued_fractions(dichotomic)))": 239, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,approximation))))": 239, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,delta_largest))))": 239, "opt(dictionary(hybrid(4,32),continued_fractions(binary)))": 235, "opt(dictionary(hybrid(4,32),continued_fractions(co_binary)))": 235, "opt(dictionary(hybrid(4,32),continued_fractions(dichotomic)))": 234, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,approximation))))": 235, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,delta_largest))))": 245, "opt(dictionary(hybrid(4,64),continued_fractions(binary)))": 234, "opt(dictionary(hybrid(4,64),continued_fractions(co_binary)))": 234, "opt(dictionary(hybrid(4,64),continued_fractions(dichotomic)))": 232, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,approximation))))": 234, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,delta_largest))))": 248, "opt(dictionary(hybrid(5,0),continued_fractions(binary)))": 330, "opt(dictionary(hybrid(5,0),continued_fractions(co_binary)))": 330, "opt(dictionary(hybrid(5,0),continued_fractions(dichotomic)))": 232, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,approximation))))": 330, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,delta_largest))))": 435, "opt(dictionary(hybrid(5,16),continued_fractions(binary)))": 239, "opt(dictionary(hybrid(5,16),continued_fractions(co_binary)))": 239, "opt(dictionary(hybrid(5,16),continued_fractions(dichotomic)))": 239, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,approximation))))": 239, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,delta_largest))))": 239, "opt(dictionary(hybrid(5,32),continued_fractions(binary)))": 235, "opt(dictionary(hybrid(5,32),continued_fractions(co_binary)))": 235, "opt(dictionary(hybrid(5,32),continued_fractions(dichotomic)))": 234, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,approximation))))": 235, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,delta_largest))))": 245, "opt(dictionary(hybrid(5,64),continued_fractions(binary)))": 234, "opt(dictionary(hybrid(5,64),continued_fractions(co_binary)))": 234, "opt(dictionary(hybrid(5,64),continued_fractions(dichotomic)))": 232, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,approximation))))": 234, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,delta_largest))))": 248, "opt(dictionary(hybrid(6,0),continued_fractions(binary)))": 330, "opt(dictionary(hybrid(6,0),continued_fractions(co_binary)))": 330, "opt(dictionary(hybrid(6,0),continued_fractions(dichotomic)))": 232, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,approximation))))": 330, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,delta_largest))))": 435, "opt(dictionary(hybrid(6,16),continued_fractions(binary)))": 239, "opt(dictionary(hybrid(6,16),continued_fractions(co_binary)))": 239, "opt(dictionary(hybrid(6,16),continued_fractions(dichotomic)))": 239, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,approximation))))": 239, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,delta_largest))))": 239, "opt(dictionary(hybrid(6,32),continued_fractions(binary)))": 235, "opt(dictionary(hybrid(6,32),continued_fractions(co_binary)))": 235, "opt(dictionary(hybrid(6,32),continued_fractions(dichotomic)))": 234, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,approximation))))": 235, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,delta_largest))))": 245, "opt(dictionary(hybrid(6,64),continued_fractions(binary)))": 234, "opt(dictionary(hybrid(6,64),continued_fractions(co_binary)))": 234, "opt(dictionary(hybrid(6,64),continued_fractions(dichotomic)))": 232, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,approximation))))": 234, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,delta_largest))))": 248, "opt(dictionary(hybrid(7,0),continued_fractions(binary)))": 330, "opt(dictionary(hybrid(7,0),continued_fractions(co_binary)))": 330, "opt(dictionary(hybrid(7,0),continued_fractions(dichotomic)))": 232, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,approximation))))": 330, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,delta_largest))))": 435, "opt(dictionary(hybrid(7,16),continued_fractions(binary)))": 239, "opt(dictionary(hybrid(7,16),continued_fractions(co_binary)))": 239, "opt(dictionary(hybrid(7,16),continued_fractions(dichotomic)))": 239, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,approximation))))": 239, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,delta_largest))))": 239, "opt(dictionary(hybrid(7,32),continued_fractions(binary)))": 235, "opt(dictionary(hybrid(7,32),continued_fractions(co_binary)))": 235, "opt(dictionary(hybrid(7,32),continued_fractions(dichotomic)))": 234, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,approximation))))": 235, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,delta_largest))))": 245, "opt(dictionary(hybrid(7,64),continued_fractions(binary)))": 234, "opt(dictionary(hybrid(7,64),continued_fractions(co_binary)))": 234, "opt(dictionary(hybrid(7,64),continued_fractions(dichotomic)))": 232, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,approximation))))": 234, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,delta_largest))))": 248, "opt(dictionary(hybrid(8,0),continued_fractions(binary)))": 330, "opt(dictionary(hybrid(8,0),continued_fractions(co_binary)))": 330, "opt(dictionary(hybrid(8,0),continued_fractions(dichotomic)))": 232, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,approximation))))": 330, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,delta_largest))))": 435, "opt(dictionary(hybrid(8,16),continued_fractions(binary)))": 239, "opt(dictionary(hybrid(8,16),continued_fractions(co_binary)))": 239, "opt(dictionary(hybrid(8,16),continued_fractions(dichotomic)))": 239, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,approximation))))": 239, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,delta_largest))))": 239, "opt(dictionary(hybrid(8,32),continued_fractions(binary)))": 235, "opt(dictionary(hybrid(8,32),continued_fractions(co_binary)))": 235, "opt(dictionary(hybrid(8,32),continued_fractions(dichotomic)))": 234, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,approximation))))": 235, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,delta_largest))))": 245, "opt(dictionary(hybrid(8,64),continued_fractions(binary)))": 234, "opt(dictionary(hybrid(8,64),continued_fractions(co_binary)))": 234, "opt(dictionary(hybrid(8,64),continued_fractions(dichotomic)))": 232, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,approximation))))": 234, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,delta_largest))))": 248, "opt(dictionary(run_length(0),continued_fractions(binary)))": 330, "opt(dictionary(run_length(0),continued_fractions(co_binary)))": 330, "opt(dictionary(run_length(0),continued_fractions(dichotomic)))": 232, "opt(dictionary(run_length(0),heuristic(use_first(halving,approximation))))": 330, "opt(dictionary(run_length(0),heuristic(use_first(halving,delta_largest))))": 435, "opt(dictionary(run_length(128),continued_fractions(binary)))": 232, "opt(dictionary(run_length(128),continued_fractions(co_binary)))": 232, "opt(dictionary(run_length(128),continued_fractions(dichotomic)))": 232, "opt(dictionary(run_length(128),heuristic(use_first(halving,approximation))))": 232, "opt(dictionary(run_length(128),heuristic(use_first(halving,delta_largest))))": 258, "opt(dictionary(run_length(16),continued_fractions(binary)))": 239, "opt(dictionary(run_length(16),continued_fractions(co_binary)))": 239, "opt(dictionary(run_length(16),continued_fractions(dichotomic)))": 239, "opt(dictionary(run_length(16),heuristic(use_first(halving,approximation))))": 239, "opt(dictionary(run_length(16),heuristic(use_first(halving,delta_largest))))": 239, "opt(dictionary(run_length(32),continued_fractions(binary)))": 235, "opt(dictionary(run_length(32),continued_fractions(co_binary)))": 235, "opt(dictionary(run_length(32),continued_fractions(dichotomic)))": 234, "opt(dictionary(run_length(32),heuristic(use_first(halving,approximation))))": 235, "opt(dictionary(run_length(32),heuristic(use_first(halving,delta_largest))))": 245, "opt(dictionary(run_length(64),continued_fractions(binary)))": 234, "opt(dictionary(run_length(64),continued_fractions(co_binary)))": 234, "opt(dictionary(run_length(64),continued_fractions(dichotomic)))": 232, "opt(dictionary(run_length(64),heuristic(use_first(halving,approximation))))": 234, "opt(dictionary(run_length(64),heuristic(use_first(halving,delta_largest))))": 248, "opt(dictionary(sliding_window(128),continued_fractions(binary)))": 270, "opt(dictionary(sliding_window(128),continued_fractions(co_binary)))": 270, "opt(dictionary(sliding_window(128),continued_fractions(dichotomic)))": 256, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,approximation))))": 236, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,delta_largest))))": 261, "opt(dictionary(sliding_window(16),continued_fractions(binary)))": 240, "opt(dictionary(sliding_window(16),continued_fractions(co_binary)))": 240, "opt(dictionary(sliding_window(16),continued_fractions(dichotomic)))": 240, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,approximation))))": 241, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,delta_largest))))": 245, "opt(dictionary(sliding_window(32),continued_fractions(binary)))": 237, "opt(dictionary(sliding_window(32),continued_fractions(co_binary)))": 237, "opt(dictionary(sliding_window(32),continued_fractions(dichotomic)))": 234, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,approximation))))": 240, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,delta_largest))))": 253, "opt(dictionary(sliding_window(4),continued_fractions(binary)))": 278, "opt(dictionary(sliding_window(4),continued_fractions(co_binary)))": 278, "opt(dictionary(sliding_window(4),continued_fractions(dichotomic)))": 278, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,approximation))))": 278, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,delta_largest))))": 278, "opt(dictionary(sliding_window(64),continued_fractions(binary)))": 242, "opt(dictionary(sliding_window(64),continued_fractions(co_binary)))": 242, "opt(dictionary(sliding_window(64),continued_fractions(dichotomic)))": 243, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,approximation))))": 235, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,delta_largest))))": 256, "opt(dictionary(sliding_window(8),continued_fractions(binary)))": 251, "opt(dictionary(sliding_window(8),continued_fractions(co_binary)))": 251, "opt(dictionary(sliding_window(8),continued_fractions(dichotomic)))": 251, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,approximation))))": 252, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,delta_largest))))": 252, "opt(runs(continued_fractions(binary)))": 232, "opt(runs(continued_fractions(co_binary)))": 232, "opt(runs(continued_fractions(dichotomic)))": 231, "opt(runs(heuristic(use_first(halving,approximation))))": 231, "opt(runs(heuristic(use_first(halving,delta_largest))))": 234 }addchain-0.4.0/alg/ensemble/testdata/p222117_field.golden000066400000000000000000000353211514305256600227020ustar00rootroot00000000000000{ "opt(dictionary(hybrid(2,0),continued_fractions(binary)))": 437, "opt(dictionary(hybrid(2,0),continued_fractions(co_binary)))": 437, "opt(dictionary(hybrid(2,0),continued_fractions(dichotomic)))": 235, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,approximation))))": 331, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,delta_largest))))": 435, "opt(dictionary(hybrid(2,16),continued_fractions(binary)))": 242, "opt(dictionary(hybrid(2,16),continued_fractions(co_binary)))": 242, "opt(dictionary(hybrid(2,16),continued_fractions(dichotomic)))": 242, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,approximation))))": 242, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,delta_largest))))": 244, "opt(dictionary(hybrid(2,32),continued_fractions(binary)))": 237, "opt(dictionary(hybrid(2,32),continued_fractions(co_binary)))": 237, "opt(dictionary(hybrid(2,32),continued_fractions(dichotomic)))": 236, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,approximation))))": 236, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,delta_largest))))": 241, "opt(dictionary(hybrid(2,64),continued_fractions(binary)))": 235, "opt(dictionary(hybrid(2,64),continued_fractions(co_binary)))": 235, "opt(dictionary(hybrid(2,64),continued_fractions(dichotomic)))": 235, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,approximation))))": 235, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,delta_largest))))": 256, "opt(dictionary(hybrid(3,0),continued_fractions(binary)))": 437, "opt(dictionary(hybrid(3,0),continued_fractions(co_binary)))": 437, "opt(dictionary(hybrid(3,0),continued_fractions(dichotomic)))": 235, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,approximation))))": 331, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,delta_largest))))": 435, "opt(dictionary(hybrid(3,16),continued_fractions(binary)))": 242, "opt(dictionary(hybrid(3,16),continued_fractions(co_binary)))": 242, "opt(dictionary(hybrid(3,16),continued_fractions(dichotomic)))": 242, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,approximation))))": 242, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,delta_largest))))": 244, "opt(dictionary(hybrid(3,32),continued_fractions(binary)))": 237, "opt(dictionary(hybrid(3,32),continued_fractions(co_binary)))": 237, "opt(dictionary(hybrid(3,32),continued_fractions(dichotomic)))": 236, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,approximation))))": 236, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,delta_largest))))": 241, "opt(dictionary(hybrid(3,64),continued_fractions(binary)))": 235, "opt(dictionary(hybrid(3,64),continued_fractions(co_binary)))": 235, "opt(dictionary(hybrid(3,64),continued_fractions(dichotomic)))": 235, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,approximation))))": 235, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,delta_largest))))": 256, "opt(dictionary(hybrid(4,0),continued_fractions(binary)))": 330, "opt(dictionary(hybrid(4,0),continued_fractions(co_binary)))": 330, "opt(dictionary(hybrid(4,0),continued_fractions(dichotomic)))": 242, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,approximation))))": 278, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,delta_largest))))": 434, "opt(dictionary(hybrid(4,16),continued_fractions(binary)))": 241, "opt(dictionary(hybrid(4,16),continued_fractions(co_binary)))": 241, "opt(dictionary(hybrid(4,16),continued_fractions(dichotomic)))": 241, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,approximation))))": 241, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,delta_largest))))": 243, "opt(dictionary(hybrid(4,32),continued_fractions(binary)))": 235, "opt(dictionary(hybrid(4,32),continued_fractions(co_binary)))": 235, "opt(dictionary(hybrid(4,32),continued_fractions(dichotomic)))": 235, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,approximation))))": 235, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,delta_largest))))": 240, "opt(dictionary(hybrid(4,64),continued_fractions(binary)))": 235, "opt(dictionary(hybrid(4,64),continued_fractions(co_binary)))": 235, "opt(dictionary(hybrid(4,64),continued_fractions(dichotomic)))": 235, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,approximation))))": 235, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,delta_largest))))": 256, "opt(dictionary(hybrid(5,0),continued_fractions(binary)))": 330, "opt(dictionary(hybrid(5,0),continued_fractions(co_binary)))": 330, "opt(dictionary(hybrid(5,0),continued_fractions(dichotomic)))": 242, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,approximation))))": 278, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,delta_largest))))": 434, "opt(dictionary(hybrid(5,16),continued_fractions(binary)))": 241, "opt(dictionary(hybrid(5,16),continued_fractions(co_binary)))": 241, "opt(dictionary(hybrid(5,16),continued_fractions(dichotomic)))": 241, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,approximation))))": 241, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,delta_largest))))": 243, "opt(dictionary(hybrid(5,32),continued_fractions(binary)))": 235, "opt(dictionary(hybrid(5,32),continued_fractions(co_binary)))": 235, "opt(dictionary(hybrid(5,32),continued_fractions(dichotomic)))": 235, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,approximation))))": 235, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,delta_largest))))": 240, "opt(dictionary(hybrid(5,64),continued_fractions(binary)))": 235, "opt(dictionary(hybrid(5,64),continued_fractions(co_binary)))": 235, "opt(dictionary(hybrid(5,64),continued_fractions(dichotomic)))": 235, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,approximation))))": 235, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,delta_largest))))": 256, "opt(dictionary(hybrid(6,0),continued_fractions(binary)))": 330, "opt(dictionary(hybrid(6,0),continued_fractions(co_binary)))": 330, "opt(dictionary(hybrid(6,0),continued_fractions(dichotomic)))": 242, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,approximation))))": 278, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,delta_largest))))": 434, "opt(dictionary(hybrid(6,16),continued_fractions(binary)))": 241, "opt(dictionary(hybrid(6,16),continued_fractions(co_binary)))": 241, "opt(dictionary(hybrid(6,16),continued_fractions(dichotomic)))": 241, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,approximation))))": 241, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,delta_largest))))": 243, "opt(dictionary(hybrid(6,32),continued_fractions(binary)))": 235, "opt(dictionary(hybrid(6,32),continued_fractions(co_binary)))": 235, "opt(dictionary(hybrid(6,32),continued_fractions(dichotomic)))": 235, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,approximation))))": 235, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,delta_largest))))": 240, "opt(dictionary(hybrid(6,64),continued_fractions(binary)))": 235, "opt(dictionary(hybrid(6,64),continued_fractions(co_binary)))": 235, "opt(dictionary(hybrid(6,64),continued_fractions(dichotomic)))": 235, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,approximation))))": 235, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,delta_largest))))": 256, "opt(dictionary(hybrid(7,0),continued_fractions(binary)))": 330, "opt(dictionary(hybrid(7,0),continued_fractions(co_binary)))": 330, "opt(dictionary(hybrid(7,0),continued_fractions(dichotomic)))": 242, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,approximation))))": 278, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,delta_largest))))": 434, "opt(dictionary(hybrid(7,16),continued_fractions(binary)))": 241, "opt(dictionary(hybrid(7,16),continued_fractions(co_binary)))": 241, "opt(dictionary(hybrid(7,16),continued_fractions(dichotomic)))": 241, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,approximation))))": 241, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,delta_largest))))": 243, "opt(dictionary(hybrid(7,32),continued_fractions(binary)))": 235, "opt(dictionary(hybrid(7,32),continued_fractions(co_binary)))": 235, "opt(dictionary(hybrid(7,32),continued_fractions(dichotomic)))": 235, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,approximation))))": 235, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,delta_largest))))": 240, "opt(dictionary(hybrid(7,64),continued_fractions(binary)))": 235, "opt(dictionary(hybrid(7,64),continued_fractions(co_binary)))": 235, "opt(dictionary(hybrid(7,64),continued_fractions(dichotomic)))": 235, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,approximation))))": 235, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,delta_largest))))": 256, "opt(dictionary(hybrid(8,0),continued_fractions(binary)))": 330, "opt(dictionary(hybrid(8,0),continued_fractions(co_binary)))": 330, "opt(dictionary(hybrid(8,0),continued_fractions(dichotomic)))": 242, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,approximation))))": 278, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,delta_largest))))": 434, "opt(dictionary(hybrid(8,16),continued_fractions(binary)))": 241, "opt(dictionary(hybrid(8,16),continued_fractions(co_binary)))": 241, "opt(dictionary(hybrid(8,16),continued_fractions(dichotomic)))": 241, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,approximation))))": 241, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,delta_largest))))": 243, "opt(dictionary(hybrid(8,32),continued_fractions(binary)))": 235, "opt(dictionary(hybrid(8,32),continued_fractions(co_binary)))": 235, "opt(dictionary(hybrid(8,32),continued_fractions(dichotomic)))": 235, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,approximation))))": 235, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,delta_largest))))": 240, "opt(dictionary(hybrid(8,64),continued_fractions(binary)))": 235, "opt(dictionary(hybrid(8,64),continued_fractions(co_binary)))": 235, "opt(dictionary(hybrid(8,64),continued_fractions(dichotomic)))": 235, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,approximation))))": 235, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,delta_largest))))": 256, "opt(dictionary(run_length(0),continued_fractions(binary)))": 437, "opt(dictionary(run_length(0),continued_fractions(co_binary)))": 437, "opt(dictionary(run_length(0),continued_fractions(dichotomic)))": 235, "opt(dictionary(run_length(0),heuristic(use_first(halving,approximation))))": 331, "opt(dictionary(run_length(0),heuristic(use_first(halving,delta_largest))))": 435, "opt(dictionary(run_length(128),continued_fractions(binary)))": 239, "opt(dictionary(run_length(128),continued_fractions(co_binary)))": 239, "opt(dictionary(run_length(128),continued_fractions(dichotomic)))": 234, "opt(dictionary(run_length(128),heuristic(use_first(halving,approximation))))": 238, "opt(dictionary(run_length(128),heuristic(use_first(halving,delta_largest))))": 267, "opt(dictionary(run_length(16),continued_fractions(binary)))": 242, "opt(dictionary(run_length(16),continued_fractions(co_binary)))": 242, "opt(dictionary(run_length(16),continued_fractions(dichotomic)))": 242, "opt(dictionary(run_length(16),heuristic(use_first(halving,approximation))))": 242, "opt(dictionary(run_length(16),heuristic(use_first(halving,delta_largest))))": 244, "opt(dictionary(run_length(32),continued_fractions(binary)))": 237, "opt(dictionary(run_length(32),continued_fractions(co_binary)))": 237, "opt(dictionary(run_length(32),continued_fractions(dichotomic)))": 236, "opt(dictionary(run_length(32),heuristic(use_first(halving,approximation))))": 236, "opt(dictionary(run_length(32),heuristic(use_first(halving,delta_largest))))": 241, "opt(dictionary(run_length(64),continued_fractions(binary)))": 235, "opt(dictionary(run_length(64),continued_fractions(co_binary)))": 235, "opt(dictionary(run_length(64),continued_fractions(dichotomic)))": 235, "opt(dictionary(run_length(64),heuristic(use_first(halving,approximation))))": 235, "opt(dictionary(run_length(64),heuristic(use_first(halving,delta_largest))))": 256, "opt(dictionary(sliding_window(128),continued_fractions(binary)))": 270, "opt(dictionary(sliding_window(128),continued_fractions(co_binary)))": 270, "opt(dictionary(sliding_window(128),continued_fractions(dichotomic)))": 263, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,approximation))))": 239, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,delta_largest))))": 267, "opt(dictionary(sliding_window(16),continued_fractions(binary)))": 242, "opt(dictionary(sliding_window(16),continued_fractions(co_binary)))": 242, "opt(dictionary(sliding_window(16),continued_fractions(dichotomic)))": 242, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,approximation))))": 242, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,delta_largest))))": 242, "opt(dictionary(sliding_window(32),continued_fractions(binary)))": 245, "opt(dictionary(sliding_window(32),continued_fractions(co_binary)))": 245, "opt(dictionary(sliding_window(32),continued_fractions(dichotomic)))": 242, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,approximation))))": 239, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,delta_largest))))": 252, "opt(dictionary(sliding_window(4),continued_fractions(binary)))": 278, "opt(dictionary(sliding_window(4),continued_fractions(co_binary)))": 278, "opt(dictionary(sliding_window(4),continued_fractions(dichotomic)))": 278, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,approximation))))": 278, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,delta_largest))))": 278, "opt(dictionary(sliding_window(64),continued_fractions(binary)))": 244, "opt(dictionary(sliding_window(64),continued_fractions(co_binary)))": 244, "opt(dictionary(sliding_window(64),continued_fractions(dichotomic)))": 244, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,approximation))))": 238, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,delta_largest))))": 254, "opt(dictionary(sliding_window(8),continued_fractions(binary)))": 253, "opt(dictionary(sliding_window(8),continued_fractions(co_binary)))": 253, "opt(dictionary(sliding_window(8),continued_fractions(dichotomic)))": 253, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,approximation))))": 253, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,delta_largest))))": 253, "opt(runs(continued_fractions(binary)))": 235, "opt(runs(continued_fractions(co_binary)))": 235, "opt(runs(continued_fractions(dichotomic)))": 233, "opt(runs(heuristic(use_first(halving,approximation))))": 235, "opt(runs(heuristic(use_first(halving,delta_largest))))": 235 }addchain-0.4.0/alg/ensemble/testdata/p224_field.golden000066400000000000000000000353211514305256600224530ustar00rootroot00000000000000{ "opt(dictionary(hybrid(2,0),continued_fractions(binary)))": 240, "opt(dictionary(hybrid(2,0),continued_fractions(co_binary)))": 240, "opt(dictionary(hybrid(2,0),continued_fractions(dichotomic)))": 235, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,approximation))))": 240, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,delta_largest))))": 288, "opt(dictionary(hybrid(2,16),continued_fractions(binary)))": 251, "opt(dictionary(hybrid(2,16),continued_fractions(co_binary)))": 251, "opt(dictionary(hybrid(2,16),continued_fractions(dichotomic)))": 243, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,approximation))))": 245, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,delta_largest))))": 249, "opt(dictionary(hybrid(2,32),continued_fractions(binary)))": 260, "opt(dictionary(hybrid(2,32),continued_fractions(co_binary)))": 260, "opt(dictionary(hybrid(2,32),continued_fractions(dichotomic)))": 238, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,approximation))))": 246, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,delta_largest))))": 258, "opt(dictionary(hybrid(2,64),continued_fractions(binary)))": 259, "opt(dictionary(hybrid(2,64),continued_fractions(co_binary)))": 259, "opt(dictionary(hybrid(2,64),continued_fractions(dichotomic)))": 237, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,approximation))))": 245, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,delta_largest))))": 257, "opt(dictionary(hybrid(3,0),continued_fractions(binary)))": 240, "opt(dictionary(hybrid(3,0),continued_fractions(co_binary)))": 240, "opt(dictionary(hybrid(3,0),continued_fractions(dichotomic)))": 235, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,approximation))))": 240, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,delta_largest))))": 288, "opt(dictionary(hybrid(3,16),continued_fractions(binary)))": 251, "opt(dictionary(hybrid(3,16),continued_fractions(co_binary)))": 251, "opt(dictionary(hybrid(3,16),continued_fractions(dichotomic)))": 243, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,approximation))))": 245, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,delta_largest))))": 249, "opt(dictionary(hybrid(3,32),continued_fractions(binary)))": 260, "opt(dictionary(hybrid(3,32),continued_fractions(co_binary)))": 260, "opt(dictionary(hybrid(3,32),continued_fractions(dichotomic)))": 238, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,approximation))))": 246, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,delta_largest))))": 258, "opt(dictionary(hybrid(3,64),continued_fractions(binary)))": 259, "opt(dictionary(hybrid(3,64),continued_fractions(co_binary)))": 259, "opt(dictionary(hybrid(3,64),continued_fractions(dichotomic)))": 237, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,approximation))))": 245, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,delta_largest))))": 257, "opt(dictionary(hybrid(4,0),continued_fractions(binary)))": 240, "opt(dictionary(hybrid(4,0),continued_fractions(co_binary)))": 240, "opt(dictionary(hybrid(4,0),continued_fractions(dichotomic)))": 235, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,approximation))))": 240, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,delta_largest))))": 288, "opt(dictionary(hybrid(4,16),continued_fractions(binary)))": 251, "opt(dictionary(hybrid(4,16),continued_fractions(co_binary)))": 251, "opt(dictionary(hybrid(4,16),continued_fractions(dichotomic)))": 243, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,approximation))))": 245, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,delta_largest))))": 249, "opt(dictionary(hybrid(4,32),continued_fractions(binary)))": 260, "opt(dictionary(hybrid(4,32),continued_fractions(co_binary)))": 260, "opt(dictionary(hybrid(4,32),continued_fractions(dichotomic)))": 238, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,approximation))))": 246, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,delta_largest))))": 258, "opt(dictionary(hybrid(4,64),continued_fractions(binary)))": 259, "opt(dictionary(hybrid(4,64),continued_fractions(co_binary)))": 259, "opt(dictionary(hybrid(4,64),continued_fractions(dichotomic)))": 237, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,approximation))))": 245, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,delta_largest))))": 257, "opt(dictionary(hybrid(5,0),continued_fractions(binary)))": 240, "opt(dictionary(hybrid(5,0),continued_fractions(co_binary)))": 240, "opt(dictionary(hybrid(5,0),continued_fractions(dichotomic)))": 235, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,approximation))))": 240, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,delta_largest))))": 288, "opt(dictionary(hybrid(5,16),continued_fractions(binary)))": 251, "opt(dictionary(hybrid(5,16),continued_fractions(co_binary)))": 251, "opt(dictionary(hybrid(5,16),continued_fractions(dichotomic)))": 243, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,approximation))))": 245, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,delta_largest))))": 249, "opt(dictionary(hybrid(5,32),continued_fractions(binary)))": 260, "opt(dictionary(hybrid(5,32),continued_fractions(co_binary)))": 260, "opt(dictionary(hybrid(5,32),continued_fractions(dichotomic)))": 238, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,approximation))))": 246, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,delta_largest))))": 258, "opt(dictionary(hybrid(5,64),continued_fractions(binary)))": 259, "opt(dictionary(hybrid(5,64),continued_fractions(co_binary)))": 259, "opt(dictionary(hybrid(5,64),continued_fractions(dichotomic)))": 237, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,approximation))))": 245, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,delta_largest))))": 257, "opt(dictionary(hybrid(6,0),continued_fractions(binary)))": 240, "opt(dictionary(hybrid(6,0),continued_fractions(co_binary)))": 240, "opt(dictionary(hybrid(6,0),continued_fractions(dichotomic)))": 235, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,approximation))))": 240, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,delta_largest))))": 288, "opt(dictionary(hybrid(6,16),continued_fractions(binary)))": 251, "opt(dictionary(hybrid(6,16),continued_fractions(co_binary)))": 251, "opt(dictionary(hybrid(6,16),continued_fractions(dichotomic)))": 243, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,approximation))))": 245, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,delta_largest))))": 249, "opt(dictionary(hybrid(6,32),continued_fractions(binary)))": 260, "opt(dictionary(hybrid(6,32),continued_fractions(co_binary)))": 260, "opt(dictionary(hybrid(6,32),continued_fractions(dichotomic)))": 238, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,approximation))))": 246, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,delta_largest))))": 258, "opt(dictionary(hybrid(6,64),continued_fractions(binary)))": 259, "opt(dictionary(hybrid(6,64),continued_fractions(co_binary)))": 259, "opt(dictionary(hybrid(6,64),continued_fractions(dichotomic)))": 237, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,approximation))))": 245, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,delta_largest))))": 257, "opt(dictionary(hybrid(7,0),continued_fractions(binary)))": 240, "opt(dictionary(hybrid(7,0),continued_fractions(co_binary)))": 240, "opt(dictionary(hybrid(7,0),continued_fractions(dichotomic)))": 235, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,approximation))))": 240, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,delta_largest))))": 288, "opt(dictionary(hybrid(7,16),continued_fractions(binary)))": 251, "opt(dictionary(hybrid(7,16),continued_fractions(co_binary)))": 251, "opt(dictionary(hybrid(7,16),continued_fractions(dichotomic)))": 243, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,approximation))))": 245, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,delta_largest))))": 249, "opt(dictionary(hybrid(7,32),continued_fractions(binary)))": 260, "opt(dictionary(hybrid(7,32),continued_fractions(co_binary)))": 260, "opt(dictionary(hybrid(7,32),continued_fractions(dichotomic)))": 238, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,approximation))))": 246, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,delta_largest))))": 258, "opt(dictionary(hybrid(7,64),continued_fractions(binary)))": 259, "opt(dictionary(hybrid(7,64),continued_fractions(co_binary)))": 259, "opt(dictionary(hybrid(7,64),continued_fractions(dichotomic)))": 237, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,approximation))))": 245, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,delta_largest))))": 257, "opt(dictionary(hybrid(8,0),continued_fractions(binary)))": 240, "opt(dictionary(hybrid(8,0),continued_fractions(co_binary)))": 240, "opt(dictionary(hybrid(8,0),continued_fractions(dichotomic)))": 235, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,approximation))))": 240, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,delta_largest))))": 288, "opt(dictionary(hybrid(8,16),continued_fractions(binary)))": 251, "opt(dictionary(hybrid(8,16),continued_fractions(co_binary)))": 251, "opt(dictionary(hybrid(8,16),continued_fractions(dichotomic)))": 243, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,approximation))))": 245, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,delta_largest))))": 249, "opt(dictionary(hybrid(8,32),continued_fractions(binary)))": 260, "opt(dictionary(hybrid(8,32),continued_fractions(co_binary)))": 260, "opt(dictionary(hybrid(8,32),continued_fractions(dichotomic)))": 238, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,approximation))))": 246, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,delta_largest))))": 258, "opt(dictionary(hybrid(8,64),continued_fractions(binary)))": 259, "opt(dictionary(hybrid(8,64),continued_fractions(co_binary)))": 259, "opt(dictionary(hybrid(8,64),continued_fractions(dichotomic)))": 237, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,approximation))))": 245, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,delta_largest))))": 257, "opt(dictionary(run_length(0),continued_fractions(binary)))": 240, "opt(dictionary(run_length(0),continued_fractions(co_binary)))": 240, "opt(dictionary(run_length(0),continued_fractions(dichotomic)))": 235, "opt(dictionary(run_length(0),heuristic(use_first(halving,approximation))))": 240, "opt(dictionary(run_length(0),heuristic(use_first(halving,delta_largest))))": 288, "opt(dictionary(run_length(128),continued_fractions(binary)))": 240, "opt(dictionary(run_length(128),continued_fractions(co_binary)))": 240, "opt(dictionary(run_length(128),continued_fractions(dichotomic)))": 235, "opt(dictionary(run_length(128),heuristic(use_first(halving,approximation))))": 240, "opt(dictionary(run_length(128),heuristic(use_first(halving,delta_largest))))": 288, "opt(dictionary(run_length(16),continued_fractions(binary)))": 251, "opt(dictionary(run_length(16),continued_fractions(co_binary)))": 251, "opt(dictionary(run_length(16),continued_fractions(dichotomic)))": 243, "opt(dictionary(run_length(16),heuristic(use_first(halving,approximation))))": 245, "opt(dictionary(run_length(16),heuristic(use_first(halving,delta_largest))))": 249, "opt(dictionary(run_length(32),continued_fractions(binary)))": 260, "opt(dictionary(run_length(32),continued_fractions(co_binary)))": 260, "opt(dictionary(run_length(32),continued_fractions(dichotomic)))": 238, "opt(dictionary(run_length(32),heuristic(use_first(halving,approximation))))": 246, "opt(dictionary(run_length(32),heuristic(use_first(halving,delta_largest))))": 258, "opt(dictionary(run_length(64),continued_fractions(binary)))": 259, "opt(dictionary(run_length(64),continued_fractions(co_binary)))": 259, "opt(dictionary(run_length(64),continued_fractions(dichotomic)))": 237, "opt(dictionary(run_length(64),heuristic(use_first(halving,approximation))))": 245, "opt(dictionary(run_length(64),heuristic(use_first(halving,delta_largest))))": 257, "opt(dictionary(sliding_window(128),continued_fractions(binary)))": 240, "opt(dictionary(sliding_window(128),continued_fractions(co_binary)))": 240, "opt(dictionary(sliding_window(128),continued_fractions(dichotomic)))": 235, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,approximation))))": 240, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,delta_largest))))": 288, "opt(dictionary(sliding_window(16),continued_fractions(binary)))": 251, "opt(dictionary(sliding_window(16),continued_fractions(co_binary)))": 251, "opt(dictionary(sliding_window(16),continued_fractions(dichotomic)))": 243, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,approximation))))": 245, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,delta_largest))))": 249, "opt(dictionary(sliding_window(32),continued_fractions(binary)))": 260, "opt(dictionary(sliding_window(32),continued_fractions(co_binary)))": 260, "opt(dictionary(sliding_window(32),continued_fractions(dichotomic)))": 238, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,approximation))))": 246, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,delta_largest))))": 258, "opt(dictionary(sliding_window(4),continued_fractions(binary)))": 281, "opt(dictionary(sliding_window(4),continued_fractions(co_binary)))": 281, "opt(dictionary(sliding_window(4),continued_fractions(dichotomic)))": 281, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,approximation))))": 281, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,delta_largest))))": 281, "opt(dictionary(sliding_window(64),continued_fractions(binary)))": 259, "opt(dictionary(sliding_window(64),continued_fractions(co_binary)))": 259, "opt(dictionary(sliding_window(64),continued_fractions(dichotomic)))": 237, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,approximation))))": 245, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,delta_largest))))": 257, "opt(dictionary(sliding_window(8),continued_fractions(binary)))": 257, "opt(dictionary(sliding_window(8),continued_fractions(co_binary)))": 257, "opt(dictionary(sliding_window(8),continued_fractions(dichotomic)))": 255, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,approximation))))": 255, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,delta_largest))))": 255, "opt(runs(continued_fractions(binary)))": 235, "opt(runs(continued_fractions(co_binary)))": 235, "opt(runs(continued_fractions(dichotomic)))": 235, "opt(runs(heuristic(use_first(halving,approximation))))": 234, "opt(runs(heuristic(use_first(halving,delta_largest))))": 234 }addchain-0.4.0/alg/ensemble/testdata/p2519_field.golden000066400000000000000000000353211514305256600225440ustar00rootroot00000000000000{ "opt(dictionary(hybrid(2,0),continued_fractions(binary)))": 498, "opt(dictionary(hybrid(2,0),continued_fractions(co_binary)))": 498, "opt(dictionary(hybrid(2,0),continued_fractions(dichotomic)))": 265, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,approximation))))": 376, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,delta_largest))))": 496, "opt(dictionary(hybrid(2,16),continued_fractions(binary)))": 273, "opt(dictionary(hybrid(2,16),continued_fractions(co_binary)))": 273, "opt(dictionary(hybrid(2,16),continued_fractions(dichotomic)))": 273, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,approximation))))": 273, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,delta_largest))))": 275, "opt(dictionary(hybrid(2,32),continued_fractions(binary)))": 267, "opt(dictionary(hybrid(2,32),continued_fractions(co_binary)))": 267, "opt(dictionary(hybrid(2,32),continued_fractions(dichotomic)))": 266, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,approximation))))": 266, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,delta_largest))))": 271, "opt(dictionary(hybrid(2,64),continued_fractions(binary)))": 270, "opt(dictionary(hybrid(2,64),continued_fractions(co_binary)))": 270, "opt(dictionary(hybrid(2,64),continued_fractions(dichotomic)))": 264, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,approximation))))": 267, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,delta_largest))))": 298, "opt(dictionary(hybrid(3,0),continued_fractions(binary)))": 375, "opt(dictionary(hybrid(3,0),continued_fractions(co_binary)))": 375, "opt(dictionary(hybrid(3,0),continued_fractions(dichotomic)))": 264, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,approximation))))": 335, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,delta_largest))))": 495, "opt(dictionary(hybrid(3,16),continued_fractions(binary)))": 272, "opt(dictionary(hybrid(3,16),continued_fractions(co_binary)))": 272, "opt(dictionary(hybrid(3,16),continued_fractions(dichotomic)))": 272, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,approximation))))": 272, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,delta_largest))))": 274, "opt(dictionary(hybrid(3,32),continued_fractions(binary)))": 265, "opt(dictionary(hybrid(3,32),continued_fractions(co_binary)))": 265, "opt(dictionary(hybrid(3,32),continued_fractions(dichotomic)))": 265, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,approximation))))": 266, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,delta_largest))))": 270, "opt(dictionary(hybrid(3,64),continued_fractions(binary)))": 266, "opt(dictionary(hybrid(3,64),continued_fractions(co_binary)))": 266, "opt(dictionary(hybrid(3,64),continued_fractions(dichotomic)))": 263, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,approximation))))": 265, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,delta_largest))))": 299, "opt(dictionary(hybrid(4,0),continued_fractions(binary)))": 375, "opt(dictionary(hybrid(4,0),continued_fractions(co_binary)))": 375, "opt(dictionary(hybrid(4,0),continued_fractions(dichotomic)))": 264, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,approximation))))": 335, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,delta_largest))))": 495, "opt(dictionary(hybrid(4,16),continued_fractions(binary)))": 272, "opt(dictionary(hybrid(4,16),continued_fractions(co_binary)))": 272, "opt(dictionary(hybrid(4,16),continued_fractions(dichotomic)))": 272, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,approximation))))": 272, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,delta_largest))))": 274, "opt(dictionary(hybrid(4,32),continued_fractions(binary)))": 265, "opt(dictionary(hybrid(4,32),continued_fractions(co_binary)))": 265, "opt(dictionary(hybrid(4,32),continued_fractions(dichotomic)))": 265, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,approximation))))": 266, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,delta_largest))))": 270, "opt(dictionary(hybrid(4,64),continued_fractions(binary)))": 266, "opt(dictionary(hybrid(4,64),continued_fractions(co_binary)))": 266, "opt(dictionary(hybrid(4,64),continued_fractions(dichotomic)))": 263, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,approximation))))": 265, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,delta_largest))))": 299, "opt(dictionary(hybrid(5,0),continued_fractions(binary)))": 375, "opt(dictionary(hybrid(5,0),continued_fractions(co_binary)))": 375, "opt(dictionary(hybrid(5,0),continued_fractions(dichotomic)))": 264, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,approximation))))": 335, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,delta_largest))))": 495, "opt(dictionary(hybrid(5,16),continued_fractions(binary)))": 272, "opt(dictionary(hybrid(5,16),continued_fractions(co_binary)))": 272, "opt(dictionary(hybrid(5,16),continued_fractions(dichotomic)))": 272, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,approximation))))": 272, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,delta_largest))))": 274, "opt(dictionary(hybrid(5,32),continued_fractions(binary)))": 265, "opt(dictionary(hybrid(5,32),continued_fractions(co_binary)))": 265, "opt(dictionary(hybrid(5,32),continued_fractions(dichotomic)))": 265, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,approximation))))": 266, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,delta_largest))))": 270, "opt(dictionary(hybrid(5,64),continued_fractions(binary)))": 266, "opt(dictionary(hybrid(5,64),continued_fractions(co_binary)))": 266, "opt(dictionary(hybrid(5,64),continued_fractions(dichotomic)))": 263, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,approximation))))": 265, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,delta_largest))))": 299, "opt(dictionary(hybrid(6,0),continued_fractions(binary)))": 375, "opt(dictionary(hybrid(6,0),continued_fractions(co_binary)))": 375, "opt(dictionary(hybrid(6,0),continued_fractions(dichotomic)))": 264, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,approximation))))": 335, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,delta_largest))))": 495, "opt(dictionary(hybrid(6,16),continued_fractions(binary)))": 272, "opt(dictionary(hybrid(6,16),continued_fractions(co_binary)))": 272, "opt(dictionary(hybrid(6,16),continued_fractions(dichotomic)))": 272, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,approximation))))": 272, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,delta_largest))))": 274, "opt(dictionary(hybrid(6,32),continued_fractions(binary)))": 265, "opt(dictionary(hybrid(6,32),continued_fractions(co_binary)))": 265, "opt(dictionary(hybrid(6,32),continued_fractions(dichotomic)))": 265, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,approximation))))": 266, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,delta_largest))))": 270, "opt(dictionary(hybrid(6,64),continued_fractions(binary)))": 266, "opt(dictionary(hybrid(6,64),continued_fractions(co_binary)))": 266, "opt(dictionary(hybrid(6,64),continued_fractions(dichotomic)))": 263, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,approximation))))": 265, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,delta_largest))))": 299, "opt(dictionary(hybrid(7,0),continued_fractions(binary)))": 375, "opt(dictionary(hybrid(7,0),continued_fractions(co_binary)))": 375, "opt(dictionary(hybrid(7,0),continued_fractions(dichotomic)))": 264, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,approximation))))": 335, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,delta_largest))))": 495, "opt(dictionary(hybrid(7,16),continued_fractions(binary)))": 272, "opt(dictionary(hybrid(7,16),continued_fractions(co_binary)))": 272, "opt(dictionary(hybrid(7,16),continued_fractions(dichotomic)))": 272, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,approximation))))": 272, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,delta_largest))))": 274, "opt(dictionary(hybrid(7,32),continued_fractions(binary)))": 265, "opt(dictionary(hybrid(7,32),continued_fractions(co_binary)))": 265, "opt(dictionary(hybrid(7,32),continued_fractions(dichotomic)))": 265, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,approximation))))": 266, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,delta_largest))))": 270, "opt(dictionary(hybrid(7,64),continued_fractions(binary)))": 266, "opt(dictionary(hybrid(7,64),continued_fractions(co_binary)))": 266, "opt(dictionary(hybrid(7,64),continued_fractions(dichotomic)))": 263, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,approximation))))": 265, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,delta_largest))))": 299, "opt(dictionary(hybrid(8,0),continued_fractions(binary)))": 375, "opt(dictionary(hybrid(8,0),continued_fractions(co_binary)))": 375, "opt(dictionary(hybrid(8,0),continued_fractions(dichotomic)))": 264, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,approximation))))": 335, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,delta_largest))))": 495, "opt(dictionary(hybrid(8,16),continued_fractions(binary)))": 272, "opt(dictionary(hybrid(8,16),continued_fractions(co_binary)))": 272, "opt(dictionary(hybrid(8,16),continued_fractions(dichotomic)))": 272, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,approximation))))": 272, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,delta_largest))))": 274, "opt(dictionary(hybrid(8,32),continued_fractions(binary)))": 265, "opt(dictionary(hybrid(8,32),continued_fractions(co_binary)))": 265, "opt(dictionary(hybrid(8,32),continued_fractions(dichotomic)))": 265, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,approximation))))": 266, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,delta_largest))))": 270, "opt(dictionary(hybrid(8,64),continued_fractions(binary)))": 266, "opt(dictionary(hybrid(8,64),continued_fractions(co_binary)))": 266, "opt(dictionary(hybrid(8,64),continued_fractions(dichotomic)))": 263, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,approximation))))": 265, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,delta_largest))))": 299, "opt(dictionary(run_length(0),continued_fractions(binary)))": 498, "opt(dictionary(run_length(0),continued_fractions(co_binary)))": 498, "opt(dictionary(run_length(0),continued_fractions(dichotomic)))": 265, "opt(dictionary(run_length(0),heuristic(use_first(halving,approximation))))": 376, "opt(dictionary(run_length(0),heuristic(use_first(halving,delta_largest))))": 496, "opt(dictionary(run_length(128),continued_fractions(binary)))": 272, "opt(dictionary(run_length(128),continued_fractions(co_binary)))": 272, "opt(dictionary(run_length(128),continued_fractions(dichotomic)))": 264, "opt(dictionary(run_length(128),heuristic(use_first(halving,approximation))))": 272, "opt(dictionary(run_length(128),heuristic(use_first(halving,delta_largest))))": 361, "opt(dictionary(run_length(16),continued_fractions(binary)))": 273, "opt(dictionary(run_length(16),continued_fractions(co_binary)))": 273, "opt(dictionary(run_length(16),continued_fractions(dichotomic)))": 273, "opt(dictionary(run_length(16),heuristic(use_first(halving,approximation))))": 273, "opt(dictionary(run_length(16),heuristic(use_first(halving,delta_largest))))": 275, "opt(dictionary(run_length(32),continued_fractions(binary)))": 267, "opt(dictionary(run_length(32),continued_fractions(co_binary)))": 267, "opt(dictionary(run_length(32),continued_fractions(dichotomic)))": 266, "opt(dictionary(run_length(32),heuristic(use_first(halving,approximation))))": 266, "opt(dictionary(run_length(32),heuristic(use_first(halving,delta_largest))))": 271, "opt(dictionary(run_length(64),continued_fractions(binary)))": 270, "opt(dictionary(run_length(64),continued_fractions(co_binary)))": 270, "opt(dictionary(run_length(64),continued_fractions(dichotomic)))": 264, "opt(dictionary(run_length(64),heuristic(use_first(halving,approximation))))": 267, "opt(dictionary(run_length(64),heuristic(use_first(halving,delta_largest))))": 298, "opt(dictionary(sliding_window(128),continued_fractions(binary)))": 306, "opt(dictionary(sliding_window(128),continued_fractions(co_binary)))": 306, "opt(dictionary(sliding_window(128),continued_fractions(dichotomic)))": 283, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,approximation))))": 283, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,delta_largest))))": 371, "opt(dictionary(sliding_window(16),continued_fractions(binary)))": 273, "opt(dictionary(sliding_window(16),continued_fractions(co_binary)))": 273, "opt(dictionary(sliding_window(16),continued_fractions(dichotomic)))": 273, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,approximation))))": 273, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,delta_largest))))": 273, "opt(dictionary(sliding_window(32),continued_fractions(binary)))": 273, "opt(dictionary(sliding_window(32),continued_fractions(co_binary)))": 273, "opt(dictionary(sliding_window(32),continued_fractions(dichotomic)))": 269, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,approximation))))": 269, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,delta_largest))))": 281, "opt(dictionary(sliding_window(4),continued_fractions(binary)))": 315, "opt(dictionary(sliding_window(4),continued_fractions(co_binary)))": 315, "opt(dictionary(sliding_window(4),continued_fractions(dichotomic)))": 315, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,approximation))))": 315, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,delta_largest))))": 315, "opt(dictionary(sliding_window(64),continued_fractions(binary)))": 284, "opt(dictionary(sliding_window(64),continued_fractions(co_binary)))": 284, "opt(dictionary(sliding_window(64),continued_fractions(dichotomic)))": 272, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,approximation))))": 269, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,delta_largest))))": 307, "opt(dictionary(sliding_window(8),continued_fractions(binary)))": 286, "opt(dictionary(sliding_window(8),continued_fractions(co_binary)))": 286, "opt(dictionary(sliding_window(8),continued_fractions(dichotomic)))": 286, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,approximation))))": 286, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,delta_largest))))": 287, "opt(runs(continued_fractions(binary)))": 265, "opt(runs(continued_fractions(co_binary)))": 265, "opt(runs(continued_fractions(dichotomic)))": 263, "opt(runs(heuristic(use_first(halving,approximation))))": 263, "opt(runs(heuristic(use_first(halving,delta_largest))))": 266 }addchain-0.4.0/alg/ensemble/testdata/p256_field.golden000066400000000000000000000353211514305256600224600ustar00rootroot00000000000000{ "opt(dictionary(hybrid(2,0),continued_fractions(binary)))": 275, "opt(dictionary(hybrid(2,0),continued_fractions(co_binary)))": 275, "opt(dictionary(hybrid(2,0),continued_fractions(dichotomic)))": 267, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,approximation))))": 275, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,delta_largest))))": 314, "opt(dictionary(hybrid(2,16),continued_fractions(binary)))": 271, "opt(dictionary(hybrid(2,16),continued_fractions(co_binary)))": 271, "opt(dictionary(hybrid(2,16),continued_fractions(dichotomic)))": 269, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,approximation))))": 271, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,delta_largest))))": 274, "opt(dictionary(hybrid(2,32),continued_fractions(binary)))": 275, "opt(dictionary(hybrid(2,32),continued_fractions(co_binary)))": 275, "opt(dictionary(hybrid(2,32),continued_fractions(dichotomic)))": 267, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,approximation))))": 275, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,delta_largest))))": 286, "opt(dictionary(hybrid(2,64),continued_fractions(binary)))": 275, "opt(dictionary(hybrid(2,64),continued_fractions(co_binary)))": 275, "opt(dictionary(hybrid(2,64),continued_fractions(dichotomic)))": 267, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,approximation))))": 275, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,delta_largest))))": 286, "opt(dictionary(hybrid(3,0),continued_fractions(binary)))": 275, "opt(dictionary(hybrid(3,0),continued_fractions(co_binary)))": 275, "opt(dictionary(hybrid(3,0),continued_fractions(dichotomic)))": 267, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,approximation))))": 275, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,delta_largest))))": 314, "opt(dictionary(hybrid(3,16),continued_fractions(binary)))": 271, "opt(dictionary(hybrid(3,16),continued_fractions(co_binary)))": 271, "opt(dictionary(hybrid(3,16),continued_fractions(dichotomic)))": 269, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,approximation))))": 271, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,delta_largest))))": 274, "opt(dictionary(hybrid(3,32),continued_fractions(binary)))": 275, "opt(dictionary(hybrid(3,32),continued_fractions(co_binary)))": 275, "opt(dictionary(hybrid(3,32),continued_fractions(dichotomic)))": 267, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,approximation))))": 275, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,delta_largest))))": 286, "opt(dictionary(hybrid(3,64),continued_fractions(binary)))": 275, "opt(dictionary(hybrid(3,64),continued_fractions(co_binary)))": 275, "opt(dictionary(hybrid(3,64),continued_fractions(dichotomic)))": 267, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,approximation))))": 275, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,delta_largest))))": 286, "opt(dictionary(hybrid(4,0),continued_fractions(binary)))": 275, "opt(dictionary(hybrid(4,0),continued_fractions(co_binary)))": 275, "opt(dictionary(hybrid(4,0),continued_fractions(dichotomic)))": 267, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,approximation))))": 275, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,delta_largest))))": 314, "opt(dictionary(hybrid(4,16),continued_fractions(binary)))": 271, "opt(dictionary(hybrid(4,16),continued_fractions(co_binary)))": 271, "opt(dictionary(hybrid(4,16),continued_fractions(dichotomic)))": 269, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,approximation))))": 271, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,delta_largest))))": 274, "opt(dictionary(hybrid(4,32),continued_fractions(binary)))": 275, "opt(dictionary(hybrid(4,32),continued_fractions(co_binary)))": 275, "opt(dictionary(hybrid(4,32),continued_fractions(dichotomic)))": 267, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,approximation))))": 275, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,delta_largest))))": 286, "opt(dictionary(hybrid(4,64),continued_fractions(binary)))": 275, "opt(dictionary(hybrid(4,64),continued_fractions(co_binary)))": 275, "opt(dictionary(hybrid(4,64),continued_fractions(dichotomic)))": 267, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,approximation))))": 275, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,delta_largest))))": 286, "opt(dictionary(hybrid(5,0),continued_fractions(binary)))": 275, "opt(dictionary(hybrid(5,0),continued_fractions(co_binary)))": 275, "opt(dictionary(hybrid(5,0),continued_fractions(dichotomic)))": 267, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,approximation))))": 275, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,delta_largest))))": 314, "opt(dictionary(hybrid(5,16),continued_fractions(binary)))": 271, "opt(dictionary(hybrid(5,16),continued_fractions(co_binary)))": 271, "opt(dictionary(hybrid(5,16),continued_fractions(dichotomic)))": 269, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,approximation))))": 271, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,delta_largest))))": 274, "opt(dictionary(hybrid(5,32),continued_fractions(binary)))": 275, "opt(dictionary(hybrid(5,32),continued_fractions(co_binary)))": 275, "opt(dictionary(hybrid(5,32),continued_fractions(dichotomic)))": 267, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,approximation))))": 275, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,delta_largest))))": 286, "opt(dictionary(hybrid(5,64),continued_fractions(binary)))": 275, "opt(dictionary(hybrid(5,64),continued_fractions(co_binary)))": 275, "opt(dictionary(hybrid(5,64),continued_fractions(dichotomic)))": 267, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,approximation))))": 275, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,delta_largest))))": 286, "opt(dictionary(hybrid(6,0),continued_fractions(binary)))": 275, "opt(dictionary(hybrid(6,0),continued_fractions(co_binary)))": 275, "opt(dictionary(hybrid(6,0),continued_fractions(dichotomic)))": 267, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,approximation))))": 275, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,delta_largest))))": 314, "opt(dictionary(hybrid(6,16),continued_fractions(binary)))": 271, "opt(dictionary(hybrid(6,16),continued_fractions(co_binary)))": 271, "opt(dictionary(hybrid(6,16),continued_fractions(dichotomic)))": 269, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,approximation))))": 271, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,delta_largest))))": 274, "opt(dictionary(hybrid(6,32),continued_fractions(binary)))": 275, "opt(dictionary(hybrid(6,32),continued_fractions(co_binary)))": 275, "opt(dictionary(hybrid(6,32),continued_fractions(dichotomic)))": 267, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,approximation))))": 275, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,delta_largest))))": 286, "opt(dictionary(hybrid(6,64),continued_fractions(binary)))": 275, "opt(dictionary(hybrid(6,64),continued_fractions(co_binary)))": 275, "opt(dictionary(hybrid(6,64),continued_fractions(dichotomic)))": 267, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,approximation))))": 275, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,delta_largest))))": 286, "opt(dictionary(hybrid(7,0),continued_fractions(binary)))": 275, "opt(dictionary(hybrid(7,0),continued_fractions(co_binary)))": 275, "opt(dictionary(hybrid(7,0),continued_fractions(dichotomic)))": 267, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,approximation))))": 275, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,delta_largest))))": 314, "opt(dictionary(hybrid(7,16),continued_fractions(binary)))": 271, "opt(dictionary(hybrid(7,16),continued_fractions(co_binary)))": 271, "opt(dictionary(hybrid(7,16),continued_fractions(dichotomic)))": 269, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,approximation))))": 271, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,delta_largest))))": 274, "opt(dictionary(hybrid(7,32),continued_fractions(binary)))": 275, "opt(dictionary(hybrid(7,32),continued_fractions(co_binary)))": 275, "opt(dictionary(hybrid(7,32),continued_fractions(dichotomic)))": 267, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,approximation))))": 275, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,delta_largest))))": 286, "opt(dictionary(hybrid(7,64),continued_fractions(binary)))": 275, "opt(dictionary(hybrid(7,64),continued_fractions(co_binary)))": 275, "opt(dictionary(hybrid(7,64),continued_fractions(dichotomic)))": 267, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,approximation))))": 275, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,delta_largest))))": 286, "opt(dictionary(hybrid(8,0),continued_fractions(binary)))": 275, "opt(dictionary(hybrid(8,0),continued_fractions(co_binary)))": 275, "opt(dictionary(hybrid(8,0),continued_fractions(dichotomic)))": 267, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,approximation))))": 275, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,delta_largest))))": 314, "opt(dictionary(hybrid(8,16),continued_fractions(binary)))": 271, "opt(dictionary(hybrid(8,16),continued_fractions(co_binary)))": 271, "opt(dictionary(hybrid(8,16),continued_fractions(dichotomic)))": 269, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,approximation))))": 271, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,delta_largest))))": 274, "opt(dictionary(hybrid(8,32),continued_fractions(binary)))": 275, "opt(dictionary(hybrid(8,32),continued_fractions(co_binary)))": 275, "opt(dictionary(hybrid(8,32),continued_fractions(dichotomic)))": 267, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,approximation))))": 275, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,delta_largest))))": 286, "opt(dictionary(hybrid(8,64),continued_fractions(binary)))": 275, "opt(dictionary(hybrid(8,64),continued_fractions(co_binary)))": 275, "opt(dictionary(hybrid(8,64),continued_fractions(dichotomic)))": 267, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,approximation))))": 275, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,delta_largest))))": 286, "opt(dictionary(run_length(0),continued_fractions(binary)))": 275, "opt(dictionary(run_length(0),continued_fractions(co_binary)))": 275, "opt(dictionary(run_length(0),continued_fractions(dichotomic)))": 267, "opt(dictionary(run_length(0),heuristic(use_first(halving,approximation))))": 275, "opt(dictionary(run_length(0),heuristic(use_first(halving,delta_largest))))": 314, "opt(dictionary(run_length(128),continued_fractions(binary)))": 275, "opt(dictionary(run_length(128),continued_fractions(co_binary)))": 275, "opt(dictionary(run_length(128),continued_fractions(dichotomic)))": 267, "opt(dictionary(run_length(128),heuristic(use_first(halving,approximation))))": 275, "opt(dictionary(run_length(128),heuristic(use_first(halving,delta_largest))))": 314, "opt(dictionary(run_length(16),continued_fractions(binary)))": 271, "opt(dictionary(run_length(16),continued_fractions(co_binary)))": 271, "opt(dictionary(run_length(16),continued_fractions(dichotomic)))": 269, "opt(dictionary(run_length(16),heuristic(use_first(halving,approximation))))": 271, "opt(dictionary(run_length(16),heuristic(use_first(halving,delta_largest))))": 274, "opt(dictionary(run_length(32),continued_fractions(binary)))": 275, "opt(dictionary(run_length(32),continued_fractions(co_binary)))": 275, "opt(dictionary(run_length(32),continued_fractions(dichotomic)))": 267, "opt(dictionary(run_length(32),heuristic(use_first(halving,approximation))))": 275, "opt(dictionary(run_length(32),heuristic(use_first(halving,delta_largest))))": 286, "opt(dictionary(run_length(64),continued_fractions(binary)))": 275, "opt(dictionary(run_length(64),continued_fractions(co_binary)))": 275, "opt(dictionary(run_length(64),continued_fractions(dichotomic)))": 267, "opt(dictionary(run_length(64),heuristic(use_first(halving,approximation))))": 275, "opt(dictionary(run_length(64),heuristic(use_first(halving,delta_largest))))": 286, "opt(dictionary(sliding_window(128),continued_fractions(binary)))": 304, "opt(dictionary(sliding_window(128),continued_fractions(co_binary)))": 304, "opt(dictionary(sliding_window(128),continued_fractions(dichotomic)))": 272, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,approximation))))": 276, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,delta_largest))))": 287, "opt(dictionary(sliding_window(16),continued_fractions(binary)))": 271, "opt(dictionary(sliding_window(16),continued_fractions(co_binary)))": 271, "opt(dictionary(sliding_window(16),continued_fractions(dichotomic)))": 269, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,approximation))))": 271, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,delta_largest))))": 274, "opt(dictionary(sliding_window(32),continued_fractions(binary)))": 275, "opt(dictionary(sliding_window(32),continued_fractions(co_binary)))": 275, "opt(dictionary(sliding_window(32),continued_fractions(dichotomic)))": 267, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,approximation))))": 275, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,delta_largest))))": 286, "opt(dictionary(sliding_window(4),continued_fractions(binary)))": 289, "opt(dictionary(sliding_window(4),continued_fractions(co_binary)))": 289, "opt(dictionary(sliding_window(4),continued_fractions(dichotomic)))": 289, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,approximation))))": 289, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,delta_largest))))": 289, "opt(dictionary(sliding_window(64),continued_fractions(binary)))": 276, "opt(dictionary(sliding_window(64),continued_fractions(co_binary)))": 276, "opt(dictionary(sliding_window(64),continued_fractions(dichotomic)))": 268, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,approximation))))": 276, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,delta_largest))))": 287, "opt(dictionary(sliding_window(8),continued_fractions(binary)))": 275, "opt(dictionary(sliding_window(8),continued_fractions(co_binary)))": 275, "opt(dictionary(sliding_window(8),continued_fractions(dichotomic)))": 275, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,approximation))))": 275, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,delta_largest))))": 275, "opt(runs(continued_fractions(binary)))": 267, "opt(runs(continued_fractions(co_binary)))": 267, "opt(runs(continued_fractions(dichotomic)))": 266, "opt(runs(heuristic(use_first(halving,approximation))))": 266, "opt(runs(heuristic(use_first(halving,delta_largest))))": 266 }addchain-0.4.0/alg/ensemble/testdata/p256_scalar.golden000066400000000000000000000353211514305256600226420ustar00rootroot00000000000000{ "opt(dictionary(hybrid(2,0),continued_fractions(binary)))": 300, "opt(dictionary(hybrid(2,0),continued_fractions(co_binary)))": 300, "opt(dictionary(hybrid(2,0),continued_fractions(dichotomic)))": 299, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,approximation))))": 300, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,delta_largest))))": 317, "opt(dictionary(hybrid(2,16),continued_fractions(binary)))": 300, "opt(dictionary(hybrid(2,16),continued_fractions(co_binary)))": 300, "opt(dictionary(hybrid(2,16),continued_fractions(dichotomic)))": 300, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,approximation))))": 300, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,delta_largest))))": 303, "opt(dictionary(hybrid(2,32),continued_fractions(binary)))": 300, "opt(dictionary(hybrid(2,32),continued_fractions(co_binary)))": 300, "opt(dictionary(hybrid(2,32),continued_fractions(dichotomic)))": 299, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,approximation))))": 300, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,delta_largest))))": 315, "opt(dictionary(hybrid(2,64),continued_fractions(binary)))": 300, "opt(dictionary(hybrid(2,64),continued_fractions(co_binary)))": 300, "opt(dictionary(hybrid(2,64),continued_fractions(dichotomic)))": 299, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,approximation))))": 300, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,delta_largest))))": 315, "opt(dictionary(hybrid(3,0),continued_fractions(binary)))": 296, "opt(dictionary(hybrid(3,0),continued_fractions(co_binary)))": 296, "opt(dictionary(hybrid(3,0),continued_fractions(dichotomic)))": 295, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,approximation))))": 296, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,delta_largest))))": 313, "opt(dictionary(hybrid(3,16),continued_fractions(binary)))": 296, "opt(dictionary(hybrid(3,16),continued_fractions(co_binary)))": 296, "opt(dictionary(hybrid(3,16),continued_fractions(dichotomic)))": 296, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,approximation))))": 296, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,delta_largest))))": 299, "opt(dictionary(hybrid(3,32),continued_fractions(binary)))": 296, "opt(dictionary(hybrid(3,32),continued_fractions(co_binary)))": 296, "opt(dictionary(hybrid(3,32),continued_fractions(dichotomic)))": 295, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,approximation))))": 296, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,delta_largest))))": 312, "opt(dictionary(hybrid(3,64),continued_fractions(binary)))": 296, "opt(dictionary(hybrid(3,64),continued_fractions(co_binary)))": 296, "opt(dictionary(hybrid(3,64),continued_fractions(dichotomic)))": 295, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,approximation))))": 296, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,delta_largest))))": 312, "opt(dictionary(hybrid(4,0),continued_fractions(binary)))": 296, "opt(dictionary(hybrid(4,0),continued_fractions(co_binary)))": 296, "opt(dictionary(hybrid(4,0),continued_fractions(dichotomic)))": 295, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,approximation))))": 296, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,delta_largest))))": 313, "opt(dictionary(hybrid(4,16),continued_fractions(binary)))": 296, "opt(dictionary(hybrid(4,16),continued_fractions(co_binary)))": 296, "opt(dictionary(hybrid(4,16),continued_fractions(dichotomic)))": 296, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,approximation))))": 296, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,delta_largest))))": 300, "opt(dictionary(hybrid(4,32),continued_fractions(binary)))": 296, "opt(dictionary(hybrid(4,32),continued_fractions(co_binary)))": 296, "opt(dictionary(hybrid(4,32),continued_fractions(dichotomic)))": 295, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,approximation))))": 296, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,delta_largest))))": 313, "opt(dictionary(hybrid(4,64),continued_fractions(binary)))": 296, "opt(dictionary(hybrid(4,64),continued_fractions(co_binary)))": 296, "opt(dictionary(hybrid(4,64),continued_fractions(dichotomic)))": 295, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,approximation))))": 296, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,delta_largest))))": 313, "opt(dictionary(hybrid(5,0),continued_fractions(binary)))": 297, "opt(dictionary(hybrid(5,0),continued_fractions(co_binary)))": 297, "opt(dictionary(hybrid(5,0),continued_fractions(dichotomic)))": 296, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,approximation))))": 297, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,delta_largest))))": 314, "opt(dictionary(hybrid(5,16),continued_fractions(binary)))": 296, "opt(dictionary(hybrid(5,16),continued_fractions(co_binary)))": 296, "opt(dictionary(hybrid(5,16),continued_fractions(dichotomic)))": 296, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,approximation))))": 296, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,delta_largest))))": 299, "opt(dictionary(hybrid(5,32),continued_fractions(binary)))": 296, "opt(dictionary(hybrid(5,32),continued_fractions(co_binary)))": 296, "opt(dictionary(hybrid(5,32),continued_fractions(dichotomic)))": 295, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,approximation))))": 296, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,delta_largest))))": 313, "opt(dictionary(hybrid(5,64),continued_fractions(binary)))": 296, "opt(dictionary(hybrid(5,64),continued_fractions(co_binary)))": 296, "opt(dictionary(hybrid(5,64),continued_fractions(dichotomic)))": 295, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,approximation))))": 296, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,delta_largest))))": 313, "opt(dictionary(hybrid(6,0),continued_fractions(binary)))": 303, "opt(dictionary(hybrid(6,0),continued_fractions(co_binary)))": 303, "opt(dictionary(hybrid(6,0),continued_fractions(dichotomic)))": 300, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,approximation))))": 299, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,delta_largest))))": 312, "opt(dictionary(hybrid(6,16),continued_fractions(binary)))": 296, "opt(dictionary(hybrid(6,16),continued_fractions(co_binary)))": 296, "opt(dictionary(hybrid(6,16),continued_fractions(dichotomic)))": 296, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,approximation))))": 297, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,delta_largest))))": 299, "opt(dictionary(hybrid(6,32),continued_fractions(binary)))": 302, "opt(dictionary(hybrid(6,32),continued_fractions(co_binary)))": 302, "opt(dictionary(hybrid(6,32),continued_fractions(dichotomic)))": 299, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,approximation))))": 298, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,delta_largest))))": 311, "opt(dictionary(hybrid(6,64),continued_fractions(binary)))": 302, "opt(dictionary(hybrid(6,64),continued_fractions(co_binary)))": 302, "opt(dictionary(hybrid(6,64),continued_fractions(dichotomic)))": 299, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,approximation))))": 298, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,delta_largest))))": 311, "opt(dictionary(hybrid(7,0),continued_fractions(binary)))": 304, "opt(dictionary(hybrid(7,0),continued_fractions(co_binary)))": 304, "opt(dictionary(hybrid(7,0),continued_fractions(dichotomic)))": 301, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,approximation))))": 297, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,delta_largest))))": 312, "opt(dictionary(hybrid(7,16),continued_fractions(binary)))": 297, "opt(dictionary(hybrid(7,16),continued_fractions(co_binary)))": 297, "opt(dictionary(hybrid(7,16),continued_fractions(dichotomic)))": 297, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,approximation))))": 300, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,delta_largest))))": 299, "opt(dictionary(hybrid(7,32),continued_fractions(binary)))": 303, "opt(dictionary(hybrid(7,32),continued_fractions(co_binary)))": 303, "opt(dictionary(hybrid(7,32),continued_fractions(dichotomic)))": 300, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,approximation))))": 298, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,delta_largest))))": 313, "opt(dictionary(hybrid(7,64),continued_fractions(binary)))": 303, "opt(dictionary(hybrid(7,64),continued_fractions(co_binary)))": 303, "opt(dictionary(hybrid(7,64),continued_fractions(dichotomic)))": 300, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,approximation))))": 298, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,delta_largest))))": 313, "opt(dictionary(hybrid(8,0),continued_fractions(binary)))": 303, "opt(dictionary(hybrid(8,0),continued_fractions(co_binary)))": 303, "opt(dictionary(hybrid(8,0),continued_fractions(dichotomic)))": 302, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,approximation))))": 298, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,delta_largest))))": 310, "opt(dictionary(hybrid(8,16),continued_fractions(binary)))": 297, "opt(dictionary(hybrid(8,16),continued_fractions(co_binary)))": 297, "opt(dictionary(hybrid(8,16),continued_fractions(dichotomic)))": 296, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,approximation))))": 298, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,delta_largest))))": 294, "opt(dictionary(hybrid(8,32),continued_fractions(binary)))": 304, "opt(dictionary(hybrid(8,32),continued_fractions(co_binary)))": 304, "opt(dictionary(hybrid(8,32),continued_fractions(dichotomic)))": 298, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,approximation))))": 297, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,delta_largest))))": 305, "opt(dictionary(hybrid(8,64),continued_fractions(binary)))": 304, "opt(dictionary(hybrid(8,64),continued_fractions(co_binary)))": 304, "opt(dictionary(hybrid(8,64),continued_fractions(dichotomic)))": 298, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,approximation))))": 297, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,delta_largest))))": 305, "opt(dictionary(run_length(0),continued_fractions(binary)))": 300, "opt(dictionary(run_length(0),continued_fractions(co_binary)))": 300, "opt(dictionary(run_length(0),continued_fractions(dichotomic)))": 299, "opt(dictionary(run_length(0),heuristic(use_first(halving,approximation))))": 300, "opt(dictionary(run_length(0),heuristic(use_first(halving,delta_largest))))": 317, "opt(dictionary(run_length(128),continued_fractions(binary)))": 300, "opt(dictionary(run_length(128),continued_fractions(co_binary)))": 300, "opt(dictionary(run_length(128),continued_fractions(dichotomic)))": 299, "opt(dictionary(run_length(128),heuristic(use_first(halving,approximation))))": 300, "opt(dictionary(run_length(128),heuristic(use_first(halving,delta_largest))))": 317, "opt(dictionary(run_length(16),continued_fractions(binary)))": 300, "opt(dictionary(run_length(16),continued_fractions(co_binary)))": 300, "opt(dictionary(run_length(16),continued_fractions(dichotomic)))": 300, "opt(dictionary(run_length(16),heuristic(use_first(halving,approximation))))": 300, "opt(dictionary(run_length(16),heuristic(use_first(halving,delta_largest))))": 303, "opt(dictionary(run_length(32),continued_fractions(binary)))": 300, "opt(dictionary(run_length(32),continued_fractions(co_binary)))": 300, "opt(dictionary(run_length(32),continued_fractions(dichotomic)))": 299, "opt(dictionary(run_length(32),heuristic(use_first(halving,approximation))))": 300, "opt(dictionary(run_length(32),heuristic(use_first(halving,delta_largest))))": 315, "opt(dictionary(run_length(64),continued_fractions(binary)))": 300, "opt(dictionary(run_length(64),continued_fractions(co_binary)))": 300, "opt(dictionary(run_length(64),continued_fractions(dichotomic)))": 299, "opt(dictionary(run_length(64),heuristic(use_first(halving,approximation))))": 300, "opt(dictionary(run_length(64),heuristic(use_first(halving,delta_largest))))": 315, "opt(dictionary(sliding_window(128),continued_fractions(binary)))": 333, "opt(dictionary(sliding_window(128),continued_fractions(co_binary)))": 333, "opt(dictionary(sliding_window(128),continued_fractions(dichotomic)))": 332, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,approximation))))": 332, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,delta_largest))))": 332, "opt(dictionary(sliding_window(16),continued_fractions(binary)))": 296, "opt(dictionary(sliding_window(16),continued_fractions(co_binary)))": 296, "opt(dictionary(sliding_window(16),continued_fractions(dichotomic)))": 296, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,approximation))))": 295, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,delta_largest))))": 296, "opt(dictionary(sliding_window(32),continued_fractions(binary)))": 299, "opt(dictionary(sliding_window(32),continued_fractions(co_binary)))": 299, "opt(dictionary(sliding_window(32),continued_fractions(dichotomic)))": 299, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,approximation))))": 304, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,delta_largest))))": 300, "opt(dictionary(sliding_window(4),continued_fractions(binary)))": 310, "opt(dictionary(sliding_window(4),continued_fractions(co_binary)))": 310, "opt(dictionary(sliding_window(4),continued_fractions(dichotomic)))": 310, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,approximation))))": 310, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,delta_largest))))": 310, "opt(dictionary(sliding_window(64),continued_fractions(binary)))": 348, "opt(dictionary(sliding_window(64),continued_fractions(co_binary)))": 348, "opt(dictionary(sliding_window(64),continued_fractions(dichotomic)))": 348, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,approximation))))": 354, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,delta_largest))))": 349, "opt(dictionary(sliding_window(8),continued_fractions(binary)))": 299, "opt(dictionary(sliding_window(8),continued_fractions(co_binary)))": 299, "opt(dictionary(sliding_window(8),continued_fractions(dichotomic)))": 299, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,approximation))))": 303, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,delta_largest))))": 299, "opt(runs(continued_fractions(binary)))": 299, "opt(runs(continued_fractions(co_binary)))": 299, "opt(runs(continued_fractions(dichotomic)))": 299, "opt(runs(heuristic(use_first(halving,approximation))))": 298, "opt(runs(heuristic(use_first(halving,delta_largest))))": 298 }addchain-0.4.0/alg/ensemble/testdata/p382105_field.golden000066400000000000000000000353211514305256600227060ustar00rootroot00000000000000{ "opt(dictionary(hybrid(2,0),continued_fractions(binary)))": 758, "opt(dictionary(hybrid(2,0),continued_fractions(co_binary)))": 758, "opt(dictionary(hybrid(2,0),continued_fractions(dichotomic)))": 398, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,approximation))))": 572, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,delta_largest))))": 756, "opt(dictionary(hybrid(2,16),continued_fractions(binary)))": 413, "opt(dictionary(hybrid(2,16),continued_fractions(co_binary)))": 413, "opt(dictionary(hybrid(2,16),continued_fractions(dichotomic)))": 413, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,approximation))))": 413, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,delta_largest))))": 415, "opt(dictionary(hybrid(2,32),continued_fractions(binary)))": 403, "opt(dictionary(hybrid(2,32),continued_fractions(co_binary)))": 403, "opt(dictionary(hybrid(2,32),continued_fractions(dichotomic)))": 402, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,approximation))))": 402, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,delta_largest))))": 407, "opt(dictionary(hybrid(2,64),continued_fractions(binary)))": 404, "opt(dictionary(hybrid(2,64),continued_fractions(co_binary)))": 404, "opt(dictionary(hybrid(2,64),continued_fractions(dichotomic)))": 398, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,approximation))))": 401, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,delta_largest))))": 432, "opt(dictionary(hybrid(3,0),continued_fractions(binary)))": 571, "opt(dictionary(hybrid(3,0),continued_fractions(co_binary)))": 571, "opt(dictionary(hybrid(3,0),continued_fractions(dichotomic)))": 397, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,approximation))))": 509, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,delta_largest))))": 753, "opt(dictionary(hybrid(3,16),continued_fractions(binary)))": 412, "opt(dictionary(hybrid(3,16),continued_fractions(co_binary)))": 412, "opt(dictionary(hybrid(3,16),continued_fractions(dichotomic)))": 412, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,approximation))))": 412, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,delta_largest))))": 414, "opt(dictionary(hybrid(3,32),continued_fractions(binary)))": 401, "opt(dictionary(hybrid(3,32),continued_fractions(co_binary)))": 401, "opt(dictionary(hybrid(3,32),continued_fractions(dichotomic)))": 401, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,approximation))))": 402, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,delta_largest))))": 406, "opt(dictionary(hybrid(3,64),continued_fractions(binary)))": 400, "opt(dictionary(hybrid(3,64),continued_fractions(co_binary)))": 400, "opt(dictionary(hybrid(3,64),continued_fractions(dichotomic)))": 397, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,approximation))))": 399, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,delta_largest))))": 433, "opt(dictionary(hybrid(4,0),continued_fractions(binary)))": 571, "opt(dictionary(hybrid(4,0),continued_fractions(co_binary)))": 571, "opt(dictionary(hybrid(4,0),continued_fractions(dichotomic)))": 397, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,approximation))))": 509, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,delta_largest))))": 753, "opt(dictionary(hybrid(4,16),continued_fractions(binary)))": 412, "opt(dictionary(hybrid(4,16),continued_fractions(co_binary)))": 412, "opt(dictionary(hybrid(4,16),continued_fractions(dichotomic)))": 412, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,approximation))))": 412, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,delta_largest))))": 414, "opt(dictionary(hybrid(4,32),continued_fractions(binary)))": 401, "opt(dictionary(hybrid(4,32),continued_fractions(co_binary)))": 401, "opt(dictionary(hybrid(4,32),continued_fractions(dichotomic)))": 401, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,approximation))))": 402, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,delta_largest))))": 406, "opt(dictionary(hybrid(4,64),continued_fractions(binary)))": 400, "opt(dictionary(hybrid(4,64),continued_fractions(co_binary)))": 400, "opt(dictionary(hybrid(4,64),continued_fractions(dichotomic)))": 397, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,approximation))))": 399, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,delta_largest))))": 433, "opt(dictionary(hybrid(5,0),continued_fractions(binary)))": 508, "opt(dictionary(hybrid(5,0),continued_fractions(co_binary)))": 508, "opt(dictionary(hybrid(5,0),continued_fractions(dichotomic)))": 395, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,approximation))))": 459, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,delta_largest))))": 749, "opt(dictionary(hybrid(5,16),continued_fractions(binary)))": 411, "opt(dictionary(hybrid(5,16),continued_fractions(co_binary)))": 411, "opt(dictionary(hybrid(5,16),continued_fractions(dichotomic)))": 411, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,approximation))))": 411, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,delta_largest))))": 412, "opt(dictionary(hybrid(5,32),continued_fractions(binary)))": 401, "opt(dictionary(hybrid(5,32),continued_fractions(co_binary)))": 401, "opt(dictionary(hybrid(5,32),continued_fractions(dichotomic)))": 401, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,approximation))))": 402, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,delta_largest))))": 405, "opt(dictionary(hybrid(5,64),continued_fractions(binary)))": 398, "opt(dictionary(hybrid(5,64),continued_fractions(co_binary)))": 398, "opt(dictionary(hybrid(5,64),continued_fractions(dichotomic)))": 396, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,approximation))))": 400, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,delta_largest))))": 431, "opt(dictionary(hybrid(6,0),continued_fractions(binary)))": 508, "opt(dictionary(hybrid(6,0),continued_fractions(co_binary)))": 508, "opt(dictionary(hybrid(6,0),continued_fractions(dichotomic)))": 395, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,approximation))))": 459, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,delta_largest))))": 749, "opt(dictionary(hybrid(6,16),continued_fractions(binary)))": 411, "opt(dictionary(hybrid(6,16),continued_fractions(co_binary)))": 411, "opt(dictionary(hybrid(6,16),continued_fractions(dichotomic)))": 411, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,approximation))))": 411, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,delta_largest))))": 412, "opt(dictionary(hybrid(6,32),continued_fractions(binary)))": 401, "opt(dictionary(hybrid(6,32),continued_fractions(co_binary)))": 401, "opt(dictionary(hybrid(6,32),continued_fractions(dichotomic)))": 401, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,approximation))))": 402, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,delta_largest))))": 405, "opt(dictionary(hybrid(6,64),continued_fractions(binary)))": 398, "opt(dictionary(hybrid(6,64),continued_fractions(co_binary)))": 398, "opt(dictionary(hybrid(6,64),continued_fractions(dichotomic)))": 396, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,approximation))))": 400, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,delta_largest))))": 431, "opt(dictionary(hybrid(7,0),continued_fractions(binary)))": 508, "opt(dictionary(hybrid(7,0),continued_fractions(co_binary)))": 508, "opt(dictionary(hybrid(7,0),continued_fractions(dichotomic)))": 395, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,approximation))))": 459, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,delta_largest))))": 749, "opt(dictionary(hybrid(7,16),continued_fractions(binary)))": 411, "opt(dictionary(hybrid(7,16),continued_fractions(co_binary)))": 411, "opt(dictionary(hybrid(7,16),continued_fractions(dichotomic)))": 411, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,approximation))))": 411, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,delta_largest))))": 412, "opt(dictionary(hybrid(7,32),continued_fractions(binary)))": 401, "opt(dictionary(hybrid(7,32),continued_fractions(co_binary)))": 401, "opt(dictionary(hybrid(7,32),continued_fractions(dichotomic)))": 401, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,approximation))))": 402, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,delta_largest))))": 405, "opt(dictionary(hybrid(7,64),continued_fractions(binary)))": 398, "opt(dictionary(hybrid(7,64),continued_fractions(co_binary)))": 398, "opt(dictionary(hybrid(7,64),continued_fractions(dichotomic)))": 396, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,approximation))))": 400, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,delta_largest))))": 431, "opt(dictionary(hybrid(8,0),continued_fractions(binary)))": 508, "opt(dictionary(hybrid(8,0),continued_fractions(co_binary)))": 508, "opt(dictionary(hybrid(8,0),continued_fractions(dichotomic)))": 395, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,approximation))))": 459, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,delta_largest))))": 749, "opt(dictionary(hybrid(8,16),continued_fractions(binary)))": 411, "opt(dictionary(hybrid(8,16),continued_fractions(co_binary)))": 411, "opt(dictionary(hybrid(8,16),continued_fractions(dichotomic)))": 411, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,approximation))))": 411, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,delta_largest))))": 412, "opt(dictionary(hybrid(8,32),continued_fractions(binary)))": 401, "opt(dictionary(hybrid(8,32),continued_fractions(co_binary)))": 401, "opt(dictionary(hybrid(8,32),continued_fractions(dichotomic)))": 401, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,approximation))))": 402, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,delta_largest))))": 405, "opt(dictionary(hybrid(8,64),continued_fractions(binary)))": 398, "opt(dictionary(hybrid(8,64),continued_fractions(co_binary)))": 398, "opt(dictionary(hybrid(8,64),continued_fractions(dichotomic)))": 396, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,approximation))))": 400, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,delta_largest))))": 431, "opt(dictionary(run_length(0),continued_fractions(binary)))": 758, "opt(dictionary(run_length(0),continued_fractions(co_binary)))": 758, "opt(dictionary(run_length(0),continued_fractions(dichotomic)))": 398, "opt(dictionary(run_length(0),heuristic(use_first(halving,approximation))))": 572, "opt(dictionary(run_length(0),heuristic(use_first(halving,delta_largest))))": 756, "opt(dictionary(run_length(128),continued_fractions(binary)))": 405, "opt(dictionary(run_length(128),continued_fractions(co_binary)))": 405, "opt(dictionary(run_length(128),continued_fractions(dichotomic)))": 397, "opt(dictionary(run_length(128),heuristic(use_first(halving,approximation))))": 405, "opt(dictionary(run_length(128),heuristic(use_first(halving,delta_largest))))": 494, "opt(dictionary(run_length(16),continued_fractions(binary)))": 413, "opt(dictionary(run_length(16),continued_fractions(co_binary)))": 413, "opt(dictionary(run_length(16),continued_fractions(dichotomic)))": 413, "opt(dictionary(run_length(16),heuristic(use_first(halving,approximation))))": 413, "opt(dictionary(run_length(16),heuristic(use_first(halving,delta_largest))))": 415, "opt(dictionary(run_length(32),continued_fractions(binary)))": 403, "opt(dictionary(run_length(32),continued_fractions(co_binary)))": 403, "opt(dictionary(run_length(32),continued_fractions(dichotomic)))": 402, "opt(dictionary(run_length(32),heuristic(use_first(halving,approximation))))": 402, "opt(dictionary(run_length(32),heuristic(use_first(halving,delta_largest))))": 407, "opt(dictionary(run_length(64),continued_fractions(binary)))": 404, "opt(dictionary(run_length(64),continued_fractions(co_binary)))": 404, "opt(dictionary(run_length(64),continued_fractions(dichotomic)))": 398, "opt(dictionary(run_length(64),heuristic(use_first(halving,approximation))))": 401, "opt(dictionary(run_length(64),heuristic(use_first(halving,delta_largest))))": 432, "opt(dictionary(sliding_window(128),continued_fractions(binary)))": 459, "opt(dictionary(sliding_window(128),continued_fractions(co_binary)))": 459, "opt(dictionary(sliding_window(128),continued_fractions(dichotomic)))": 409, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,approximation))))": 407, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,delta_largest))))": 503, "opt(dictionary(sliding_window(16),continued_fractions(binary)))": 412, "opt(dictionary(sliding_window(16),continued_fractions(co_binary)))": 412, "opt(dictionary(sliding_window(16),continued_fractions(dichotomic)))": 412, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,approximation))))": 412, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,delta_largest))))": 412, "opt(dictionary(sliding_window(32),continued_fractions(binary)))": 410, "opt(dictionary(sliding_window(32),continued_fractions(co_binary)))": 410, "opt(dictionary(sliding_window(32),continued_fractions(dichotomic)))": 406, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,approximation))))": 405, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,delta_largest))))": 418, "opt(dictionary(sliding_window(4),continued_fractions(binary)))": 479, "opt(dictionary(sliding_window(4),continued_fractions(co_binary)))": 479, "opt(dictionary(sliding_window(4),continued_fractions(dichotomic)))": 479, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,approximation))))": 479, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,delta_largest))))": 479, "opt(dictionary(sliding_window(64),continued_fractions(binary)))": 426, "opt(dictionary(sliding_window(64),continued_fractions(co_binary)))": 426, "opt(dictionary(sliding_window(64),continued_fractions(dichotomic)))": 408, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,approximation))))": 406, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,delta_largest))))": 443, "opt(dictionary(sliding_window(8),continued_fractions(binary)))": 433, "opt(dictionary(sliding_window(8),continued_fractions(co_binary)))": 433, "opt(dictionary(sliding_window(8),continued_fractions(dichotomic)))": 433, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,approximation))))": 433, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,delta_largest))))": 433, "opt(runs(continued_fractions(binary)))": 398, "opt(runs(continued_fractions(co_binary)))": 398, "opt(runs(continued_fractions(dichotomic)))": 396, "opt(runs(heuristic(use_first(halving,approximation))))": 398, "opt(runs(heuristic(use_first(halving,delta_largest))))": 399 }addchain-0.4.0/alg/ensemble/testdata/p383187_field.golden000066400000000000000000000353211514305256600227210ustar00rootroot00000000000000{ "opt(dictionary(hybrid(2,0),continued_fractions(binary)))": 572, "opt(dictionary(hybrid(2,0),continued_fractions(co_binary)))": 572, "opt(dictionary(hybrid(2,0),continued_fractions(dichotomic)))": 398, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,approximation))))": 572, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,delta_largest))))": 756, "opt(dictionary(hybrid(2,16),continued_fractions(binary)))": 413, "opt(dictionary(hybrid(2,16),continued_fractions(co_binary)))": 413, "opt(dictionary(hybrid(2,16),continued_fractions(dichotomic)))": 413, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,approximation))))": 413, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,delta_largest))))": 415, "opt(dictionary(hybrid(2,32),continued_fractions(binary)))": 402, "opt(dictionary(hybrid(2,32),continued_fractions(co_binary)))": 402, "opt(dictionary(hybrid(2,32),continued_fractions(dichotomic)))": 402, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,approximation))))": 402, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,delta_largest))))": 407, "opt(dictionary(hybrid(2,64),continued_fractions(binary)))": 401, "opt(dictionary(hybrid(2,64),continued_fractions(co_binary)))": 401, "opt(dictionary(hybrid(2,64),continued_fractions(dichotomic)))": 398, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,approximation))))": 401, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,delta_largest))))": 432, "opt(dictionary(hybrid(3,0),continued_fractions(binary)))": 572, "opt(dictionary(hybrid(3,0),continued_fractions(co_binary)))": 572, "opt(dictionary(hybrid(3,0),continued_fractions(dichotomic)))": 398, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,approximation))))": 572, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,delta_largest))))": 756, "opt(dictionary(hybrid(3,16),continued_fractions(binary)))": 413, "opt(dictionary(hybrid(3,16),continued_fractions(co_binary)))": 413, "opt(dictionary(hybrid(3,16),continued_fractions(dichotomic)))": 413, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,approximation))))": 413, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,delta_largest))))": 415, "opt(dictionary(hybrid(3,32),continued_fractions(binary)))": 402, "opt(dictionary(hybrid(3,32),continued_fractions(co_binary)))": 402, "opt(dictionary(hybrid(3,32),continued_fractions(dichotomic)))": 402, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,approximation))))": 402, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,delta_largest))))": 407, "opt(dictionary(hybrid(3,64),continued_fractions(binary)))": 401, "opt(dictionary(hybrid(3,64),continued_fractions(co_binary)))": 401, "opt(dictionary(hybrid(3,64),continued_fractions(dichotomic)))": 398, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,approximation))))": 401, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,delta_largest))))": 432, "opt(dictionary(hybrid(4,0),continued_fractions(binary)))": 572, "opt(dictionary(hybrid(4,0),continued_fractions(co_binary)))": 572, "opt(dictionary(hybrid(4,0),continued_fractions(dichotomic)))": 398, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,approximation))))": 572, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,delta_largest))))": 756, "opt(dictionary(hybrid(4,16),continued_fractions(binary)))": 413, "opt(dictionary(hybrid(4,16),continued_fractions(co_binary)))": 413, "opt(dictionary(hybrid(4,16),continued_fractions(dichotomic)))": 413, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,approximation))))": 413, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,delta_largest))))": 415, "opt(dictionary(hybrid(4,32),continued_fractions(binary)))": 402, "opt(dictionary(hybrid(4,32),continued_fractions(co_binary)))": 402, "opt(dictionary(hybrid(4,32),continued_fractions(dichotomic)))": 402, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,approximation))))": 402, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,delta_largest))))": 407, "opt(dictionary(hybrid(4,64),continued_fractions(binary)))": 401, "opt(dictionary(hybrid(4,64),continued_fractions(co_binary)))": 401, "opt(dictionary(hybrid(4,64),continued_fractions(dichotomic)))": 398, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,approximation))))": 401, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,delta_largest))))": 432, "opt(dictionary(hybrid(5,0),continued_fractions(binary)))": 572, "opt(dictionary(hybrid(5,0),continued_fractions(co_binary)))": 572, "opt(dictionary(hybrid(5,0),continued_fractions(dichotomic)))": 398, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,approximation))))": 572, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,delta_largest))))": 756, "opt(dictionary(hybrid(5,16),continued_fractions(binary)))": 413, "opt(dictionary(hybrid(5,16),continued_fractions(co_binary)))": 413, "opt(dictionary(hybrid(5,16),continued_fractions(dichotomic)))": 413, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,approximation))))": 413, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,delta_largest))))": 415, "opt(dictionary(hybrid(5,32),continued_fractions(binary)))": 402, "opt(dictionary(hybrid(5,32),continued_fractions(co_binary)))": 402, "opt(dictionary(hybrid(5,32),continued_fractions(dichotomic)))": 402, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,approximation))))": 402, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,delta_largest))))": 407, "opt(dictionary(hybrid(5,64),continued_fractions(binary)))": 401, "opt(dictionary(hybrid(5,64),continued_fractions(co_binary)))": 401, "opt(dictionary(hybrid(5,64),continued_fractions(dichotomic)))": 398, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,approximation))))": 401, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,delta_largest))))": 432, "opt(dictionary(hybrid(6,0),continued_fractions(binary)))": 573, "opt(dictionary(hybrid(6,0),continued_fractions(co_binary)))": 573, "opt(dictionary(hybrid(6,0),continued_fractions(dichotomic)))": 398, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,approximation))))": 450, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,delta_largest))))": 754, "opt(dictionary(hybrid(6,16),continued_fractions(binary)))": 414, "opt(dictionary(hybrid(6,16),continued_fractions(co_binary)))": 414, "opt(dictionary(hybrid(6,16),continued_fractions(dichotomic)))": 414, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,approximation))))": 413, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,delta_largest))))": 415, "opt(dictionary(hybrid(6,32),continued_fractions(binary)))": 406, "opt(dictionary(hybrid(6,32),continued_fractions(co_binary)))": 406, "opt(dictionary(hybrid(6,32),continued_fractions(dichotomic)))": 405, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,approximation))))": 404, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,delta_largest))))": 408, "opt(dictionary(hybrid(6,64),continued_fractions(binary)))": 401, "opt(dictionary(hybrid(6,64),continued_fractions(co_binary)))": 401, "opt(dictionary(hybrid(6,64),continued_fractions(dichotomic)))": 398, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,approximation))))": 401, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,delta_largest))))": 433, "opt(dictionary(hybrid(7,0),continued_fractions(binary)))": 572, "opt(dictionary(hybrid(7,0),continued_fractions(co_binary)))": 572, "opt(dictionary(hybrid(7,0),continued_fractions(dichotomic)))": 433, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,approximation))))": 440, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,delta_largest))))": 751, "opt(dictionary(hybrid(7,16),continued_fractions(binary)))": 412, "opt(dictionary(hybrid(7,16),continued_fractions(co_binary)))": 412, "opt(dictionary(hybrid(7,16),continued_fractions(dichotomic)))": 412, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,approximation))))": 412, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,delta_largest))))": 415, "opt(dictionary(hybrid(7,32),continued_fractions(binary)))": 404, "opt(dictionary(hybrid(7,32),continued_fractions(co_binary)))": 404, "opt(dictionary(hybrid(7,32),continued_fractions(dichotomic)))": 404, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,approximation))))": 403, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,delta_largest))))": 407, "opt(dictionary(hybrid(7,64),continued_fractions(binary)))": 400, "opt(dictionary(hybrid(7,64),continued_fractions(co_binary)))": 400, "opt(dictionary(hybrid(7,64),continued_fractions(dichotomic)))": 398, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,approximation))))": 400, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,delta_largest))))": 432, "opt(dictionary(hybrid(8,0),continued_fractions(binary)))": 572, "opt(dictionary(hybrid(8,0),continued_fractions(co_binary)))": 572, "opt(dictionary(hybrid(8,0),continued_fractions(dichotomic)))": 433, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,approximation))))": 440, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,delta_largest))))": 751, "opt(dictionary(hybrid(8,16),continued_fractions(binary)))": 412, "opt(dictionary(hybrid(8,16),continued_fractions(co_binary)))": 412, "opt(dictionary(hybrid(8,16),continued_fractions(dichotomic)))": 412, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,approximation))))": 412, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,delta_largest))))": 415, "opt(dictionary(hybrid(8,32),continued_fractions(binary)))": 404, "opt(dictionary(hybrid(8,32),continued_fractions(co_binary)))": 404, "opt(dictionary(hybrid(8,32),continued_fractions(dichotomic)))": 404, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,approximation))))": 403, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,delta_largest))))": 407, "opt(dictionary(hybrid(8,64),continued_fractions(binary)))": 400, "opt(dictionary(hybrid(8,64),continued_fractions(co_binary)))": 400, "opt(dictionary(hybrid(8,64),continued_fractions(dichotomic)))": 398, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,approximation))))": 400, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,delta_largest))))": 432, "opt(dictionary(run_length(0),continued_fractions(binary)))": 572, "opt(dictionary(run_length(0),continued_fractions(co_binary)))": 572, "opt(dictionary(run_length(0),continued_fractions(dichotomic)))": 398, "opt(dictionary(run_length(0),heuristic(use_first(halving,approximation))))": 572, "opt(dictionary(run_length(0),heuristic(use_first(halving,delta_largest))))": 756, "opt(dictionary(run_length(128),continued_fractions(binary)))": 405, "opt(dictionary(run_length(128),continued_fractions(co_binary)))": 405, "opt(dictionary(run_length(128),continued_fractions(dichotomic)))": 397, "opt(dictionary(run_length(128),heuristic(use_first(halving,approximation))))": 405, "opt(dictionary(run_length(128),heuristic(use_first(halving,delta_largest))))": 494, "opt(dictionary(run_length(16),continued_fractions(binary)))": 413, "opt(dictionary(run_length(16),continued_fractions(co_binary)))": 413, "opt(dictionary(run_length(16),continued_fractions(dichotomic)))": 413, "opt(dictionary(run_length(16),heuristic(use_first(halving,approximation))))": 413, "opt(dictionary(run_length(16),heuristic(use_first(halving,delta_largest))))": 415, "opt(dictionary(run_length(32),continued_fractions(binary)))": 402, "opt(dictionary(run_length(32),continued_fractions(co_binary)))": 402, "opt(dictionary(run_length(32),continued_fractions(dichotomic)))": 402, "opt(dictionary(run_length(32),heuristic(use_first(halving,approximation))))": 402, "opt(dictionary(run_length(32),heuristic(use_first(halving,delta_largest))))": 407, "opt(dictionary(run_length(64),continued_fractions(binary)))": 401, "opt(dictionary(run_length(64),continued_fractions(co_binary)))": 401, "opt(dictionary(run_length(64),continued_fractions(dichotomic)))": 398, "opt(dictionary(run_length(64),heuristic(use_first(halving,approximation))))": 401, "opt(dictionary(run_length(64),heuristic(use_first(halving,delta_largest))))": 432, "opt(dictionary(sliding_window(128),continued_fractions(binary)))": 451, "opt(dictionary(sliding_window(128),continued_fractions(co_binary)))": 451, "opt(dictionary(sliding_window(128),continued_fractions(dichotomic)))": 411, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,approximation))))": 413, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,delta_largest))))": 504, "opt(dictionary(sliding_window(16),continued_fractions(binary)))": 416, "opt(dictionary(sliding_window(16),continued_fractions(co_binary)))": 416, "opt(dictionary(sliding_window(16),continued_fractions(dichotomic)))": 414, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,approximation))))": 413, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,delta_largest))))": 413, "opt(dictionary(sliding_window(32),continued_fractions(binary)))": 412, "opt(dictionary(sliding_window(32),continued_fractions(co_binary)))": 412, "opt(dictionary(sliding_window(32),continued_fractions(dichotomic)))": 407, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,approximation))))": 410, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,delta_largest))))": 417, "opt(dictionary(sliding_window(4),continued_fractions(binary)))": 480, "opt(dictionary(sliding_window(4),continued_fractions(co_binary)))": 480, "opt(dictionary(sliding_window(4),continued_fractions(dichotomic)))": 480, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,approximation))))": 480, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,delta_largest))))": 480, "opt(dictionary(sliding_window(64),continued_fractions(binary)))": 424, "opt(dictionary(sliding_window(64),continued_fractions(co_binary)))": 424, "opt(dictionary(sliding_window(64),continued_fractions(dichotomic)))": 411, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,approximation))))": 408, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,delta_largest))))": 443, "opt(dictionary(sliding_window(8),continued_fractions(binary)))": 434, "opt(dictionary(sliding_window(8),continued_fractions(co_binary)))": 434, "opt(dictionary(sliding_window(8),continued_fractions(dichotomic)))": 434, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,approximation))))": 434, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,delta_largest))))": 434, "opt(runs(continued_fractions(binary)))": 398, "opt(runs(continued_fractions(co_binary)))": 398, "opt(runs(continued_fractions(dichotomic)))": 396, "opt(runs(heuristic(use_first(halving,approximation))))": 398, "opt(runs(heuristic(use_first(halving,delta_largest))))": 399 }addchain-0.4.0/alg/ensemble/testdata/p384_field.golden000066400000000000000000000353211514305256600224620ustar00rootroot00000000000000{ "opt(dictionary(hybrid(2,0),continued_fractions(binary)))": 423, "opt(dictionary(hybrid(2,0),continued_fractions(co_binary)))": 423, "opt(dictionary(hybrid(2,0),continued_fractions(dichotomic)))": 399, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,approximation))))": 409, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,delta_largest))))": 605, "opt(dictionary(hybrid(2,16),continued_fractions(binary)))": 417, "opt(dictionary(hybrid(2,16),continued_fractions(co_binary)))": 417, "opt(dictionary(hybrid(2,16),continued_fractions(dichotomic)))": 409, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,approximation))))": 411, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,delta_largest))))": 414, "opt(dictionary(hybrid(2,32),continued_fractions(binary)))": 423, "opt(dictionary(hybrid(2,32),continued_fractions(co_binary)))": 423, "opt(dictionary(hybrid(2,32),continued_fractions(dichotomic)))": 401, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,approximation))))": 409, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,delta_largest))))": 420, "opt(dictionary(hybrid(2,64),continued_fractions(binary)))": 421, "opt(dictionary(hybrid(2,64),continued_fractions(co_binary)))": 421, "opt(dictionary(hybrid(2,64),continued_fractions(dichotomic)))": 399, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,approximation))))": 407, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,delta_largest))))": 418, "opt(dictionary(hybrid(3,0),continued_fractions(binary)))": 423, "opt(dictionary(hybrid(3,0),continued_fractions(co_binary)))": 423, "opt(dictionary(hybrid(3,0),continued_fractions(dichotomic)))": 399, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,approximation))))": 409, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,delta_largest))))": 605, "opt(dictionary(hybrid(3,16),continued_fractions(binary)))": 417, "opt(dictionary(hybrid(3,16),continued_fractions(co_binary)))": 417, "opt(dictionary(hybrid(3,16),continued_fractions(dichotomic)))": 409, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,approximation))))": 411, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,delta_largest))))": 414, "opt(dictionary(hybrid(3,32),continued_fractions(binary)))": 423, "opt(dictionary(hybrid(3,32),continued_fractions(co_binary)))": 423, "opt(dictionary(hybrid(3,32),continued_fractions(dichotomic)))": 401, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,approximation))))": 409, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,delta_largest))))": 420, "opt(dictionary(hybrid(3,64),continued_fractions(binary)))": 421, "opt(dictionary(hybrid(3,64),continued_fractions(co_binary)))": 421, "opt(dictionary(hybrid(3,64),continued_fractions(dichotomic)))": 399, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,approximation))))": 407, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,delta_largest))))": 418, "opt(dictionary(hybrid(4,0),continued_fractions(binary)))": 423, "opt(dictionary(hybrid(4,0),continued_fractions(co_binary)))": 423, "opt(dictionary(hybrid(4,0),continued_fractions(dichotomic)))": 399, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,approximation))))": 409, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,delta_largest))))": 605, "opt(dictionary(hybrid(4,16),continued_fractions(binary)))": 417, "opt(dictionary(hybrid(4,16),continued_fractions(co_binary)))": 417, "opt(dictionary(hybrid(4,16),continued_fractions(dichotomic)))": 409, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,approximation))))": 411, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,delta_largest))))": 414, "opt(dictionary(hybrid(4,32),continued_fractions(binary)))": 423, "opt(dictionary(hybrid(4,32),continued_fractions(co_binary)))": 423, "opt(dictionary(hybrid(4,32),continued_fractions(dichotomic)))": 401, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,approximation))))": 409, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,delta_largest))))": 420, "opt(dictionary(hybrid(4,64),continued_fractions(binary)))": 421, "opt(dictionary(hybrid(4,64),continued_fractions(co_binary)))": 421, "opt(dictionary(hybrid(4,64),continued_fractions(dichotomic)))": 399, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,approximation))))": 407, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,delta_largest))))": 418, "opt(dictionary(hybrid(5,0),continued_fractions(binary)))": 423, "opt(dictionary(hybrid(5,0),continued_fractions(co_binary)))": 423, "opt(dictionary(hybrid(5,0),continued_fractions(dichotomic)))": 399, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,approximation))))": 409, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,delta_largest))))": 605, "opt(dictionary(hybrid(5,16),continued_fractions(binary)))": 417, "opt(dictionary(hybrid(5,16),continued_fractions(co_binary)))": 417, "opt(dictionary(hybrid(5,16),continued_fractions(dichotomic)))": 409, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,approximation))))": 411, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,delta_largest))))": 414, "opt(dictionary(hybrid(5,32),continued_fractions(binary)))": 423, "opt(dictionary(hybrid(5,32),continued_fractions(co_binary)))": 423, "opt(dictionary(hybrid(5,32),continued_fractions(dichotomic)))": 401, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,approximation))))": 409, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,delta_largest))))": 420, "opt(dictionary(hybrid(5,64),continued_fractions(binary)))": 421, "opt(dictionary(hybrid(5,64),continued_fractions(co_binary)))": 421, "opt(dictionary(hybrid(5,64),continued_fractions(dichotomic)))": 399, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,approximation))))": 407, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,delta_largest))))": 418, "opt(dictionary(hybrid(6,0),continued_fractions(binary)))": 423, "opt(dictionary(hybrid(6,0),continued_fractions(co_binary)))": 423, "opt(dictionary(hybrid(6,0),continued_fractions(dichotomic)))": 399, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,approximation))))": 409, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,delta_largest))))": 605, "opt(dictionary(hybrid(6,16),continued_fractions(binary)))": 417, "opt(dictionary(hybrid(6,16),continued_fractions(co_binary)))": 417, "opt(dictionary(hybrid(6,16),continued_fractions(dichotomic)))": 409, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,approximation))))": 411, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,delta_largest))))": 414, "opt(dictionary(hybrid(6,32),continued_fractions(binary)))": 423, "opt(dictionary(hybrid(6,32),continued_fractions(co_binary)))": 423, "opt(dictionary(hybrid(6,32),continued_fractions(dichotomic)))": 401, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,approximation))))": 409, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,delta_largest))))": 420, "opt(dictionary(hybrid(6,64),continued_fractions(binary)))": 421, "opt(dictionary(hybrid(6,64),continued_fractions(co_binary)))": 421, "opt(dictionary(hybrid(6,64),continued_fractions(dichotomic)))": 399, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,approximation))))": 407, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,delta_largest))))": 418, "opt(dictionary(hybrid(7,0),continued_fractions(binary)))": 423, "opt(dictionary(hybrid(7,0),continued_fractions(co_binary)))": 423, "opt(dictionary(hybrid(7,0),continued_fractions(dichotomic)))": 399, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,approximation))))": 409, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,delta_largest))))": 605, "opt(dictionary(hybrid(7,16),continued_fractions(binary)))": 417, "opt(dictionary(hybrid(7,16),continued_fractions(co_binary)))": 417, "opt(dictionary(hybrid(7,16),continued_fractions(dichotomic)))": 409, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,approximation))))": 411, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,delta_largest))))": 414, "opt(dictionary(hybrid(7,32),continued_fractions(binary)))": 423, "opt(dictionary(hybrid(7,32),continued_fractions(co_binary)))": 423, "opt(dictionary(hybrid(7,32),continued_fractions(dichotomic)))": 401, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,approximation))))": 409, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,delta_largest))))": 420, "opt(dictionary(hybrid(7,64),continued_fractions(binary)))": 421, "opt(dictionary(hybrid(7,64),continued_fractions(co_binary)))": 421, "opt(dictionary(hybrid(7,64),continued_fractions(dichotomic)))": 399, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,approximation))))": 407, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,delta_largest))))": 418, "opt(dictionary(hybrid(8,0),continued_fractions(binary)))": 423, "opt(dictionary(hybrid(8,0),continued_fractions(co_binary)))": 423, "opt(dictionary(hybrid(8,0),continued_fractions(dichotomic)))": 399, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,approximation))))": 409, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,delta_largest))))": 605, "opt(dictionary(hybrid(8,16),continued_fractions(binary)))": 417, "opt(dictionary(hybrid(8,16),continued_fractions(co_binary)))": 417, "opt(dictionary(hybrid(8,16),continued_fractions(dichotomic)))": 409, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,approximation))))": 411, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,delta_largest))))": 414, "opt(dictionary(hybrid(8,32),continued_fractions(binary)))": 423, "opt(dictionary(hybrid(8,32),continued_fractions(co_binary)))": 423, "opt(dictionary(hybrid(8,32),continued_fractions(dichotomic)))": 401, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,approximation))))": 409, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,delta_largest))))": 420, "opt(dictionary(hybrid(8,64),continued_fractions(binary)))": 421, "opt(dictionary(hybrid(8,64),continued_fractions(co_binary)))": 421, "opt(dictionary(hybrid(8,64),continued_fractions(dichotomic)))": 399, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,approximation))))": 407, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,delta_largest))))": 418, "opt(dictionary(run_length(0),continued_fractions(binary)))": 423, "opt(dictionary(run_length(0),continued_fractions(co_binary)))": 423, "opt(dictionary(run_length(0),continued_fractions(dichotomic)))": 399, "opt(dictionary(run_length(0),heuristic(use_first(halving,approximation))))": 409, "opt(dictionary(run_length(0),heuristic(use_first(halving,delta_largest))))": 605, "opt(dictionary(run_length(128),continued_fractions(binary)))": 421, "opt(dictionary(run_length(128),continued_fractions(co_binary)))": 421, "opt(dictionary(run_length(128),continued_fractions(dichotomic)))": 399, "opt(dictionary(run_length(128),heuristic(use_first(halving,approximation))))": 407, "opt(dictionary(run_length(128),heuristic(use_first(halving,delta_largest))))": 479, "opt(dictionary(run_length(16),continued_fractions(binary)))": 417, "opt(dictionary(run_length(16),continued_fractions(co_binary)))": 417, "opt(dictionary(run_length(16),continued_fractions(dichotomic)))": 409, "opt(dictionary(run_length(16),heuristic(use_first(halving,approximation))))": 411, "opt(dictionary(run_length(16),heuristic(use_first(halving,delta_largest))))": 414, "opt(dictionary(run_length(32),continued_fractions(binary)))": 423, "opt(dictionary(run_length(32),continued_fractions(co_binary)))": 423, "opt(dictionary(run_length(32),continued_fractions(dichotomic)))": 401, "opt(dictionary(run_length(32),heuristic(use_first(halving,approximation))))": 409, "opt(dictionary(run_length(32),heuristic(use_first(halving,delta_largest))))": 420, "opt(dictionary(run_length(64),continued_fractions(binary)))": 421, "opt(dictionary(run_length(64),continued_fractions(co_binary)))": 421, "opt(dictionary(run_length(64),continued_fractions(dichotomic)))": 399, "opt(dictionary(run_length(64),heuristic(use_first(halving,approximation))))": 407, "opt(dictionary(run_length(64),heuristic(use_first(halving,delta_largest))))": 418, "opt(dictionary(sliding_window(128),continued_fractions(binary)))": 451, "opt(dictionary(sliding_window(128),continued_fractions(co_binary)))": 451, "opt(dictionary(sliding_window(128),continued_fractions(dichotomic)))": 419, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,approximation))))": 406, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,delta_largest))))": 421, "opt(dictionary(sliding_window(16),continued_fractions(binary)))": 417, "opt(dictionary(sliding_window(16),continued_fractions(co_binary)))": 417, "opt(dictionary(sliding_window(16),continued_fractions(dichotomic)))": 409, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,approximation))))": 411, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,delta_largest))))": 414, "opt(dictionary(sliding_window(32),continued_fractions(binary)))": 423, "opt(dictionary(sliding_window(32),continued_fractions(co_binary)))": 423, "opt(dictionary(sliding_window(32),continued_fractions(dichotomic)))": 401, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,approximation))))": 409, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,delta_largest))))": 420, "opt(dictionary(sliding_window(4),continued_fractions(binary)))": 465, "opt(dictionary(sliding_window(4),continued_fractions(co_binary)))": 465, "opt(dictionary(sliding_window(4),continued_fractions(dichotomic)))": 465, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,approximation))))": 465, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,delta_largest))))": 465, "opt(dictionary(sliding_window(64),continued_fractions(binary)))": 421, "opt(dictionary(sliding_window(64),continued_fractions(co_binary)))": 421, "opt(dictionary(sliding_window(64),continued_fractions(dichotomic)))": 399, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,approximation))))": 407, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,delta_largest))))": 418, "opt(dictionary(sliding_window(8),continued_fractions(binary)))": 429, "opt(dictionary(sliding_window(8),continued_fractions(co_binary)))": 429, "opt(dictionary(sliding_window(8),continued_fractions(dichotomic)))": 427, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,approximation))))": 427, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,delta_largest))))": 427, "opt(runs(continued_fractions(binary)))": 399, "opt(runs(continued_fractions(co_binary)))": 399, "opt(runs(continued_fractions(dichotomic)))": 399, "opt(runs(heuristic(use_first(halving,approximation))))": 397, "opt(runs(heuristic(use_first(halving,delta_largest))))": 397 }addchain-0.4.0/alg/ensemble/testdata/p384_scalar.golden000066400000000000000000000353211514305256600226440ustar00rootroot00000000000000{ "opt(dictionary(hybrid(2,0),continued_fractions(binary)))": 475, "opt(dictionary(hybrid(2,0),continued_fractions(co_binary)))": 475, "opt(dictionary(hybrid(2,0),continued_fractions(dichotomic)))": 445, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,approximation))))": 475, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,delta_largest))))": 622, "opt(dictionary(hybrid(2,16),continued_fractions(binary)))": 452, "opt(dictionary(hybrid(2,16),continued_fractions(co_binary)))": 452, "opt(dictionary(hybrid(2,16),continued_fractions(dichotomic)))": 452, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,approximation))))": 452, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,delta_largest))))": 455, "opt(dictionary(hybrid(2,32),continued_fractions(binary)))": 449, "opt(dictionary(hybrid(2,32),continued_fractions(co_binary)))": 449, "opt(dictionary(hybrid(2,32),continued_fractions(dichotomic)))": 447, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,approximation))))": 449, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,delta_largest))))": 465, "opt(dictionary(hybrid(2,64),continued_fractions(binary)))": 452, "opt(dictionary(hybrid(2,64),continued_fractions(co_binary)))": 452, "opt(dictionary(hybrid(2,64),continued_fractions(dichotomic)))": 445, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,approximation))))": 452, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,delta_largest))))": 495, "opt(dictionary(hybrid(3,0),continued_fractions(binary)))": 471, "opt(dictionary(hybrid(3,0),continued_fractions(co_binary)))": 471, "opt(dictionary(hybrid(3,0),continued_fractions(dichotomic)))": 441, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,approximation))))": 471, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,delta_largest))))": 618, "opt(dictionary(hybrid(3,16),continued_fractions(binary)))": 448, "opt(dictionary(hybrid(3,16),continued_fractions(co_binary)))": 448, "opt(dictionary(hybrid(3,16),continued_fractions(dichotomic)))": 448, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,approximation))))": 448, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,delta_largest))))": 451, "opt(dictionary(hybrid(3,32),continued_fractions(binary)))": 445, "opt(dictionary(hybrid(3,32),continued_fractions(co_binary)))": 445, "opt(dictionary(hybrid(3,32),continued_fractions(dichotomic)))": 443, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,approximation))))": 445, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,delta_largest))))": 462, "opt(dictionary(hybrid(3,64),continued_fractions(binary)))": 448, "opt(dictionary(hybrid(3,64),continued_fractions(co_binary)))": 448, "opt(dictionary(hybrid(3,64),continued_fractions(dichotomic)))": 441, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,approximation))))": 448, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,delta_largest))))": 491, "opt(dictionary(hybrid(4,0),continued_fractions(binary)))": 464, "opt(dictionary(hybrid(4,0),continued_fractions(co_binary)))": 464, "opt(dictionary(hybrid(4,0),continued_fractions(dichotomic)))": 434, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,approximation))))": 464, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,delta_largest))))": 611, "opt(dictionary(hybrid(4,16),continued_fractions(binary)))": 441, "opt(dictionary(hybrid(4,16),continued_fractions(co_binary)))": 441, "opt(dictionary(hybrid(4,16),continued_fractions(dichotomic)))": 441, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,approximation))))": 441, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,delta_largest))))": 444, "opt(dictionary(hybrid(4,32),continued_fractions(binary)))": 438, "opt(dictionary(hybrid(4,32),continued_fractions(co_binary)))": 438, "opt(dictionary(hybrid(4,32),continued_fractions(dichotomic)))": 436, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,approximation))))": 438, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,delta_largest))))": 455, "opt(dictionary(hybrid(4,64),continued_fractions(binary)))": 441, "opt(dictionary(hybrid(4,64),continued_fractions(co_binary)))": 441, "opt(dictionary(hybrid(4,64),continued_fractions(dichotomic)))": 434, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,approximation))))": 441, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,delta_largest))))": 484, "opt(dictionary(hybrid(5,0),continued_fractions(binary)))": 465, "opt(dictionary(hybrid(5,0),continued_fractions(co_binary)))": 465, "opt(dictionary(hybrid(5,0),continued_fractions(dichotomic)))": 435, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,approximation))))": 465, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,delta_largest))))": 612, "opt(dictionary(hybrid(5,16),continued_fractions(binary)))": 441, "opt(dictionary(hybrid(5,16),continued_fractions(co_binary)))": 441, "opt(dictionary(hybrid(5,16),continued_fractions(dichotomic)))": 441, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,approximation))))": 441, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,delta_largest))))": 445, "opt(dictionary(hybrid(5,32),continued_fractions(binary)))": 438, "opt(dictionary(hybrid(5,32),continued_fractions(co_binary)))": 438, "opt(dictionary(hybrid(5,32),continued_fractions(dichotomic)))": 436, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,approximation))))": 438, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,delta_largest))))": 456, "opt(dictionary(hybrid(5,64),continued_fractions(binary)))": 442, "opt(dictionary(hybrid(5,64),continued_fractions(co_binary)))": 442, "opt(dictionary(hybrid(5,64),continued_fractions(dichotomic)))": 435, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,approximation))))": 442, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,delta_largest))))": 485, "opt(dictionary(hybrid(6,0),continued_fractions(binary)))": 520, "opt(dictionary(hybrid(6,0),continued_fractions(co_binary)))": 520, "opt(dictionary(hybrid(6,0),continued_fractions(dichotomic)))": 454, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,approximation))))": 460, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,delta_largest))))": 612, "opt(dictionary(hybrid(6,16),continued_fractions(binary)))": 443, "opt(dictionary(hybrid(6,16),continued_fractions(co_binary)))": 443, "opt(dictionary(hybrid(6,16),continued_fractions(dichotomic)))": 442, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,approximation))))": 441, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,delta_largest))))": 445, "opt(dictionary(hybrid(6,32),continued_fractions(binary)))": 448, "opt(dictionary(hybrid(6,32),continued_fractions(co_binary)))": 448, "opt(dictionary(hybrid(6,32),continued_fractions(dichotomic)))": 442, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,approximation))))": 439, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,delta_largest))))": 456, "opt(dictionary(hybrid(6,64),continued_fractions(binary)))": 459, "opt(dictionary(hybrid(6,64),continued_fractions(co_binary)))": 459, "opt(dictionary(hybrid(6,64),continued_fractions(dichotomic)))": 444, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,approximation))))": 440, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,delta_largest))))": 484, "opt(dictionary(hybrid(7,0),continued_fractions(binary)))": 523, "opt(dictionary(hybrid(7,0),continued_fractions(co_binary)))": 523, "opt(dictionary(hybrid(7,0),continued_fractions(dichotomic)))": 451, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,approximation))))": 458, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,delta_largest))))": 611, "opt(dictionary(hybrid(7,16),continued_fractions(binary)))": 443, "opt(dictionary(hybrid(7,16),continued_fractions(co_binary)))": 443, "opt(dictionary(hybrid(7,16),continued_fractions(dichotomic)))": 443, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,approximation))))": 444, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,delta_largest))))": 444, "opt(dictionary(hybrid(7,32),continued_fractions(binary)))": 445, "opt(dictionary(hybrid(7,32),continued_fractions(co_binary)))": 445, "opt(dictionary(hybrid(7,32),continued_fractions(dichotomic)))": 442, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,approximation))))": 441, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,delta_largest))))": 455, "opt(dictionary(hybrid(7,64),continued_fractions(binary)))": 462, "opt(dictionary(hybrid(7,64),continued_fractions(co_binary)))": 462, "opt(dictionary(hybrid(7,64),continued_fractions(dichotomic)))": 445, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,approximation))))": 443, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,delta_largest))))": 482, "opt(dictionary(hybrid(8,0),continued_fractions(binary)))": 520, "opt(dictionary(hybrid(8,0),continued_fractions(co_binary)))": 520, "opt(dictionary(hybrid(8,0),continued_fractions(dichotomic)))": 458, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,approximation))))": 451, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,delta_largest))))": 607, "opt(dictionary(hybrid(8,16),continued_fractions(binary)))": 443, "opt(dictionary(hybrid(8,16),continued_fractions(co_binary)))": 443, "opt(dictionary(hybrid(8,16),continued_fractions(dichotomic)))": 443, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,approximation))))": 441, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,delta_largest))))": 439, "opt(dictionary(hybrid(8,32),continued_fractions(binary)))": 447, "opt(dictionary(hybrid(8,32),continued_fractions(co_binary)))": 447, "opt(dictionary(hybrid(8,32),continued_fractions(dichotomic)))": 441, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,approximation))))": 437, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,delta_largest))))": 447, "opt(dictionary(hybrid(8,64),continued_fractions(binary)))": 460, "opt(dictionary(hybrid(8,64),continued_fractions(co_binary)))": 460, "opt(dictionary(hybrid(8,64),continued_fractions(dichotomic)))": 441, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,approximation))))": 438, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,delta_largest))))": 476, "opt(dictionary(run_length(0),continued_fractions(binary)))": 475, "opt(dictionary(run_length(0),continued_fractions(co_binary)))": 475, "opt(dictionary(run_length(0),continued_fractions(dichotomic)))": 445, "opt(dictionary(run_length(0),heuristic(use_first(halving,approximation))))": 475, "opt(dictionary(run_length(0),heuristic(use_first(halving,delta_largest))))": 622, "opt(dictionary(run_length(128),continued_fractions(binary)))": 452, "opt(dictionary(run_length(128),continued_fractions(co_binary)))": 452, "opt(dictionary(run_length(128),continued_fractions(dichotomic)))": 445, "opt(dictionary(run_length(128),heuristic(use_first(halving,approximation))))": 452, "opt(dictionary(run_length(128),heuristic(use_first(halving,delta_largest))))": 492, "opt(dictionary(run_length(16),continued_fractions(binary)))": 452, "opt(dictionary(run_length(16),continued_fractions(co_binary)))": 452, "opt(dictionary(run_length(16),continued_fractions(dichotomic)))": 452, "opt(dictionary(run_length(16),heuristic(use_first(halving,approximation))))": 452, "opt(dictionary(run_length(16),heuristic(use_first(halving,delta_largest))))": 455, "opt(dictionary(run_length(32),continued_fractions(binary)))": 449, "opt(dictionary(run_length(32),continued_fractions(co_binary)))": 449, "opt(dictionary(run_length(32),continued_fractions(dichotomic)))": 447, "opt(dictionary(run_length(32),heuristic(use_first(halving,approximation))))": 449, "opt(dictionary(run_length(32),heuristic(use_first(halving,delta_largest))))": 465, "opt(dictionary(run_length(64),continued_fractions(binary)))": 452, "opt(dictionary(run_length(64),continued_fractions(co_binary)))": 452, "opt(dictionary(run_length(64),continued_fractions(dichotomic)))": 445, "opt(dictionary(run_length(64),heuristic(use_first(halving,approximation))))": 452, "opt(dictionary(run_length(64),heuristic(use_first(halving,delta_largest))))": 495, "opt(dictionary(sliding_window(128),continued_fractions(binary)))": 477, "opt(dictionary(sliding_window(128),continued_fractions(co_binary)))": 477, "opt(dictionary(sliding_window(128),continued_fractions(dichotomic)))": 476, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,approximation))))": 474, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,delta_largest))))": 473, "opt(dictionary(sliding_window(16),continued_fractions(binary)))": 443, "opt(dictionary(sliding_window(16),continued_fractions(co_binary)))": 443, "opt(dictionary(sliding_window(16),continued_fractions(dichotomic)))": 443, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,approximation))))": 445, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,delta_largest))))": 443, "opt(dictionary(sliding_window(32),continued_fractions(binary)))": 446, "opt(dictionary(sliding_window(32),continued_fractions(co_binary)))": 446, "opt(dictionary(sliding_window(32),continued_fractions(dichotomic)))": 446, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,approximation))))": 450, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,delta_largest))))": 445, "opt(dictionary(sliding_window(4),continued_fractions(binary)))": 474, "opt(dictionary(sliding_window(4),continued_fractions(co_binary)))": 474, "opt(dictionary(sliding_window(4),continued_fractions(dichotomic)))": 474, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,approximation))))": 474, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,delta_largest))))": 474, "opt(dictionary(sliding_window(64),continued_fractions(binary)))": 450, "opt(dictionary(sliding_window(64),continued_fractions(co_binary)))": 450, "opt(dictionary(sliding_window(64),continued_fractions(dichotomic)))": 450, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,approximation))))": 453, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,delta_largest))))": 455, "opt(dictionary(sliding_window(8),continued_fractions(binary)))": 450, "opt(dictionary(sliding_window(8),continued_fractions(co_binary)))": 450, "opt(dictionary(sliding_window(8),continued_fractions(dichotomic)))": 450, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,approximation))))": 452, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,delta_largest))))": 450, "opt(runs(continued_fractions(binary)))": 445, "opt(runs(continued_fractions(co_binary)))": 445, "opt(runs(continued_fractions(dichotomic)))": 445, "opt(runs(heuristic(use_first(halving,approximation))))": 444, "opt(runs(heuristic(use_first(halving,delta_largest))))": 444 }addchain-0.4.0/alg/ensemble/testdata/p41417_field.golden000066400000000000000000000353211514305256600226240ustar00rootroot00000000000000{ "opt(dictionary(hybrid(2,0),continued_fractions(binary)))": 620, "opt(dictionary(hybrid(2,0),continued_fractions(co_binary)))": 620, "opt(dictionary(hybrid(2,0),continued_fractions(dichotomic)))": 427, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,approximation))))": 620, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,delta_largest))))": 821, "opt(dictionary(hybrid(2,16),continued_fractions(binary)))": 446, "opt(dictionary(hybrid(2,16),continued_fractions(co_binary)))": 446, "opt(dictionary(hybrid(2,16),continued_fractions(dichotomic)))": 446, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,approximation))))": 446, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,delta_largest))))": 446, "opt(dictionary(hybrid(2,32),continued_fractions(binary)))": 435, "opt(dictionary(hybrid(2,32),continued_fractions(co_binary)))": 435, "opt(dictionary(hybrid(2,32),continued_fractions(dichotomic)))": 435, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,approximation))))": 435, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,delta_largest))))": 444, "opt(dictionary(hybrid(2,64),continued_fractions(binary)))": 430, "opt(dictionary(hybrid(2,64),continued_fractions(co_binary)))": 430, "opt(dictionary(hybrid(2,64),continued_fractions(dichotomic)))": 430, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,approximation))))": 430, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,delta_largest))))": 448, "opt(dictionary(hybrid(3,0),continued_fractions(binary)))": 620, "opt(dictionary(hybrid(3,0),continued_fractions(co_binary)))": 620, "opt(dictionary(hybrid(3,0),continued_fractions(dichotomic)))": 427, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,approximation))))": 620, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,delta_largest))))": 821, "opt(dictionary(hybrid(3,16),continued_fractions(binary)))": 446, "opt(dictionary(hybrid(3,16),continued_fractions(co_binary)))": 446, "opt(dictionary(hybrid(3,16),continued_fractions(dichotomic)))": 446, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,approximation))))": 446, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,delta_largest))))": 446, "opt(dictionary(hybrid(3,32),continued_fractions(binary)))": 435, "opt(dictionary(hybrid(3,32),continued_fractions(co_binary)))": 435, "opt(dictionary(hybrid(3,32),continued_fractions(dichotomic)))": 435, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,approximation))))": 435, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,delta_largest))))": 444, "opt(dictionary(hybrid(3,64),continued_fractions(binary)))": 430, "opt(dictionary(hybrid(3,64),continued_fractions(co_binary)))": 430, "opt(dictionary(hybrid(3,64),continued_fractions(dichotomic)))": 430, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,approximation))))": 430, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,delta_largest))))": 448, "opt(dictionary(hybrid(4,0),continued_fractions(binary)))": 620, "opt(dictionary(hybrid(4,0),continued_fractions(co_binary)))": 620, "opt(dictionary(hybrid(4,0),continued_fractions(dichotomic)))": 437, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,approximation))))": 519, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,delta_largest))))": 819, "opt(dictionary(hybrid(4,16),continued_fractions(binary)))": 446, "opt(dictionary(hybrid(4,16),continued_fractions(co_binary)))": 446, "opt(dictionary(hybrid(4,16),continued_fractions(dichotomic)))": 446, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,approximation))))": 445, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,delta_largest))))": 445, "opt(dictionary(hybrid(4,32),continued_fractions(binary)))": 434, "opt(dictionary(hybrid(4,32),continued_fractions(co_binary)))": 434, "opt(dictionary(hybrid(4,32),continued_fractions(dichotomic)))": 434, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,approximation))))": 434, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,delta_largest))))": 443, "opt(dictionary(hybrid(4,64),continued_fractions(binary)))": 431, "opt(dictionary(hybrid(4,64),continued_fractions(co_binary)))": 431, "opt(dictionary(hybrid(4,64),continued_fractions(dichotomic)))": 430, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,approximation))))": 429, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,delta_largest))))": 448, "opt(dictionary(hybrid(5,0),continued_fractions(binary)))": 620, "opt(dictionary(hybrid(5,0),continued_fractions(co_binary)))": 620, "opt(dictionary(hybrid(5,0),continued_fractions(dichotomic)))": 437, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,approximation))))": 519, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,delta_largest))))": 819, "opt(dictionary(hybrid(5,16),continued_fractions(binary)))": 446, "opt(dictionary(hybrid(5,16),continued_fractions(co_binary)))": 446, "opt(dictionary(hybrid(5,16),continued_fractions(dichotomic)))": 446, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,approximation))))": 445, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,delta_largest))))": 445, "opt(dictionary(hybrid(5,32),continued_fractions(binary)))": 434, "opt(dictionary(hybrid(5,32),continued_fractions(co_binary)))": 434, "opt(dictionary(hybrid(5,32),continued_fractions(dichotomic)))": 434, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,approximation))))": 434, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,delta_largest))))": 443, "opt(dictionary(hybrid(5,64),continued_fractions(binary)))": 431, "opt(dictionary(hybrid(5,64),continued_fractions(co_binary)))": 431, "opt(dictionary(hybrid(5,64),continued_fractions(dichotomic)))": 430, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,approximation))))": 429, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,delta_largest))))": 448, "opt(dictionary(hybrid(6,0),continued_fractions(binary)))": 620, "opt(dictionary(hybrid(6,0),continued_fractions(co_binary)))": 620, "opt(dictionary(hybrid(6,0),continued_fractions(dichotomic)))": 437, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,approximation))))": 519, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,delta_largest))))": 819, "opt(dictionary(hybrid(6,16),continued_fractions(binary)))": 446, "opt(dictionary(hybrid(6,16),continued_fractions(co_binary)))": 446, "opt(dictionary(hybrid(6,16),continued_fractions(dichotomic)))": 446, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,approximation))))": 445, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,delta_largest))))": 445, "opt(dictionary(hybrid(6,32),continued_fractions(binary)))": 434, "opt(dictionary(hybrid(6,32),continued_fractions(co_binary)))": 434, "opt(dictionary(hybrid(6,32),continued_fractions(dichotomic)))": 434, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,approximation))))": 434, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,delta_largest))))": 443, "opt(dictionary(hybrid(6,64),continued_fractions(binary)))": 431, "opt(dictionary(hybrid(6,64),continued_fractions(co_binary)))": 431, "opt(dictionary(hybrid(6,64),continued_fractions(dichotomic)))": 430, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,approximation))))": 429, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,delta_largest))))": 448, "opt(dictionary(hybrid(7,0),continued_fractions(binary)))": 620, "opt(dictionary(hybrid(7,0),continued_fractions(co_binary)))": 620, "opt(dictionary(hybrid(7,0),continued_fractions(dichotomic)))": 437, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,approximation))))": 519, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,delta_largest))))": 819, "opt(dictionary(hybrid(7,16),continued_fractions(binary)))": 446, "opt(dictionary(hybrid(7,16),continued_fractions(co_binary)))": 446, "opt(dictionary(hybrid(7,16),continued_fractions(dichotomic)))": 446, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,approximation))))": 445, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,delta_largest))))": 445, "opt(dictionary(hybrid(7,32),continued_fractions(binary)))": 434, "opt(dictionary(hybrid(7,32),continued_fractions(co_binary)))": 434, "opt(dictionary(hybrid(7,32),continued_fractions(dichotomic)))": 434, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,approximation))))": 434, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,delta_largest))))": 443, "opt(dictionary(hybrid(7,64),continued_fractions(binary)))": 431, "opt(dictionary(hybrid(7,64),continued_fractions(co_binary)))": 431, "opt(dictionary(hybrid(7,64),continued_fractions(dichotomic)))": 430, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,approximation))))": 429, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,delta_largest))))": 448, "opt(dictionary(hybrid(8,0),continued_fractions(binary)))": 620, "opt(dictionary(hybrid(8,0),continued_fractions(co_binary)))": 620, "opt(dictionary(hybrid(8,0),continued_fractions(dichotomic)))": 437, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,approximation))))": 519, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,delta_largest))))": 819, "opt(dictionary(hybrid(8,16),continued_fractions(binary)))": 446, "opt(dictionary(hybrid(8,16),continued_fractions(co_binary)))": 446, "opt(dictionary(hybrid(8,16),continued_fractions(dichotomic)))": 446, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,approximation))))": 445, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,delta_largest))))": 445, "opt(dictionary(hybrid(8,32),continued_fractions(binary)))": 434, "opt(dictionary(hybrid(8,32),continued_fractions(co_binary)))": 434, "opt(dictionary(hybrid(8,32),continued_fractions(dichotomic)))": 434, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,approximation))))": 434, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,delta_largest))))": 443, "opt(dictionary(hybrid(8,64),continued_fractions(binary)))": 431, "opt(dictionary(hybrid(8,64),continued_fractions(co_binary)))": 431, "opt(dictionary(hybrid(8,64),continued_fractions(dichotomic)))": 430, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,approximation))))": 429, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,delta_largest))))": 448, "opt(dictionary(run_length(0),continued_fractions(binary)))": 620, "opt(dictionary(run_length(0),continued_fractions(co_binary)))": 620, "opt(dictionary(run_length(0),continued_fractions(dichotomic)))": 427, "opt(dictionary(run_length(0),heuristic(use_first(halving,approximation))))": 620, "opt(dictionary(run_length(0),heuristic(use_first(halving,delta_largest))))": 821, "opt(dictionary(run_length(128),continued_fractions(binary)))": 433, "opt(dictionary(run_length(128),continued_fractions(co_binary)))": 433, "opt(dictionary(run_length(128),continued_fractions(dichotomic)))": 428, "opt(dictionary(run_length(128),heuristic(use_first(halving,approximation))))": 433, "opt(dictionary(run_length(128),heuristic(use_first(halving,delta_largest))))": 519, "opt(dictionary(run_length(16),continued_fractions(binary)))": 446, "opt(dictionary(run_length(16),continued_fractions(co_binary)))": 446, "opt(dictionary(run_length(16),continued_fractions(dichotomic)))": 446, "opt(dictionary(run_length(16),heuristic(use_first(halving,approximation))))": 446, "opt(dictionary(run_length(16),heuristic(use_first(halving,delta_largest))))": 446, "opt(dictionary(run_length(32),continued_fractions(binary)))": 435, "opt(dictionary(run_length(32),continued_fractions(co_binary)))": 435, "opt(dictionary(run_length(32),continued_fractions(dichotomic)))": 435, "opt(dictionary(run_length(32),heuristic(use_first(halving,approximation))))": 435, "opt(dictionary(run_length(32),heuristic(use_first(halving,delta_largest))))": 444, "opt(dictionary(run_length(64),continued_fractions(binary)))": 430, "opt(dictionary(run_length(64),continued_fractions(co_binary)))": 430, "opt(dictionary(run_length(64),continued_fractions(dichotomic)))": 430, "opt(dictionary(run_length(64),heuristic(use_first(halving,approximation))))": 430, "opt(dictionary(run_length(64),heuristic(use_first(halving,delta_largest))))": 448, "opt(dictionary(sliding_window(128),continued_fractions(binary)))": 449, "opt(dictionary(sliding_window(128),continued_fractions(co_binary)))": 449, "opt(dictionary(sliding_window(128),continued_fractions(dichotomic)))": 445, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,approximation))))": 430, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,delta_largest))))": 507, "opt(dictionary(sliding_window(16),continued_fractions(binary)))": 447, "opt(dictionary(sliding_window(16),continued_fractions(co_binary)))": 447, "opt(dictionary(sliding_window(16),continued_fractions(dichotomic)))": 446, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,approximation))))": 449, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,delta_largest))))": 449, "opt(dictionary(sliding_window(32),continued_fractions(binary)))": 441, "opt(dictionary(sliding_window(32),continued_fractions(co_binary)))": 441, "opt(dictionary(sliding_window(32),continued_fractions(dichotomic)))": 437, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,approximation))))": 435, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,delta_largest))))": 451, "opt(dictionary(sliding_window(4),continued_fractions(binary)))": 519, "opt(dictionary(sliding_window(4),continued_fractions(co_binary)))": 519, "opt(dictionary(sliding_window(4),continued_fractions(dichotomic)))": 519, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,approximation))))": 519, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,delta_largest))))": 519, "opt(dictionary(sliding_window(64),continued_fractions(binary)))": 439, "opt(dictionary(sliding_window(64),continued_fractions(co_binary)))": 439, "opt(dictionary(sliding_window(64),continued_fractions(dichotomic)))": 440, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,approximation))))": 431, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,delta_largest))))": 449, "opt(dictionary(sliding_window(8),continued_fractions(binary)))": 469, "opt(dictionary(sliding_window(8),continued_fractions(co_binary)))": 469, "opt(dictionary(sliding_window(8),continued_fractions(dichotomic)))": 468, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,approximation))))": 470, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,delta_largest))))": 470, "opt(runs(continued_fractions(binary)))": 427, "opt(runs(continued_fractions(co_binary)))": 427, "opt(runs(continued_fractions(dichotomic)))": 426, "opt(runs(heuristic(use_first(halving,approximation))))": 426, "opt(runs(heuristic(use_first(halving,delta_largest))))": 429 }addchain-0.4.0/alg/ensemble/testdata/p511187_field.golden000066400000000000000000000353311514305256600227130ustar00rootroot00000000000000{ "opt(dictionary(hybrid(2,0),continued_fractions(binary)))": 764, "opt(dictionary(hybrid(2,0),continued_fractions(co_binary)))": 764, "opt(dictionary(hybrid(2,0),continued_fractions(dichotomic)))": 527, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,approximation))))": 764, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,delta_largest))))": 1012, "opt(dictionary(hybrid(2,16),continued_fractions(binary)))": 549, "opt(dictionary(hybrid(2,16),continued_fractions(co_binary)))": 549, "opt(dictionary(hybrid(2,16),continued_fractions(dichotomic)))": 549, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,approximation))))": 549, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,delta_largest))))": 551, "opt(dictionary(hybrid(2,32),continued_fractions(binary)))": 534, "opt(dictionary(hybrid(2,32),continued_fractions(co_binary)))": 534, "opt(dictionary(hybrid(2,32),continued_fractions(dichotomic)))": 534, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,approximation))))": 534, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,delta_largest))))": 539, "opt(dictionary(hybrid(2,64),continued_fractions(binary)))": 531, "opt(dictionary(hybrid(2,64),continued_fractions(co_binary)))": 531, "opt(dictionary(hybrid(2,64),continued_fractions(dichotomic)))": 528, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,approximation))))": 531, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,delta_largest))))": 562, "opt(dictionary(hybrid(3,0),continued_fractions(binary)))": 764, "opt(dictionary(hybrid(3,0),continued_fractions(co_binary)))": 764, "opt(dictionary(hybrid(3,0),continued_fractions(dichotomic)))": 527, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,approximation))))": 764, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,delta_largest))))": 1012, "opt(dictionary(hybrid(3,16),continued_fractions(binary)))": 549, "opt(dictionary(hybrid(3,16),continued_fractions(co_binary)))": 549, "opt(dictionary(hybrid(3,16),continued_fractions(dichotomic)))": 549, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,approximation))))": 549, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,delta_largest))))": 551, "opt(dictionary(hybrid(3,32),continued_fractions(binary)))": 534, "opt(dictionary(hybrid(3,32),continued_fractions(co_binary)))": 534, "opt(dictionary(hybrid(3,32),continued_fractions(dichotomic)))": 534, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,approximation))))": 534, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,delta_largest))))": 539, "opt(dictionary(hybrid(3,64),continued_fractions(binary)))": 531, "opt(dictionary(hybrid(3,64),continued_fractions(co_binary)))": 531, "opt(dictionary(hybrid(3,64),continued_fractions(dichotomic)))": 528, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,approximation))))": 531, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,delta_largest))))": 562, "opt(dictionary(hybrid(4,0),continued_fractions(binary)))": 764, "opt(dictionary(hybrid(4,0),continued_fractions(co_binary)))": 764, "opt(dictionary(hybrid(4,0),continued_fractions(dichotomic)))": 527, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,approximation))))": 764, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,delta_largest))))": 1012, "opt(dictionary(hybrid(4,16),continued_fractions(binary)))": 549, "opt(dictionary(hybrid(4,16),continued_fractions(co_binary)))": 549, "opt(dictionary(hybrid(4,16),continued_fractions(dichotomic)))": 549, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,approximation))))": 549, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,delta_largest))))": 551, "opt(dictionary(hybrid(4,32),continued_fractions(binary)))": 534, "opt(dictionary(hybrid(4,32),continued_fractions(co_binary)))": 534, "opt(dictionary(hybrid(4,32),continued_fractions(dichotomic)))": 534, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,approximation))))": 534, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,delta_largest))))": 539, "opt(dictionary(hybrid(4,64),continued_fractions(binary)))": 531, "opt(dictionary(hybrid(4,64),continued_fractions(co_binary)))": 531, "opt(dictionary(hybrid(4,64),continued_fractions(dichotomic)))": 528, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,approximation))))": 531, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,delta_largest))))": 562, "opt(dictionary(hybrid(5,0),continued_fractions(binary)))": 764, "opt(dictionary(hybrid(5,0),continued_fractions(co_binary)))": 764, "opt(dictionary(hybrid(5,0),continued_fractions(dichotomic)))": 527, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,approximation))))": 764, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,delta_largest))))": 1012, "opt(dictionary(hybrid(5,16),continued_fractions(binary)))": 549, "opt(dictionary(hybrid(5,16),continued_fractions(co_binary)))": 549, "opt(dictionary(hybrid(5,16),continued_fractions(dichotomic)))": 549, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,approximation))))": 549, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,delta_largest))))": 551, "opt(dictionary(hybrid(5,32),continued_fractions(binary)))": 534, "opt(dictionary(hybrid(5,32),continued_fractions(co_binary)))": 534, "opt(dictionary(hybrid(5,32),continued_fractions(dichotomic)))": 534, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,approximation))))": 534, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,delta_largest))))": 539, "opt(dictionary(hybrid(5,64),continued_fractions(binary)))": 531, "opt(dictionary(hybrid(5,64),continued_fractions(co_binary)))": 531, "opt(dictionary(hybrid(5,64),continued_fractions(dichotomic)))": 528, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,approximation))))": 531, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,delta_largest))))": 562, "opt(dictionary(hybrid(6,0),continued_fractions(binary)))": 764, "opt(dictionary(hybrid(6,0),continued_fractions(co_binary)))": 764, "opt(dictionary(hybrid(6,0),continued_fractions(dichotomic)))": 528, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,approximation))))": 600, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,delta_largest))))": 1009, "opt(dictionary(hybrid(6,16),continued_fractions(binary)))": 550, "opt(dictionary(hybrid(6,16),continued_fractions(co_binary)))": 550, "opt(dictionary(hybrid(6,16),continued_fractions(dichotomic)))": 550, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,approximation))))": 549, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,delta_largest))))": 551, "opt(dictionary(hybrid(6,32),continued_fractions(binary)))": 538, "opt(dictionary(hybrid(6,32),continued_fractions(co_binary)))": 538, "opt(dictionary(hybrid(6,32),continued_fractions(dichotomic)))": 537, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,approximation))))": 536, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,delta_largest))))": 540, "opt(dictionary(hybrid(6,64),continued_fractions(binary)))": 531, "opt(dictionary(hybrid(6,64),continued_fractions(co_binary)))": 531, "opt(dictionary(hybrid(6,64),continued_fractions(dichotomic)))": 528, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,approximation))))": 531, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,delta_largest))))": 563, "opt(dictionary(hybrid(7,0),continued_fractions(binary)))": 764, "opt(dictionary(hybrid(7,0),continued_fractions(co_binary)))": 764, "opt(dictionary(hybrid(7,0),continued_fractions(dichotomic)))": 565, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,approximation))))": 587, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,delta_largest))))": 1006, "opt(dictionary(hybrid(7,16),continued_fractions(binary)))": 548, "opt(dictionary(hybrid(7,16),continued_fractions(co_binary)))": 548, "opt(dictionary(hybrid(7,16),continued_fractions(dichotomic)))": 548, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,approximation))))": 548, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,delta_largest))))": 551, "opt(dictionary(hybrid(7,32),continued_fractions(binary)))": 536, "opt(dictionary(hybrid(7,32),continued_fractions(co_binary)))": 536, "opt(dictionary(hybrid(7,32),continued_fractions(dichotomic)))": 536, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,approximation))))": 535, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,delta_largest))))": 539, "opt(dictionary(hybrid(7,64),continued_fractions(binary)))": 530, "opt(dictionary(hybrid(7,64),continued_fractions(co_binary)))": 530, "opt(dictionary(hybrid(7,64),continued_fractions(dichotomic)))": 528, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,approximation))))": 530, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,delta_largest))))": 562, "opt(dictionary(hybrid(8,0),continued_fractions(binary)))": 764, "opt(dictionary(hybrid(8,0),continued_fractions(co_binary)))": 764, "opt(dictionary(hybrid(8,0),continued_fractions(dichotomic)))": 565, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,approximation))))": 587, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,delta_largest))))": 1006, "opt(dictionary(hybrid(8,16),continued_fractions(binary)))": 548, "opt(dictionary(hybrid(8,16),continued_fractions(co_binary)))": 548, "opt(dictionary(hybrid(8,16),continued_fractions(dichotomic)))": 548, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,approximation))))": 548, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,delta_largest))))": 551, "opt(dictionary(hybrid(8,32),continued_fractions(binary)))": 536, "opt(dictionary(hybrid(8,32),continued_fractions(co_binary)))": 536, "opt(dictionary(hybrid(8,32),continued_fractions(dichotomic)))": 536, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,approximation))))": 535, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,delta_largest))))": 539, "opt(dictionary(hybrid(8,64),continued_fractions(binary)))": 530, "opt(dictionary(hybrid(8,64),continued_fractions(co_binary)))": 530, "opt(dictionary(hybrid(8,64),continued_fractions(dichotomic)))": 528, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,approximation))))": 530, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,delta_largest))))": 562, "opt(dictionary(run_length(0),continued_fractions(binary)))": 764, "opt(dictionary(run_length(0),continued_fractions(co_binary)))": 764, "opt(dictionary(run_length(0),continued_fractions(dichotomic)))": 527, "opt(dictionary(run_length(0),heuristic(use_first(halving,approximation))))": 764, "opt(dictionary(run_length(0),heuristic(use_first(halving,delta_largest))))": 1012, "opt(dictionary(run_length(128),continued_fractions(binary)))": 534, "opt(dictionary(run_length(128),continued_fractions(co_binary)))": 534, "opt(dictionary(run_length(128),continued_fractions(dichotomic)))": 526, "opt(dictionary(run_length(128),heuristic(use_first(halving,approximation))))": 534, "opt(dictionary(run_length(128),heuristic(use_first(halving,delta_largest))))": 623, "opt(dictionary(run_length(16),continued_fractions(binary)))": 549, "opt(dictionary(run_length(16),continued_fractions(co_binary)))": 549, "opt(dictionary(run_length(16),continued_fractions(dichotomic)))": 549, "opt(dictionary(run_length(16),heuristic(use_first(halving,approximation))))": 549, "opt(dictionary(run_length(16),heuristic(use_first(halving,delta_largest))))": 551, "opt(dictionary(run_length(32),continued_fractions(binary)))": 534, "opt(dictionary(run_length(32),continued_fractions(co_binary)))": 534, "opt(dictionary(run_length(32),continued_fractions(dichotomic)))": 534, "opt(dictionary(run_length(32),heuristic(use_first(halving,approximation))))": 534, "opt(dictionary(run_length(32),heuristic(use_first(halving,delta_largest))))": 539, "opt(dictionary(run_length(64),continued_fractions(binary)))": 531, "opt(dictionary(run_length(64),continued_fractions(co_binary)))": 531, "opt(dictionary(run_length(64),continued_fractions(dichotomic)))": 528, "opt(dictionary(run_length(64),heuristic(use_first(halving,approximation))))": 531, "opt(dictionary(run_length(64),heuristic(use_first(halving,delta_largest))))": 562, "opt(dictionary(sliding_window(128),continued_fractions(binary)))": 580, "opt(dictionary(sliding_window(128),continued_fractions(co_binary)))": 580, "opt(dictionary(sliding_window(128),continued_fractions(dichotomic)))": 540, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,approximation))))": 542, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,delta_largest))))": 633, "opt(dictionary(sliding_window(16),continued_fractions(binary)))": 552, "opt(dictionary(sliding_window(16),continued_fractions(co_binary)))": 552, "opt(dictionary(sliding_window(16),continued_fractions(dichotomic)))": 550, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,approximation))))": 549, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,delta_largest))))": 549, "opt(dictionary(sliding_window(32),continued_fractions(binary)))": 544, "opt(dictionary(sliding_window(32),continued_fractions(co_binary)))": 544, "opt(dictionary(sliding_window(32),continued_fractions(dichotomic)))": 539, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,approximation))))": 542, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,delta_largest))))": 549, "opt(dictionary(sliding_window(4),continued_fractions(binary)))": 640, "opt(dictionary(sliding_window(4),continued_fractions(co_binary)))": 640, "opt(dictionary(sliding_window(4),continued_fractions(dichotomic)))": 640, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,approximation))))": 640, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,delta_largest))))": 640, "opt(dictionary(sliding_window(64),continued_fractions(binary)))": 554, "opt(dictionary(sliding_window(64),continued_fractions(co_binary)))": 554, "opt(dictionary(sliding_window(64),continued_fractions(dichotomic)))": 541, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,approximation))))": 538, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,delta_largest))))": 573, "opt(dictionary(sliding_window(8),continued_fractions(binary)))": 578, "opt(dictionary(sliding_window(8),continued_fractions(co_binary)))": 578, "opt(dictionary(sliding_window(8),continued_fractions(dichotomic)))": 578, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,approximation))))": 578, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,delta_largest))))": 578, "opt(runs(continued_fractions(binary)))": 527, "opt(runs(continued_fractions(co_binary)))": 527, "opt(runs(continued_fractions(dichotomic)))": 525, "opt(runs(heuristic(use_first(halving,approximation))))": 526, "opt(runs(heuristic(use_first(halving,delta_largest))))": 528 }addchain-0.4.0/alg/ensemble/testdata/secp192k1_field.golden000066400000000000000000000353211514305256600234060ustar00rootroot00000000000000{ "opt(dictionary(hybrid(2,0),continued_fractions(binary)))": 210, "opt(dictionary(hybrid(2,0),continued_fractions(co_binary)))": 210, "opt(dictionary(hybrid(2,0),continued_fractions(dichotomic)))": 206, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,approximation))))": 210, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,delta_largest))))": 328, "opt(dictionary(hybrid(2,16),continued_fractions(binary)))": 213, "opt(dictionary(hybrid(2,16),continued_fractions(co_binary)))": 213, "opt(dictionary(hybrid(2,16),continued_fractions(dichotomic)))": 212, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,approximation))))": 213, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,delta_largest))))": 217, "opt(dictionary(hybrid(2,32),continued_fractions(binary)))": 208, "opt(dictionary(hybrid(2,32),continued_fractions(co_binary)))": 208, "opt(dictionary(hybrid(2,32),continued_fractions(dichotomic)))": 208, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,approximation))))": 208, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,delta_largest))))": 208, "opt(dictionary(hybrid(2,64),continued_fractions(binary)))": 207, "opt(dictionary(hybrid(2,64),continued_fractions(co_binary)))": 207, "opt(dictionary(hybrid(2,64),continued_fractions(dichotomic)))": 207, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,approximation))))": 207, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,delta_largest))))": 210, "opt(dictionary(hybrid(3,0),continued_fractions(binary)))": 209, "opt(dictionary(hybrid(3,0),continued_fractions(co_binary)))": 209, "opt(dictionary(hybrid(3,0),continued_fractions(dichotomic)))": 205, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,approximation))))": 209, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,delta_largest))))": 327, "opt(dictionary(hybrid(3,16),continued_fractions(binary)))": 212, "opt(dictionary(hybrid(3,16),continued_fractions(co_binary)))": 212, "opt(dictionary(hybrid(3,16),continued_fractions(dichotomic)))": 211, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,approximation))))": 212, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,delta_largest))))": 216, "opt(dictionary(hybrid(3,32),continued_fractions(binary)))": 207, "opt(dictionary(hybrid(3,32),continued_fractions(co_binary)))": 207, "opt(dictionary(hybrid(3,32),continued_fractions(dichotomic)))": 207, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,approximation))))": 207, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,delta_largest))))": 207, "opt(dictionary(hybrid(3,64),continued_fractions(binary)))": 206, "opt(dictionary(hybrid(3,64),continued_fractions(co_binary)))": 206, "opt(dictionary(hybrid(3,64),continued_fractions(dichotomic)))": 206, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,approximation))))": 206, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,delta_largest))))": 209, "opt(dictionary(hybrid(4,0),continued_fractions(binary)))": 210, "opt(dictionary(hybrid(4,0),continued_fractions(co_binary)))": 210, "opt(dictionary(hybrid(4,0),continued_fractions(dichotomic)))": 206, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,approximation))))": 210, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,delta_largest))))": 328, "opt(dictionary(hybrid(4,16),continued_fractions(binary)))": 214, "opt(dictionary(hybrid(4,16),continued_fractions(co_binary)))": 214, "opt(dictionary(hybrid(4,16),continued_fractions(dichotomic)))": 212, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,approximation))))": 212, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,delta_largest))))": 218, "opt(dictionary(hybrid(4,32),continued_fractions(binary)))": 208, "opt(dictionary(hybrid(4,32),continued_fractions(co_binary)))": 208, "opt(dictionary(hybrid(4,32),continued_fractions(dichotomic)))": 208, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,approximation))))": 208, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,delta_largest))))": 208, "opt(dictionary(hybrid(4,64),continued_fractions(binary)))": 207, "opt(dictionary(hybrid(4,64),continued_fractions(co_binary)))": 207, "opt(dictionary(hybrid(4,64),continued_fractions(dichotomic)))": 207, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,approximation))))": 207, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,delta_largest))))": 210, "opt(dictionary(hybrid(5,0),continued_fractions(binary)))": 210, "opt(dictionary(hybrid(5,0),continued_fractions(co_binary)))": 210, "opt(dictionary(hybrid(5,0),continued_fractions(dichotomic)))": 206, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,approximation))))": 210, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,delta_largest))))": 328, "opt(dictionary(hybrid(5,16),continued_fractions(binary)))": 214, "opt(dictionary(hybrid(5,16),continued_fractions(co_binary)))": 214, "opt(dictionary(hybrid(5,16),continued_fractions(dichotomic)))": 213, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,approximation))))": 213, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,delta_largest))))": 216, "opt(dictionary(hybrid(5,32),continued_fractions(binary)))": 208, "opt(dictionary(hybrid(5,32),continued_fractions(co_binary)))": 208, "opt(dictionary(hybrid(5,32),continued_fractions(dichotomic)))": 208, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,approximation))))": 208, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,delta_largest))))": 208, "opt(dictionary(hybrid(5,64),continued_fractions(binary)))": 207, "opt(dictionary(hybrid(5,64),continued_fractions(co_binary)))": 207, "opt(dictionary(hybrid(5,64),continued_fractions(dichotomic)))": 207, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,approximation))))": 207, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,delta_largest))))": 210, "opt(dictionary(hybrid(6,0),continued_fractions(binary)))": 210, "opt(dictionary(hybrid(6,0),continued_fractions(co_binary)))": 210, "opt(dictionary(hybrid(6,0),continued_fractions(dichotomic)))": 206, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,approximation))))": 211, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,delta_largest))))": 329, "opt(dictionary(hybrid(6,16),continued_fractions(binary)))": 214, "opt(dictionary(hybrid(6,16),continued_fractions(co_binary)))": 214, "opt(dictionary(hybrid(6,16),continued_fractions(dichotomic)))": 213, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,approximation))))": 212, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,delta_largest))))": 214, "opt(dictionary(hybrid(6,32),continued_fractions(binary)))": 208, "opt(dictionary(hybrid(6,32),continued_fractions(co_binary)))": 208, "opt(dictionary(hybrid(6,32),continued_fractions(dichotomic)))": 208, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,approximation))))": 209, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,delta_largest))))": 209, "opt(dictionary(hybrid(6,64),continued_fractions(binary)))": 207, "opt(dictionary(hybrid(6,64),continued_fractions(co_binary)))": 207, "opt(dictionary(hybrid(6,64),continued_fractions(dichotomic)))": 207, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,approximation))))": 208, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,delta_largest))))": 211, "opt(dictionary(hybrid(7,0),continued_fractions(binary)))": 210, "opt(dictionary(hybrid(7,0),continued_fractions(co_binary)))": 210, "opt(dictionary(hybrid(7,0),continued_fractions(dichotomic)))": 206, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,approximation))))": 211, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,delta_largest))))": 329, "opt(dictionary(hybrid(7,16),continued_fractions(binary)))": 214, "opt(dictionary(hybrid(7,16),continued_fractions(co_binary)))": 214, "opt(dictionary(hybrid(7,16),continued_fractions(dichotomic)))": 214, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,approximation))))": 213, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,delta_largest))))": 213, "opt(dictionary(hybrid(7,32),continued_fractions(binary)))": 208, "opt(dictionary(hybrid(7,32),continued_fractions(co_binary)))": 208, "opt(dictionary(hybrid(7,32),continued_fractions(dichotomic)))": 208, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,approximation))))": 209, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,delta_largest))))": 208, "opt(dictionary(hybrid(7,64),continued_fractions(binary)))": 208, "opt(dictionary(hybrid(7,64),continued_fractions(co_binary)))": 208, "opt(dictionary(hybrid(7,64),continued_fractions(dichotomic)))": 208, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,approximation))))": 208, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,delta_largest))))": 209, "opt(dictionary(hybrid(8,0),continued_fractions(binary)))": 212, "opt(dictionary(hybrid(8,0),continued_fractions(co_binary)))": 212, "opt(dictionary(hybrid(8,0),continued_fractions(dichotomic)))": 209, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,approximation))))": 212, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,delta_largest))))": 329, "opt(dictionary(hybrid(8,16),continued_fractions(binary)))": 214, "opt(dictionary(hybrid(8,16),continued_fractions(co_binary)))": 214, "opt(dictionary(hybrid(8,16),continued_fractions(dichotomic)))": 214, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,approximation))))": 213, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,delta_largest))))": 213, "opt(dictionary(hybrid(8,32),continued_fractions(binary)))": 209, "opt(dictionary(hybrid(8,32),continued_fractions(co_binary)))": 209, "opt(dictionary(hybrid(8,32),continued_fractions(dichotomic)))": 209, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,approximation))))": 210, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,delta_largest))))": 209, "opt(dictionary(hybrid(8,64),continued_fractions(binary)))": 208, "opt(dictionary(hybrid(8,64),continued_fractions(co_binary)))": 208, "opt(dictionary(hybrid(8,64),continued_fractions(dichotomic)))": 208, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,approximation))))": 209, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,delta_largest))))": 210, "opt(dictionary(run_length(0),continued_fractions(binary)))": 210, "opt(dictionary(run_length(0),continued_fractions(co_binary)))": 210, "opt(dictionary(run_length(0),continued_fractions(dichotomic)))": 206, "opt(dictionary(run_length(0),heuristic(use_first(halving,approximation))))": 210, "opt(dictionary(run_length(0),heuristic(use_first(halving,delta_largest))))": 328, "opt(dictionary(run_length(128),continued_fractions(binary)))": 209, "opt(dictionary(run_length(128),continued_fractions(co_binary)))": 209, "opt(dictionary(run_length(128),continued_fractions(dichotomic)))": 208, "opt(dictionary(run_length(128),heuristic(use_first(halving,approximation))))": 209, "opt(dictionary(run_length(128),heuristic(use_first(halving,delta_largest))))": 274, "opt(dictionary(run_length(16),continued_fractions(binary)))": 213, "opt(dictionary(run_length(16),continued_fractions(co_binary)))": 213, "opt(dictionary(run_length(16),continued_fractions(dichotomic)))": 212, "opt(dictionary(run_length(16),heuristic(use_first(halving,approximation))))": 213, "opt(dictionary(run_length(16),heuristic(use_first(halving,delta_largest))))": 217, "opt(dictionary(run_length(32),continued_fractions(binary)))": 208, "opt(dictionary(run_length(32),continued_fractions(co_binary)))": 208, "opt(dictionary(run_length(32),continued_fractions(dichotomic)))": 208, "opt(dictionary(run_length(32),heuristic(use_first(halving,approximation))))": 208, "opt(dictionary(run_length(32),heuristic(use_first(halving,delta_largest))))": 208, "opt(dictionary(run_length(64),continued_fractions(binary)))": 207, "opt(dictionary(run_length(64),continued_fractions(co_binary)))": 207, "opt(dictionary(run_length(64),continued_fractions(dichotomic)))": 207, "opt(dictionary(run_length(64),heuristic(use_first(halving,approximation))))": 207, "opt(dictionary(run_length(64),heuristic(use_first(halving,delta_largest))))": 210, "opt(dictionary(sliding_window(128),continued_fractions(binary)))": 236, "opt(dictionary(sliding_window(128),continued_fractions(co_binary)))": 236, "opt(dictionary(sliding_window(128),continued_fractions(dichotomic)))": 239, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,approximation))))": 216, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,delta_largest))))": 213, "opt(dictionary(sliding_window(16),continued_fractions(binary)))": 213, "opt(dictionary(sliding_window(16),continued_fractions(co_binary)))": 213, "opt(dictionary(sliding_window(16),continued_fractions(dichotomic)))": 213, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,approximation))))": 212, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,delta_largest))))": 214, "opt(dictionary(sliding_window(32),continued_fractions(binary)))": 214, "opt(dictionary(sliding_window(32),continued_fractions(co_binary)))": 214, "opt(dictionary(sliding_window(32),continued_fractions(dichotomic)))": 212, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,approximation))))": 213, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,delta_largest))))": 217, "opt(dictionary(sliding_window(4),continued_fractions(binary)))": 241, "opt(dictionary(sliding_window(4),continued_fractions(co_binary)))": 241, "opt(dictionary(sliding_window(4),continued_fractions(dichotomic)))": 241, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,approximation))))": 241, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,delta_largest))))": 241, "opt(dictionary(sliding_window(64),continued_fractions(binary)))": 237, "opt(dictionary(sliding_window(64),continued_fractions(co_binary)))": 237, "opt(dictionary(sliding_window(64),continued_fractions(dichotomic)))": 222, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,approximation))))": 216, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,delta_largest))))": 213, "opt(dictionary(sliding_window(8),continued_fractions(binary)))": 220, "opt(dictionary(sliding_window(8),continued_fractions(co_binary)))": 220, "opt(dictionary(sliding_window(8),continued_fractions(dichotomic)))": 220, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,approximation))))": 222, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,delta_largest))))": 222, "opt(runs(continued_fractions(binary)))": 206, "opt(runs(continued_fractions(co_binary)))": 206, "opt(runs(continued_fractions(dichotomic)))": 206, "opt(runs(heuristic(use_first(halving,approximation))))": 207, "opt(runs(heuristic(use_first(halving,delta_largest))))": 207 }addchain-0.4.0/alg/ensemble/testdata/secp224k1_field.golden000066400000000000000000000353211514305256600234020ustar00rootroot00000000000000{ "opt(dictionary(hybrid(2,0),continued_fractions(binary)))": 249, "opt(dictionary(hybrid(2,0),continued_fractions(co_binary)))": 249, "opt(dictionary(hybrid(2,0),continued_fractions(dichotomic)))": 240, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,approximation))))": 249, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,delta_largest))))": 397, "opt(dictionary(hybrid(2,16),continued_fractions(binary)))": 248, "opt(dictionary(hybrid(2,16),continued_fractions(co_binary)))": 248, "opt(dictionary(hybrid(2,16),continued_fractions(dichotomic)))": 247, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,approximation))))": 248, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,delta_largest))))": 252, "opt(dictionary(hybrid(2,32),continued_fractions(binary)))": 242, "opt(dictionary(hybrid(2,32),continued_fractions(co_binary)))": 242, "opt(dictionary(hybrid(2,32),continued_fractions(dichotomic)))": 242, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,approximation))))": 242, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,delta_largest))))": 242, "opt(dictionary(hybrid(2,64),continued_fractions(binary)))": 241, "opt(dictionary(hybrid(2,64),continued_fractions(co_binary)))": 241, "opt(dictionary(hybrid(2,64),continued_fractions(dichotomic)))": 241, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,approximation))))": 241, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,delta_largest))))": 271, "opt(dictionary(hybrid(3,0),continued_fractions(binary)))": 248, "opt(dictionary(hybrid(3,0),continued_fractions(co_binary)))": 248, "opt(dictionary(hybrid(3,0),continued_fractions(dichotomic)))": 240, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,approximation))))": 246, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,delta_largest))))": 395, "opt(dictionary(hybrid(3,16),continued_fractions(binary)))": 247, "opt(dictionary(hybrid(3,16),continued_fractions(co_binary)))": 247, "opt(dictionary(hybrid(3,16),continued_fractions(dichotomic)))": 246, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,approximation))))": 247, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,delta_largest))))": 251, "opt(dictionary(hybrid(3,32),continued_fractions(binary)))": 241, "opt(dictionary(hybrid(3,32),continued_fractions(co_binary)))": 241, "opt(dictionary(hybrid(3,32),continued_fractions(dichotomic)))": 241, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,approximation))))": 241, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,delta_largest))))": 241, "opt(dictionary(hybrid(3,64),continued_fractions(binary)))": 240, "opt(dictionary(hybrid(3,64),continued_fractions(co_binary)))": 240, "opt(dictionary(hybrid(3,64),continued_fractions(dichotomic)))": 240, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,approximation))))": 240, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,delta_largest))))": 270, "opt(dictionary(hybrid(4,0),continued_fractions(binary)))": 247, "opt(dictionary(hybrid(4,0),continued_fractions(co_binary)))": 247, "opt(dictionary(hybrid(4,0),continued_fractions(dichotomic)))": 241, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,approximation))))": 245, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,delta_largest))))": 398, "opt(dictionary(hybrid(4,16),continued_fractions(binary)))": 249, "opt(dictionary(hybrid(4,16),continued_fractions(co_binary)))": 249, "opt(dictionary(hybrid(4,16),continued_fractions(dichotomic)))": 247, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,approximation))))": 247, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,delta_largest))))": 252, "opt(dictionary(hybrid(4,32),continued_fractions(binary)))": 240, "opt(dictionary(hybrid(4,32),continued_fractions(co_binary)))": 240, "opt(dictionary(hybrid(4,32),continued_fractions(dichotomic)))": 240, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,approximation))))": 242, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,delta_largest))))": 242, "opt(dictionary(hybrid(4,64),continued_fractions(binary)))": 240, "opt(dictionary(hybrid(4,64),continued_fractions(co_binary)))": 240, "opt(dictionary(hybrid(4,64),continued_fractions(dichotomic)))": 240, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,approximation))))": 241, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,delta_largest))))": 270, "opt(dictionary(hybrid(5,0),continued_fractions(binary)))": 245, "opt(dictionary(hybrid(5,0),continued_fractions(co_binary)))": 245, "opt(dictionary(hybrid(5,0),continued_fractions(dichotomic)))": 238, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,approximation))))": 245, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,delta_largest))))": 396, "opt(dictionary(hybrid(5,16),continued_fractions(binary)))": 246, "opt(dictionary(hybrid(5,16),continued_fractions(co_binary)))": 246, "opt(dictionary(hybrid(5,16),continued_fractions(dichotomic)))": 245, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,approximation))))": 246, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,delta_largest))))": 249, "opt(dictionary(hybrid(5,32),continued_fractions(binary)))": 241, "opt(dictionary(hybrid(5,32),continued_fractions(co_binary)))": 241, "opt(dictionary(hybrid(5,32),continued_fractions(dichotomic)))": 241, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,approximation))))": 240, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,delta_largest))))": 240, "opt(dictionary(hybrid(5,64),continued_fractions(binary)))": 239, "opt(dictionary(hybrid(5,64),continued_fractions(co_binary)))": 239, "opt(dictionary(hybrid(5,64),continued_fractions(dichotomic)))": 239, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,approximation))))": 240, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,delta_largest))))": 268, "opt(dictionary(hybrid(6,0),continued_fractions(binary)))": 247, "opt(dictionary(hybrid(6,0),continued_fractions(co_binary)))": 247, "opt(dictionary(hybrid(6,0),continued_fractions(dichotomic)))": 241, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,approximation))))": 244, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,delta_largest))))": 391, "opt(dictionary(hybrid(6,16),continued_fractions(binary)))": 251, "opt(dictionary(hybrid(6,16),continued_fractions(co_binary)))": 251, "opt(dictionary(hybrid(6,16),continued_fractions(dichotomic)))": 250, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,approximation))))": 247, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,delta_largest))))": 249, "opt(dictionary(hybrid(6,32),continued_fractions(binary)))": 241, "opt(dictionary(hybrid(6,32),continued_fractions(co_binary)))": 241, "opt(dictionary(hybrid(6,32),continued_fractions(dichotomic)))": 241, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,approximation))))": 242, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,delta_largest))))": 241, "opt(dictionary(hybrid(6,64),continued_fractions(binary)))": 239, "opt(dictionary(hybrid(6,64),continued_fractions(co_binary)))": 239, "opt(dictionary(hybrid(6,64),continued_fractions(dichotomic)))": 239, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,approximation))))": 240, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,delta_largest))))": 269, "opt(dictionary(hybrid(7,0),continued_fractions(binary)))": 247, "opt(dictionary(hybrid(7,0),continued_fractions(co_binary)))": 247, "opt(dictionary(hybrid(7,0),continued_fractions(dichotomic)))": 241, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,approximation))))": 244, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,delta_largest))))": 391, "opt(dictionary(hybrid(7,16),continued_fractions(binary)))": 251, "opt(dictionary(hybrid(7,16),continued_fractions(co_binary)))": 251, "opt(dictionary(hybrid(7,16),continued_fractions(dichotomic)))": 250, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,approximation))))": 247, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,delta_largest))))": 249, "opt(dictionary(hybrid(7,32),continued_fractions(binary)))": 241, "opt(dictionary(hybrid(7,32),continued_fractions(co_binary)))": 241, "opt(dictionary(hybrid(7,32),continued_fractions(dichotomic)))": 241, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,approximation))))": 242, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,delta_largest))))": 241, "opt(dictionary(hybrid(7,64),continued_fractions(binary)))": 239, "opt(dictionary(hybrid(7,64),continued_fractions(co_binary)))": 239, "opt(dictionary(hybrid(7,64),continued_fractions(dichotomic)))": 239, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,approximation))))": 240, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,delta_largest))))": 269, "opt(dictionary(hybrid(8,0),continued_fractions(binary)))": 248, "opt(dictionary(hybrid(8,0),continued_fractions(co_binary)))": 248, "opt(dictionary(hybrid(8,0),continued_fractions(dichotomic)))": 241, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,approximation))))": 244, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,delta_largest))))": 390, "opt(dictionary(hybrid(8,16),continued_fractions(binary)))": 249, "opt(dictionary(hybrid(8,16),continued_fractions(co_binary)))": 249, "opt(dictionary(hybrid(8,16),continued_fractions(dichotomic)))": 249, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,approximation))))": 246, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,delta_largest))))": 245, "opt(dictionary(hybrid(8,32),continued_fractions(binary)))": 243, "opt(dictionary(hybrid(8,32),continued_fractions(co_binary)))": 243, "opt(dictionary(hybrid(8,32),continued_fractions(dichotomic)))": 242, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,approximation))))": 244, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,delta_largest))))": 241, "opt(dictionary(hybrid(8,64),continued_fractions(binary)))": 244, "opt(dictionary(hybrid(8,64),continued_fractions(co_binary)))": 244, "opt(dictionary(hybrid(8,64),continued_fractions(dichotomic)))": 242, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,approximation))))": 242, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,delta_largest))))": 269, "opt(dictionary(run_length(0),continued_fractions(binary)))": 249, "opt(dictionary(run_length(0),continued_fractions(co_binary)))": 249, "opt(dictionary(run_length(0),continued_fractions(dichotomic)))": 240, "opt(dictionary(run_length(0),heuristic(use_first(halving,approximation))))": 249, "opt(dictionary(run_length(0),heuristic(use_first(halving,delta_largest))))": 397, "opt(dictionary(run_length(128),continued_fractions(binary)))": 241, "opt(dictionary(run_length(128),continued_fractions(co_binary)))": 241, "opt(dictionary(run_length(128),continued_fractions(dichotomic)))": 241, "opt(dictionary(run_length(128),heuristic(use_first(halving,approximation))))": 241, "opt(dictionary(run_length(128),heuristic(use_first(halving,delta_largest))))": 273, "opt(dictionary(run_length(16),continued_fractions(binary)))": 248, "opt(dictionary(run_length(16),continued_fractions(co_binary)))": 248, "opt(dictionary(run_length(16),continued_fractions(dichotomic)))": 247, "opt(dictionary(run_length(16),heuristic(use_first(halving,approximation))))": 248, "opt(dictionary(run_length(16),heuristic(use_first(halving,delta_largest))))": 252, "opt(dictionary(run_length(32),continued_fractions(binary)))": 242, "opt(dictionary(run_length(32),continued_fractions(co_binary)))": 242, "opt(dictionary(run_length(32),continued_fractions(dichotomic)))": 242, "opt(dictionary(run_length(32),heuristic(use_first(halving,approximation))))": 242, "opt(dictionary(run_length(32),heuristic(use_first(halving,delta_largest))))": 242, "opt(dictionary(run_length(64),continued_fractions(binary)))": 241, "opt(dictionary(run_length(64),continued_fractions(co_binary)))": 241, "opt(dictionary(run_length(64),continued_fractions(dichotomic)))": 241, "opt(dictionary(run_length(64),heuristic(use_first(halving,approximation))))": 241, "opt(dictionary(run_length(64),heuristic(use_first(halving,delta_largest))))": 271, "opt(dictionary(sliding_window(128),continued_fractions(binary)))": 287, "opt(dictionary(sliding_window(128),continued_fractions(co_binary)))": 287, "opt(dictionary(sliding_window(128),continued_fractions(dichotomic)))": 272, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,approximation))))": 275, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,delta_largest))))": 279, "opt(dictionary(sliding_window(16),continued_fractions(binary)))": 248, "opt(dictionary(sliding_window(16),continued_fractions(co_binary)))": 248, "opt(dictionary(sliding_window(16),continued_fractions(dichotomic)))": 248, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,approximation))))": 248, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,delta_largest))))": 247, "opt(dictionary(sliding_window(32),continued_fractions(binary)))": 248, "opt(dictionary(sliding_window(32),continued_fractions(co_binary)))": 248, "opt(dictionary(sliding_window(32),continued_fractions(dichotomic)))": 244, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,approximation))))": 248, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,delta_largest))))": 249, "opt(dictionary(sliding_window(4),continued_fractions(binary)))": 282, "opt(dictionary(sliding_window(4),continued_fractions(co_binary)))": 282, "opt(dictionary(sliding_window(4),continued_fractions(dichotomic)))": 282, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,approximation))))": 282, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,delta_largest))))": 282, "opt(dictionary(sliding_window(64),continued_fractions(binary)))": 253, "opt(dictionary(sliding_window(64),continued_fractions(co_binary)))": 253, "opt(dictionary(sliding_window(64),continued_fractions(dichotomic)))": 254, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,approximation))))": 247, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,delta_largest))))": 248, "opt(dictionary(sliding_window(8),continued_fractions(binary)))": 257, "opt(dictionary(sliding_window(8),continued_fractions(co_binary)))": 257, "opt(dictionary(sliding_window(8),continued_fractions(dichotomic)))": 257, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,approximation))))": 257, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,delta_largest))))": 256, "opt(runs(continued_fractions(binary)))": 240, "opt(runs(continued_fractions(co_binary)))": 240, "opt(runs(continued_fractions(dichotomic)))": 240, "opt(runs(heuristic(use_first(halving,approximation))))": 241, "opt(runs(heuristic(use_first(halving,delta_largest))))": 241 }addchain-0.4.0/alg/ensemble/testdata/secp256k1_field.golden000066400000000000000000000353211514305256600234070ustar00rootroot00000000000000{ "opt(dictionary(hybrid(2,0),continued_fractions(binary)))": 277, "opt(dictionary(hybrid(2,0),continued_fractions(co_binary)))": 277, "opt(dictionary(hybrid(2,0),continued_fractions(dichotomic)))": 270, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,approximation))))": 277, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,delta_largest))))": 457, "opt(dictionary(hybrid(2,16),continued_fractions(binary)))": 278, "opt(dictionary(hybrid(2,16),continued_fractions(co_binary)))": 278, "opt(dictionary(hybrid(2,16),continued_fractions(dichotomic)))": 278, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,approximation))))": 278, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,delta_largest))))": 280, "opt(dictionary(hybrid(2,32),continued_fractions(binary)))": 272, "opt(dictionary(hybrid(2,32),continued_fractions(co_binary)))": 272, "opt(dictionary(hybrid(2,32),continued_fractions(dichotomic)))": 272, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,approximation))))": 272, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,delta_largest))))": 276, "opt(dictionary(hybrid(2,64),continued_fractions(binary)))": 270, "opt(dictionary(hybrid(2,64),continued_fractions(co_binary)))": 270, "opt(dictionary(hybrid(2,64),continued_fractions(dichotomic)))": 270, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,approximation))))": 270, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,delta_largest))))": 277, "opt(dictionary(hybrid(3,0),continued_fractions(binary)))": 277, "opt(dictionary(hybrid(3,0),continued_fractions(co_binary)))": 277, "opt(dictionary(hybrid(3,0),continued_fractions(dichotomic)))": 270, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,approximation))))": 277, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,delta_largest))))": 458, "opt(dictionary(hybrid(3,16),continued_fractions(binary)))": 278, "opt(dictionary(hybrid(3,16),continued_fractions(co_binary)))": 278, "opt(dictionary(hybrid(3,16),continued_fractions(dichotomic)))": 278, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,approximation))))": 278, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,delta_largest))))": 280, "opt(dictionary(hybrid(3,32),continued_fractions(binary)))": 272, "opt(dictionary(hybrid(3,32),continued_fractions(co_binary)))": 272, "opt(dictionary(hybrid(3,32),continued_fractions(dichotomic)))": 272, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,approximation))))": 273, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,delta_largest))))": 277, "opt(dictionary(hybrid(3,64),continued_fractions(binary)))": 270, "opt(dictionary(hybrid(3,64),continued_fractions(co_binary)))": 270, "opt(dictionary(hybrid(3,64),continued_fractions(dichotomic)))": 270, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,approximation))))": 271, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,delta_largest))))": 278, "opt(dictionary(hybrid(4,0),continued_fractions(binary)))": 279, "opt(dictionary(hybrid(4,0),continued_fractions(co_binary)))": 279, "opt(dictionary(hybrid(4,0),continued_fractions(dichotomic)))": 270, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,approximation))))": 275, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,delta_largest))))": 456, "opt(dictionary(hybrid(4,16),continued_fractions(binary)))": 279, "opt(dictionary(hybrid(4,16),continued_fractions(co_binary)))": 279, "opt(dictionary(hybrid(4,16),continued_fractions(dichotomic)))": 279, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,approximation))))": 278, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,delta_largest))))": 280, "opt(dictionary(hybrid(4,32),continued_fractions(binary)))": 272, "opt(dictionary(hybrid(4,32),continued_fractions(co_binary)))": 272, "opt(dictionary(hybrid(4,32),continued_fractions(dichotomic)))": 272, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,approximation))))": 272, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,delta_largest))))": 276, "opt(dictionary(hybrid(4,64),continued_fractions(binary)))": 270, "opt(dictionary(hybrid(4,64),continued_fractions(co_binary)))": 270, "opt(dictionary(hybrid(4,64),continued_fractions(dichotomic)))": 270, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,approximation))))": 270, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,delta_largest))))": 278, "opt(dictionary(hybrid(5,0),continued_fractions(binary)))": 279, "opt(dictionary(hybrid(5,0),continued_fractions(co_binary)))": 279, "opt(dictionary(hybrid(5,0),continued_fractions(dichotomic)))": 270, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,approximation))))": 275, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,delta_largest))))": 456, "opt(dictionary(hybrid(5,16),continued_fractions(binary)))": 279, "opt(dictionary(hybrid(5,16),continued_fractions(co_binary)))": 279, "opt(dictionary(hybrid(5,16),continued_fractions(dichotomic)))": 279, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,approximation))))": 278, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,delta_largest))))": 280, "opt(dictionary(hybrid(5,32),continued_fractions(binary)))": 272, "opt(dictionary(hybrid(5,32),continued_fractions(co_binary)))": 272, "opt(dictionary(hybrid(5,32),continued_fractions(dichotomic)))": 272, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,approximation))))": 272, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,delta_largest))))": 276, "opt(dictionary(hybrid(5,64),continued_fractions(binary)))": 270, "opt(dictionary(hybrid(5,64),continued_fractions(co_binary)))": 270, "opt(dictionary(hybrid(5,64),continued_fractions(dichotomic)))": 270, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,approximation))))": 270, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,delta_largest))))": 278, "opt(dictionary(hybrid(6,0),continued_fractions(binary)))": 279, "opt(dictionary(hybrid(6,0),continued_fractions(co_binary)))": 279, "opt(dictionary(hybrid(6,0),continued_fractions(dichotomic)))": 270, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,approximation))))": 275, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,delta_largest))))": 456, "opt(dictionary(hybrid(6,16),continued_fractions(binary)))": 279, "opt(dictionary(hybrid(6,16),continued_fractions(co_binary)))": 279, "opt(dictionary(hybrid(6,16),continued_fractions(dichotomic)))": 279, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,approximation))))": 278, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,delta_largest))))": 280, "opt(dictionary(hybrid(6,32),continued_fractions(binary)))": 272, "opt(dictionary(hybrid(6,32),continued_fractions(co_binary)))": 272, "opt(dictionary(hybrid(6,32),continued_fractions(dichotomic)))": 272, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,approximation))))": 272, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,delta_largest))))": 276, "opt(dictionary(hybrid(6,64),continued_fractions(binary)))": 270, "opt(dictionary(hybrid(6,64),continued_fractions(co_binary)))": 270, "opt(dictionary(hybrid(6,64),continued_fractions(dichotomic)))": 270, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,approximation))))": 270, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,delta_largest))))": 278, "opt(dictionary(hybrid(7,0),continued_fractions(binary)))": 279, "opt(dictionary(hybrid(7,0),continued_fractions(co_binary)))": 279, "opt(dictionary(hybrid(7,0),continued_fractions(dichotomic)))": 270, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,approximation))))": 275, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,delta_largest))))": 456, "opt(dictionary(hybrid(7,16),continued_fractions(binary)))": 279, "opt(dictionary(hybrid(7,16),continued_fractions(co_binary)))": 279, "opt(dictionary(hybrid(7,16),continued_fractions(dichotomic)))": 279, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,approximation))))": 278, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,delta_largest))))": 280, "opt(dictionary(hybrid(7,32),continued_fractions(binary)))": 272, "opt(dictionary(hybrid(7,32),continued_fractions(co_binary)))": 272, "opt(dictionary(hybrid(7,32),continued_fractions(dichotomic)))": 272, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,approximation))))": 272, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,delta_largest))))": 276, "opt(dictionary(hybrid(7,64),continued_fractions(binary)))": 270, "opt(dictionary(hybrid(7,64),continued_fractions(co_binary)))": 270, "opt(dictionary(hybrid(7,64),continued_fractions(dichotomic)))": 270, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,approximation))))": 270, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,delta_largest))))": 278, "opt(dictionary(hybrid(8,0),continued_fractions(binary)))": 279, "opt(dictionary(hybrid(8,0),continued_fractions(co_binary)))": 279, "opt(dictionary(hybrid(8,0),continued_fractions(dichotomic)))": 270, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,approximation))))": 275, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,delta_largest))))": 456, "opt(dictionary(hybrid(8,16),continued_fractions(binary)))": 279, "opt(dictionary(hybrid(8,16),continued_fractions(co_binary)))": 279, "opt(dictionary(hybrid(8,16),continued_fractions(dichotomic)))": 279, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,approximation))))": 278, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,delta_largest))))": 280, "opt(dictionary(hybrid(8,32),continued_fractions(binary)))": 272, "opt(dictionary(hybrid(8,32),continued_fractions(co_binary)))": 272, "opt(dictionary(hybrid(8,32),continued_fractions(dichotomic)))": 272, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,approximation))))": 272, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,delta_largest))))": 276, "opt(dictionary(hybrid(8,64),continued_fractions(binary)))": 270, "opt(dictionary(hybrid(8,64),continued_fractions(co_binary)))": 270, "opt(dictionary(hybrid(8,64),continued_fractions(dichotomic)))": 270, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,approximation))))": 270, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,delta_largest))))": 278, "opt(dictionary(run_length(0),continued_fractions(binary)))": 277, "opt(dictionary(run_length(0),continued_fractions(co_binary)))": 277, "opt(dictionary(run_length(0),continued_fractions(dichotomic)))": 270, "opt(dictionary(run_length(0),heuristic(use_first(halving,approximation))))": 277, "opt(dictionary(run_length(0),heuristic(use_first(halving,delta_largest))))": 457, "opt(dictionary(run_length(128),continued_fractions(binary)))": 271, "opt(dictionary(run_length(128),continued_fractions(co_binary)))": 271, "opt(dictionary(run_length(128),continued_fractions(dichotomic)))": 271, "opt(dictionary(run_length(128),heuristic(use_first(halving,approximation))))": 271, "opt(dictionary(run_length(128),heuristic(use_first(halving,delta_largest))))": 315, "opt(dictionary(run_length(16),continued_fractions(binary)))": 278, "opt(dictionary(run_length(16),continued_fractions(co_binary)))": 278, "opt(dictionary(run_length(16),continued_fractions(dichotomic)))": 278, "opt(dictionary(run_length(16),heuristic(use_first(halving,approximation))))": 278, "opt(dictionary(run_length(16),heuristic(use_first(halving,delta_largest))))": 280, "opt(dictionary(run_length(32),continued_fractions(binary)))": 272, "opt(dictionary(run_length(32),continued_fractions(co_binary)))": 272, "opt(dictionary(run_length(32),continued_fractions(dichotomic)))": 272, "opt(dictionary(run_length(32),heuristic(use_first(halving,approximation))))": 272, "opt(dictionary(run_length(32),heuristic(use_first(halving,delta_largest))))": 276, "opt(dictionary(run_length(64),continued_fractions(binary)))": 270, "opt(dictionary(run_length(64),continued_fractions(co_binary)))": 270, "opt(dictionary(run_length(64),continued_fractions(dichotomic)))": 270, "opt(dictionary(run_length(64),heuristic(use_first(halving,approximation))))": 270, "opt(dictionary(run_length(64),heuristic(use_first(halving,delta_largest))))": 277, "opt(dictionary(sliding_window(128),continued_fractions(binary)))": 326, "opt(dictionary(sliding_window(128),continued_fractions(co_binary)))": 326, "opt(dictionary(sliding_window(128),continued_fractions(dichotomic)))": 306, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,approximation))))": 276, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,delta_largest))))": 348, "opt(dictionary(sliding_window(16),continued_fractions(binary)))": 279, "opt(dictionary(sliding_window(16),continued_fractions(co_binary)))": 279, "opt(dictionary(sliding_window(16),continued_fractions(dichotomic)))": 279, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,approximation))))": 279, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,delta_largest))))": 279, "opt(dictionary(sliding_window(32),continued_fractions(binary)))": 276, "opt(dictionary(sliding_window(32),continued_fractions(co_binary)))": 276, "opt(dictionary(sliding_window(32),continued_fractions(dichotomic)))": 275, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,approximation))))": 278, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,delta_largest))))": 289, "opt(dictionary(sliding_window(4),continued_fractions(binary)))": 320, "opt(dictionary(sliding_window(4),continued_fractions(co_binary)))": 320, "opt(dictionary(sliding_window(4),continued_fractions(dichotomic)))": 320, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,approximation))))": 320, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,delta_largest))))": 320, "opt(dictionary(sliding_window(64),continued_fractions(binary)))": 298, "opt(dictionary(sliding_window(64),continued_fractions(co_binary)))": 298, "opt(dictionary(sliding_window(64),continued_fractions(dichotomic)))": 284, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,approximation))))": 274, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,delta_largest))))": 284, "opt(dictionary(sliding_window(8),continued_fractions(binary)))": 292, "opt(dictionary(sliding_window(8),continued_fractions(co_binary)))": 292, "opt(dictionary(sliding_window(8),continued_fractions(dichotomic)))": 292, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,approximation))))": 292, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,delta_largest))))": 292, "opt(runs(continued_fractions(binary)))": 270, "opt(runs(continued_fractions(co_binary)))": 270, "opt(runs(continued_fractions(dichotomic)))": 270, "opt(runs(heuristic(use_first(halving,approximation))))": 270, "opt(runs(heuristic(use_first(halving,delta_largest))))": 269 }addchain-0.4.0/alg/ensemble/testdata/secp256k1_scalar.golden000066400000000000000000000353211514305256600235710ustar00rootroot00000000000000{ "opt(dictionary(hybrid(2,0),continued_fractions(binary)))": 309, "opt(dictionary(hybrid(2,0),continued_fractions(co_binary)))": 309, "opt(dictionary(hybrid(2,0),continued_fractions(dichotomic)))": 301, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,approximation))))": 309, "opt(dictionary(hybrid(2,0),heuristic(use_first(halving,delta_largest))))": 406, "opt(dictionary(hybrid(2,16),continued_fractions(binary)))": 303, "opt(dictionary(hybrid(2,16),continued_fractions(co_binary)))": 303, "opt(dictionary(hybrid(2,16),continued_fractions(dichotomic)))": 303, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,approximation))))": 303, "opt(dictionary(hybrid(2,16),heuristic(use_first(halving,delta_largest))))": 303, "opt(dictionary(hybrid(2,32),continued_fractions(binary)))": 301, "opt(dictionary(hybrid(2,32),continued_fractions(co_binary)))": 301, "opt(dictionary(hybrid(2,32),continued_fractions(dichotomic)))": 301, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,approximation))))": 301, "opt(dictionary(hybrid(2,32),heuristic(use_first(halving,delta_largest))))": 314, "opt(dictionary(hybrid(2,64),continued_fractions(binary)))": 303, "opt(dictionary(hybrid(2,64),continued_fractions(co_binary)))": 303, "opt(dictionary(hybrid(2,64),continued_fractions(dichotomic)))": 301, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,approximation))))": 303, "opt(dictionary(hybrid(2,64),heuristic(use_first(halving,delta_largest))))": 344, "opt(dictionary(hybrid(3,0),continued_fractions(binary)))": 306, "opt(dictionary(hybrid(3,0),continued_fractions(co_binary)))": 306, "opt(dictionary(hybrid(3,0),continued_fractions(dichotomic)))": 298, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,approximation))))": 306, "opt(dictionary(hybrid(3,0),heuristic(use_first(halving,delta_largest))))": 403, "opt(dictionary(hybrid(3,16),continued_fractions(binary)))": 300, "opt(dictionary(hybrid(3,16),continued_fractions(co_binary)))": 300, "opt(dictionary(hybrid(3,16),continued_fractions(dichotomic)))": 300, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,approximation))))": 300, "opt(dictionary(hybrid(3,16),heuristic(use_first(halving,delta_largest))))": 300, "opt(dictionary(hybrid(3,32),continued_fractions(binary)))": 298, "opt(dictionary(hybrid(3,32),continued_fractions(co_binary)))": 298, "opt(dictionary(hybrid(3,32),continued_fractions(dichotomic)))": 298, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,approximation))))": 298, "opt(dictionary(hybrid(3,32),heuristic(use_first(halving,delta_largest))))": 311, "opt(dictionary(hybrid(3,64),continued_fractions(binary)))": 300, "opt(dictionary(hybrid(3,64),continued_fractions(co_binary)))": 300, "opt(dictionary(hybrid(3,64),continued_fractions(dichotomic)))": 298, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,approximation))))": 300, "opt(dictionary(hybrid(3,64),heuristic(use_first(halving,delta_largest))))": 341, "opt(dictionary(hybrid(4,0),continued_fractions(binary)))": 301, "opt(dictionary(hybrid(4,0),continued_fractions(co_binary)))": 301, "opt(dictionary(hybrid(4,0),continued_fractions(dichotomic)))": 293, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,approximation))))": 302, "opt(dictionary(hybrid(4,0),heuristic(use_first(halving,delta_largest))))": 399, "opt(dictionary(hybrid(4,16),continued_fractions(binary)))": 295, "opt(dictionary(hybrid(4,16),continued_fractions(co_binary)))": 295, "opt(dictionary(hybrid(4,16),continued_fractions(dichotomic)))": 295, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,approximation))))": 296, "opt(dictionary(hybrid(4,16),heuristic(use_first(halving,delta_largest))))": 296, "opt(dictionary(hybrid(4,32),continued_fractions(binary)))": 293, "opt(dictionary(hybrid(4,32),continued_fractions(co_binary)))": 293, "opt(dictionary(hybrid(4,32),continued_fractions(dichotomic)))": 293, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,approximation))))": 294, "opt(dictionary(hybrid(4,32),heuristic(use_first(halving,delta_largest))))": 307, "opt(dictionary(hybrid(4,64),continued_fractions(binary)))": 295, "opt(dictionary(hybrid(4,64),continued_fractions(co_binary)))": 295, "opt(dictionary(hybrid(4,64),continued_fractions(dichotomic)))": 293, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,approximation))))": 296, "opt(dictionary(hybrid(4,64),heuristic(use_first(halving,delta_largest))))": 337, "opt(dictionary(hybrid(5,0),continued_fractions(binary)))": 304, "opt(dictionary(hybrid(5,0),continued_fractions(co_binary)))": 304, "opt(dictionary(hybrid(5,0),continued_fractions(dichotomic)))": 296, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,approximation))))": 305, "opt(dictionary(hybrid(5,0),heuristic(use_first(halving,delta_largest))))": 402, "opt(dictionary(hybrid(5,16),continued_fractions(binary)))": 298, "opt(dictionary(hybrid(5,16),continued_fractions(co_binary)))": 298, "opt(dictionary(hybrid(5,16),continued_fractions(dichotomic)))": 298, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,approximation))))": 299, "opt(dictionary(hybrid(5,16),heuristic(use_first(halving,delta_largest))))": 299, "opt(dictionary(hybrid(5,32),continued_fractions(binary)))": 296, "opt(dictionary(hybrid(5,32),continued_fractions(co_binary)))": 296, "opt(dictionary(hybrid(5,32),continued_fractions(dichotomic)))": 296, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,approximation))))": 297, "opt(dictionary(hybrid(5,32),heuristic(use_first(halving,delta_largest))))": 310, "opt(dictionary(hybrid(5,64),continued_fractions(binary)))": 298, "opt(dictionary(hybrid(5,64),continued_fractions(co_binary)))": 298, "opt(dictionary(hybrid(5,64),continued_fractions(dichotomic)))": 296, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,approximation))))": 299, "opt(dictionary(hybrid(5,64),heuristic(use_first(halving,delta_largest))))": 340, "opt(dictionary(hybrid(6,0),continued_fractions(binary)))": 305, "opt(dictionary(hybrid(6,0),continued_fractions(co_binary)))": 305, "opt(dictionary(hybrid(6,0),continued_fractions(dichotomic)))": 297, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,approximation))))": 307, "opt(dictionary(hybrid(6,0),heuristic(use_first(halving,delta_largest))))": 403, "opt(dictionary(hybrid(6,16),continued_fractions(binary)))": 299, "opt(dictionary(hybrid(6,16),continued_fractions(co_binary)))": 299, "opt(dictionary(hybrid(6,16),continued_fractions(dichotomic)))": 299, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,approximation))))": 301, "opt(dictionary(hybrid(6,16),heuristic(use_first(halving,delta_largest))))": 300, "opt(dictionary(hybrid(6,32),continued_fractions(binary)))": 297, "opt(dictionary(hybrid(6,32),continued_fractions(co_binary)))": 297, "opt(dictionary(hybrid(6,32),continued_fractions(dichotomic)))": 297, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,approximation))))": 299, "opt(dictionary(hybrid(6,32),heuristic(use_first(halving,delta_largest))))": 311, "opt(dictionary(hybrid(6,64),continued_fractions(binary)))": 299, "opt(dictionary(hybrid(6,64),continued_fractions(co_binary)))": 299, "opt(dictionary(hybrid(6,64),continued_fractions(dichotomic)))": 297, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,approximation))))": 301, "opt(dictionary(hybrid(6,64),heuristic(use_first(halving,delta_largest))))": 341, "opt(dictionary(hybrid(7,0),continued_fractions(binary)))": 302, "opt(dictionary(hybrid(7,0),continued_fractions(co_binary)))": 302, "opt(dictionary(hybrid(7,0),continued_fractions(dichotomic)))": 294, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,approximation))))": 303, "opt(dictionary(hybrid(7,0),heuristic(use_first(halving,delta_largest))))": 399, "opt(dictionary(hybrid(7,16),continued_fractions(binary)))": 296, "opt(dictionary(hybrid(7,16),continued_fractions(co_binary)))": 296, "opt(dictionary(hybrid(7,16),continued_fractions(dichotomic)))": 296, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,approximation))))": 297, "opt(dictionary(hybrid(7,16),heuristic(use_first(halving,delta_largest))))": 296, "opt(dictionary(hybrid(7,32),continued_fractions(binary)))": 294, "opt(dictionary(hybrid(7,32),continued_fractions(co_binary)))": 294, "opt(dictionary(hybrid(7,32),continued_fractions(dichotomic)))": 294, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,approximation))))": 295, "opt(dictionary(hybrid(7,32),heuristic(use_first(halving,delta_largest))))": 307, "opt(dictionary(hybrid(7,64),continued_fractions(binary)))": 296, "opt(dictionary(hybrid(7,64),continued_fractions(co_binary)))": 296, "opt(dictionary(hybrid(7,64),continued_fractions(dichotomic)))": 294, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,approximation))))": 297, "opt(dictionary(hybrid(7,64),heuristic(use_first(halving,delta_largest))))": 337, "opt(dictionary(hybrid(8,0),continued_fractions(binary)))": 302, "opt(dictionary(hybrid(8,0),continued_fractions(co_binary)))": 302, "opt(dictionary(hybrid(8,0),continued_fractions(dichotomic)))": 294, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,approximation))))": 304, "opt(dictionary(hybrid(8,0),heuristic(use_first(halving,delta_largest))))": 400, "opt(dictionary(hybrid(8,16),continued_fractions(binary)))": 296, "opt(dictionary(hybrid(8,16),continued_fractions(co_binary)))": 296, "opt(dictionary(hybrid(8,16),continued_fractions(dichotomic)))": 296, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,approximation))))": 298, "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,delta_largest))))": 296, "opt(dictionary(hybrid(8,32),continued_fractions(binary)))": 294, "opt(dictionary(hybrid(8,32),continued_fractions(co_binary)))": 294, "opt(dictionary(hybrid(8,32),continued_fractions(dichotomic)))": 294, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,approximation))))": 296, "opt(dictionary(hybrid(8,32),heuristic(use_first(halving,delta_largest))))": 308, "opt(dictionary(hybrid(8,64),continued_fractions(binary)))": 296, "opt(dictionary(hybrid(8,64),continued_fractions(co_binary)))": 296, "opt(dictionary(hybrid(8,64),continued_fractions(dichotomic)))": 294, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,approximation))))": 298, "opt(dictionary(hybrid(8,64),heuristic(use_first(halving,delta_largest))))": 338, "opt(dictionary(run_length(0),continued_fractions(binary)))": 309, "opt(dictionary(run_length(0),continued_fractions(co_binary)))": 309, "opt(dictionary(run_length(0),continued_fractions(dichotomic)))": 301, "opt(dictionary(run_length(0),heuristic(use_first(halving,approximation))))": 309, "opt(dictionary(run_length(0),heuristic(use_first(halving,delta_largest))))": 406, "opt(dictionary(run_length(128),continued_fractions(binary)))": 309, "opt(dictionary(run_length(128),continued_fractions(co_binary)))": 309, "opt(dictionary(run_length(128),continued_fractions(dichotomic)))": 301, "opt(dictionary(run_length(128),heuristic(use_first(halving,approximation))))": 309, "opt(dictionary(run_length(128),heuristic(use_first(halving,delta_largest))))": 406, "opt(dictionary(run_length(16),continued_fractions(binary)))": 303, "opt(dictionary(run_length(16),continued_fractions(co_binary)))": 303, "opt(dictionary(run_length(16),continued_fractions(dichotomic)))": 303, "opt(dictionary(run_length(16),heuristic(use_first(halving,approximation))))": 303, "opt(dictionary(run_length(16),heuristic(use_first(halving,delta_largest))))": 303, "opt(dictionary(run_length(32),continued_fractions(binary)))": 301, "opt(dictionary(run_length(32),continued_fractions(co_binary)))": 301, "opt(dictionary(run_length(32),continued_fractions(dichotomic)))": 301, "opt(dictionary(run_length(32),heuristic(use_first(halving,approximation))))": 301, "opt(dictionary(run_length(32),heuristic(use_first(halving,delta_largest))))": 314, "opt(dictionary(run_length(64),continued_fractions(binary)))": 303, "opt(dictionary(run_length(64),continued_fractions(co_binary)))": 303, "opt(dictionary(run_length(64),continued_fractions(dichotomic)))": 301, "opt(dictionary(run_length(64),heuristic(use_first(halving,approximation))))": 303, "opt(dictionary(run_length(64),heuristic(use_first(halving,delta_largest))))": 344, "opt(dictionary(sliding_window(128),continued_fractions(binary)))": 330, "opt(dictionary(sliding_window(128),continued_fractions(co_binary)))": 330, "opt(dictionary(sliding_window(128),continued_fractions(dichotomic)))": 327, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,approximation))))": 328, "opt(dictionary(sliding_window(128),heuristic(use_first(halving,delta_largest))))": 327, "opt(dictionary(sliding_window(16),continued_fractions(binary)))": 303, "opt(dictionary(sliding_window(16),continued_fractions(co_binary)))": 303, "opt(dictionary(sliding_window(16),continued_fractions(dichotomic)))": 303, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,approximation))))": 304, "opt(dictionary(sliding_window(16),heuristic(use_first(halving,delta_largest))))": 303, "opt(dictionary(sliding_window(32),continued_fractions(binary)))": 301, "opt(dictionary(sliding_window(32),continued_fractions(co_binary)))": 301, "opt(dictionary(sliding_window(32),continued_fractions(dichotomic)))": 301, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,approximation))))": 312, "opt(dictionary(sliding_window(32),heuristic(use_first(halving,delta_largest))))": 301, "opt(dictionary(sliding_window(4),continued_fractions(binary)))": 317, "opt(dictionary(sliding_window(4),continued_fractions(co_binary)))": 317, "opt(dictionary(sliding_window(4),continued_fractions(dichotomic)))": 317, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,approximation))))": 317, "opt(dictionary(sliding_window(4),heuristic(use_first(halving,delta_largest))))": 317, "opt(dictionary(sliding_window(64),continued_fractions(binary)))": 311, "opt(dictionary(sliding_window(64),continued_fractions(co_binary)))": 311, "opt(dictionary(sliding_window(64),continued_fractions(dichotomic)))": 311, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,approximation))))": 310, "opt(dictionary(sliding_window(64),heuristic(use_first(halving,delta_largest))))": 313, "opt(dictionary(sliding_window(8),continued_fractions(binary)))": 302, "opt(dictionary(sliding_window(8),continued_fractions(co_binary)))": 302, "opt(dictionary(sliding_window(8),continued_fractions(dichotomic)))": 302, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,approximation))))": 304, "opt(dictionary(sliding_window(8),heuristic(use_first(halving,delta_largest))))": 302, "opt(runs(continued_fractions(binary)))": 301, "opt(runs(continued_fractions(co_binary)))": 301, "opt(runs(continued_fractions(dichotomic)))": 300, "opt(runs(heuristic(use_first(halving,approximation))))": 299, "opt(runs(heuristic(use_first(halving,delta_largest))))": 299 }addchain-0.4.0/alg/exec/000077500000000000000000000000001514305256600147445ustar00rootroot00000000000000addchain-0.4.0/alg/exec/example_test.go000066400000000000000000000015231514305256600177660ustar00rootroot00000000000000package exec_test import ( "fmt" "log" "math/big" "github.com/mmcloughlin/addchain/alg/ensemble" "github.com/mmcloughlin/addchain/alg/exec" ) 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))) } addchain-0.4.0/alg/exec/exec.go000066400000000000000000000037721514305256600162300ustar00rootroot00000000000000// 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 } addchain-0.4.0/alg/heuristic/000077500000000000000000000000001514305256600160175ustar00rootroot00000000000000addchain-0.4.0/alg/heuristic/heuristic.go000066400000000000000000000165211514305256600203520ustar00rootroot00000000000000// 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 } addchain-0.4.0/alg/heuristic/heuristic_test.go000066400000000000000000000025541514305256600214120ustar00rootroot00000000000000package heuristic import ( "math/big" "reflect" "testing" "github.com/mmcloughlin/addchain/alg/algtest" "github.com/mmcloughlin/addchain/internal/bigints" ) // References: // // [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 func TestAlgorithms(t *testing.T) { heuristics := []Heuristic{ UseFirst(Halving{}, DeltaLargest{}), UseFirst(Halving{}, Approximation{}), } for _, heuristic := range heuristics { suite := algtest.SequenceAlgorithmSuite{ Algorithm: NewAlgorithm(heuristic), AcceptsLargeInputs: true, } t.Run(suite.Algorithm.String(), suite.Tests()) } } func TestHalving(t *testing.T) { cases := []struct { F []*big.Int Target *big.Int Expect []*big.Int }{ // Example from [hehcc:exp], page 163. { F: bigints.Int64s(14), Target: big.NewInt(382), Expect: bigints.Int64s(14, 23, 46, 92, 184, 368), }, // Simple powers of two case. { F: bigints.Int64s(1, 2), Target: big.NewInt(8), Expect: bigints.Int64s(2, 4), }, } h := Halving{} for _, c := range cases { if got := h.Suggest(c.F, c.Target); !reflect.DeepEqual(c.Expect, got) { t.Errorf("Suggest(%v, %v) = %v; expect %v", c.F, c.Target, got, c.Expect) } } } addchain-0.4.0/alg/opt/000077500000000000000000000000001514305256600146225ustar00rootroot00000000000000addchain-0.4.0/alg/opt/opt.go000066400000000000000000000043011514305256600157510ustar00rootroot00000000000000// 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 } addchain-0.4.0/alg/opt/opt_test.go000066400000000000000000000023561514305256600170200ustar00rootroot00000000000000package opt import ( "testing" "github.com/mmcloughlin/addchain" "github.com/mmcloughlin/addchain/internal/bigints" ) func TestOptimize(t *testing.T) { cases := []struct { Input addchain.Chain Expect addchain.Chain }{ // Sub-optimal case. Should remove 3 or 4. { Input: bigints.Int64s(1, 2, 3, 4, 5), Expect: bigints.Int64s(1, 2, 4, 5), }, // Optimal case. Should do nothing. { Input: bigints.Int64s(1, 2, 4, 5), Expect: bigints.Int64s(1, 2, 4, 5), }, // Two removals are possible in this case. { Input: bigints.Int64s(1, 2, 3, 4, 6, 7, 8, 14, 20, 24), Expect: bigints.Int64s(1, 2, 4, 6, 7, 14, 20, 24), }, } for _, c := range cases { // Verify both are possible. if err := c.Input.Validate(); err != nil { t.Fatal(err) } if err := c.Expect.Validate(); err != nil { t.Fatal(err) } // Run optimization. got, err := Optimize(c.Input) if err != nil { t.Fatal(err) } // Require that the result is still valid, and at least as good as the expected. if err := got.Produces(c.Input.End()); err != nil { t.Fatal("optimization result does not end in the same value") } if len(c.Expect) < len(got) { t.Fatalf("Optimize(%v) = %v; expect %v", c.Input, got, c.Expect) } } } addchain-0.4.0/chain.go000066400000000000000000000111101514305256600146600ustar00rootroot00000000000000// 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) } addchain-0.4.0/chain_test.go000066400000000000000000000037221514305256600157310ustar00rootroot00000000000000package addchain import ( "reflect" "testing" ) func TestChainOps(t *testing.T) { cases := []struct { Name string Chain Chain Expect [][]Op }{ { Name: "short", Chain: Int64s(1, 2), Expect: [][]Op{ {{0, 0}}, // 2 }, }, { Name: "multiple_choices", Chain: Int64s(1, 2, 3, 4), Expect: [][]Op{ {{0, 0}}, // 2 {{0, 1}}, // 3 {{0, 2}, {1, 1}}, // 4 }, }, { Name: "non_ascending", Chain: Int64s(1, 2, 3, 4, 7, 5, 6), Expect: [][]Op{ {{0, 0}}, // 2 {{0, 1}}, // 3 {{0, 2}, {1, 1}}, // 4 {{2, 3}}, // 7 {{0, 3}, {1, 2}}, // 5 {{0, 5}, {1, 3}, {2, 2}}, // 6 }, }, } for _, c := range cases { c := c // scopelint t.Run(c.Name, func(t *testing.T) { var got [][]Op for k := 1; k < len(c.Chain); k++ { got = append(got, c.Chain.Ops(k)) } if !reflect.DeepEqual(got, c.Expect) { t.Logf("got = %v", got) t.Logf("expect = %v", c.Expect) t.Fail() } }) } } func TestChainIsAscending(t *testing.T) { cases := []struct { Name string Chain Chain Expect bool }{ {Name: "empty", Chain: Int64s(), Expect: false}, {Name: "does_not_start_with_one", Chain: Int64s(42), Expect: false}, {Name: "ascending", Chain: Int64s(1, 2, 3, 5, 8), Expect: true}, {Name: "repeat", Chain: Int64s(1, 2, 3, 3, 8), Expect: false}, {Name: "not_sorted", Chain: Int64s(1, 2, 3, 4, 7, 5, 6), Expect: false}, } for _, c := range cases { c := c // scopelint t.Run(c.Name, func(t *testing.T) { if got := c.Chain.IsAscending(); got != c.Expect { t.Fatalf("%v.IsAscending() = %v; expect %v", c.Chain, got, c.Expect) } }) } } func TestProduct(t *testing.T) { a := Int64s(1, 2, 4, 6, 10) b := Int64s(1, 2, 4, 8) got := Product(a, b) expect := Int64s(1, 2, 4, 6, 10, 20, 40, 80) if !reflect.DeepEqual(expect, got) { t.Fatalf("Product(%v, %v) = %v; expect %v", a, b, got, expect) } } addchain-0.4.0/cmd/000077500000000000000000000000001514305256600140205ustar00rootroot00000000000000addchain-0.4.0/cmd/addchain/000077500000000000000000000000001514305256600155535ustar00rootroot00000000000000addchain-0.4.0/cmd/addchain/cite.go000066400000000000000000000014761514305256600170360ustar00rootroot00000000000000package main import ( "context" "flag" "os" "github.com/google/subcommands" "github.com/mmcloughlin/addchain/internal/cli" "github.com/mmcloughlin/addchain/meta" ) // cite subcommand. type cite struct { properties *meta.Properties cli.Command } func (*cite) Name() string { return "cite" } func (*cite) Synopsis() string { return "output addchain citation" } func (*cite) Usage() string { return `Usage: cite Output citation for addchain. ` } func (cmd *cite) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) (status subcommands.ExitStatus) { // Check citable. if err := cmd.properties.CheckCitable(); err != nil { return cmd.Error(err) } // Generate citation. if err := cmd.properties.WriteCitation(os.Stdout); err != nil { return cmd.Error(err) } return subcommands.ExitSuccess } addchain-0.4.0/cmd/addchain/eval.go000066400000000000000000000025431514305256600170350ustar00rootroot00000000000000package main import ( "context" "flag" "fmt" "github.com/google/subcommands" "github.com/mmcloughlin/addchain/acc" "github.com/mmcloughlin/addchain/acc/parse" "github.com/mmcloughlin/addchain/acc/pass" "github.com/mmcloughlin/addchain/internal/cli" ) // eval subcommand. type eval struct { cli.Command } func (*eval) Name() string { return "eval" } func (*eval) Synopsis() string { return "evaluate an addition chain script" } func (*eval) Usage() string { return `Usage: eval [] Evaluate an addition chain script. ` } func (cmd *eval) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) (status subcommands.ExitStatus) { // Read input. input, r, err := cli.OpenInput(f.Arg(0)) if err != nil { return cmd.Error(err) } defer cmd.CheckClose(&status, r) // Parse to a syntax tree. s, err := parse.Reader(input, r) if err != nil { return cmd.Error(err) } // Generate intermediate representation. p, err := acc.Translate(s) if err != nil { return cmd.Error(err) } // Evaluate and compile. if err := pass.Eval(p); err != nil { return cmd.Error(err) } // Dump. for n, op := range p.Program { fmt.Printf("[%3d] %3d+%3d\t%x\n", n+1, op.I, op.J, p.Chain[n+1]) } doubles, adds := p.Program.Count() fmt.Printf("total: %d\tdoubles: \t%d adds: %d\n", doubles+adds, doubles, adds) return subcommands.ExitSuccess } addchain-0.4.0/cmd/addchain/fmt.go000066400000000000000000000025231514305256600166720ustar00rootroot00000000000000package main import ( "context" "flag" "github.com/google/subcommands" "github.com/mmcloughlin/addchain/acc" "github.com/mmcloughlin/addchain/acc/parse" "github.com/mmcloughlin/addchain/acc/printer" "github.com/mmcloughlin/addchain/internal/cli" ) // format subcommand. type format struct { cli.Command build bool } func (*format) Name() string { return "fmt" } func (*format) Synopsis() string { return "format an addition chain script" } func (*format) Usage() string { return `Usage: fmt [] Format an addition chain script. ` } func (cmd *format) SetFlags(f *flag.FlagSet) { f.BoolVar(&cmd.build, "b", false, "rebuild from intermediate representation") } func (cmd *format) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) (status subcommands.ExitStatus) { // Read input. input, r, err := cli.OpenInput(f.Arg(0)) if err != nil { return cmd.Error(err) } defer cmd.CheckClose(&status, r) // Parse to a syntax tree. s, err := parse.Reader(input, r) if err != nil { return cmd.Error(err) } // Rebuild, if configured. if cmd.build { r, err := acc.Translate(s) if err != nil { return cmd.Error(err) } s, err = acc.Build(r) if err != nil { return cmd.Error(err) } } // Print. if err := printer.Print(s); err != nil { return cmd.Error(err) } return subcommands.ExitSuccess } addchain-0.4.0/cmd/addchain/gen.go000066400000000000000000000047641514305256600166660ustar00rootroot00000000000000package main import ( "context" "errors" "flag" "fmt" "io/ioutil" "strings" "github.com/google/subcommands" "github.com/mmcloughlin/addchain/acc/parse" "github.com/mmcloughlin/addchain/acc/pass" "github.com/mmcloughlin/addchain/internal/cli" "github.com/mmcloughlin/addchain/internal/gen" ) // generate subcommand. type generate struct { cli.Command typ string tmpl string output string } func (*generate) Name() string { return "gen" } func (*generate) Synopsis() string { return "generate output from an addition chain program" } func (*generate) Usage() string { return `Usage: gen [-type ] [-tmpl ] [-out ] [] Generate output from an addition chain program. ` } func (cmd *generate) SetFlags(f *flag.FlagSet) { defaulttype := "listing" if !gen.IsBuiltinTemplate(defaulttype) { panic("bad default template") } f.StringVar(&cmd.typ, "type", defaulttype, fmt.Sprintf("`name` of a builtin template (%s)", strings.Join(gen.BuiltinTemplateNames(), ","))) f.StringVar(&cmd.tmpl, "tmpl", "", "template `file` (overrides type)") f.StringVar(&cmd.output, "out", "", "output `file` (default stdout)") } func (cmd *generate) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) (status subcommands.ExitStatus) { // Read input. input, r, err := cli.OpenInput(f.Arg(0)) if err != nil { return cmd.Error(err) } defer cmd.CheckClose(&status, r) // Parse to a syntax tree. s, err := parse.Reader(input, r) if err != nil { return cmd.Error(err) } // Prepare template data. cfg := gen.Config{ Allocator: pass.Allocator{ Input: "x", Output: "z", Format: "t%d", }, } data, err := gen.PrepareData(cfg, s) if err != nil { return cmd.Error(err) } // Load template. tmpl, err := cmd.LoadTemplate() if err != nil { return cmd.Error(err) } // Open output. _, w, err := cli.OpenOutput(cmd.output) if err != nil { return cmd.Error(err) } defer cmd.CheckClose(&status, w) // Generate. if err := gen.Generate(w, tmpl, data); err != nil { return cmd.Error(err) } return subcommands.ExitSuccess } func (cmd *generate) LoadTemplate() (string, error) { // Explicit filename has precedence. if cmd.tmpl != "" { b, err := ioutil.ReadFile(cmd.tmpl) if err != nil { return "", err } return string(b), nil } // Lookup type name in builtin templates. if cmd.typ == "" { return "", errors.New("no builtin template specified") } s, err := gen.BuiltinTemplate(cmd.typ) if err != nil { return "", err } return s, nil } addchain-0.4.0/cmd/addchain/main.go000066400000000000000000000014521514305256600170300ustar00rootroot00000000000000// Command addchain generates addition chains. package main import ( "context" "flag" "os" "github.com/google/subcommands" "github.com/mmcloughlin/addchain/internal/cli" "github.com/mmcloughlin/addchain/meta" ) func main() { base := cli.NewBaseCommand("addchain") subcommands.Register(subcommands.HelpCommand(), "") subcommands.Register(&search{Command: base}, "") subcommands.Register(&eval{Command: base}, "") subcommands.Register(&format{Command: base}, "") subcommands.Register(&generate{Command: base}, "") if meta.Meta.BuildVersion != "" { subcommands.Register(&version{version: meta.Meta.BuildVersion, Command: base}, "") } subcommands.Register(&cite{properties: meta.Meta, Command: base}, "") flag.Parse() ctx := context.Background() os.Exit(int(subcommands.Execute(ctx))) } addchain-0.4.0/cmd/addchain/search.go000066400000000000000000000057431514305256600173600ustar00rootroot00000000000000package main import ( "context" "flag" "math" "runtime" "github.com/google/subcommands" "github.com/mmcloughlin/profile" "github.com/mmcloughlin/addchain/acc" "github.com/mmcloughlin/addchain/acc/printer" "github.com/mmcloughlin/addchain/alg/ensemble" "github.com/mmcloughlin/addchain/alg/exec" "github.com/mmcloughlin/addchain/internal/calc" "github.com/mmcloughlin/addchain/internal/cli" ) // search subcommand. type search struct { cli.Command add float64 double float64 concurrency int verbose bool } func (*search) Name() string { return "search" } func (*search) Synopsis() string { return "search for an addition chain." } func (*search) Usage() string { return `Usage: search [-v] [-p ] [-add ] [-double ] Search for an addition chain for . ` } func (cmd *search) SetFlags(f *flag.FlagSet) { f.IntVar(&cmd.concurrency, "p", runtime.NumCPU(), "run `N` algorithms in parallel") f.BoolVar(&cmd.verbose, "v", false, "verbose output") f.Float64Var(&cmd.add, "add", 1, "add `cost`") f.Float64Var(&cmd.double, "double", 1, "double `cost`") } func (cmd *search) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) (status subcommands.ExitStatus) { // Enable profiling. defer profile.Start( profile.AllProfiles, profile.ConfigEnvVar("ADDCHAIN_PROFILE"), profile.WithLogger(cmd.Log), ).Stop() // Parse arguments. if f.NArg() < 1 { return cmd.UsageError("missing expression") } expr := f.Arg(0) // Evaluate expression. cmd.Log.Printf("expr: %q", expr) n, err := calc.Eval(expr) if err != nil { return cmd.Fail("failed to evaluate %q: %s", expr, err) } cmd.Log.Printf("hex: %x", n) cmd.Log.Printf("dec: %s", n) // Execute an ensemble of algorithms. ex := exec.NewParallel() if cmd.verbose { ex.SetLogger(cmd.Log) } ex.SetConcurrency(cmd.concurrency) as := ensemble.Ensemble() rs := ex.Execute(n, as) // Report results. best := 0 mincost := math.Inf(+1) for i, r := range rs { cmd.Debugf("algorithm: %s", r.Algorithm) if r.Err != nil { return cmd.Fail("algorithm error: %v", r.Err) } doubles, adds := r.Program.Count() cost := cmd.double*float64(doubles) + cmd.add*float64(adds) cmd.Debugf("cost: %v\tdoubles: \t%d adds: %d", cost, doubles, adds) if cost < mincost { best = i mincost = cost } } // Details for the best chain. b := rs[best] for n, op := range b.Program { cmd.Debugf("[%3d] %3d+%3d\t%x", n+1, op.I, op.J, b.Chain[n+1]) } cmd.Log.Printf("best: %s", b.Algorithm) cmd.Log.Printf("cost: %v", mincost) // Produce a program for it. p, err := acc.Decompile(b.Program) if err != nil { return cmd.Error(err) } syntax, err := acc.Build(p) if err != nil { return cmd.Error(err) } if err := printer.Print(syntax); err != nil { return cmd.Error(err) } return subcommands.ExitSuccess } // Debugf prints a message in verbose mode only. func (cmd *search) Debugf(format string, args ...interface{}) { if cmd.verbose { cmd.Log.Printf(format, args...) } } addchain-0.4.0/cmd/addchain/version.go000066400000000000000000000012611514305256600175670ustar00rootroot00000000000000package main import ( "context" "flag" "fmt" "runtime" "github.com/google/subcommands" "github.com/mmcloughlin/addchain/internal/cli" ) // version subcommand. type version struct { version string cli.Command } func (*version) Name() string { return "version" } func (*version) Synopsis() string { return "print addchain version" } func (*version) Usage() string { return `Usage: version Print the version of the addchain tool. ` } func (cmd *version) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) (status subcommands.ExitStatus) { fmt.Printf("addchain version %s %s/%s\n", cmd.version, runtime.GOOS, runtime.GOARCH) return subcommands.ExitSuccess } addchain-0.4.0/codecov.yml000066400000000000000000000000641514305256600154220ustar00rootroot00000000000000coverage: status: project: off patch: off addchain-0.4.0/doc/000077500000000000000000000000001514305256600140225ustar00rootroot00000000000000addchain-0.4.0/doc/bibliography.md000066400000000000000000000122641514305256600170240ustar00rootroot00000000000000# Bibliography * 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 addchain-0.4.0/doc/gen.md000066400000000000000000001040341514305256600151170ustar00rootroot00000000000000# Output Generation ## Table of Contents * [Example](#example) * [Template Reference](#template-reference) * [Builtin Templates](#builtin-templates) * [chain](#chain) * [listing](#listing) * [ops](#ops) * [script](#script) ## Example Let's show an example of generating code for curve25519 field inversion. Search for the best addition chain and save the result: ```sh addchain search '2^255 - 19 - 2' > inv.acc ``` Now we can use the `addchain` generate command to generate code to execute the addition chain. By default, the generate command will show us a concise listing of the instructions required to compute the addition chain. ```sh addchain gen inv.acc ``` Output: ``` tmp t0 t1 t2 double z x add z x z shift t0 z 2 add t0 z t0 shift t1 t0 4 add t0 t0 t1 shift t0 t0 2 add t0 z t0 shift t1 t0 10 add t1 t0 t1 shift t1 t1 10 add t1 t0 t1 shift t2 t1 30 add t1 t1 t2 shift t2 t1 60 add t1 t1 t2 shift t2 t1 120 add t1 t1 t2 shift t1 t1 10 add t0 t0 t1 shift t0 t0 2 add t0 x t0 shift t0 t0 3 add z z t0 ``` This listing is intended to be a simple text format that could directly be turned into code. The directives mean: * `tmp v ...`: declare temporary variables `v ...` * `add z x y`: execute addition `z = x+y` * `double z x`: execute doubling `z = 2*x` * `shift z x n`: execute repeated doubling z = 2n*x Under the hood, `addchain` has processed the addition chain into the [`ir.Program`](https://pkg.go.dev/github.com/mmcloughlin/addchain/acc/ir#Program) intermediate representation and used an allocation pass to assign the minimum number of temporary variables. The listing format is intended be a convient and easy-to-parse text format to use as input to other tools. In addition, `addchain` also offers templated output. In fact, the listing is actually produced by the [listing](#listing) builtin template. See below for details of the [templating language](#template-reference) and [builtin template examples](#builtin-templates). The following template can be used to directly produce Go code to execute the inversion chain: ``` // Code generated by {{ .Meta.Name }}. DO NOT EDIT. package fp25519 // Inv computes z = 1/x (mod p) and returns it. func (z *Elt) Inv(x *Elt) *Elt { // Inversion computation is derived from the addition chain: // {{- range lines (format .Script) }} // {{ . }} {{- end }} // // Operations: {{ .Ops.Doubles }} squares {{ .Ops.Adds }} multiplies // // Generated by {{ .Meta.Module }} {{ .Meta.ReleaseTag }}. // Allocate Temporaries. var ( {{- range .Program.Temporaries }} {{ . }} = new(Elt) {{- end -}} ) {{ range $i := .Program.Instructions }} // {{ printf "Step %d: %s = x^%#x" $i.Output.Index $i.Output (index $.Chain $i.Output.Index) }} {{- with add $i.Op }} {{ $i.Output }}.Mul({{ .X }}, {{ .Y }}) {{ end -}} {{- with double $i.Op }} {{ $i.Output }}.Sqr({{ .X }}) {{ end -}} {{- with shift $i.Op -}} {{- $first := 0 -}} {{- if ne $i.Output.Identifier .X.Identifier }} {{ $i.Output }}.Sqr({{ .X }}) {{- $first = 1 -}} {{- end }} for s := {{ $first }}; s < {{ .S }}; s++ { {{ $i.Output }}.Sqr({{ $i.Output }}) } {{ end -}} {{- end }} return z } ``` Generate code by passing the template to `addchain`: ```sh addchain gen -tmpl inv.tmpl inv.acc | gofmt > inv.go ``` The end product: ```go // Code generated by addchain. DO NOT EDIT. package fp25519 // Inv computes z = 1/x (mod p) and returns it. func (z *Elt) Inv(x *Elt) *Elt { // Inversion computation is derived from the addition chain: // // _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 // // Operations: 254 squares 12 multiplies // // Generated by github.com/mmcloughlin/addchain v0.4.0. // Allocate Temporaries. var ( t0 = new(Elt) t1 = new(Elt) t2 = new(Elt) ) // Step 1: z = x^0x2 z.Sqr(x) // Step 2: z = x^0x3 z.Mul(x, z) // Step 4: t0 = x^0xc t0.Sqr(z) for s := 1; s < 2; s++ { t0.Sqr(t0) } // Step 5: t0 = x^0xf t0.Mul(z, t0) // Step 9: t1 = x^0xf0 t1.Sqr(t0) for s := 1; s < 4; s++ { t1.Sqr(t1) } // Step 10: t0 = x^0xff t0.Mul(t0, t1) // Step 12: t0 = x^0x3fc for s := 0; s < 2; s++ { t0.Sqr(t0) } // Step 13: t0 = x^0x3ff t0.Mul(z, t0) // Step 23: t1 = x^0xffc00 t1.Sqr(t0) for s := 1; s < 10; s++ { t1.Sqr(t1) } // Step 24: t1 = x^0xfffff t1.Mul(t0, t1) // Step 34: t1 = x^0x3ffffc00 for s := 0; s < 10; s++ { t1.Sqr(t1) } // Step 35: t1 = x^0x3fffffff t1.Mul(t0, t1) // Step 65: t2 = x^0xfffffffc0000000 t2.Sqr(t1) for s := 1; s < 30; s++ { t2.Sqr(t2) } // Step 66: t1 = x^0xfffffffffffffff t1.Mul(t1, t2) // Step 126: t2 = x^0xfffffffffffffff000000000000000 t2.Sqr(t1) for s := 1; s < 60; s++ { t2.Sqr(t2) } // Step 127: t1 = x^0xffffffffffffffffffffffffffffff t1.Mul(t1, t2) // Step 247: t2 = x^0xffffffffffffffffffffffffffffff000000000000000000000000000000 t2.Sqr(t1) for s := 1; s < 120; s++ { t2.Sqr(t2) } // Step 248: t1 = x^0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff t1.Mul(t1, t2) // Step 258: t1 = x^0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00 for s := 0; s < 10; s++ { t1.Sqr(t1) } // Step 259: t0 = x^0x3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff t0.Mul(t0, t1) // Step 261: t0 = x^0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc for s := 0; s < 2; s++ { t0.Sqr(t0) } // Step 262: t0 = x^0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd t0.Mul(x, t0) // Step 265: t0 = x^0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe8 for s := 0; s < 3; s++ { t0.Sqr(t0) } // Step 266: z = x^0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeb z.Mul(z, t0) return z } ``` This code is part of a [full working example](../internal/examples/fp25519) that passes tests. ## Template Reference Templates use Go [`text/template`](https://pkg.go.dev/text/template) syntax. The data structure passed to the template is: ```go type Data 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 } ``` In addition to the [builtin functions](https://pkg.go.dev/text/template#hdr-Functions), templates may use: | Name | Signature | Description | | ---- | --------- | ----------- | | **`add`** | `func(ir.Op) ir.Op` | If the input operation is an `ir.Add` then return it, otherwise return `nil` | | **`double`** | `func(ir.Op) ir.Op` | If the input operation is an `ir.Double` then return it, otherwise return `nil` | | **`shift`** | `func(ir.Op) ir.Op` | If the input operation is an `ir.Shift` then return it, otherwise return `nil` | | **`inc`** | `func(int) int` | Increment an integer | | **`format`** | `func(interface {}) (string, error)` | Formats an addition chain script (`*ast.Chain`) as a string | | **`split`** | `func(string, string) []string` | Calls `strings.Split` | | **`join`** | `func([]string, string) string` | Calls `strings.Join` | | **`lines`** | `func(string) []string` | Split input string into lines | ## Builtin Templates Example output for each builtin template is generated from the chain: ``` _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 ``` ### chain ``` {{- range $n, $value := .Chain -}} {{- printf "%3d: %#x\n" (inc $n) $value -}} {{- end -}} ```
Output of chain template ``` 1: 0x1 2: 0x2 3: 0x3 4: 0x6 5: 0xc 6: 0xf 7: 0x1e 8: 0x3c 9: 0x78 10: 0xf0 11: 0xff 12: 0x1fe 13: 0x3fc 14: 0x3ff 15: 0x7fe 16: 0xffc 17: 0x1ff8 18: 0x3ff0 19: 0x7fe0 20: 0xffc0 21: 0x1ff80 22: 0x3ff00 23: 0x7fe00 24: 0xffc00 25: 0xfffff 26: 0x1ffffe 27: 0x3ffffc 28: 0x7ffff8 29: 0xfffff0 30: 0x1ffffe0 31: 0x3ffffc0 32: 0x7ffff80 33: 0xfffff00 34: 0x1ffffe00 35: 0x3ffffc00 36: 0x3fffffff 37: 0x7ffffffe 38: 0xfffffffc 39: 0x1fffffff8 40: 0x3fffffff0 41: 0x7ffffffe0 42: 0xfffffffc0 43: 0x1fffffff80 44: 0x3fffffff00 45: 0x7ffffffe00 46: 0xfffffffc00 47: 0x1fffffff800 48: 0x3fffffff000 49: 0x7ffffffe000 50: 0xfffffffc000 51: 0x1fffffff8000 52: 0x3fffffff0000 53: 0x7ffffffe0000 54: 0xfffffffc0000 55: 0x1fffffff80000 56: 0x3fffffff00000 57: 0x7ffffffe00000 58: 0xfffffffc00000 59: 0x1fffffff800000 60: 0x3fffffff000000 61: 0x7ffffffe000000 62: 0xfffffffc000000 63: 0x1fffffff8000000 64: 0x3fffffff0000000 65: 0x7ffffffe0000000 66: 0xfffffffc0000000 67: 0xfffffffffffffff 68: 0x1ffffffffffffffe 69: 0x3ffffffffffffffc 70: 0x7ffffffffffffff8 71: 0xfffffffffffffff0 72: 0x1ffffffffffffffe0 73: 0x3ffffffffffffffc0 74: 0x7ffffffffffffff80 75: 0xfffffffffffffff00 76: 0x1ffffffffffffffe00 77: 0x3ffffffffffffffc00 78: 0x7ffffffffffffff800 79: 0xfffffffffffffff000 80: 0x1ffffffffffffffe000 81: 0x3ffffffffffffffc000 82: 0x7ffffffffffffff8000 83: 0xfffffffffffffff0000 84: 0x1ffffffffffffffe0000 85: 0x3ffffffffffffffc0000 86: 0x7ffffffffffffff80000 87: 0xfffffffffffffff00000 88: 0x1ffffffffffffffe00000 89: 0x3ffffffffffffffc00000 90: 0x7ffffffffffffff800000 91: 0xfffffffffffffff000000 92: 0x1ffffffffffffffe000000 93: 0x3ffffffffffffffc000000 94: 0x7ffffffffffffff8000000 95: 0xfffffffffffffff0000000 96: 0x1ffffffffffffffe0000000 97: 0x3ffffffffffffffc0000000 98: 0x7ffffffffffffff80000000 99: 0xfffffffffffffff00000000 100: 0x1ffffffffffffffe00000000 101: 0x3ffffffffffffffc00000000 102: 0x7ffffffffffffff800000000 103: 0xfffffffffffffff000000000 104: 0x1ffffffffffffffe000000000 105: 0x3ffffffffffffffc000000000 106: 0x7ffffffffffffff8000000000 107: 0xfffffffffffffff0000000000 108: 0x1ffffffffffffffe0000000000 109: 0x3ffffffffffffffc0000000000 110: 0x7ffffffffffffff80000000000 111: 0xfffffffffffffff00000000000 112: 0x1ffffffffffffffe00000000000 113: 0x3ffffffffffffffc00000000000 114: 0x7ffffffffffffff800000000000 115: 0xfffffffffffffff000000000000 116: 0x1ffffffffffffffe000000000000 117: 0x3ffffffffffffffc000000000000 118: 0x7ffffffffffffff8000000000000 119: 0xfffffffffffffff0000000000000 120: 0x1ffffffffffffffe0000000000000 121: 0x3ffffffffffffffc0000000000000 122: 0x7ffffffffffffff80000000000000 123: 0xfffffffffffffff00000000000000 124: 0x1ffffffffffffffe00000000000000 125: 0x3ffffffffffffffc00000000000000 126: 0x7ffffffffffffff800000000000000 127: 0xfffffffffffffff000000000000000 128: 0xffffffffffffffffffffffffffffff 129: 0x1fffffffffffffffffffffffffffffe 130: 0x3fffffffffffffffffffffffffffffc 131: 0x7fffffffffffffffffffffffffffff8 132: 0xffffffffffffffffffffffffffffff0 133: 0x1fffffffffffffffffffffffffffffe0 134: 0x3fffffffffffffffffffffffffffffc0 135: 0x7fffffffffffffffffffffffffffff80 136: 0xffffffffffffffffffffffffffffff00 137: 0x1fffffffffffffffffffffffffffffe00 138: 0x3fffffffffffffffffffffffffffffc00 139: 0x7fffffffffffffffffffffffffffff800 140: 0xffffffffffffffffffffffffffffff000 141: 0x1fffffffffffffffffffffffffffffe000 142: 0x3fffffffffffffffffffffffffffffc000 143: 0x7fffffffffffffffffffffffffffff8000 144: 0xffffffffffffffffffffffffffffff0000 145: 0x1fffffffffffffffffffffffffffffe0000 146: 0x3fffffffffffffffffffffffffffffc0000 147: 0x7fffffffffffffffffffffffffffff80000 148: 0xffffffffffffffffffffffffffffff00000 149: 0x1fffffffffffffffffffffffffffffe00000 150: 0x3fffffffffffffffffffffffffffffc00000 151: 0x7fffffffffffffffffffffffffffff800000 152: 0xffffffffffffffffffffffffffffff000000 153: 0x1fffffffffffffffffffffffffffffe000000 154: 0x3fffffffffffffffffffffffffffffc000000 155: 0x7fffffffffffffffffffffffffffff8000000 156: 0xffffffffffffffffffffffffffffff0000000 157: 0x1fffffffffffffffffffffffffffffe0000000 158: 0x3fffffffffffffffffffffffffffffc0000000 159: 0x7fffffffffffffffffffffffffffff80000000 160: 0xffffffffffffffffffffffffffffff00000000 161: 0x1fffffffffffffffffffffffffffffe00000000 162: 0x3fffffffffffffffffffffffffffffc00000000 163: 0x7fffffffffffffffffffffffffffff800000000 164: 0xffffffffffffffffffffffffffffff000000000 165: 0x1fffffffffffffffffffffffffffffe000000000 166: 0x3fffffffffffffffffffffffffffffc000000000 167: 0x7fffffffffffffffffffffffffffff8000000000 168: 0xffffffffffffffffffffffffffffff0000000000 169: 0x1fffffffffffffffffffffffffffffe0000000000 170: 0x3fffffffffffffffffffffffffffffc0000000000 171: 0x7fffffffffffffffffffffffffffff80000000000 172: 0xffffffffffffffffffffffffffffff00000000000 173: 0x1fffffffffffffffffffffffffffffe00000000000 174: 0x3fffffffffffffffffffffffffffffc00000000000 175: 0x7fffffffffffffffffffffffffffff800000000000 176: 0xffffffffffffffffffffffffffffff000000000000 177: 0x1fffffffffffffffffffffffffffffe000000000000 178: 0x3fffffffffffffffffffffffffffffc000000000000 179: 0x7fffffffffffffffffffffffffffff8000000000000 180: 0xffffffffffffffffffffffffffffff0000000000000 181: 0x1fffffffffffffffffffffffffffffe0000000000000 182: 0x3fffffffffffffffffffffffffffffc0000000000000 183: 0x7fffffffffffffffffffffffffffff80000000000000 184: 0xffffffffffffffffffffffffffffff00000000000000 185: 0x1fffffffffffffffffffffffffffffe00000000000000 186: 0x3fffffffffffffffffffffffffffffc00000000000000 187: 0x7fffffffffffffffffffffffffffff800000000000000 188: 0xffffffffffffffffffffffffffffff000000000000000 189: 0x1fffffffffffffffffffffffffffffe000000000000000 190: 0x3fffffffffffffffffffffffffffffc000000000000000 191: 0x7fffffffffffffffffffffffffffff8000000000000000 192: 0xffffffffffffffffffffffffffffff0000000000000000 193: 0x1fffffffffffffffffffffffffffffe0000000000000000 194: 0x3fffffffffffffffffffffffffffffc0000000000000000 195: 0x7fffffffffffffffffffffffffffff80000000000000000 196: 0xffffffffffffffffffffffffffffff00000000000000000 197: 0x1fffffffffffffffffffffffffffffe00000000000000000 198: 0x3fffffffffffffffffffffffffffffc00000000000000000 199: 0x7fffffffffffffffffffffffffffff800000000000000000 200: 0xffffffffffffffffffffffffffffff000000000000000000 201: 0x1fffffffffffffffffffffffffffffe000000000000000000 202: 0x3fffffffffffffffffffffffffffffc000000000000000000 203: 0x7fffffffffffffffffffffffffffff8000000000000000000 204: 0xffffffffffffffffffffffffffffff0000000000000000000 205: 0x1fffffffffffffffffffffffffffffe0000000000000000000 206: 0x3fffffffffffffffffffffffffffffc0000000000000000000 207: 0x7fffffffffffffffffffffffffffff80000000000000000000 208: 0xffffffffffffffffffffffffffffff00000000000000000000 209: 0x1fffffffffffffffffffffffffffffe00000000000000000000 210: 0x3fffffffffffffffffffffffffffffc00000000000000000000 211: 0x7fffffffffffffffffffffffffffff800000000000000000000 212: 0xffffffffffffffffffffffffffffff000000000000000000000 213: 0x1fffffffffffffffffffffffffffffe000000000000000000000 214: 0x3fffffffffffffffffffffffffffffc000000000000000000000 215: 0x7fffffffffffffffffffffffffffff8000000000000000000000 216: 0xffffffffffffffffffffffffffffff0000000000000000000000 217: 0x1fffffffffffffffffffffffffffffe0000000000000000000000 218: 0x3fffffffffffffffffffffffffffffc0000000000000000000000 219: 0x7fffffffffffffffffffffffffffff80000000000000000000000 220: 0xffffffffffffffffffffffffffffff00000000000000000000000 221: 0x1fffffffffffffffffffffffffffffe00000000000000000000000 222: 0x3fffffffffffffffffffffffffffffc00000000000000000000000 223: 0x7fffffffffffffffffffffffffffff800000000000000000000000 224: 0xffffffffffffffffffffffffffffff000000000000000000000000 225: 0x1fffffffffffffffffffffffffffffe000000000000000000000000 226: 0x3fffffffffffffffffffffffffffffc000000000000000000000000 227: 0x7fffffffffffffffffffffffffffff8000000000000000000000000 228: 0xffffffffffffffffffffffffffffff0000000000000000000000000 229: 0x1fffffffffffffffffffffffffffffe0000000000000000000000000 230: 0x3fffffffffffffffffffffffffffffc0000000000000000000000000 231: 0x7fffffffffffffffffffffffffffff80000000000000000000000000 232: 0xffffffffffffffffffffffffffffff00000000000000000000000000 233: 0x1fffffffffffffffffffffffffffffe00000000000000000000000000 234: 0x3fffffffffffffffffffffffffffffc00000000000000000000000000 235: 0x7fffffffffffffffffffffffffffff800000000000000000000000000 236: 0xffffffffffffffffffffffffffffff000000000000000000000000000 237: 0x1fffffffffffffffffffffffffffffe000000000000000000000000000 238: 0x3fffffffffffffffffffffffffffffc000000000000000000000000000 239: 0x7fffffffffffffffffffffffffffff8000000000000000000000000000 240: 0xffffffffffffffffffffffffffffff0000000000000000000000000000 241: 0x1fffffffffffffffffffffffffffffe0000000000000000000000000000 242: 0x3fffffffffffffffffffffffffffffc0000000000000000000000000000 243: 0x7fffffffffffffffffffffffffffff80000000000000000000000000000 244: 0xffffffffffffffffffffffffffffff00000000000000000000000000000 245: 0x1fffffffffffffffffffffffffffffe00000000000000000000000000000 246: 0x3fffffffffffffffffffffffffffffc00000000000000000000000000000 247: 0x7fffffffffffffffffffffffffffff800000000000000000000000000000 248: 0xffffffffffffffffffffffffffffff000000000000000000000000000000 249: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 250: 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe 251: 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc 252: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8 253: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0 254: 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0 255: 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0 256: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80 257: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00 258: 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00 259: 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00 260: 0x3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 261: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe 262: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc 263: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd 264: 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa 265: 0x3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4 266: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe8 267: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeb ```
### listing ``` {{ printf "tmp\t%s" (join .Program.Temporaries "\t") }} {{ range $i := .Program.Instructions -}} {{- with add $i.Op -}} {{ printf "add\t%s\t%s\t%s" $i.Output .X .Y }} {{ end -}} {{- with double $i.Op -}} {{ printf "double\t%s\t%s" $i.Output .X }} {{ end -}} {{- with shift $i.Op -}} {{ printf "shift\t%s\t%s\t%d" $i.Output .X .S }} {{ end -}} {{- end -}} ```
Output of listing template ``` tmp t0 t1 t2 double z x add z x z shift t0 z 2 add t0 z t0 shift t1 t0 4 add t0 t0 t1 shift t0 t0 2 add t0 z t0 shift t1 t0 10 add t1 t0 t1 shift t1 t1 10 add t1 t0 t1 shift t2 t1 30 add t1 t1 t2 shift t2 t1 60 add t1 t1 t2 shift t2 t1 120 add t1 t1 t2 shift t1 t1 10 add t0 t0 t1 shift t0 t0 2 add t0 x t0 shift t0 t0 3 add z z t0 ```
### ops ``` {{- range $n, $op := .Ops -}} {{- printf "[%3d] %4d+%-4d %#x\n" $n $op.I $op.J (index $.Chain (inc $n)) -}} {{- end -}} ```
Output of ops template ``` [ 0] 0+0 0x2 [ 1] 0+1 0x3 [ 2] 2+2 0x6 [ 3] 3+3 0xc [ 4] 2+4 0xf [ 5] 5+5 0x1e [ 6] 6+6 0x3c [ 7] 7+7 0x78 [ 8] 8+8 0xf0 [ 9] 5+9 0xff [ 10] 10+10 0x1fe [ 11] 11+11 0x3fc [ 12] 2+12 0x3ff [ 13] 13+13 0x7fe [ 14] 14+14 0xffc [ 15] 15+15 0x1ff8 [ 16] 16+16 0x3ff0 [ 17] 17+17 0x7fe0 [ 18] 18+18 0xffc0 [ 19] 19+19 0x1ff80 [ 20] 20+20 0x3ff00 [ 21] 21+21 0x7fe00 [ 22] 22+22 0xffc00 [ 23] 13+23 0xfffff [ 24] 24+24 0x1ffffe [ 25] 25+25 0x3ffffc [ 26] 26+26 0x7ffff8 [ 27] 27+27 0xfffff0 [ 28] 28+28 0x1ffffe0 [ 29] 29+29 0x3ffffc0 [ 30] 30+30 0x7ffff80 [ 31] 31+31 0xfffff00 [ 32] 32+32 0x1ffffe00 [ 33] 33+33 0x3ffffc00 [ 34] 13+34 0x3fffffff [ 35] 35+35 0x7ffffffe [ 36] 36+36 0xfffffffc [ 37] 37+37 0x1fffffff8 [ 38] 38+38 0x3fffffff0 [ 39] 39+39 0x7ffffffe0 [ 40] 40+40 0xfffffffc0 [ 41] 41+41 0x1fffffff80 [ 42] 42+42 0x3fffffff00 [ 43] 43+43 0x7ffffffe00 [ 44] 44+44 0xfffffffc00 [ 45] 45+45 0x1fffffff800 [ 46] 46+46 0x3fffffff000 [ 47] 47+47 0x7ffffffe000 [ 48] 48+48 0xfffffffc000 [ 49] 49+49 0x1fffffff8000 [ 50] 50+50 0x3fffffff0000 [ 51] 51+51 0x7ffffffe0000 [ 52] 52+52 0xfffffffc0000 [ 53] 53+53 0x1fffffff80000 [ 54] 54+54 0x3fffffff00000 [ 55] 55+55 0x7ffffffe00000 [ 56] 56+56 0xfffffffc00000 [ 57] 57+57 0x1fffffff800000 [ 58] 58+58 0x3fffffff000000 [ 59] 59+59 0x7ffffffe000000 [ 60] 60+60 0xfffffffc000000 [ 61] 61+61 0x1fffffff8000000 [ 62] 62+62 0x3fffffff0000000 [ 63] 63+63 0x7ffffffe0000000 [ 64] 64+64 0xfffffffc0000000 [ 65] 35+65 0xfffffffffffffff [ 66] 66+66 0x1ffffffffffffffe [ 67] 67+67 0x3ffffffffffffffc [ 68] 68+68 0x7ffffffffffffff8 [ 69] 69+69 0xfffffffffffffff0 [ 70] 70+70 0x1ffffffffffffffe0 [ 71] 71+71 0x3ffffffffffffffc0 [ 72] 72+72 0x7ffffffffffffff80 [ 73] 73+73 0xfffffffffffffff00 [ 74] 74+74 0x1ffffffffffffffe00 [ 75] 75+75 0x3ffffffffffffffc00 [ 76] 76+76 0x7ffffffffffffff800 [ 77] 77+77 0xfffffffffffffff000 [ 78] 78+78 0x1ffffffffffffffe000 [ 79] 79+79 0x3ffffffffffffffc000 [ 80] 80+80 0x7ffffffffffffff8000 [ 81] 81+81 0xfffffffffffffff0000 [ 82] 82+82 0x1ffffffffffffffe0000 [ 83] 83+83 0x3ffffffffffffffc0000 [ 84] 84+84 0x7ffffffffffffff80000 [ 85] 85+85 0xfffffffffffffff00000 [ 86] 86+86 0x1ffffffffffffffe00000 [ 87] 87+87 0x3ffffffffffffffc00000 [ 88] 88+88 0x7ffffffffffffff800000 [ 89] 89+89 0xfffffffffffffff000000 [ 90] 90+90 0x1ffffffffffffffe000000 [ 91] 91+91 0x3ffffffffffffffc000000 [ 92] 92+92 0x7ffffffffffffff8000000 [ 93] 93+93 0xfffffffffffffff0000000 [ 94] 94+94 0x1ffffffffffffffe0000000 [ 95] 95+95 0x3ffffffffffffffc0000000 [ 96] 96+96 0x7ffffffffffffff80000000 [ 97] 97+97 0xfffffffffffffff00000000 [ 98] 98+98 0x1ffffffffffffffe00000000 [ 99] 99+99 0x3ffffffffffffffc00000000 [100] 100+100 0x7ffffffffffffff800000000 [101] 101+101 0xfffffffffffffff000000000 [102] 102+102 0x1ffffffffffffffe000000000 [103] 103+103 0x3ffffffffffffffc000000000 [104] 104+104 0x7ffffffffffffff8000000000 [105] 105+105 0xfffffffffffffff0000000000 [106] 106+106 0x1ffffffffffffffe0000000000 [107] 107+107 0x3ffffffffffffffc0000000000 [108] 108+108 0x7ffffffffffffff80000000000 [109] 109+109 0xfffffffffffffff00000000000 [110] 110+110 0x1ffffffffffffffe00000000000 [111] 111+111 0x3ffffffffffffffc00000000000 [112] 112+112 0x7ffffffffffffff800000000000 [113] 113+113 0xfffffffffffffff000000000000 [114] 114+114 0x1ffffffffffffffe000000000000 [115] 115+115 0x3ffffffffffffffc000000000000 [116] 116+116 0x7ffffffffffffff8000000000000 [117] 117+117 0xfffffffffffffff0000000000000 [118] 118+118 0x1ffffffffffffffe0000000000000 [119] 119+119 0x3ffffffffffffffc0000000000000 [120] 120+120 0x7ffffffffffffff80000000000000 [121] 121+121 0xfffffffffffffff00000000000000 [122] 122+122 0x1ffffffffffffffe00000000000000 [123] 123+123 0x3ffffffffffffffc00000000000000 [124] 124+124 0x7ffffffffffffff800000000000000 [125] 125+125 0xfffffffffffffff000000000000000 [126] 66+126 0xffffffffffffffffffffffffffffff [127] 127+127 0x1fffffffffffffffffffffffffffffe [128] 128+128 0x3fffffffffffffffffffffffffffffc [129] 129+129 0x7fffffffffffffffffffffffffffff8 [130] 130+130 0xffffffffffffffffffffffffffffff0 [131] 131+131 0x1fffffffffffffffffffffffffffffe0 [132] 132+132 0x3fffffffffffffffffffffffffffffc0 [133] 133+133 0x7fffffffffffffffffffffffffffff80 [134] 134+134 0xffffffffffffffffffffffffffffff00 [135] 135+135 0x1fffffffffffffffffffffffffffffe00 [136] 136+136 0x3fffffffffffffffffffffffffffffc00 [137] 137+137 0x7fffffffffffffffffffffffffffff800 [138] 138+138 0xffffffffffffffffffffffffffffff000 [139] 139+139 0x1fffffffffffffffffffffffffffffe000 [140] 140+140 0x3fffffffffffffffffffffffffffffc000 [141] 141+141 0x7fffffffffffffffffffffffffffff8000 [142] 142+142 0xffffffffffffffffffffffffffffff0000 [143] 143+143 0x1fffffffffffffffffffffffffffffe0000 [144] 144+144 0x3fffffffffffffffffffffffffffffc0000 [145] 145+145 0x7fffffffffffffffffffffffffffff80000 [146] 146+146 0xffffffffffffffffffffffffffffff00000 [147] 147+147 0x1fffffffffffffffffffffffffffffe00000 [148] 148+148 0x3fffffffffffffffffffffffffffffc00000 [149] 149+149 0x7fffffffffffffffffffffffffffff800000 [150] 150+150 0xffffffffffffffffffffffffffffff000000 [151] 151+151 0x1fffffffffffffffffffffffffffffe000000 [152] 152+152 0x3fffffffffffffffffffffffffffffc000000 [153] 153+153 0x7fffffffffffffffffffffffffffff8000000 [154] 154+154 0xffffffffffffffffffffffffffffff0000000 [155] 155+155 0x1fffffffffffffffffffffffffffffe0000000 [156] 156+156 0x3fffffffffffffffffffffffffffffc0000000 [157] 157+157 0x7fffffffffffffffffffffffffffff80000000 [158] 158+158 0xffffffffffffffffffffffffffffff00000000 [159] 159+159 0x1fffffffffffffffffffffffffffffe00000000 [160] 160+160 0x3fffffffffffffffffffffffffffffc00000000 [161] 161+161 0x7fffffffffffffffffffffffffffff800000000 [162] 162+162 0xffffffffffffffffffffffffffffff000000000 [163] 163+163 0x1fffffffffffffffffffffffffffffe000000000 [164] 164+164 0x3fffffffffffffffffffffffffffffc000000000 [165] 165+165 0x7fffffffffffffffffffffffffffff8000000000 [166] 166+166 0xffffffffffffffffffffffffffffff0000000000 [167] 167+167 0x1fffffffffffffffffffffffffffffe0000000000 [168] 168+168 0x3fffffffffffffffffffffffffffffc0000000000 [169] 169+169 0x7fffffffffffffffffffffffffffff80000000000 [170] 170+170 0xffffffffffffffffffffffffffffff00000000000 [171] 171+171 0x1fffffffffffffffffffffffffffffe00000000000 [172] 172+172 0x3fffffffffffffffffffffffffffffc00000000000 [173] 173+173 0x7fffffffffffffffffffffffffffff800000000000 [174] 174+174 0xffffffffffffffffffffffffffffff000000000000 [175] 175+175 0x1fffffffffffffffffffffffffffffe000000000000 [176] 176+176 0x3fffffffffffffffffffffffffffffc000000000000 [177] 177+177 0x7fffffffffffffffffffffffffffff8000000000000 [178] 178+178 0xffffffffffffffffffffffffffffff0000000000000 [179] 179+179 0x1fffffffffffffffffffffffffffffe0000000000000 [180] 180+180 0x3fffffffffffffffffffffffffffffc0000000000000 [181] 181+181 0x7fffffffffffffffffffffffffffff80000000000000 [182] 182+182 0xffffffffffffffffffffffffffffff00000000000000 [183] 183+183 0x1fffffffffffffffffffffffffffffe00000000000000 [184] 184+184 0x3fffffffffffffffffffffffffffffc00000000000000 [185] 185+185 0x7fffffffffffffffffffffffffffff800000000000000 [186] 186+186 0xffffffffffffffffffffffffffffff000000000000000 [187] 187+187 0x1fffffffffffffffffffffffffffffe000000000000000 [188] 188+188 0x3fffffffffffffffffffffffffffffc000000000000000 [189] 189+189 0x7fffffffffffffffffffffffffffff8000000000000000 [190] 190+190 0xffffffffffffffffffffffffffffff0000000000000000 [191] 191+191 0x1fffffffffffffffffffffffffffffe0000000000000000 [192] 192+192 0x3fffffffffffffffffffffffffffffc0000000000000000 [193] 193+193 0x7fffffffffffffffffffffffffffff80000000000000000 [194] 194+194 0xffffffffffffffffffffffffffffff00000000000000000 [195] 195+195 0x1fffffffffffffffffffffffffffffe00000000000000000 [196] 196+196 0x3fffffffffffffffffffffffffffffc00000000000000000 [197] 197+197 0x7fffffffffffffffffffffffffffff800000000000000000 [198] 198+198 0xffffffffffffffffffffffffffffff000000000000000000 [199] 199+199 0x1fffffffffffffffffffffffffffffe000000000000000000 [200] 200+200 0x3fffffffffffffffffffffffffffffc000000000000000000 [201] 201+201 0x7fffffffffffffffffffffffffffff8000000000000000000 [202] 202+202 0xffffffffffffffffffffffffffffff0000000000000000000 [203] 203+203 0x1fffffffffffffffffffffffffffffe0000000000000000000 [204] 204+204 0x3fffffffffffffffffffffffffffffc0000000000000000000 [205] 205+205 0x7fffffffffffffffffffffffffffff80000000000000000000 [206] 206+206 0xffffffffffffffffffffffffffffff00000000000000000000 [207] 207+207 0x1fffffffffffffffffffffffffffffe00000000000000000000 [208] 208+208 0x3fffffffffffffffffffffffffffffc00000000000000000000 [209] 209+209 0x7fffffffffffffffffffffffffffff800000000000000000000 [210] 210+210 0xffffffffffffffffffffffffffffff000000000000000000000 [211] 211+211 0x1fffffffffffffffffffffffffffffe000000000000000000000 [212] 212+212 0x3fffffffffffffffffffffffffffffc000000000000000000000 [213] 213+213 0x7fffffffffffffffffffffffffffff8000000000000000000000 [214] 214+214 0xffffffffffffffffffffffffffffff0000000000000000000000 [215] 215+215 0x1fffffffffffffffffffffffffffffe0000000000000000000000 [216] 216+216 0x3fffffffffffffffffffffffffffffc0000000000000000000000 [217] 217+217 0x7fffffffffffffffffffffffffffff80000000000000000000000 [218] 218+218 0xffffffffffffffffffffffffffffff00000000000000000000000 [219] 219+219 0x1fffffffffffffffffffffffffffffe00000000000000000000000 [220] 220+220 0x3fffffffffffffffffffffffffffffc00000000000000000000000 [221] 221+221 0x7fffffffffffffffffffffffffffff800000000000000000000000 [222] 222+222 0xffffffffffffffffffffffffffffff000000000000000000000000 [223] 223+223 0x1fffffffffffffffffffffffffffffe000000000000000000000000 [224] 224+224 0x3fffffffffffffffffffffffffffffc000000000000000000000000 [225] 225+225 0x7fffffffffffffffffffffffffffff8000000000000000000000000 [226] 226+226 0xffffffffffffffffffffffffffffff0000000000000000000000000 [227] 227+227 0x1fffffffffffffffffffffffffffffe0000000000000000000000000 [228] 228+228 0x3fffffffffffffffffffffffffffffc0000000000000000000000000 [229] 229+229 0x7fffffffffffffffffffffffffffff80000000000000000000000000 [230] 230+230 0xffffffffffffffffffffffffffffff00000000000000000000000000 [231] 231+231 0x1fffffffffffffffffffffffffffffe00000000000000000000000000 [232] 232+232 0x3fffffffffffffffffffffffffffffc00000000000000000000000000 [233] 233+233 0x7fffffffffffffffffffffffffffff800000000000000000000000000 [234] 234+234 0xffffffffffffffffffffffffffffff000000000000000000000000000 [235] 235+235 0x1fffffffffffffffffffffffffffffe000000000000000000000000000 [236] 236+236 0x3fffffffffffffffffffffffffffffc000000000000000000000000000 [237] 237+237 0x7fffffffffffffffffffffffffffff8000000000000000000000000000 [238] 238+238 0xffffffffffffffffffffffffffffff0000000000000000000000000000 [239] 239+239 0x1fffffffffffffffffffffffffffffe0000000000000000000000000000 [240] 240+240 0x3fffffffffffffffffffffffffffffc0000000000000000000000000000 [241] 241+241 0x7fffffffffffffffffffffffffffff80000000000000000000000000000 [242] 242+242 0xffffffffffffffffffffffffffffff00000000000000000000000000000 [243] 243+243 0x1fffffffffffffffffffffffffffffe00000000000000000000000000000 [244] 244+244 0x3fffffffffffffffffffffffffffffc00000000000000000000000000000 [245] 245+245 0x7fffffffffffffffffffffffffffff800000000000000000000000000000 [246] 246+246 0xffffffffffffffffffffffffffffff000000000000000000000000000000 [247] 127+247 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff [248] 248+248 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe [249] 249+249 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc [250] 250+250 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8 [251] 251+251 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0 [252] 252+252 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0 [253] 253+253 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0 [254] 254+254 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80 [255] 255+255 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00 [256] 256+256 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00 [257] 257+257 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00 [258] 13+258 0x3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff [259] 259+259 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe [260] 260+260 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc [261] 0+261 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd [262] 262+262 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa [263] 263+263 0x3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4 [264] 264+264 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe8 [265] 2+265 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeb ```
### script ``` {{- format .Script -}} ```
Output of script template ``` _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 ```
addchain-0.4.0/doc/references.bib000066400000000000000000000232561514305256600166310ustar00rootroot00000000000000@article{addchainreview, title = "A Review on Heuristics for Addition Chain Problem: Towards Efficient Public Key Cryptosystems", author = "Adamu Muhammad Noma and Abdullah Muhammed and Mohamad Afendee Mohamed and Zuriati Ahmad Zulkarnain", url = "https://thescipub.com/pdf/10.3844/jcssp.2017.275.289.pdf", journal = "Journal of Computer Science", number = 8, pages = "275-289", volume = 13, year = 2017, } @misc{aranha, title = "A note on high-security general-purpose elliptic curves", author = "Diego F. Aranha and Paulo S. L. M. Barreto and Geovandro C. C. F. Pereira and Jefferson E. Ricardini", url = "https://eprint.iacr.org/2013/647", howpublished = "Cryptology ePrint Archive, Report 2013/647", year = 2013, } @inproceedings{boscoster, title = "Addition Chain Heuristics", author = "Bos, Jurjen and Coster, Matthijs", url = "https://link.springer.com/content/pdf/10.1007/0-387-34805-0_37.pdf", abstract = "Much current research focuses on fast evaluation of RSA, which consists of computing powers modulo a large number n. While some try to increase the speed of multiplica- tions, here we consider reducing the number of multiplications. In particular, we present a precomputation method that reduces the number of multiplications for the computation of a given power.", address = "New York, NY", booktitle = "Advances in Cryptology --- CRYPTO' 89 Proceedings", editor = "Brassard, Gilles", isbn = "978-0-387-34805-6", pages = "400--407", publisher = "Springer New York", year = 1990, } @phdthesis{braueraddsubchains, title = "Brauer addition-subtraction chains", author = "Martin Otto", url = "http://www.martin-otto.de/publications/docs/2001_MartinOtto_Diplom_BrauerAddition-SubtractionChains.pdf", school = "Universitat Paderborn", year = 2001, } @article{contfrac, title = "Addition chains using continued fractions", author = "F Bergeron and J Berstel and S Brlek and C Duboc", url = "http://www-igm.univ-mlv.fr/~berstel/Articles/1989AdditionChainDuboc.pdf", issn = "0196-6774", journal = "Journal of Algorithms", number = 3, pages = "403 - 412", volume = 10, year = 1989, } @misc{crandallprime, title = "Method and apparatus for public key exchange in a cryptographic system", author = "Richard E. Crandall", url = "https://patents.google.com/patent/US5159632A", howpublished = "US Patent 5,159,632", year = 1992, } @inproceedings{curve25519, title = "Curve25519: New Diffie-Hellman Speed Records", author = "Bernstein, Daniel J.", url = "https://cr.yp.to/ecdh/curve25519-20060209.pdf", abstract = "This paper explains the design and implementation of a high-security elliptic-curve-Diffie-Hellman function achieving record-setting speeds: e.g., 832457 Pentium III cycles (with several side benefits: free key compression, free key validation, and state-of-the-art timing-attack protection), more than twice as fast as other authors' results at the same conjectured security level (with or without the side benefits).", address = "Berlin, Heidelberg", booktitle = "Public Key Cryptography - PKC 2006", editor = "Yung, Moti and Dodis, Yevgeniy and Kiayias, Aggelos and Malkin, Tal", isbn = "978-3-540-33852-9", pages = "207--228", publisher = "Springer Berlin Heidelberg", year = 2006, } @misc{curvechains, title = "The Most Efficient Known Addition Chains for Field Element and Scalar Inversion for the Most Popular and Most Unpopular Elliptic Curves", author = "Brian Smith", url = "https://briansmith.org/ecc-inversion-addition-chains-01", urldate = "2019-06-30", year = 2017, } @article{efficientcompaddchain, title = "Efficient computation of addition chains", author = "Bergeron, F. and Berstel, J. and Brlek, S.", url = "http://www.numdam.org/item/JTNB_1994__6_1_21_0", journal = "Journal de theorie des nombres de Bordeaux", language = "en", mrnumber = 1305286, number = 1, pages = "21-38", publisher = "Universite Bordeaux I", volume = 6, year = 1994, zbl = "0812.11072", } @misc{elligator, title = "Elligator: Elliptic-curve points indistinguishable from uniform random strings", author = "Daniel J. Bernstein and Mike Hamburg and Anna Krasnova and Tanja Lange", url = "https://eprint.iacr.org/2013/325", howpublished = "Cryptology ePrint Archive, Report 2013/325", year = 2013, } @misc{fips186-2, title = "Digital Signature Standard (DSS)", author = "NIST", url = "https://csrc.nist.gov/csrc/media/publications/fips/186/2/archive/2000-01-27/documents/fips186-2.pdf", howpublished = "Federal Information Processing Standards Publication 186-2", year = 2000, } @misc{gencontfrac, title = "Efficient computation of addition-subtraction chains using generalized continued Fractions", author = "Amadou Tall and Ali Yassin Sanghare", url = "https://eprint.iacr.org/2013/466", howpublished = "Cryptology ePrint Archive, Report 2013/466", year = 2013, } @article{genshortchains, title = "New Methods for Generating Short Addition Chains", author = "Kunihiro, Noboru and Yamamoto, Hirosuke", url = "https://pdfs.semanticscholar.org/b398/d10faca35af9ce5a6026458b251fd0a5640c.pdf", journal = "IEICE Transactions on Fundamentals of Electronics Communications and Computer Sciences", month = 01, volume = "E83A", year = 2000, } @misc{github:kwantam/addchain, title = "kwantam/addchain", author = "Riad S. Wahby", url = "https://github.com/kwantam/addchain", howpublished = "Github Repository", license = "Apache License, Version 2.0", year = 2018, } @misc{goldilocks, title = "Ed448-Goldilocks, a new elliptic curve", author = "Mike Hamburg", url = "https://eprint.iacr.org/2015/625", howpublished = "Cryptology ePrint Archive, Report 2015/625", year = 2015, } @misc{hashbls12-381, title = "Fast and simple constant-time hashing to the BLS12-381 elliptic curve", author = "Riad S. Wahby and Dan Boneh", url = "https://eprint.iacr.org/2019/403", howpublished = "Cryptology ePrint Archive, Report 2019/403", year = 2019, } @inbook{hehcc:exp, title = "Exponentiation", author = "Christophe Doche", url = "http://koclab.cs.ucsb.edu/teaching/ecc/eccPapers/Doche-ch09.pdf", booktitle = "Handbook of Elliptic and Hyperelliptic Curve Cryptography", chapter = 9, publisher = "Chapman and Hall", year = 2006, } @inbook{knuth, title = "Evaluation of Powers", author = "Knuth, Donald E.", url = "https://www-cs-faculty.stanford.edu/~knuth/taocp.html", booktitle = "The Art of Computer Programming, Volume 2 (Third Edition): Seminumerical Algorithms", chapter = "4.6.3", publisher = "Addison-Wesley Longman Publishing Co., Inc.", year = 1997, } @mastersthesis{modboscoster, title = "Modifications of Bos and Coster’s Heuristics in search of a shorter addition chain for faster exponentiation", author = "Ayan Nandy", url = "http://library.isical.ac.in:8080/jspui/bitstream/10263/6441/1/DISS-285.pdf", school = "Indian Statistical Institute Kolkata", year = 2011, } @techreport{mpnt, title = "MpNT: A Multi-Precision Number Theory Package, Number Theoretical Algorithms (I)", author = "F. L. Ţiplea and S. Iftene and C. Hriţcu and I. Goriac and R. Gordân and E. Erbiceanu", url = "https://profs.info.uaic.ro/~tr/tr03-02.pdf", institution = {Faculty of Computer Science, "Alexandru Ioan Cuza" University, Iasi}, number = "TR03-02", year = 2003, } @misc{nistdanger, title = "Security dangers of the NIST curves", author = "Daniel J. Bernstein and Tanja Lange", url = "https://cr.yp.to/talks/2013.09.16/slides-djb-20130916-a4.pdf", year = 2013, } @misc{pairingsfinalexp, title = "On the final exponentiation for calculating pairings on ordinary elliptic curves", author = "Michael Scott and Naomi Benger and Manuel Charlemagne and Luis J. Dominguez Perez and Ezekiel J. Kachisa", url = "https://eprint.iacr.org/2008/490", howpublished = "Cryptology ePrint Archive, Report 2008/490", year = 2008, } @misc{safecurves, title = "SafeCurves: choosing safe curves for elliptic-curve cryptography", author = "Daniel J. Bernstein and Tanja Lange", url = "https://safecurves.cr.yp.to", } @misc{sec2, title = "SEC 2: Recommended Elliptic Curve Domain Parameters, Version 2.0", author = "Certicom Research", url = "https://safecurves.cr.yp.to/www.secg.org/sec2-v2.pdf", howpublished = "Standards for Efficient Cryptography 2", year = 2010, } @techreport{solinasprime, title = "Generalized Mersenne Primes", author = "Jerome A. Solinas", url = "http://cacr.uwaterloo.ca/techreports/1999/corr99-39.pdf", institution = "Centre for Applied Cryptographic Research (CACR) at the University of Waterloo", number = "CORR 99-39", year = 1999, } @phdthesis{speedsubgroup, title = "Speeding up subgroup cryptosystems", author = "Stam, Martijn", url = "https://cr.yp.to/bib/2003/stam-thesis.pdf", school = "Technische Universiteit Eindhoven", year = 2003, } addchain-0.4.0/doc/results.md000066400000000000000000000457041514305256600160570ustar00rootroot00000000000000# Results * [Curve25519 Field Inversion](#curve25519-field-inversion) * [NIST P-256 Field Inversion](#nist-p-256-field-inversion) * [NIST P-384 Field Inversion](#nist-p-384-field-inversion) * [secp256k1 (Bitcoin) Field Inversion](#secp256k1-bitcoin-field-inversion) * [Curve25519 Scalar Inversion](#curve25519-scalar-inversion) * [NIST P-256 Scalar Inversion](#nist-p-256-scalar-inversion) * [NIST P-384 Scalar Inversion](#nist-p-384-scalar-inversion) * [secp256k1 (Bitcoin) Scalar Inversion](#secp256k1-bitcoin-scalar-inversion) * [M-221 Field Inversion](#m-221-field-inversion) * [E-222 Field Inversion](#e-222-field-inversion) * [Curve1174 Field Inversion](#curve1174-field-inversion) * [E-382 Field Inversion](#e-382-field-inversion) * [M-383/Curve383187 Field Inversion](#m-383curve383187-field-inversion) * [Curve41417 Field Inversion](#curve41417-field-inversion) * [M-511 Field Inversion](#m-511-field-inversion) * [NIST P-192 Field Inversion](#nist-p-192-field-inversion) * [NIST P-224 Field Inversion](#nist-p-224-field-inversion) * [Goldilocks Field Inversion](#goldilocks-field-inversion) * [secp192k1 Field Inversion](#secp192k1-field-inversion) * [secp224k1 Field Inversion](#secp224k1-field-inversion) ## Curve25519 Field Inversion | Property | Value | | --- | ----- | | _N_ | `2^255-19` | | _d_ | `2` | | _N_-_d_ | `7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeb` | | Length | 266 | | Algorithm | `opt(runs(continued_fractions(dichotomic)))` | | Best Known | 265 | | Delta | +1 | Addition chain produced by `addchain`: ```go _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 ``` ## NIST P-256 Field Inversion | Property | Value | | --- | ----- | | _N_ | `2^256-2^224+2^192+2^96-1` | | _d_ | `3` | | _N_-_d_ | `ffffffff00000001000000000000000000000000fffffffffffffffffffffffc` | | Length | 266 | | Algorithm | `opt(runs(continued_fractions(dichotomic)))` | | Best Known | 266 | | Delta | +0 | Addition chain produced by `addchain`: ```go _10 = 2*1 _11 = 1 + _10 _1100 = _11 << 2 _1111 = _11 + _1100 _111100 = _1111 << 2 _111111 = _11 + _111100 x12 = _111111 << 6 + _111111 x24 = x12 << 12 + x12 x30 = x24 << 6 + _111111 x32 = x30 << 2 + _11 i232 = ((x32 << 32 + 1) << 128 + x32) << 32 return ((x32 + i232) << 30 + x30) << 2 ``` ## NIST P-384 Field Inversion | Property | Value | | --- | ----- | | _N_ | `2^384-2^128-2^96+2^32-1` | | _d_ | `3` | | _N_-_d_ | `fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffc` | | Length | 397 | | Algorithm | `opt(runs(heuristic(use_first(halving,approximation))))` | | Best Known | 396 | | Delta | +1 | Addition chain produced by `addchain`: ```go _10 = 2*1 _11 = 1 + _10 _110 = 2*_11 _111 = 1 + _110 _111000 = _111 << 3 _111111 = _111 + _111000 x12 = _111111 << 6 + _111111 x24 = x12 << 12 + x12 x30 = x24 << 6 + _111111 x31 = 2*x30 + 1 x32 = 2*x31 + 1 x63 = x32 << 31 + x31 x126 = x63 << 63 + x63 x252 = x126 << 126 + x126 x255 = x252 << 3 + _111 return ((x255 << 33 + x32) << 94 + x30) << 2 ``` ## secp256k1 (Bitcoin) Field Inversion | Property | Value | | --- | ----- | | _N_ | `fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f` | | _d_ | `3` | | _N_-_d_ | `fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2c` | | Length | 269 | | Algorithm | `opt(runs(heuristic(use_first(halving,delta_largest))))` | | Best Known | 269 | | Delta | +0 | Addition chain produced by `addchain`: ```go _10 = 2*1 _11 = 1 + _10 _1100 = _11 << 2 _1111 = _11 + _1100 _11110 = 2*_1111 _11111 = 1 + _11110 _1111100 = _11111 << 2 _1111111 = _11 + _1111100 x11 = _1111111 << 4 + _1111 x22 = x11 << 11 + x11 x27 = x22 << 5 + _11111 x54 = x27 << 27 + x27 x108 = x54 << 54 + x54 x216 = x108 << 108 + x108 x223 = x216 << 7 + _1111111 i266 = ((x223 << 23 + x22) << 5 + 1) << 3 return (_11 + i266) << 2 ``` ## Curve25519 Scalar Inversion | Property | Value | | --- | ----- | | _N_ | `1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed` | | _d_ | `2` | | _N_-_d_ | `1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3eb` | | Length | 283 | | Algorithm | `opt(dictionary(hybrid(4,0),continued_fractions(binary)))` | | Best Known | 284 | | Delta | -1 | Addition chain produced by `addchain`: ```go _10 = 2*1 _11 = 1 + _10 _100 = 1 + _11 _1000 = 2*_100 _1010 = _10 + _1000 _1011 = 1 + _1010 _10000 = 2*_1000 _10110 = 2*_1011 _100000 = _1010 + _10110 _100110 = _10000 + _10110 _1000000 = 2*_100000 _1010000 = _10000 + _1000000 _1010011 = _11 + _1010000 _1100011 = _10000 + _1010011 _1100111 = _100 + _1100011 _1101011 = _100 + _1100111 _10010011 = _1000000 + _1010011 _10010111 = _100 + _10010011 _10111101 = _100110 + _10010111 _11010011 = _10110 + _10111101 _11100111 = _1010000 + _10010111 _11101011 = _100 + _11100111 _11110101 = _1010 + _11101011 i161 = ((_1011 + _11110101) << 126 + _1010011) << 9 + _10 i180 = ((_11110101 + i161) << 7 + _1100111) << 9 + _11110101 i210 = ((i180 << 11 + _10111101) << 8 + _11100111) << 9 i233 = ((_1101011 + i210) << 6 + _1011) << 14 + _10010011 i264 = ((i233 << 10 + _1100011) << 9 + _10010111) << 10 return ((_11110101 + i264) << 8 + _11010011) << 8 + _11101011 ``` ## NIST P-256 Scalar Inversion | Property | Value | | --- | ----- | | _N_ | `ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551` | | _d_ | `2` | | _N_-_d_ | `ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f` | | Length | 294 | | Algorithm | `opt(dictionary(hybrid(8,16),heuristic(use_first(halving,delta_largest))))` | | Best Known | 292 | | Delta | +2 | Addition chain produced by `addchain`: ```go _10 = 2*1 _100 = 2*_10 _101 = 1 + _100 _110 = 1 + _101 _1001 = _100 + _101 _1111 = _110 + _1001 _10010 = 2*_1001 _10101 = _110 + _1111 _11000 = _110 + _10010 _11010 = _10 + _11000 _101111 = _10101 + _11010 _111000 = _1001 + _101111 _111101 = _101 + _111000 _111111 = _10 + _111101 _1001111 = _10010 + _111101 _1100001 = _10010 + _1001111 _1100011 = _10 + _1100001 _1110011 = _10010 + _1100001 _1110111 = _100 + _1110011 _1111101 = _110 + _1110111 _10010101 = _11000 + _1111101 _10100111 = _10010 + _10010101 _10101101 = _110 + _10100111 _11100101 = _111000 + _10101101 _11111111 = _11010 + _11100101 x16 = _11111111 << 8 + _11111111 x32 = x16 << 16 + x16 i133 = ((x32 << 48 + x16) << 16 + x16) << 16 i158 = ((x16 + i133) << 16 + x16) << 6 + _101111 i186 = ((i158 << 9 + _1110011) << 8 + _1111101) << 9 i206 = ((_10101101 + i186) << 8 + _10100111) << 9 + _101111 i236 = ((i206 << 8 + _111101) << 11 + _1001111) << 9 i257 = ((_1110111 + i236) << 10 + _11100101) << 8 + _1100001 i286 = ((i257 << 7 + _111111) << 10 + _1100011) << 10 return (_10010101 + i286) << 6 + _1111 ``` ## NIST P-384 Scalar Inversion | Property | Value | | --- | ----- | | _N_ | `ffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973` | | _d_ | `2` | | _N_-_d_ | `ffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52971` | | Length | 434 | | Algorithm | `opt(dictionary(hybrid(4,0),continued_fractions(dichotomic)))` | | Best Known | 433 | | Delta | +1 | Addition chain produced by `addchain`: ```go _10 = 2*1 _11 = 1 + _10 _101 = _10 + _11 _111 = _10 + _101 _1001 = _10 + _111 _1011 = _10 + _1001 _1101 = _10 + _1011 _1111 = _10 + _1101 _11110 = 2*_1111 _11111 = 1 + _11110 _1111100 = _11111 << 2 i14 = _1111100 << 2 i26 = (i14 << 3 + _1111100) << 7 + i14 i42 = i26 << 15 + i26 x64 = i42 << 30 + i42 + _1111 x128 = x64 << 64 + x64 x192 = x128 << 64 + x64 x194 = x192 << 2 + _11 i225 = ((x194 << 6 + _111) << 3 + _11) << 7 i235 = 2*((_1101 + i225) << 6 + _1101) + 1 i258 = ((i235 << 11 + _11111) << 2 + 1) << 8 i269 = ((_1101 + i258) << 2 + _11) << 6 + _1011 i286 = ((i269 << 4 + _111) << 6 + _11111) << 5 i308 = ((_1011 + i286) << 10 + _1101) << 9 + _1101 i323 = ((i308 << 4 + _1011) << 6 + _1001) << 3 i340 = ((1 + i323) << 7 + _1011) << 7 + _101 i357 = ((i340 << 5 + _111) << 5 + _1111) << 5 i369 = ((_1011 + i357) << 4 + _1011) << 5 + _111 i387 = ((i369 << 3 + _11) << 7 + _11) << 6 i397 = ((_1011 + i387) << 4 + _101) << 3 + _11 i413 = ((i397 << 4 + _11) << 4 + _11) << 6 i427 = ((_101 + i413) << 5 + _101) << 6 + _1011 return (2*i427 + 1) << 4 + 1 ``` ## secp256k1 (Bitcoin) Scalar Inversion | Property | Value | | --- | ----- | | _N_ | `fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141` | | _d_ | `2` | | _N_-_d_ | `fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413f` | | Length | 293 | | Algorithm | `opt(dictionary(hybrid(4,0),continued_fractions(dichotomic)))` | | Best Known | 290 | | Delta | +3 | Addition chain produced by `addchain`: ```go _10 = 2*1 _11 = 1 + _10 _101 = _10 + _11 _111 = _10 + _101 _1001 = _10 + _111 _1011 = _10 + _1001 _1101 = _10 + _1011 _110100 = _1101 << 2 _111111 = _1011 + _110100 _1111110 = 2*_111111 _1111111 = 1 + _1111110 _11111110 = 2*_1111111 _11111111 = 1 + _11111110 i17 = _11111111 << 3 i19 = i17 << 2 i21 = i19 << 2 i39 = (i21 << 6 + i19) << 10 + i21 x63 = (i39 << 4 + i17) << 28 + i39 + _1111111 x64 = 2*x63 + 1 x127 = x64 << 63 + x63 i154 = ((x127 << 5 + _1011) << 3 + _101) << 4 i166 = ((_101 + i154) << 4 + _111) << 5 + _1101 i181 = ((i166 << 2 + _11) << 5 + _111) << 6 i193 = ((_1101 + i181) << 5 + _1011) << 4 + _1101 i214 = ((i193 << 3 + 1) << 6 + _101) << 10 i230 = ((_111 + i214) << 4 + _111) << 9 + _11111111 i247 = ((i230 << 5 + _1001) << 6 + _1011) << 4 i261 = ((_1101 + i247) << 5 + _11) << 6 + _1101 i283 = ((i261 << 10 + _1101) << 4 + _1001) << 6 return (1 + i283) << 8 + _111111 ``` ## M-221 Field Inversion | Property | Value | | --- | ----- | | _N_ | `2^221-3` | | _d_ | `2` | | _N_-_d_ | `1ffffffffffffffffffffffffffffffffffffffffffffffffffffffb` | | Length | 231 | | Algorithm | `opt(runs(continued_fractions(dichotomic)))` | Addition chain produced by `addchain`: ```go _10 = 2*1 _11 = 1 + _10 _1100 = _11 << 2 _1111 = _11 + _1100 _111100 = _1111 << 2 _111111 = _11 + _111100 x10 = _111111 << 4 + _1111 x20 = x10 << 10 + x10 x26 = x20 << 6 + _111111 x52 = x26 << 26 + x26 x104 = x52 << 52 + x52 x208 = x104 << 104 + x104 x218 = x208 << 10 + x10 return x218 << 3 + _11 ``` ## E-222 Field Inversion | Property | Value | | --- | ----- | | _N_ | `2^222-117` | | _d_ | `2` | | _N_-_d_ | `3fffffffffffffffffffffffffffffffffffffffffffffffffffff89` | | Length | 233 | | Algorithm | `opt(runs(continued_fractions(dichotomic)))` | Addition chain produced by `addchain`: ```go _10 = 2*1 _11 = 1 + _10 _110 = 2*_11 _111 = 1 + _110 _111000 = _111 << 3 _111111 = _111 + _111000 _1111110 = 2*_111111 _1111111 = 1 + _1111110 x13 = _1111111 << 6 + _111111 x26 = x13 << 13 + x13 x52 = x26 << 26 + x26 x104 = x52 << 52 + x52 x208 = x104 << 104 + x104 x215 = x208 << 7 + _1111111 return (x215 << 4 + 1) << 3 + 1 ``` ## Curve1174 Field Inversion | Property | Value | | --- | ----- | | _N_ | `2^251-9` | | _d_ | `2` | | _N_-_d_ | `7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5` | | Length | 263 | | Algorithm | `opt(dictionary(hybrid(3,64),continued_fractions(dichotomic)))` | Addition chain produced by `addchain`: ```go _10 = 2*1 _11 = 1 + _10 _110 = 2*_11 _111 = 1 + _110 _111000 = _111 << 3 _111111 = _111 + _111000 _1111110 = 2*_111111 _1111111 = 1 + _1111110 x14 = _1111111 << 7 + _1111111 x15 = 2*x14 + 1 x30 = x15 << 15 + x15 x60 = x30 << 30 + x30 x120 = x60 << 60 + x60 x240 = x120 << 120 + x120 x247 = x240 << 7 + _1111111 return (x247 << 2 + 1) << 2 + 1 ``` ## E-382 Field Inversion | Property | Value | | --- | ----- | | _N_ | `2^382-105` | | _d_ | `2` | | _N_-_d_ | `3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff95` | | Length | 395 | | Algorithm | `opt(dictionary(hybrid(5,0),continued_fractions(dichotomic)))` | Addition chain produced by `addchain`: ```go _10 = 2*1 _11 = 1 + _10 _110 = 2*_11 _111 = 1 + _110 _1110 = 2*_111 _10101 = _111 + _1110 _101010 = 2*_10101 _111111 = _10101 + _101010 _1111110 = 2*_111111 _11111100 = 2*_1111110 i11 = 2*_11111100 i25 = (i11 << 5 + _11111100) << 7 + i11 i51 = (i25 << 5 + _11111100) << 19 + i25 i101 = (i51 << 5 + _11111100) << 43 + i51 i199 = (i101 << 4 + _1111110) << 92 + i101 x375 = i199 << 186 + i199 + _111 return x375 << 7 + _10101 ``` ## M-383/Curve383187 Field Inversion | Property | Value | | --- | ----- | | _N_ | `2^383-187` | | _d_ | `2` | | _N_-_d_ | `7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff43` | | Length | 396 | | Algorithm | `opt(runs(continued_fractions(dichotomic)))` | Addition chain produced by `addchain`: ```go _10 = 2*1 _11 = 1 + _10 _1100 = _11 << 2 _1111 = _11 + _1100 _11110000 = _1111 << 4 _11111111 = _1111 + _11110000 x16 = _11111111 << 8 + _11111111 x20 = x16 << 4 + _1111 x22 = x20 << 2 + _11 x44 = x22 << 22 + x22 x88 = x44 << 44 + x44 x176 = x88 << 88 + x88 x352 = x176 << 176 + x176 x374 = x352 << 22 + x22 x375 = 2*x374 + 1 return (x375 << 2 + 1) << 6 + _11 ``` ## Curve41417 Field Inversion | Property | Value | | --- | ----- | | _N_ | `2^414-17` | | _d_ | `2` | | _N_-_d_ | `3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed` | | Length | 426 | | Algorithm | `opt(runs(continued_fractions(dichotomic)))` | Addition chain produced by `addchain`: ```go _10 = 2*1 _11 = 1 + _10 _1100 = _11 << 2 _1111 = _11 + _1100 _111100 = _1111 << 2 _111111 = _11 + _111100 x12 = _111111 << 6 + _111111 x24 = x12 << 12 + x12 x48 = x24 << 24 + x24 x96 = x48 << 48 + x48 x192 = x96 << 96 + x96 x384 = x192 << 192 + x192 x408 = x384 << 24 + x24 x409 = 2*x408 + 1 return (x409 << 3 + _11) << 2 + 1 ``` ## M-511 Field Inversion | Property | Value | | --- | ----- | | _N_ | `2^511-187` | | _d_ | `2` | | _N_-_d_ | `7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff43` | | Length | 525 | | Algorithm | `opt(runs(continued_fractions(dichotomic)))` | Addition chain produced by `addchain`: ```go _10 = 2*1 _11 = 1 + _10 _1100 = _11 << 2 _1111 = _11 + _1100 _111100 = _1111 << 2 _111111 = _11 + _111100 _11111100 = _111111 << 2 _11111111 = _11 + _11111100 x16 = _11111111 << 8 + _11111111 x22 = x16 << 6 + _111111 x30 = x22 << 8 + _11111111 x60 = x30 << 30 + x30 x120 = x60 << 60 + x60 x240 = x120 << 120 + x120 x480 = x240 << 240 + x240 x502 = x480 << 22 + x22 x503 = 2*x502 + 1 return (x503 << 2 + 1) << 6 + _11 ``` ## NIST P-192 Field Inversion | Property | Value | | --- | ----- | | _N_ | `2^192-2^64-1` | | _d_ | `2` | | _N_-_d_ | `fffffffffffffffffffffffffffffffefffffffffffffffd` | | Length | 203 | | Algorithm | `opt(dictionary(hybrid(2,0),continued_fractions(dichotomic)))` | Addition chain produced by `addchain`: ```go _10 = 2*1 _11 = 1 + _10 _110 = 2*_11 _111 = 1 + _110 _111000 = _111 << 3 _111111 = _111 + _111000 x12 = _111111 << 6 + _111111 x15 = x12 << 3 + _111 x30 = x15 << 15 + x15 x60 = x30 << 30 + x30 x62 = x60 << 2 + _11 x124 = x62 << 62 + x62 x127 = x124 << 3 + _111 return (x127 << 63 + x62) << 2 + 1 ``` ## NIST P-224 Field Inversion | Property | Value | | --- | ----- | | _N_ | `2^224-2^96+1` | | _d_ | `2` | | _N_-_d_ | `fffffffffffffffffffffffffffffffeffffffffffffffffffffffff` | | Length | 234 | | Algorithm | `opt(runs(heuristic(use_first(halving,approximation))))` | Addition chain produced by `addchain`: ```go _10 = 2*1 _11 = 1 + _10 _110 = 2*_11 _111 = 1 + _110 _111000 = _111 << 3 _111111 = _111 + _111000 x12 = _111111 << 6 + _111111 x14 = x12 << 2 + _11 x17 = x14 << 3 + _111 x31 = x17 << 14 + x14 x48 = x31 << 17 + x17 x96 = x48 << 48 + x48 x127 = x96 << 31 + x31 return x127 << 97 + x96 ``` ## Goldilocks Field Inversion | Property | Value | | --- | ----- | | _N_ | `2^448-2^224-1` | | _d_ | `2` | | _N_-_d_ | `fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffffffffffffffffffffffffffffffffffffffffffffffffffffd` | | Length | 460 | | Algorithm | `opt(runs(heuristic(use_first(halving,approximation))))` | Addition chain produced by `addchain`: ```go _10 = 2*1 _11 = 1 + _10 _110 = 2*_11 _111 = 1 + _110 _111000 = _111 << 3 _111111 = _111 + _111000 x12 = _111111 << 6 + _111111 x24 = x12 << 12 + x12 i34 = x24 << 6 x30 = _111111 + i34 x48 = i34 << 18 + x24 x96 = x48 << 48 + x48 x192 = x96 << 96 + x96 x222 = x192 << 30 + x30 x223 = 2*x222 + 1 return (x223 << 223 + x222) << 2 + 1 ``` ## secp192k1 Field Inversion | Property | Value | | --- | ----- | | _N_ | `fffffffffffffffffffffffffffffffffffffffeffffee37` | | _d_ | `2` | | _N_-_d_ | `fffffffffffffffffffffffffffffffffffffffeffffee35` | | Length | 205 | | Algorithm | `opt(dictionary(hybrid(3,0),continued_fractions(dichotomic)))` | Addition chain produced by `addchain`: ```go _10 = 2*1 _11 = 1 + _10 _101 = _10 + _11 _111 = _10 + _101 _11100 = _111 << 2 _11111 = _11 + _11100 _1111100 = _11111 << 2 _1111111 = _11 + _1111100 i15 = _1111111 << 5 x19 = i15 << 7 + i15 + _11111 i31 = x19 << 7 i51 = i31 << 19 + i31 i90 = i51 << 38 + i51 x159 = i90 << 76 + i90 + _1111111 i199 = ((x159 << 20 + x19) << 4 + _111) << 5 return (_11 + i199) << 4 + _101 ``` ## secp224k1 Field Inversion | Property | Value | | --- | ----- | | _N_ | `fffffffffffffffffffffffffffffffffffffffffffffffeffffe56d` | | _d_ | `2` | | _N_-_d_ | `fffffffffffffffffffffffffffffffffffffffffffffffeffffe56b` | | Length | 238 | | Algorithm | `opt(dictionary(hybrid(5,0),continued_fractions(dichotomic)))` | Addition chain produced by `addchain`: ```go _100 = 1 << 2 _101 = 1 + _100 _10100 = _101 << 2 _10101 = 1 + _10100 _101010 = 2*_10101 _111111 = _10101 + _101010 _1111110 = 2*_111111 x12 = _1111110 << 5 + _111111 x19 = x12 << 7 + _1111110 + 1 i25 = 2*x19 i45 = i25 << 19 + i25 x57 = i45 << 18 + x19 i104 = x57 << 39 + i45 x191 = i104 << 95 + i104 + 1 i235 = ((x191 << 20 + x19) << 7 + _10101) << 5 return 2*(_10101 + i235) + 1 ``` addchain-0.4.0/go.mod000066400000000000000000000002121514305256600143560ustar00rootroot00000000000000module github.com/mmcloughlin/addchain go 1.16 require ( github.com/google/subcommands v1.2.0 github.com/mmcloughlin/profile v0.1.1 ) addchain-0.4.0/go.sum000066400000000000000000000005441514305256600144130ustar00rootroot00000000000000github.com/google/subcommands v1.2.0 h1:vWQspBTo2nEqTUFita5/KeEWlUL8kQObDFbub/EN9oE= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/mmcloughlin/profile v0.1.1 h1:jhDmAqPyebOsVDOCICJoINoLb/AnLBaUw58nFzxWS2w= github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= addchain-0.4.0/install.sh000077500000000000000000000222141514305256600152630ustar00rootroot00000000000000#!/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 } addchain-0.4.0/internal/bigints/bigints_test.go000066400000000000000000000007601514305256600215600ustar00rootroot00000000000000package bigints import ( "math/big" "math/rand" "testing" "time" "github.com/mmcloughlin/addchain/internal/bigint" ) func TestContainsSorted(t *testing.T) { const n = 256 // Generate random sorted array. r := rand.New(rand.NewSource(time.Now().UnixNano())) xs := make([]*big.Int, n) for i := range xs { xs[i] = bigint.RandBits(r, 256) } Sort(xs) // Confirm every element is found. for _, x := range xs { if found := ContainsSorted(x, xs); !found { t.FailNow() } } } addchain-0.4.0/internal/bigvector/000077500000000000000000000000001514305256600170555ustar00rootroot00000000000000addchain-0.4.0/internal/bigvector/bigvector.go000066400000000000000000000032701514305256600213720ustar00rootroot00000000000000// 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") } } addchain-0.4.0/internal/calc/000077500000000000000000000000001514305256600157735ustar00rootroot00000000000000addchain-0.4.0/internal/calc/calc.go000066400000000000000000000100421514305256600172210ustar00rootroot00000000000000// Package calc evaluates simple arithmetic expressions. package calc import ( "bytes" "errors" "math/big" ) // associativity of an operator. type associativity int // associativity values. const ( leftassociative associativity = iota rightassociative ) // operator is a binary operator. type operator struct { precedence int associativity associativity apply func(*big.Int, *big.Int, *big.Int) *big.Int } // operators supported by the calculator. var operators = map[byte]operator{ '^': {precedence: 3, associativity: rightassociative, apply: func(z, x, y *big.Int) *big.Int { return z.Exp(x, y, nil) }}, '*': {precedence: 3, associativity: leftassociative, apply: (*big.Int).Mul}, '/': {precedence: 3, associativity: leftassociative, apply: (*big.Int).Div}, '+': {precedence: 2, associativity: leftassociative, apply: (*big.Int).Add}, '-': {precedence: 2, associativity: leftassociative, apply: (*big.Int).Sub}, } // yard implements the "shunting yard" algorithm. type yard struct { operands []*big.Int operators []operator } // operand pushes a new operand x. func (y *yard) operand(x *big.Int) { y.operands = append(y.operands, x) } // operator pushes a new operator. func (y *yard) operator(op operator) error { // Pop higher precedence operators. for len(y.operators) > 0 { top := y.peek() if top.precedence < op.precedence || (top.precedence == op.precedence && op.associativity != leftassociative) { break } if err := y.apply(top); err != nil { return err } y.pop() } // Push operator on the stack. y.operators = append(y.operators, op) return nil } // apply operator to the operand stack. func (y *yard) apply(op operator) error { n := len(y.operands) if n < 2 { return errors.New("too few operands") } z := new(big.Int) op.apply(z, y.operands[n-2], y.operands[n-1]) y.operands = append(y.operands[:n-2], z) return nil } // result finalizes the evaluation and returns the result. func (y *yard) result() (*big.Int, error) { for len(y.operators) > 0 { if err := y.apply(y.pop()); err != nil { return nil, err } } if len(y.operands) != 1 { return nil, errors.New("wrong operand count") } return y.operands[0], nil } // peek returns the operator at the top of the stack. func (y *yard) peek() operator { return y.operators[len(y.operators)-1] } // pop removes and returns the operator at the top of the stack. func (y *yard) pop() operator { top := len(y.operators) - 1 op := y.operators[top] y.operators = y.operators[:top] return op } // Eval evaluates the arithmetic expression. func Eval(expr string) (*big.Int, error) { b := []byte(expr) y := &yard{} operand := true for len(b) > 0 { // Skip this character? if skip(b[0]) { b = b[1:] continue } // Expect an operand. if operand { x, rest, err := number(b) if err != nil { return nil, err } y.operand(x) b = rest operand = false continue } // Expect an operator. op, ok := operators[b[0]] if !ok { return nil, errors.New("expected operator") } if err := y.operator(op); err != nil { return nil, err } b = b[1:] operand = true } return y.result() } // number parses a number. func number(b []byte) (*big.Int, []byte, error) { // Find the end. i := 0 if len(b) > 0 && b[0] == '-' { i++ } isdigit := isdecimal switch { case bytes.HasPrefix(b[i:], []byte("0b")): isdigit = isbinary i += 2 case bytes.HasPrefix(b[i:], []byte("0x")): isdigit = ishex i += 2 } for ; i < len(b) && isdigit(b[i]); i++ { } // Parse. x, ok := new(big.Int).SetString(string(b[:i]), 0) if !ok { return nil, nil, errors.New("expected number") } return x, b[i:], nil } // skip reports whether b should be skipped. func skip(b byte) bool { return b == ' ' } // isdecimal reports whether b is a decimal digit. func isdecimal(b byte) bool { return '0' <= b && b <= '9' } // ishex reports whether b is a hex digit. func ishex(b byte) bool { return isdecimal(b) || ('a' <= b && b <= 'f') } // isbinary reports whether b is a binary digit. func isbinary(b byte) bool { return b == '0' || b == '1' } addchain-0.4.0/internal/calc/calc_test.go000066400000000000000000000022611514305256600202640ustar00rootroot00000000000000package calc import ( "testing" "github.com/mmcloughlin/addchain/internal/bigint" ) func TestEval(t *testing.T) { cases := []struct { Expr string Expect int64 }{ // Numeric literals. {"2", 2}, {"34534", 34534}, {"-42", -42}, {"-0xab", -0xab}, {"0b1011", 11}, // Single operators. {"15-2", 15 - 2}, {"15+2", 15 + 2}, {"15/2", 15 / 2}, {"15*2", 15 * 2}, {"2^10", 1 << 10}, // Whitespace. {" 2 ^ 10 ", 1 << 10}, // Operator combinations. {"15+2-9", 15 + 2 - 9}, {"15+2*9", 15 + 2*9}, {"15+9/2", 15 + 9/2}, {"15+2^9", 15 + (1 << 9)}, {"15*2+9", 15*2 + 9}, {"15/2+9", 15/2 + 9}, {"15^2+9", 15*15 + 9}, {"15^2*9+40/2^2", 15*15*9 + 10}, } for _, c := range cases { x, err := Eval(c.Expr) if err != nil { t.Fatalf("Eval(%v) returned error %q", c.Expr, err) } if !bigint.EqualInt64(x, c.Expect) { t.Errorf("Eval(%v) = %v; expect %v", c.Expr, x, c.Expect) } } } func TestEvalErrors(t *testing.T) { exprs := []string{ "", "10 +", "1 + +", " + ", " + abc", "10 20 +", "10 20 3 + -", } for _, expr := range exprs { _, err := Eval(expr) if err == nil { t.Errorf("Eval(%v): expected error", expr) } } } addchain-0.4.0/internal/cli/000077500000000000000000000000001514305256600156405ustar00rootroot00000000000000addchain-0.4.0/internal/cli/cmd.go000066400000000000000000000024301514305256600167310ustar00rootroot00000000000000package cli import ( "flag" "io" "log" "os" "github.com/google/subcommands" ) // Command is a base for all subcommands. type Command struct { Log *log.Logger } // NewBaseCommand builds a new base command for the named tool. func NewBaseCommand(name string) Command { return Command{ Log: log.New(os.Stderr, name+": ", 0), } } // SetFlags is a stub implementation of the SetFlags methods that does nothing. func (Command) SetFlags(f *flag.FlagSet) {} // UsageError logs a usage error and returns a suitable exit code. func (c Command) UsageError(format string, args ...interface{}) subcommands.ExitStatus { c.Log.Printf(format, args...) return subcommands.ExitUsageError } // Fail logs an error message and returns a failing exit code. func (c Command) Fail(format string, args ...interface{}) subcommands.ExitStatus { c.Log.Printf(format, args...) return subcommands.ExitFailure } // Error logs err and returns a failing exit code. func (c Command) Error(err error) subcommands.ExitStatus { return c.Fail(err.Error()) } // CheckClose closes cl. On error it logs and writes to the status pointer. // Intended for deferred Close() calls. func (c Command) CheckClose(statusp *subcommands.ExitStatus, cl io.Closer) { if err := cl.Close(); err != nil { *statusp = c.Error(err) } } addchain-0.4.0/internal/cli/doc.go000066400000000000000000000001451514305256600167340ustar00rootroot00000000000000// Package cli provides utilities for building subcommand-based command line interfaces. package cli addchain-0.4.0/internal/cli/util.go000066400000000000000000000014751514305256600171530ustar00rootroot00000000000000package cli import ( "io" "io/ioutil" "os" ) // OpenInput is a convenience for possibly opening an input file, or otherwise returning standard in. func OpenInput(filename string) (string, io.ReadCloser, error) { if filename == "" { return "", ioutil.NopCloser(os.Stdin), nil } f, err := os.Open(filename) return filename, f, err } // OpenOutput is a convenience for possibly opening an output file, or otherwise returning standard out. func OpenOutput(filename string) (string, io.WriteCloser, error) { if filename == "" { return "", nopwritercloser{os.Stdout}, nil } f, err := os.Create(filename) return filename, f, err } // nopwritercloser wraps an io.Writer and provides a no-op Close() method. type nopwritercloser struct { io.Writer } func (nopwritercloser) Close() error { return nil } addchain-0.4.0/internal/container/000077500000000000000000000000001514305256600170535ustar00rootroot00000000000000addchain-0.4.0/internal/container/heap/000077500000000000000000000000001514305256600177705ustar00rootroot00000000000000addchain-0.4.0/internal/container/heap/heap.go000066400000000000000000000020471514305256600212370ustar00rootroot00000000000000// 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 } addchain-0.4.0/internal/errutil/000077500000000000000000000000001514305256600165575ustar00rootroot00000000000000addchain-0.4.0/internal/errutil/errutil.go000066400000000000000000000016461514305256600206030ustar00rootroot00000000000000// 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 } } addchain-0.4.0/internal/errutil/errutil_test.go000066400000000000000000000013221514305256600216310ustar00rootroot00000000000000package errutil import ( "errors" "reflect" "testing" ) type errcloser struct { err error } func (e errcloser) Close() error { return e.err } func TestCheckClose(t *testing.T) { a := errors.New("a") b := errors.New("b") cases := []struct { Previous error CloseError error Expect error }{ {Previous: nil, CloseError: nil, Expect: nil}, {Previous: a, CloseError: nil, Expect: a}, {Previous: nil, CloseError: b, Expect: b}, {Previous: a, CloseError: b, Expect: a}, } for _, c := range cases { err := c.Previous closer := errcloser{err: c.CloseError} CheckClose(&err, closer) if !reflect.DeepEqual(err, c.Expect) { t.Fatalf("CheckErr() got %v expected %v", err, c.Expect) } } } addchain-0.4.0/internal/examples/000077500000000000000000000000001514305256600167075ustar00rootroot00000000000000addchain-0.4.0/internal/examples/fp25519/000077500000000000000000000000001514305256600177225ustar00rootroot00000000000000addchain-0.4.0/internal/examples/fp25519/00-search.out000066400000000000000000000004351514305256600221370ustar00rootroot00000000000000addchain: expr: "2^255 - 19 - 2" addchain: hex: 7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeb addchain: dec: 57896044618658097711785492504343953926634992332820282019728792003956564819947 addchain: best: opt(runs(continued_fractions(dichotomic))) addchain: cost: 266 addchain-0.4.0/internal/examples/fp25519/00-search.sh000066400000000000000000000000531514305256600217360ustar00rootroot00000000000000addchain search '2^255 - 19 - 2' > inv.acc addchain-0.4.0/internal/examples/fp25519/01-listing.out000066400000000000000000000005141514305256600223420ustar00rootroot00000000000000tmp t0 t1 t2 double z x add z x z shift t0 z 2 add t0 z t0 shift t1 t0 4 add t0 t0 t1 shift t0 t0 2 add t0 z t0 shift t1 t0 10 add t1 t0 t1 shift t1 t1 10 add t1 t0 t1 shift t2 t1 30 add t1 t1 t2 shift t2 t1 60 add t1 t1 t2 shift t2 t1 120 add t1 t1 t2 shift t1 t1 10 add t0 t0 t1 shift t0 t0 2 add t0 x t0 shift t0 t0 3 add z z t0 addchain-0.4.0/internal/examples/fp25519/01-listing.sh000066400000000000000000000000251514305256600221420ustar00rootroot00000000000000addchain gen inv.acc addchain-0.4.0/internal/examples/fp25519/02-generate.out000066400000000000000000000000001514305256600224520ustar00rootroot00000000000000addchain-0.4.0/internal/examples/fp25519/02-generate.sh000066400000000000000000000000651514305256600222700ustar00rootroot00000000000000addchain gen -tmpl inv.tmpl inv.acc | gofmt > inv.go addchain-0.4.0/internal/examples/fp25519/fp.go000066400000000000000000000015111514305256600206540ustar00rootroot00000000000000package fp25519 import "math/big" // p is the field prime modulus. var p, _ = new(big.Int).SetString("57896044618658097711785492504343953926634992332820282019728792003956564819949", 10) // Elt is an element of the field modulo 2²⁵⁵-19. type Elt struct{ n big.Int } // SetInt sets z = x (mod p) and returns it. func (z *Elt) SetInt(x *big.Int) *Elt { z.n.Set(x) return z.modp() } // Int returns z as a big integer. func (z *Elt) Int() *big.Int { return new(big.Int).Set(&z.n) } // Mul computes z = x*y (mod p) and returns it. func (z *Elt) Mul(x, y *Elt) *Elt { z.n.Mul(&x.n, &y.n) return z.modp() } // Sqr computes z = x² (mod p) and returns it. func (z *Elt) Sqr(x *Elt) *Elt { return z.Mul(x, x) } // modp reduces z modulo p, ensuring it's in the range [0, p). func (z *Elt) modp() *Elt { z.n.Mod(&z.n, p) return z } addchain-0.4.0/internal/examples/fp25519/fp_test.go000066400000000000000000000010361514305256600217150ustar00rootroot00000000000000package fp25519 import ( "crypto/rand" "math/big" "testing" ) func RandElt(t *testing.T) *Elt { t.Helper() one := new(big.Int).SetInt64(1) max := new(big.Int).Sub(p, one) x, err := rand.Int(rand.Reader, max) if err != nil { t.Fatal(err) } x.Add(x, one) return new(Elt).SetInt(x) } func TestInv(t *testing.T) { const trials = 1 << 12 for trial := 0; trial < trials; trial++ { x := RandElt(t) got := new(Elt).Inv(x) expect := new(big.Int).ModInverse(x.Int(), p) if got.Int().Cmp(expect) != 0 { t.FailNow() } } } addchain-0.4.0/internal/examples/fp25519/inv.acc000066400000000000000000000005721514305256600211720ustar00rootroot00000000000000_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 addchain-0.4.0/internal/examples/fp25519/inv.go000066400000000000000000000053461514305256600210550ustar00rootroot00000000000000// Code generated by addchain. DO NOT EDIT. package fp25519 // Inv computes z = 1/x (mod p) and returns it. func (z *Elt) Inv(x *Elt) *Elt { // Inversion computation is derived from the addition chain: // // _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 // // Operations: 254 squares 12 multiplies // // Generated by github.com/mmcloughlin/addchain v0.4.0. // Allocate Temporaries. var ( t0 = new(Elt) t1 = new(Elt) t2 = new(Elt) ) // Step 1: z = x^0x2 z.Sqr(x) // Step 2: z = x^0x3 z.Mul(x, z) // Step 4: t0 = x^0xc t0.Sqr(z) for s := 1; s < 2; s++ { t0.Sqr(t0) } // Step 5: t0 = x^0xf t0.Mul(z, t0) // Step 9: t1 = x^0xf0 t1.Sqr(t0) for s := 1; s < 4; s++ { t1.Sqr(t1) } // Step 10: t0 = x^0xff t0.Mul(t0, t1) // Step 12: t0 = x^0x3fc for s := 0; s < 2; s++ { t0.Sqr(t0) } // Step 13: t0 = x^0x3ff t0.Mul(z, t0) // Step 23: t1 = x^0xffc00 t1.Sqr(t0) for s := 1; s < 10; s++ { t1.Sqr(t1) } // Step 24: t1 = x^0xfffff t1.Mul(t0, t1) // Step 34: t1 = x^0x3ffffc00 for s := 0; s < 10; s++ { t1.Sqr(t1) } // Step 35: t1 = x^0x3fffffff t1.Mul(t0, t1) // Step 65: t2 = x^0xfffffffc0000000 t2.Sqr(t1) for s := 1; s < 30; s++ { t2.Sqr(t2) } // Step 66: t1 = x^0xfffffffffffffff t1.Mul(t1, t2) // Step 126: t2 = x^0xfffffffffffffff000000000000000 t2.Sqr(t1) for s := 1; s < 60; s++ { t2.Sqr(t2) } // Step 127: t1 = x^0xffffffffffffffffffffffffffffff t1.Mul(t1, t2) // Step 247: t2 = x^0xffffffffffffffffffffffffffffff000000000000000000000000000000 t2.Sqr(t1) for s := 1; s < 120; s++ { t2.Sqr(t2) } // Step 248: t1 = x^0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff t1.Mul(t1, t2) // Step 258: t1 = x^0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00 for s := 0; s < 10; s++ { t1.Sqr(t1) } // Step 259: t0 = x^0x3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff t0.Mul(t0, t1) // Step 261: t0 = x^0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc for s := 0; s < 2; s++ { t0.Sqr(t0) } // Step 262: t0 = x^0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd t0.Mul(x, t0) // Step 265: t0 = x^0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe8 for s := 0; s < 3; s++ { t0.Sqr(t0) } // Step 266: z = x^0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeb z.Mul(z, t0) return z } addchain-0.4.0/internal/examples/fp25519/inv.tmpl000066400000000000000000000021031514305256600214100ustar00rootroot00000000000000// Code generated by {{ .Meta.Name }}. DO NOT EDIT. package fp25519 // Inv computes z = 1/x (mod p) and returns it. func (z *Elt) Inv(x *Elt) *Elt { // Inversion computation is derived from the addition chain: // {{- range lines (format .Script) }} // {{ . }} {{- end }} // // Operations: {{ .Ops.Doubles }} squares {{ .Ops.Adds }} multiplies // // Generated by {{ .Meta.Module }} {{ .Meta.ReleaseTag }}. // Allocate Temporaries. var ( {{- range .Program.Temporaries }} {{ . }} = new(Elt) {{- end -}} ) {{ range $i := .Program.Instructions }} // {{ printf "Step %d: %s = x^%#x" $i.Output.Index $i.Output (index $.Chain $i.Output.Index) }} {{- with add $i.Op }} {{ $i.Output }}.Mul({{ .X }}, {{ .Y }}) {{ end -}} {{- with double $i.Op }} {{ $i.Output }}.Sqr({{ .X }}) {{ end -}} {{- with shift $i.Op -}} {{- $first := 0 -}} {{- if ne $i.Output.Identifier .X.Identifier }} {{ $i.Output }}.Sqr({{ .X }}) {{- $first = 1 -}} {{- end }} for s := {{ $first }}; s < {{ .S }}; s++ { {{ $i.Output }}.Sqr({{ $i.Output }}) } {{ end -}} {{- end }} return z } addchain-0.4.0/internal/examples/search/000077500000000000000000000000001514305256600201545ustar00rootroot00000000000000addchain-0.4.0/internal/examples/search/cmd.out000066400000000000000000000012271514305256600214520ustar00rootroot00000000000000addchain: 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 addchain-0.4.0/internal/examples/search/cmd.sh000066400000000000000000000000411514305256600212460ustar00rootroot00000000000000addchain search '2^255 - 19 - 2' addchain-0.4.0/internal/gen/000077500000000000000000000000001514305256600156425ustar00rootroot00000000000000addchain-0.4.0/internal/gen/functions.go000066400000000000000000000036251514305256600202070ustar00rootroot00000000000000package gen import ( "bufio" "reflect" "strings" "github.com/mmcloughlin/addchain/acc/ir" "github.com/mmcloughlin/addchain/acc/printer" ) // 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 }, }, } addchain-0.4.0/internal/gen/functions_test.go000066400000000000000000000007721514305256600212460ustar00rootroot00000000000000package gen import "testing" func TestFunctionSignature(t *testing.T) { f := &Function{ Name: "sig", Description: "Test for function signature", Func: func(x, y int) int { return x + y }, } expect := "func(int, int) int" if f.Signature() != expect { t.FailNow() } } func TestFunctionsLint(t *testing.T) { for _, f := range Functions { if f.Name == "" { t.Fatalf("nameless function") } if f.Description == "" { t.Errorf("%s: missing description", f.Name) } } } addchain-0.4.0/internal/gen/gen.go000066400000000000000000000047431514305256600167520ustar00rootroot00000000000000// Package gen provides templated output generation from addition chain // programs. package gen import ( "io" "text/template" "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/meta" ) // Data provided to templates. type Data 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 } // Config for template input generation. type Config struct { // Allocator for temporary variables. This configuration determines variable // naming. Allocator pass.Allocator } // PrepareData builds input template data for the given addition chain script. func PrepareData(cfg Config, s *ast.Chain) (*Data, error) { // 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, cfg.Allocator, pass.Func(pass.Eval)); err != nil { return nil, err } return &Data{ Chain: p.Chain, Ops: p.Program, Script: s, Program: p, Meta: meta.Meta, }, nil } // Generate templated output for the given data, writing to w. func Generate(w io.Writer, tmpl string, d *Data) error { // Custom template functions. funcs := template.FuncMap{} for _, f := range Functions { funcs[f.Name] = f.Func } // Parse template. t, err := template.New("").Funcs(funcs).Parse(tmpl) if err != nil { return err } // Execute. return t.Execute(w, d) } addchain-0.4.0/internal/gen/gen_test.go000066400000000000000000000026471514305256600200120ustar00rootroot00000000000000package gen import ( "bytes" "io/ioutil" "path/filepath" "testing" "github.com/mmcloughlin/addchain/acc/parse" "github.com/mmcloughlin/addchain/acc/pass" "github.com/mmcloughlin/addchain/internal/test" ) func TestBuiltinTemplatesGolden(t *testing.T) { d := LoadTestData(t) for _, name := range BuiltinTemplateNames() { name := name // scopelint t.Run(name, func(t *testing.T) { // Load the template. tmpl, err := BuiltinTemplate(name) if err != nil { t.Fatal(err) } // Generate output. var buf bytes.Buffer if err := Generate(&buf, tmpl, d); err != nil { t.Fatal(err) } got := buf.Bytes() // Compare to golden case. filename := test.GoldenName(filepath.Join("builtin", name)) if test.Golden() { if err := ioutil.WriteFile(filename, got, 0644); err != nil { t.Fatalf("write golden file: %v", err) } } expect, err := ioutil.ReadFile(filename) if err != nil { t.Fatalf("read golden file: %v", err) } if !bytes.Equal(got, expect) { t.Fatal("output does not match golden file") } }) } } func LoadTestData(t *testing.T) *Data { t.Helper() // Prepare data for a fixed test input. s, err := parse.File("testdata/input.acc") if err != nil { t.Fatal(err) } cfg := Config{ Allocator: pass.Allocator{ Input: "x", Output: "z", Format: "t%d", }, } d, err := PrepareData(cfg, s) if err != nil { t.Fatal(err) } return d } addchain-0.4.0/internal/gen/templates.go000066400000000000000000000023061514305256600201700ustar00rootroot00000000000000package gen import ( "embed" "fmt" "path" "strings" ) //go:embed templates var templates embed.FS // Template file extension. const templateext = ".tmpl" // BuiltinTemplate loads the named template. Returns an error if the template is // unknown. func BuiltinTemplate(name string) (string, error) { path := fmt.Sprintf("templates/%s%s", name, templateext) b, err := templates.ReadFile(path) if err != nil { return "", fmt.Errorf("unknown template %q", name) } return string(b), nil } // BuiltinTemplateNames returns all builtin template names. func BuiltinTemplateNames() []string { entries, err := templates.ReadDir("templates") if err != nil { panic("gen: could not read embedded templates") } var names []string for _, entry := range entries { filename := entry.Name() if path.Ext(filename) != templateext { panic("gen: builtin template has wrong extension") } name := strings.TrimSuffix(filename, templateext) names = append(names, name) } return names } // IsBuiltinTemplate reports whether name is a builtin template name. func IsBuiltinTemplate(name string) bool { for _, builtin := range BuiltinTemplateNames() { if builtin == name { return true } } return false } addchain-0.4.0/internal/gen/templates/000077500000000000000000000000001514305256600176405ustar00rootroot00000000000000addchain-0.4.0/internal/gen/templates/chain.tmpl000066400000000000000000000001331514305256600216150ustar00rootroot00000000000000{{- range $n, $value := .Chain -}} {{- printf "%3d: %#x\n" (inc $n) $value -}} {{- end -}} addchain-0.4.0/internal/gen/templates/listing.tmpl000066400000000000000000000005471514305256600222150ustar00rootroot00000000000000{{ printf "tmp\t%s" (join .Program.Temporaries "\t") }} {{ range $i := .Program.Instructions -}} {{- with add $i.Op -}} {{ printf "add\t%s\t%s\t%s" $i.Output .X .Y }} {{ end -}} {{- with double $i.Op -}} {{ printf "double\t%s\t%s" $i.Output .X }} {{ end -}} {{- with shift $i.Op -}} {{ printf "shift\t%s\t%s\t%d" $i.Output .X .S }} {{ end -}} {{- end -}} addchain-0.4.0/internal/gen/templates/ops.tmpl000066400000000000000000000001701514305256600213350ustar00rootroot00000000000000{{- range $n, $op := .Ops -}} {{- printf "[%3d] %4d+%-4d %#x\n" $n $op.I $op.J (index $.Chain (inc $n)) -}} {{- end -}} addchain-0.4.0/internal/gen/templates/script.tmpl000066400000000000000000000000271514305256600220410ustar00rootroot00000000000000{{- format .Script -}} addchain-0.4.0/internal/gen/testdata/000077500000000000000000000000001514305256600174535ustar00rootroot00000000000000addchain-0.4.0/internal/gen/testdata/builtin/000077500000000000000000000000001514305256600211215ustar00rootroot00000000000000addchain-0.4.0/internal/gen/testdata/builtin/chain.golden000066400000000000000000000247231514305256600234050ustar00rootroot00000000000000 1: 0x1 2: 0x2 3: 0x3 4: 0x6 5: 0xc 6: 0xf 7: 0x1e 8: 0x3c 9: 0x78 10: 0xf0 11: 0xff 12: 0x1fe 13: 0x3fc 14: 0x3ff 15: 0x7fe 16: 0xffc 17: 0x1ff8 18: 0x3ff0 19: 0x7fe0 20: 0xffc0 21: 0x1ff80 22: 0x3ff00 23: 0x7fe00 24: 0xffc00 25: 0xfffff 26: 0x1ffffe 27: 0x3ffffc 28: 0x7ffff8 29: 0xfffff0 30: 0x1ffffe0 31: 0x3ffffc0 32: 0x7ffff80 33: 0xfffff00 34: 0x1ffffe00 35: 0x3ffffc00 36: 0x3fffffff 37: 0x7ffffffe 38: 0xfffffffc 39: 0x1fffffff8 40: 0x3fffffff0 41: 0x7ffffffe0 42: 0xfffffffc0 43: 0x1fffffff80 44: 0x3fffffff00 45: 0x7ffffffe00 46: 0xfffffffc00 47: 0x1fffffff800 48: 0x3fffffff000 49: 0x7ffffffe000 50: 0xfffffffc000 51: 0x1fffffff8000 52: 0x3fffffff0000 53: 0x7ffffffe0000 54: 0xfffffffc0000 55: 0x1fffffff80000 56: 0x3fffffff00000 57: 0x7ffffffe00000 58: 0xfffffffc00000 59: 0x1fffffff800000 60: 0x3fffffff000000 61: 0x7ffffffe000000 62: 0xfffffffc000000 63: 0x1fffffff8000000 64: 0x3fffffff0000000 65: 0x7ffffffe0000000 66: 0xfffffffc0000000 67: 0xfffffffffffffff 68: 0x1ffffffffffffffe 69: 0x3ffffffffffffffc 70: 0x7ffffffffffffff8 71: 0xfffffffffffffff0 72: 0x1ffffffffffffffe0 73: 0x3ffffffffffffffc0 74: 0x7ffffffffffffff80 75: 0xfffffffffffffff00 76: 0x1ffffffffffffffe00 77: 0x3ffffffffffffffc00 78: 0x7ffffffffffffff800 79: 0xfffffffffffffff000 80: 0x1ffffffffffffffe000 81: 0x3ffffffffffffffc000 82: 0x7ffffffffffffff8000 83: 0xfffffffffffffff0000 84: 0x1ffffffffffffffe0000 85: 0x3ffffffffffffffc0000 86: 0x7ffffffffffffff80000 87: 0xfffffffffffffff00000 88: 0x1ffffffffffffffe00000 89: 0x3ffffffffffffffc00000 90: 0x7ffffffffffffff800000 91: 0xfffffffffffffff000000 92: 0x1ffffffffffffffe000000 93: 0x3ffffffffffffffc000000 94: 0x7ffffffffffffff8000000 95: 0xfffffffffffffff0000000 96: 0x1ffffffffffffffe0000000 97: 0x3ffffffffffffffc0000000 98: 0x7ffffffffffffff80000000 99: 0xfffffffffffffff00000000 100: 0x1ffffffffffffffe00000000 101: 0x3ffffffffffffffc00000000 102: 0x7ffffffffffffff800000000 103: 0xfffffffffffffff000000000 104: 0x1ffffffffffffffe000000000 105: 0x3ffffffffffffffc000000000 106: 0x7ffffffffffffff8000000000 107: 0xfffffffffffffff0000000000 108: 0x1ffffffffffffffe0000000000 109: 0x3ffffffffffffffc0000000000 110: 0x7ffffffffffffff80000000000 111: 0xfffffffffffffff00000000000 112: 0x1ffffffffffffffe00000000000 113: 0x3ffffffffffffffc00000000000 114: 0x7ffffffffffffff800000000000 115: 0xfffffffffffffff000000000000 116: 0x1ffffffffffffffe000000000000 117: 0x3ffffffffffffffc000000000000 118: 0x7ffffffffffffff8000000000000 119: 0xfffffffffffffff0000000000000 120: 0x1ffffffffffffffe0000000000000 121: 0x3ffffffffffffffc0000000000000 122: 0x7ffffffffffffff80000000000000 123: 0xfffffffffffffff00000000000000 124: 0x1ffffffffffffffe00000000000000 125: 0x3ffffffffffffffc00000000000000 126: 0x7ffffffffffffff800000000000000 127: 0xfffffffffffffff000000000000000 128: 0xffffffffffffffffffffffffffffff 129: 0x1fffffffffffffffffffffffffffffe 130: 0x3fffffffffffffffffffffffffffffc 131: 0x7fffffffffffffffffffffffffffff8 132: 0xffffffffffffffffffffffffffffff0 133: 0x1fffffffffffffffffffffffffffffe0 134: 0x3fffffffffffffffffffffffffffffc0 135: 0x7fffffffffffffffffffffffffffff80 136: 0xffffffffffffffffffffffffffffff00 137: 0x1fffffffffffffffffffffffffffffe00 138: 0x3fffffffffffffffffffffffffffffc00 139: 0x7fffffffffffffffffffffffffffff800 140: 0xffffffffffffffffffffffffffffff000 141: 0x1fffffffffffffffffffffffffffffe000 142: 0x3fffffffffffffffffffffffffffffc000 143: 0x7fffffffffffffffffffffffffffff8000 144: 0xffffffffffffffffffffffffffffff0000 145: 0x1fffffffffffffffffffffffffffffe0000 146: 0x3fffffffffffffffffffffffffffffc0000 147: 0x7fffffffffffffffffffffffffffff80000 148: 0xffffffffffffffffffffffffffffff00000 149: 0x1fffffffffffffffffffffffffffffe00000 150: 0x3fffffffffffffffffffffffffffffc00000 151: 0x7fffffffffffffffffffffffffffff800000 152: 0xffffffffffffffffffffffffffffff000000 153: 0x1fffffffffffffffffffffffffffffe000000 154: 0x3fffffffffffffffffffffffffffffc000000 155: 0x7fffffffffffffffffffffffffffff8000000 156: 0xffffffffffffffffffffffffffffff0000000 157: 0x1fffffffffffffffffffffffffffffe0000000 158: 0x3fffffffffffffffffffffffffffffc0000000 159: 0x7fffffffffffffffffffffffffffff80000000 160: 0xffffffffffffffffffffffffffffff00000000 161: 0x1fffffffffffffffffffffffffffffe00000000 162: 0x3fffffffffffffffffffffffffffffc00000000 163: 0x7fffffffffffffffffffffffffffff800000000 164: 0xffffffffffffffffffffffffffffff000000000 165: 0x1fffffffffffffffffffffffffffffe000000000 166: 0x3fffffffffffffffffffffffffffffc000000000 167: 0x7fffffffffffffffffffffffffffff8000000000 168: 0xffffffffffffffffffffffffffffff0000000000 169: 0x1fffffffffffffffffffffffffffffe0000000000 170: 0x3fffffffffffffffffffffffffffffc0000000000 171: 0x7fffffffffffffffffffffffffffff80000000000 172: 0xffffffffffffffffffffffffffffff00000000000 173: 0x1fffffffffffffffffffffffffffffe00000000000 174: 0x3fffffffffffffffffffffffffffffc00000000000 175: 0x7fffffffffffffffffffffffffffff800000000000 176: 0xffffffffffffffffffffffffffffff000000000000 177: 0x1fffffffffffffffffffffffffffffe000000000000 178: 0x3fffffffffffffffffffffffffffffc000000000000 179: 0x7fffffffffffffffffffffffffffff8000000000000 180: 0xffffffffffffffffffffffffffffff0000000000000 181: 0x1fffffffffffffffffffffffffffffe0000000000000 182: 0x3fffffffffffffffffffffffffffffc0000000000000 183: 0x7fffffffffffffffffffffffffffff80000000000000 184: 0xffffffffffffffffffffffffffffff00000000000000 185: 0x1fffffffffffffffffffffffffffffe00000000000000 186: 0x3fffffffffffffffffffffffffffffc00000000000000 187: 0x7fffffffffffffffffffffffffffff800000000000000 188: 0xffffffffffffffffffffffffffffff000000000000000 189: 0x1fffffffffffffffffffffffffffffe000000000000000 190: 0x3fffffffffffffffffffffffffffffc000000000000000 191: 0x7fffffffffffffffffffffffffffff8000000000000000 192: 0xffffffffffffffffffffffffffffff0000000000000000 193: 0x1fffffffffffffffffffffffffffffe0000000000000000 194: 0x3fffffffffffffffffffffffffffffc0000000000000000 195: 0x7fffffffffffffffffffffffffffff80000000000000000 196: 0xffffffffffffffffffffffffffffff00000000000000000 197: 0x1fffffffffffffffffffffffffffffe00000000000000000 198: 0x3fffffffffffffffffffffffffffffc00000000000000000 199: 0x7fffffffffffffffffffffffffffff800000000000000000 200: 0xffffffffffffffffffffffffffffff000000000000000000 201: 0x1fffffffffffffffffffffffffffffe000000000000000000 202: 0x3fffffffffffffffffffffffffffffc000000000000000000 203: 0x7fffffffffffffffffffffffffffff8000000000000000000 204: 0xffffffffffffffffffffffffffffff0000000000000000000 205: 0x1fffffffffffffffffffffffffffffe0000000000000000000 206: 0x3fffffffffffffffffffffffffffffc0000000000000000000 207: 0x7fffffffffffffffffffffffffffff80000000000000000000 208: 0xffffffffffffffffffffffffffffff00000000000000000000 209: 0x1fffffffffffffffffffffffffffffe00000000000000000000 210: 0x3fffffffffffffffffffffffffffffc00000000000000000000 211: 0x7fffffffffffffffffffffffffffff800000000000000000000 212: 0xffffffffffffffffffffffffffffff000000000000000000000 213: 0x1fffffffffffffffffffffffffffffe000000000000000000000 214: 0x3fffffffffffffffffffffffffffffc000000000000000000000 215: 0x7fffffffffffffffffffffffffffff8000000000000000000000 216: 0xffffffffffffffffffffffffffffff0000000000000000000000 217: 0x1fffffffffffffffffffffffffffffe0000000000000000000000 218: 0x3fffffffffffffffffffffffffffffc0000000000000000000000 219: 0x7fffffffffffffffffffffffffffff80000000000000000000000 220: 0xffffffffffffffffffffffffffffff00000000000000000000000 221: 0x1fffffffffffffffffffffffffffffe00000000000000000000000 222: 0x3fffffffffffffffffffffffffffffc00000000000000000000000 223: 0x7fffffffffffffffffffffffffffff800000000000000000000000 224: 0xffffffffffffffffffffffffffffff000000000000000000000000 225: 0x1fffffffffffffffffffffffffffffe000000000000000000000000 226: 0x3fffffffffffffffffffffffffffffc000000000000000000000000 227: 0x7fffffffffffffffffffffffffffff8000000000000000000000000 228: 0xffffffffffffffffffffffffffffff0000000000000000000000000 229: 0x1fffffffffffffffffffffffffffffe0000000000000000000000000 230: 0x3fffffffffffffffffffffffffffffc0000000000000000000000000 231: 0x7fffffffffffffffffffffffffffff80000000000000000000000000 232: 0xffffffffffffffffffffffffffffff00000000000000000000000000 233: 0x1fffffffffffffffffffffffffffffe00000000000000000000000000 234: 0x3fffffffffffffffffffffffffffffc00000000000000000000000000 235: 0x7fffffffffffffffffffffffffffff800000000000000000000000000 236: 0xffffffffffffffffffffffffffffff000000000000000000000000000 237: 0x1fffffffffffffffffffffffffffffe000000000000000000000000000 238: 0x3fffffffffffffffffffffffffffffc000000000000000000000000000 239: 0x7fffffffffffffffffffffffffffff8000000000000000000000000000 240: 0xffffffffffffffffffffffffffffff0000000000000000000000000000 241: 0x1fffffffffffffffffffffffffffffe0000000000000000000000000000 242: 0x3fffffffffffffffffffffffffffffc0000000000000000000000000000 243: 0x7fffffffffffffffffffffffffffff80000000000000000000000000000 244: 0xffffffffffffffffffffffffffffff00000000000000000000000000000 245: 0x1fffffffffffffffffffffffffffffe00000000000000000000000000000 246: 0x3fffffffffffffffffffffffffffffc00000000000000000000000000000 247: 0x7fffffffffffffffffffffffffffff800000000000000000000000000000 248: 0xffffffffffffffffffffffffffffff000000000000000000000000000000 249: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 250: 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe 251: 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc 252: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8 253: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0 254: 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0 255: 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0 256: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80 257: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00 258: 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00 259: 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00 260: 0x3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 261: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe 262: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc 263: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd 264: 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa 265: 0x3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4 266: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe8 267: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeb addchain-0.4.0/internal/gen/testdata/builtin/listing.golden000066400000000000000000000005141514305256600237640ustar00rootroot00000000000000tmp t0 t1 t2 double z x add z x z shift t0 z 2 add t0 z t0 shift t1 t0 4 add t0 t0 t1 shift t0 t0 2 add t0 z t0 shift t1 t0 10 add t1 t0 t1 shift t1 t1 10 add t1 t0 t1 shift t2 t1 30 add t1 t1 t2 shift t2 t1 60 add t1 t1 t2 shift t2 t1 120 add t1 t1 t2 shift t1 t1 10 add t0 t0 t1 shift t0 t0 2 add t0 x t0 shift t0 t0 3 add z z t0 addchain-0.4.0/internal/gen/testdata/builtin/ops.golden000066400000000000000000000324701514305256600231220ustar00rootroot00000000000000[ 0] 0+0 0x2 [ 1] 0+1 0x3 [ 2] 2+2 0x6 [ 3] 3+3 0xc [ 4] 2+4 0xf [ 5] 5+5 0x1e [ 6] 6+6 0x3c [ 7] 7+7 0x78 [ 8] 8+8 0xf0 [ 9] 5+9 0xff [ 10] 10+10 0x1fe [ 11] 11+11 0x3fc [ 12] 2+12 0x3ff [ 13] 13+13 0x7fe [ 14] 14+14 0xffc [ 15] 15+15 0x1ff8 [ 16] 16+16 0x3ff0 [ 17] 17+17 0x7fe0 [ 18] 18+18 0xffc0 [ 19] 19+19 0x1ff80 [ 20] 20+20 0x3ff00 [ 21] 21+21 0x7fe00 [ 22] 22+22 0xffc00 [ 23] 13+23 0xfffff [ 24] 24+24 0x1ffffe [ 25] 25+25 0x3ffffc [ 26] 26+26 0x7ffff8 [ 27] 27+27 0xfffff0 [ 28] 28+28 0x1ffffe0 [ 29] 29+29 0x3ffffc0 [ 30] 30+30 0x7ffff80 [ 31] 31+31 0xfffff00 [ 32] 32+32 0x1ffffe00 [ 33] 33+33 0x3ffffc00 [ 34] 13+34 0x3fffffff [ 35] 35+35 0x7ffffffe [ 36] 36+36 0xfffffffc [ 37] 37+37 0x1fffffff8 [ 38] 38+38 0x3fffffff0 [ 39] 39+39 0x7ffffffe0 [ 40] 40+40 0xfffffffc0 [ 41] 41+41 0x1fffffff80 [ 42] 42+42 0x3fffffff00 [ 43] 43+43 0x7ffffffe00 [ 44] 44+44 0xfffffffc00 [ 45] 45+45 0x1fffffff800 [ 46] 46+46 0x3fffffff000 [ 47] 47+47 0x7ffffffe000 [ 48] 48+48 0xfffffffc000 [ 49] 49+49 0x1fffffff8000 [ 50] 50+50 0x3fffffff0000 [ 51] 51+51 0x7ffffffe0000 [ 52] 52+52 0xfffffffc0000 [ 53] 53+53 0x1fffffff80000 [ 54] 54+54 0x3fffffff00000 [ 55] 55+55 0x7ffffffe00000 [ 56] 56+56 0xfffffffc00000 [ 57] 57+57 0x1fffffff800000 [ 58] 58+58 0x3fffffff000000 [ 59] 59+59 0x7ffffffe000000 [ 60] 60+60 0xfffffffc000000 [ 61] 61+61 0x1fffffff8000000 [ 62] 62+62 0x3fffffff0000000 [ 63] 63+63 0x7ffffffe0000000 [ 64] 64+64 0xfffffffc0000000 [ 65] 35+65 0xfffffffffffffff [ 66] 66+66 0x1ffffffffffffffe [ 67] 67+67 0x3ffffffffffffffc [ 68] 68+68 0x7ffffffffffffff8 [ 69] 69+69 0xfffffffffffffff0 [ 70] 70+70 0x1ffffffffffffffe0 [ 71] 71+71 0x3ffffffffffffffc0 [ 72] 72+72 0x7ffffffffffffff80 [ 73] 73+73 0xfffffffffffffff00 [ 74] 74+74 0x1ffffffffffffffe00 [ 75] 75+75 0x3ffffffffffffffc00 [ 76] 76+76 0x7ffffffffffffff800 [ 77] 77+77 0xfffffffffffffff000 [ 78] 78+78 0x1ffffffffffffffe000 [ 79] 79+79 0x3ffffffffffffffc000 [ 80] 80+80 0x7ffffffffffffff8000 [ 81] 81+81 0xfffffffffffffff0000 [ 82] 82+82 0x1ffffffffffffffe0000 [ 83] 83+83 0x3ffffffffffffffc0000 [ 84] 84+84 0x7ffffffffffffff80000 [ 85] 85+85 0xfffffffffffffff00000 [ 86] 86+86 0x1ffffffffffffffe00000 [ 87] 87+87 0x3ffffffffffffffc00000 [ 88] 88+88 0x7ffffffffffffff800000 [ 89] 89+89 0xfffffffffffffff000000 [ 90] 90+90 0x1ffffffffffffffe000000 [ 91] 91+91 0x3ffffffffffffffc000000 [ 92] 92+92 0x7ffffffffffffff8000000 [ 93] 93+93 0xfffffffffffffff0000000 [ 94] 94+94 0x1ffffffffffffffe0000000 [ 95] 95+95 0x3ffffffffffffffc0000000 [ 96] 96+96 0x7ffffffffffffff80000000 [ 97] 97+97 0xfffffffffffffff00000000 [ 98] 98+98 0x1ffffffffffffffe00000000 [ 99] 99+99 0x3ffffffffffffffc00000000 [100] 100+100 0x7ffffffffffffff800000000 [101] 101+101 0xfffffffffffffff000000000 [102] 102+102 0x1ffffffffffffffe000000000 [103] 103+103 0x3ffffffffffffffc000000000 [104] 104+104 0x7ffffffffffffff8000000000 [105] 105+105 0xfffffffffffffff0000000000 [106] 106+106 0x1ffffffffffffffe0000000000 [107] 107+107 0x3ffffffffffffffc0000000000 [108] 108+108 0x7ffffffffffffff80000000000 [109] 109+109 0xfffffffffffffff00000000000 [110] 110+110 0x1ffffffffffffffe00000000000 [111] 111+111 0x3ffffffffffffffc00000000000 [112] 112+112 0x7ffffffffffffff800000000000 [113] 113+113 0xfffffffffffffff000000000000 [114] 114+114 0x1ffffffffffffffe000000000000 [115] 115+115 0x3ffffffffffffffc000000000000 [116] 116+116 0x7ffffffffffffff8000000000000 [117] 117+117 0xfffffffffffffff0000000000000 [118] 118+118 0x1ffffffffffffffe0000000000000 [119] 119+119 0x3ffffffffffffffc0000000000000 [120] 120+120 0x7ffffffffffffff80000000000000 [121] 121+121 0xfffffffffffffff00000000000000 [122] 122+122 0x1ffffffffffffffe00000000000000 [123] 123+123 0x3ffffffffffffffc00000000000000 [124] 124+124 0x7ffffffffffffff800000000000000 [125] 125+125 0xfffffffffffffff000000000000000 [126] 66+126 0xffffffffffffffffffffffffffffff [127] 127+127 0x1fffffffffffffffffffffffffffffe [128] 128+128 0x3fffffffffffffffffffffffffffffc [129] 129+129 0x7fffffffffffffffffffffffffffff8 [130] 130+130 0xffffffffffffffffffffffffffffff0 [131] 131+131 0x1fffffffffffffffffffffffffffffe0 [132] 132+132 0x3fffffffffffffffffffffffffffffc0 [133] 133+133 0x7fffffffffffffffffffffffffffff80 [134] 134+134 0xffffffffffffffffffffffffffffff00 [135] 135+135 0x1fffffffffffffffffffffffffffffe00 [136] 136+136 0x3fffffffffffffffffffffffffffffc00 [137] 137+137 0x7fffffffffffffffffffffffffffff800 [138] 138+138 0xffffffffffffffffffffffffffffff000 [139] 139+139 0x1fffffffffffffffffffffffffffffe000 [140] 140+140 0x3fffffffffffffffffffffffffffffc000 [141] 141+141 0x7fffffffffffffffffffffffffffff8000 [142] 142+142 0xffffffffffffffffffffffffffffff0000 [143] 143+143 0x1fffffffffffffffffffffffffffffe0000 [144] 144+144 0x3fffffffffffffffffffffffffffffc0000 [145] 145+145 0x7fffffffffffffffffffffffffffff80000 [146] 146+146 0xffffffffffffffffffffffffffffff00000 [147] 147+147 0x1fffffffffffffffffffffffffffffe00000 [148] 148+148 0x3fffffffffffffffffffffffffffffc00000 [149] 149+149 0x7fffffffffffffffffffffffffffff800000 [150] 150+150 0xffffffffffffffffffffffffffffff000000 [151] 151+151 0x1fffffffffffffffffffffffffffffe000000 [152] 152+152 0x3fffffffffffffffffffffffffffffc000000 [153] 153+153 0x7fffffffffffffffffffffffffffff8000000 [154] 154+154 0xffffffffffffffffffffffffffffff0000000 [155] 155+155 0x1fffffffffffffffffffffffffffffe0000000 [156] 156+156 0x3fffffffffffffffffffffffffffffc0000000 [157] 157+157 0x7fffffffffffffffffffffffffffff80000000 [158] 158+158 0xffffffffffffffffffffffffffffff00000000 [159] 159+159 0x1fffffffffffffffffffffffffffffe00000000 [160] 160+160 0x3fffffffffffffffffffffffffffffc00000000 [161] 161+161 0x7fffffffffffffffffffffffffffff800000000 [162] 162+162 0xffffffffffffffffffffffffffffff000000000 [163] 163+163 0x1fffffffffffffffffffffffffffffe000000000 [164] 164+164 0x3fffffffffffffffffffffffffffffc000000000 [165] 165+165 0x7fffffffffffffffffffffffffffff8000000000 [166] 166+166 0xffffffffffffffffffffffffffffff0000000000 [167] 167+167 0x1fffffffffffffffffffffffffffffe0000000000 [168] 168+168 0x3fffffffffffffffffffffffffffffc0000000000 [169] 169+169 0x7fffffffffffffffffffffffffffff80000000000 [170] 170+170 0xffffffffffffffffffffffffffffff00000000000 [171] 171+171 0x1fffffffffffffffffffffffffffffe00000000000 [172] 172+172 0x3fffffffffffffffffffffffffffffc00000000000 [173] 173+173 0x7fffffffffffffffffffffffffffff800000000000 [174] 174+174 0xffffffffffffffffffffffffffffff000000000000 [175] 175+175 0x1fffffffffffffffffffffffffffffe000000000000 [176] 176+176 0x3fffffffffffffffffffffffffffffc000000000000 [177] 177+177 0x7fffffffffffffffffffffffffffff8000000000000 [178] 178+178 0xffffffffffffffffffffffffffffff0000000000000 [179] 179+179 0x1fffffffffffffffffffffffffffffe0000000000000 [180] 180+180 0x3fffffffffffffffffffffffffffffc0000000000000 [181] 181+181 0x7fffffffffffffffffffffffffffff80000000000000 [182] 182+182 0xffffffffffffffffffffffffffffff00000000000000 [183] 183+183 0x1fffffffffffffffffffffffffffffe00000000000000 [184] 184+184 0x3fffffffffffffffffffffffffffffc00000000000000 [185] 185+185 0x7fffffffffffffffffffffffffffff800000000000000 [186] 186+186 0xffffffffffffffffffffffffffffff000000000000000 [187] 187+187 0x1fffffffffffffffffffffffffffffe000000000000000 [188] 188+188 0x3fffffffffffffffffffffffffffffc000000000000000 [189] 189+189 0x7fffffffffffffffffffffffffffff8000000000000000 [190] 190+190 0xffffffffffffffffffffffffffffff0000000000000000 [191] 191+191 0x1fffffffffffffffffffffffffffffe0000000000000000 [192] 192+192 0x3fffffffffffffffffffffffffffffc0000000000000000 [193] 193+193 0x7fffffffffffffffffffffffffffff80000000000000000 [194] 194+194 0xffffffffffffffffffffffffffffff00000000000000000 [195] 195+195 0x1fffffffffffffffffffffffffffffe00000000000000000 [196] 196+196 0x3fffffffffffffffffffffffffffffc00000000000000000 [197] 197+197 0x7fffffffffffffffffffffffffffff800000000000000000 [198] 198+198 0xffffffffffffffffffffffffffffff000000000000000000 [199] 199+199 0x1fffffffffffffffffffffffffffffe000000000000000000 [200] 200+200 0x3fffffffffffffffffffffffffffffc000000000000000000 [201] 201+201 0x7fffffffffffffffffffffffffffff8000000000000000000 [202] 202+202 0xffffffffffffffffffffffffffffff0000000000000000000 [203] 203+203 0x1fffffffffffffffffffffffffffffe0000000000000000000 [204] 204+204 0x3fffffffffffffffffffffffffffffc0000000000000000000 [205] 205+205 0x7fffffffffffffffffffffffffffff80000000000000000000 [206] 206+206 0xffffffffffffffffffffffffffffff00000000000000000000 [207] 207+207 0x1fffffffffffffffffffffffffffffe00000000000000000000 [208] 208+208 0x3fffffffffffffffffffffffffffffc00000000000000000000 [209] 209+209 0x7fffffffffffffffffffffffffffff800000000000000000000 [210] 210+210 0xffffffffffffffffffffffffffffff000000000000000000000 [211] 211+211 0x1fffffffffffffffffffffffffffffe000000000000000000000 [212] 212+212 0x3fffffffffffffffffffffffffffffc000000000000000000000 [213] 213+213 0x7fffffffffffffffffffffffffffff8000000000000000000000 [214] 214+214 0xffffffffffffffffffffffffffffff0000000000000000000000 [215] 215+215 0x1fffffffffffffffffffffffffffffe0000000000000000000000 [216] 216+216 0x3fffffffffffffffffffffffffffffc0000000000000000000000 [217] 217+217 0x7fffffffffffffffffffffffffffff80000000000000000000000 [218] 218+218 0xffffffffffffffffffffffffffffff00000000000000000000000 [219] 219+219 0x1fffffffffffffffffffffffffffffe00000000000000000000000 [220] 220+220 0x3fffffffffffffffffffffffffffffc00000000000000000000000 [221] 221+221 0x7fffffffffffffffffffffffffffff800000000000000000000000 [222] 222+222 0xffffffffffffffffffffffffffffff000000000000000000000000 [223] 223+223 0x1fffffffffffffffffffffffffffffe000000000000000000000000 [224] 224+224 0x3fffffffffffffffffffffffffffffc000000000000000000000000 [225] 225+225 0x7fffffffffffffffffffffffffffff8000000000000000000000000 [226] 226+226 0xffffffffffffffffffffffffffffff0000000000000000000000000 [227] 227+227 0x1fffffffffffffffffffffffffffffe0000000000000000000000000 [228] 228+228 0x3fffffffffffffffffffffffffffffc0000000000000000000000000 [229] 229+229 0x7fffffffffffffffffffffffffffff80000000000000000000000000 [230] 230+230 0xffffffffffffffffffffffffffffff00000000000000000000000000 [231] 231+231 0x1fffffffffffffffffffffffffffffe00000000000000000000000000 [232] 232+232 0x3fffffffffffffffffffffffffffffc00000000000000000000000000 [233] 233+233 0x7fffffffffffffffffffffffffffff800000000000000000000000000 [234] 234+234 0xffffffffffffffffffffffffffffff000000000000000000000000000 [235] 235+235 0x1fffffffffffffffffffffffffffffe000000000000000000000000000 [236] 236+236 0x3fffffffffffffffffffffffffffffc000000000000000000000000000 [237] 237+237 0x7fffffffffffffffffffffffffffff8000000000000000000000000000 [238] 238+238 0xffffffffffffffffffffffffffffff0000000000000000000000000000 [239] 239+239 0x1fffffffffffffffffffffffffffffe0000000000000000000000000000 [240] 240+240 0x3fffffffffffffffffffffffffffffc0000000000000000000000000000 [241] 241+241 0x7fffffffffffffffffffffffffffff80000000000000000000000000000 [242] 242+242 0xffffffffffffffffffffffffffffff00000000000000000000000000000 [243] 243+243 0x1fffffffffffffffffffffffffffffe00000000000000000000000000000 [244] 244+244 0x3fffffffffffffffffffffffffffffc00000000000000000000000000000 [245] 245+245 0x7fffffffffffffffffffffffffffff800000000000000000000000000000 [246] 246+246 0xffffffffffffffffffffffffffffff000000000000000000000000000000 [247] 127+247 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff [248] 248+248 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe [249] 249+249 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc [250] 250+250 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8 [251] 251+251 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0 [252] 252+252 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0 [253] 253+253 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0 [254] 254+254 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80 [255] 255+255 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00 [256] 256+256 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00 [257] 257+257 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00 [258] 13+258 0x3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff [259] 259+259 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe [260] 260+260 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc [261] 0+261 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd [262] 262+262 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa [263] 263+263 0x3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4 [264] 264+264 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe8 [265] 2+265 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeb addchain-0.4.0/internal/gen/testdata/builtin/script.golden000066400000000000000000000005721514305256600236230ustar00rootroot00000000000000_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 addchain-0.4.0/internal/gen/testdata/input.acc000066400000000000000000000005721514305256600212660ustar00rootroot00000000000000_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 addchain-0.4.0/internal/metavars/000077500000000000000000000000001514305256600167135ustar00rootroot00000000000000addchain-0.4.0/internal/metavars/metavars.go000066400000000000000000000111711514305256600210650ustar00rootroot00000000000000// Package metavars allows manipulation of "meta variables" stored as variable // declarations in Go files. package metavars import ( "bytes" "fmt" "go/ast" "go/format" "go/parser" "go/token" "io" "os" "strconv" "strings" "github.com/mmcloughlin/addchain/internal/errutil" "github.com/mmcloughlin/addchain/internal/print" ) // Property is a string variable. type Property struct { Name string Doc string Value string } // File of property definitions. type File struct { Package string Properties []Property } // Get property with given name. func (f *File) Get(name string) (string, bool) { if p := f.get(name); p != nil { return p.Value, true } return "", false } // Add property to the file, which must not already exist. func (f *File) Add(p Property) error { if q := f.get(p.Name); q != nil { return fmt.Errorf("property %q already exists", p.Name) } f.Properties = append(f.Properties, p) return nil } // Set property name to value. The property must exist. func (f *File) Set(name, value string) error { if p := f.get(name); p != nil { p.Value = value return nil } return fmt.Errorf("unknown property %q", name) } func (f *File) get(name string) *Property { for i := range f.Properties { p := &f.Properties[i] if p.Name == name { return p } } return nil } // Write file f to write w. func Write(w io.Writer, f *File) error { // Write source code. buf := bytes.NewBuffer(nil) p := print.New(buf) p.Linef("package %s", f.Package) p.NL() p.Linef("var (") p.Indent() for _, prop := range f.Properties { if prop.Doc != "" { p.Linef("// %s", prop.Doc) } p.Linef("%s = %q", prop.Name, prop.Value) } p.Dedent() p.Linef(")") if err := p.Error(); err != nil { return err } // Format and write. src, err := format.Source(buf.Bytes()) if err != nil { return err } _, err = w.Write(src) return err } // WriteFile writes f to the given file. func WriteFile(filename string, f *File) error { return writefile(filename, f) } func writefile(filename string, f *File) (err error) { w, err := os.Create(filename) if err != nil { return err } defer errutil.CheckClose(&err, w) return Write(w, f) } // Read properties from the given reader. func Read(r io.Reader) (*File, error) { return parse("", r) } // ReadFile reads properties file. func ReadFile(filename string) (*File, error) { return parse(filename, nil) } func parse(filename string, src interface{}) (*File, error) { // Parse AST. fset := token.NewFileSet() // positions are relative to fset f, err := parser.ParseFile(fset, filename, src, parser.ParseComments) if err != nil { return nil, err } // Build file from AST. b := &builder{f: &File{}} b.file(f) if b.err != nil { return nil, b.err } return b.f, nil } type builder struct { f *File err error } func (b *builder) file(f *ast.File) { // Package name. b.f.Package = f.Name.Name // Declarations. for _, d := range f.Decls { b.decl(d) } } func (b *builder) decl(i ast.Decl) { switch d := i.(type) { case *ast.GenDecl: b.gendecl(d) default: b.seterrorf("unexpected declaration type %T", i) } } func (b *builder) gendecl(g *ast.GenDecl) { // Confirm this is a variable declaration. if g.Tok != token.VAR { b.seterrorf("expected variable declaration, got %s", g.Tok) return } // Process each spec. for _, spec := range g.Specs { v, ok := spec.(*ast.ValueSpec) if !ok { b.seterrorf("expected value spec") } b.valuespec(v) } } func (b *builder) valuespec(v *ast.ValueSpec) { p := Property{} // Extract name. if len(v.Names) != 1 { b.seterrorf("expected one name, got %d", len(v.Names)) return } p.Name = v.Names[0].Name // Extract value. if len(v.Values) != 1 { b.seterrorf("expected one value, got %d", len(v.Values)) return } expr := v.Values[0] lit, ok := expr.(*ast.BasicLit) if !ok { b.seterrorf("expected basic literal") return } if lit.Kind != token.STRING { b.seterrorf("expected string literal") return } s, err := strconv.Unquote(lit.Value) if err != nil { b.seterrorf("parse string literal: %w", err) return } p.Value = s // Optional documentation. if v.Doc != nil { const leader = "// " if len(v.Doc.List) != 1 { b.seterrorf("expect single line documentation") return } comment := v.Doc.List[0] if !strings.HasPrefix(comment.Text, leader) { b.seterrorf("expected documentation to have %q leader", leader) return } p.Doc = strings.TrimPrefix(comment.Text, leader) } // Add property to file. b.f.Properties = append(b.f.Properties, p) } func (b *builder) seterrorf(format string, args ...interface{}) { if b.err == nil { b.err = fmt.Errorf(format, args...) } } addchain-0.4.0/internal/metavars/metavars_test.go000066400000000000000000000043731514305256600221320ustar00rootroot00000000000000package metavars import ( "bytes" "reflect" "testing" ) func TestFileAccessors(t *testing.T) { f := &File{ Package: "test", } // Get non-existent property. if _, ok := f.Get("name"); ok { t.Fatal("returned ok for non-existent property") } // Add it. p := Property{Name: "name", Value: "value"} if err := f.Add(p); err != nil { t.Fatal(err) } // Cannot Add the same property again. if err := f.Add(p); err == nil { t.Fatal("cannot add duplicate properties") } // Get should work now. if v, ok := f.Get("name"); v != "value" || !ok { t.Fatal("unexpected property value") } // Set it to something else. if err := f.Set("name", "new"); err != nil { t.Fatal(err) } // Get the new value. if v, ok := f.Get("name"); v != "new" || !ok { t.Fatal("did not see value update") } // Cannot set unknown property. if err := f.Set("other", "value"); err == nil { t.Fatal("cannot set unknown property") } } func TestRoundtrip(t *testing.T) { cases := []*File{ { Package: "standard", Properties: []Property{ {Name: "A", Doc: "A is the first variable.", Value: "one"}, {Name: "B", Doc: "B is the second variable.", Value: "two"}, {Name: "C", Doc: "C is the third variable.", Value: "three"}, }, }, { Package: "single", Properties: []Property{ {Name: "A", Doc: "A is the first variable.", Value: "one"}, }, }, { Package: "empty", }, { Package: "nodoc", Properties: []Property{ {Name: "A", Value: "one"}, {Name: "B", Value: "two"}, }, }, { Package: "mixeddoc", Properties: []Property{ {Name: "A", Doc: "A is the first variable.", Value: "one"}, {Name: "B", Value: "two"}, {Name: "C", Doc: "C is the third variable.", Value: "three"}, }, }, { Package: "quoting", Properties: []Property{ {Name: "A", Value: `this "would" need 'to' be quoted correctly`}, }, }, } for _, f := range cases { f := f // scopelint t.Run(f.Package, func(t *testing.T) { buf := bytes.NewBuffer(nil) if err := Write(buf, f); err != nil { t.Fatal(err) } got, err := Read(buf) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(got, f) { t.Logf("got = %#v", got) t.Logf("expect = %#v", f) t.Fatal("roundtrip fail") } }) } } addchain-0.4.0/internal/polynomial/000077500000000000000000000000001514305256600172545ustar00rootroot00000000000000addchain-0.4.0/internal/polynomial/polynomial.go000066400000000000000000000027131514305256600217710ustar00rootroot00000000000000// Package polynomial provides a polynomial type. package polynomial import ( "fmt" "math/big" "strings" "github.com/mmcloughlin/addchain/internal/bigint" ) // Term is the term A*xᴺ in a polynomial. type Term struct { A int64 N uint } func (t Term) String() string { return Polynomial{t}.String() } // Evaluate term at x. func (t Term) Evaluate(x *big.Int) *big.Int { n := big.NewInt(int64(t.N)) y := new(big.Int).Exp(x, n, nil) return y.Mul(big.NewInt(t.A), y) } // Polynomial is a single-variable polynomial. Terms are expected (but not // required) to be in increasing order of exponent. type Polynomial []Term func (p Polynomial) String() string { return p.Format("x") } // Format polynomial as a string, using v to represent the variable. func (p Polynomial) Format(v string) string { s := "" for i := len(p) - 1; i >= 0; i-- { t := p[i] if t.N == 0 { s += fmt.Sprintf("%+d", t.A) continue } switch t.A { case 1: s += "+" case -1: s += "-" default: s += fmt.Sprintf("%+d", t.A) } s += v if t.N > 1 { s += fmt.Sprintf("^%d", t.N) } } return strings.TrimPrefix(s, "+") } // Degree returns the degree of p, namely the highest exponent. func (p Polynomial) Degree() uint { n := uint(0) for _, t := range p { if t.N > n { n = t.N } } return n } // Evaluate p at x. func (p Polynomial) Evaluate(x *big.Int) *big.Int { y := bigint.Zero() for _, t := range p { y.Add(y, t.Evaluate(x)) } return y } addchain-0.4.0/internal/polynomial/polynomial_test.go000066400000000000000000000027321514305256600230310ustar00rootroot00000000000000package polynomial import ( "math/big" "testing" "github.com/mmcloughlin/addchain/internal/bigint" ) func TestTermEvaluate(t *testing.T) { term := Term{A: 42, N: 3} x := big.NewInt(7) got := term.Evaluate(x) expect := int64(42 * 7 * 7 * 7) if !bigint.EqualInt64(got, expect) { t.Fatalf("evaluate %s at %v: got %v; expect %v", term, x, got, expect) } } func TestPolynomialString(t *testing.T) { cases := []struct { Polynomial Polynomial Expect string }{ {Polynomial{{1, 0}}, "1"}, {Polynomial{{-1, 0}}, "-1"}, {Polynomial{{42, 0}}, "42"}, {Polynomial{{-42, 0}}, "-42"}, {Polynomial{{1, 1}}, "x"}, {Polynomial{{-1, 1}}, "-x"}, {Polynomial{{42, 1}}, "42x"}, {Polynomial{{-42, 1}}, "-42x"}, {Polynomial{{1, 2}}, "x^2"}, {Polynomial{{-1, 2}}, "-x^2"}, {Polynomial{{42, 2}}, "42x^2"}, {Polynomial{{-42, 2}}, "-42x^2"}, {Polynomial{{-7, 0}, {-3, 3}, {1, 4}}, "x^4-3x^3-7"}, } for _, c := range cases { if got := c.Polynomial.String(); got != c.Expect { t.Errorf("%#v.String() = %s; expect %s", c.Polynomial, got, c.Expect) } } } func TestPolynomialEvaluate(t *testing.T) { p := Polynomial{{-11, 0}, {-3, 3}, {1, 4}} x := big.NewInt(7) got := p.Evaluate(x) expect := int64(7*7*7*7 - 3*7*7*7 - 11) if !bigint.EqualInt64(got, expect) { t.Fatalf("evaluate %s at %v: got %v; expect %v", p, x, got, expect) } } func TestPolynomialDegree(t *testing.T) { p := Polynomial{{-11, 0}, {1, 4}, {2, 3}} if p.Degree() != 4 { t.FailNow() } } addchain-0.4.0/internal/prime/000077500000000000000000000000001514305256600162055ustar00rootroot00000000000000addchain-0.4.0/internal/prime/distinguished.go000066400000000000000000000114251514305256600214020ustar00rootroot00000000000000package prime import "github.com/mmcloughlin/addchain/internal/polynomial" // References: // // [aranha] 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 // [curve25519] 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 // [elligator] 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 // [fips186-2] 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 // [goldilocks] Mike Hamburg. Ed448-Goldilocks, a new elliptic curve. Cryptology ePrint Archive, // Report 2015/625. 2015. https://eprint.iacr.org/2015/625 // [nistdanger] 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 // [safecurves] Daniel J. Bernstein and Tanja Lange. SafeCurves: choosing safe curves for // elliptic-curve cryptography. https://safecurves.cr.yp.to // [sec2] 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 var ( // P2213 is the prime 2²²¹ - 3 used in curve M-221 [aranha]. P2213 = NewCrandall(221, 3) // P222117 is the prime 2²²² - 117 used in curve E-222 [aranha]. P222117 = NewCrandall(222, 117) // P2519 is the prime 2²⁵¹ - 9 used in Curve1174 [elligator]. P2519 = NewCrandall(251, 9) // P25519 is the prime 2²⁵⁵ - 19 used in Curve25519 [curve25519]. P25519 = NewCrandall(255, 19) // P382105 is the prime 2³⁸² - 105 used in curve E-382 [aranha]. P382105 = NewCrandall(382, 105) // P383187 is the prime 2³⁸³ - 187 used in curves M-383 and Curve383187 [aranha]. P383187 = NewCrandall(383, 187) // P41417 is the prime 2⁴¹⁴ - 17 used in Curve41417 [nistdanger]. P41417 = NewCrandall(414, 17) // P511187 is the prime 2⁵¹¹ - 187 used in M-511 [aranha]. P511187 = NewCrandall(511, 187) // NISTP192 is the P-192 prime 2¹⁹² - 2⁶⁴ - 1 defined in [fips186-2]. NISTP192 = NewSolinas(polynomial.Polynomial{{A: -1, N: 0}, {A: -1, N: 1}, {A: 1, N: 3}}, 64) // NISTP224 is the P-224 prime 2²²⁴ - 2⁹⁶ + 1 defined in [fips186-2]. NISTP224 = NewSolinas(polynomial.Polynomial{{A: 1, N: 0}, {A: -1, N: 3}, {A: 1, N: 7}}, 32) // NISTP256 is the P-256 prime 2²⁵⁶ - 2²²⁴ + 2¹⁹² + 2⁹⁶ - 1 defined in [fips186-2]. NISTP256 = NewSolinas(polynomial.Polynomial{{A: -1, N: 0}, {A: +1, N: 3}, {A: +1, N: 6}, {A: -1, N: 7}, {A: +1, N: 8}}, 32) // NISTP384 is the P-384 prime 2³⁸⁴ - 2¹²⁸ - 2⁹⁶ + 2³² - 1 defined in [fips186-2]. NISTP384 = NewSolinas(polynomial.Polynomial{{A: -1, N: 0}, {A: 1, N: 1}, {A: -1, N: 3}, {A: -1, N: 4}, {A: 1, N: 12}}, 32) // Goldilocks is the prime 2⁴⁴⁸ - 2²²⁴ - 1 defined in [goldilocks]. Goldilocks = NewSolinas(polynomial.Polynomial{{A: -1, N: 0}, {A: -1, N: 1}, {A: 1, N: 2}}, 224) // Secp192k1 is the prime for the 192-bit Koblitz curve recommended in [sec2]. Secp192k1 = MustHex("FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFE_FFFFEE37") // Secp192r1 is the prime for the 192-bit "random" curve recommended in [sec2]. Secp192r1 = NISTP192 // Secp224k1 is the prime for the 224-bit Koblitz curve recommended in [sec2]. Secp224k1 = MustHex("FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFE_FFFFE56D") // Secp224r1 is the prime for the 224-bit "random" curve recommended in [sec2]. Secp224r1 = NISTP224 // Secp256k1 is the prime for the 256-bit Koblitz curve recommended in [sec2]. Secp256k1 = MustHex("FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFE_FFFFFC2F") // Secp256r1 is the prime for the 256-bit "random" curve recommended in [sec2]. Secp256r1 = NISTP256 // Secp384r1 is the prime for the 384-bit "random" curve recommended in [sec2]. Secp384r1 = NISTP384 ) // Distinguished is a list of well-known primes. var Distinguished = []Prime{ P2213, P222117, P2519, P25519, P382105, P383187, P41417, P511187, NISTP192, NISTP224, NISTP256, NISTP384, Goldilocks, Secp192k1, Secp224k1, Secp256k1, } addchain-0.4.0/internal/prime/distinguished_test.go000066400000000000000000000015251514305256600224410ustar00rootroot00000000000000package prime import "testing" // Rudimentary tests to guard against transcription errors. func TestDistinguishedArePrime(t *testing.T) { for _, p := range Distinguished { if !p.Int().ProbablyPrime(20) { t.Errorf("%s is not prime", p) } } } func TestDistinguishedDecimal(t *testing.T) { cases := []struct { P Prime Decimal string }{ {NISTP192, "6277101735386680763835789423207666416083908700390324961279"}, {NISTP224, "26959946667150639794667015087019630673557916260026308143510066298881"}, {NISTP256, "115792089210356248762697446949407573530086143415290314195533631308867097853951"}, {NISTP384, "39402006196394479212279040100143613805079739270465446667948293404245721771496870329047266088258938001861606973112319"}, } for _, c := range cases { got := c.P.Int().String() if got != c.Decimal { t.Fail() } } } addchain-0.4.0/internal/prime/prime.go000066400000000000000000000055671514305256600176650ustar00rootroot00000000000000// Package prime provides representations of classes of prime numbers. package prime import ( "fmt" "math/big" "github.com/mmcloughlin/addchain/internal/bigint" "github.com/mmcloughlin/addchain/internal/polynomial" ) // References: // // [crandallprime] 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 // [solinasprime] 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 // Prime is the interface for a prime number. type Prime interface { Bits() int Int() *big.Int String() string } // Crandall represents a prime of the form 2ⁿ - c. Named after Richard E. Crandall [crandallprime]. type Crandall struct { N int C int } // NewCrandall constructs a Crandall prime. func NewCrandall(n, c int) Crandall { return Crandall{N: n, C: c} } // Bits returns the number of bits required to represent p. func (p Crandall) Bits() int { return p.N } func (p Crandall) String() string { return fmt.Sprintf("2^%d%+d", p.N, -p.C) } // Int returns the prime as a big integer. func (p Crandall) Int() *big.Int { one := big.NewInt(1) c := big.NewInt(int64(p.C)) e := new(big.Int).Lsh(one, uint(p.N)) return new(big.Int).Sub(e, c) } // Solinas is a "Generalized Mersenne Prime", as introduced by Jerome Solinas // [solinasprime]. Such primes are of the form f( 2ᵏ ) for a low-degree // polynomial f. type Solinas struct { F polynomial.Polynomial K uint } // NewSolinas constructs a Solinas prime. func NewSolinas(f polynomial.Polynomial, k uint) Solinas { return Solinas{F: f, K: k} } // Bits returns the number of bits required to represent p. func (p Solinas) Bits() int { return int(p.F.Degree() * p.K) } // Int returns p as an integer. func (p Solinas) Int() *big.Int { return p.F.Evaluate(bigint.Pow2(p.K)) } func (p Solinas) String() string { // Create another polynomial with all terms scaled by k. g := polynomial.Polynomial{} for _, t := range p.F { s := t s.N *= p.K g = append(g, s) } return g.Format("2") } // Other is a prime whose structure does not match any of the other specific // types in this package. type Other struct { P *big.Int } // NewOther builds a prime from the provided integer. func NewOther(p *big.Int) Other { return Other{P: p} } // MustHex parses a prime from the hex literal p. Panics on error. func MustHex(p string) Other { return NewOther(bigint.MustHex(p)) } // Bits returns the bit length of p. func (p Other) Bits() int { return p.P.BitLen() } // Int returns p as an integer. func (p Other) Int() *big.Int { return p.P } func (p Other) String() string { return fmt.Sprintf("%x", p.P) } addchain-0.4.0/internal/prime/prime_test.go000066400000000000000000000010461514305256600207100ustar00rootroot00000000000000package prime import ( "testing" "github.com/mmcloughlin/addchain/internal/polynomial" ) func TestSolinas(t *testing.T) { // The "Goldilocks" prime. p := NewSolinas(polynomial.Polynomial{{A: -1, N: 0}, {A: -1, N: 1}, {A: 1, N: 2}}, 224) if p.Bits() != 448 { t.FailNow() } x := p.Int() decimal := "726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018365439" if x.String() != decimal { t.FailNow() } if p.String() != "2^448-2^224-1" { t.FailNow() } } addchain-0.4.0/internal/print/000077500000000000000000000000001514305256600162255ustar00rootroot00000000000000addchain-0.4.0/internal/print/printer.go000066400000000000000000000045541514305256600202470ustar00rootroot00000000000000// 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()) } addchain-0.4.0/internal/results/000077500000000000000000000000001514305256600165725ustar00rootroot00000000000000addchain-0.4.0/internal/results/results.go000066400000000000000000000157661514305256600206410ustar00rootroot00000000000000// Package results stores results of this library on popular cryptographic // exponents for testing and documentation purposes. package results import ( "fmt" "math/big" "github.com/mmcloughlin/addchain/internal/bigint" "github.com/mmcloughlin/addchain/internal/prime" ) // 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) // Integer of interest. type Integer interface { Int() *big.Int String() string } type integer struct { x *big.Int } // Hex constructs an integer target from a hex string. func Hex(s string) Integer { return integer{x: bigint.MustHex(s)} } func (i integer) String() string { return fmt.Sprintf("%x", i.x) } func (i integer) Int() *big.Int { return i.x } // Result represents the best result of this library on a particular input. type Result struct { Name string Slug string N Integer D int64 // Length is the length of the most efficient chain produced by this library. Length int // AlgorithmName is the name of the algorithm that found the most efficient // chain. AlgorithmName string // BestKnown is the length of the most efficient chain known, found by any // method. These are currently all from [curvechains], it's possible there // are better results elsewhere. BestKnown int } // Target computes the addition chain target value N-d. func (r Result) Target() *big.Int { return new(big.Int).Sub(r.N.Int(), big.NewInt(r.D)) } // Delta relative to best known. func (r Result) Delta() int { return r.Length - r.BestKnown } // Results on inversion exponents for various interesting or popular fields. // These results set a baseline to prevent regressions, as well as to compare // against the best hand-crafted chains [curvechains]. var Results = []Result{ { Name: "Curve25519 Field Inversion", Slug: "curve25519_field", N: prime.P25519, D: 2, Length: 266, AlgorithmName: "opt(runs(continued_fractions(dichotomic)))", BestKnown: 265, }, { Name: "NIST P-256 Field Inversion", Slug: "p256_field", N: prime.NISTP256, D: 3, Length: 266, AlgorithmName: "opt(runs(continued_fractions(dichotomic)))", BestKnown: 266, }, { Name: "NIST P-384 Field Inversion", Slug: "p384_field", N: prime.NISTP384, D: 3, Length: 397, AlgorithmName: "opt(runs(heuristic(use_first(halving,approximation))))", BestKnown: 396, }, { Name: "secp256k1 (Bitcoin) Field Inversion", Slug: "secp256k1_field", N: prime.Secp256k1, D: 3, Length: 269, AlgorithmName: "opt(runs(heuristic(use_first(halving,delta_largest))))", BestKnown: 269, }, { Name: "Curve25519 Scalar Inversion", Slug: "curve25519_scalar", N: Hex("1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed"), D: 2, Length: 283, AlgorithmName: "opt(dictionary(hybrid(4,0),continued_fractions(binary)))", BestKnown: 284, }, { Name: "NIST P-256 Scalar Inversion", Slug: "p256_scalar", N: Hex("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551"), D: 2, Length: 294, AlgorithmName: "opt(dictionary(hybrid(8,16),heuristic(use_first(halving,delta_largest))))", BestKnown: 292, }, { Name: "NIST P-384 Scalar Inversion", Slug: "p384_scalar", N: Hex("ffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973"), D: 2, Length: 434, AlgorithmName: "opt(dictionary(hybrid(4,0),continued_fractions(dichotomic)))", BestKnown: 433, }, { Name: "secp256k1 (Bitcoin) Scalar Inversion", Slug: "secp256k1_scalar", N: Hex("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"), D: 2, Length: 293, AlgorithmName: "opt(dictionary(hybrid(4,0),continued_fractions(dichotomic)))", BestKnown: 290, }, { Name: "M-221 Field Inversion", Slug: "p2213_field", N: prime.P2213, D: 2, Length: 231, AlgorithmName: "opt(runs(continued_fractions(dichotomic)))", }, { Name: "E-222 Field Inversion", Slug: "p222117_field", N: prime.P222117, D: 2, Length: 233, AlgorithmName: "opt(runs(continued_fractions(dichotomic)))", }, { Name: "Curve1174 Field Inversion", Slug: "p2519_field", N: prime.P2519, D: 2, Length: 263, AlgorithmName: "opt(dictionary(hybrid(3,64),continued_fractions(dichotomic)))", }, { Name: "E-382 Field Inversion", Slug: "p382105_field", AlgorithmName: "opt(dictionary(hybrid(5,0),continued_fractions(dichotomic)))", N: prime.P382105, D: 2, Length: 395, }, { Name: "M-383/Curve383187 Field Inversion", Slug: "p383187_field", N: prime.P383187, D: 2, Length: 396, AlgorithmName: "opt(runs(continued_fractions(dichotomic)))", }, { Name: "Curve41417 Field Inversion", Slug: "p41417_field", N: prime.P41417, D: 2, Length: 426, AlgorithmName: "opt(runs(continued_fractions(dichotomic)))", }, { Name: "M-511 Field Inversion", Slug: "p511187_field", N: prime.P511187, D: 2, Length: 525, AlgorithmName: "opt(runs(continued_fractions(dichotomic)))", }, { Name: "NIST P-192 Field Inversion", Slug: "p192_field", N: prime.NISTP192, D: 2, Length: 203, AlgorithmName: "opt(dictionary(hybrid(2,0),continued_fractions(dichotomic)))", }, { Name: "NIST P-224 Field Inversion", Slug: "p224_field", N: prime.NISTP224, D: 2, Length: 234, AlgorithmName: "opt(runs(heuristic(use_first(halving,approximation))))", }, { Name: "Goldilocks Field Inversion", Slug: "goldilocks_field", N: prime.Goldilocks, D: 2, Length: 460, AlgorithmName: "opt(runs(heuristic(use_first(halving,approximation))))", }, { Name: "secp192k1 Field Inversion", Slug: "secp192k1_field", N: prime.Secp192k1, D: 2, Length: 205, AlgorithmName: "opt(dictionary(hybrid(3,0),continued_fractions(dichotomic)))", }, { Name: "secp224k1 Field Inversion", Slug: "secp224k1_field", N: prime.Secp224k1, D: 2, Length: 238, AlgorithmName: "opt(dictionary(hybrid(5,0),continued_fractions(dichotomic)))", }, } addchain-0.4.0/internal/results/results_test.go000066400000000000000000000057141514305256600216700ustar00rootroot00000000000000package results import ( "flag" "log" "os" "sort" "testing" "github.com/mmcloughlin/addchain/acc" "github.com/mmcloughlin/addchain/alg/ensemble" "github.com/mmcloughlin/addchain/alg/exec" "github.com/mmcloughlin/addchain/internal/test" ) // verbose flag for customizing log output from algorithm executor. var verbose = flag.Bool("verbose", false, "enable verbose logging") func TestResults(t *testing.T) { t.Parallel() as := ensemble.Ensemble() for _, c := range Results { c := c // scopelint t.Run(c.Slug, func(t *testing.T) { t.Parallel() // Tests with a best known result are prioritized. Only run all tests in // stress test mode. if c.BestKnown == 0 { test.RequireStress(t) } else { test.RequireLong(t) } n := c.Target() t.Logf("n-%d=%x", c.D, n) // Execute. ex := exec.NewParallel() if *verbose { ex.SetLogger(log.New(os.Stderr, "", log.Ltime|log.Lmicroseconds)) } rs := ex.Execute(n, as) // Check for errors. for _, r := range rs { if r.Err != nil { t.Fatalf("error with %s: %v", r.Algorithm, r.Err) } } // Find the best. best := []exec.Result{rs[0]} for _, r := range rs[1:] { if len(r.Program) == len(best[0].Program) { best = append(best, r) } else if len(r.Program) < len(best[0].Program) { best = []exec.Result{r} } } sort.Slice(best, func(i, j int) bool { ai := best[i].Program.Adds() aj := best[j].Program.Adds() ni := best[i].Algorithm.String() nj := best[j].Algorithm.String() return ai < aj || (ai == aj && ni < nj) }) // Report. for _, b := range best { doubles, adds := b.Program.Count() t.Logf(" alg: %s", b.Algorithm) t.Logf("total: %d\tadds: %d\tdoubles: %d", adds+doubles, adds, doubles) } b := best[0] length := len(b.Program) if c.BestKnown > 0 { t.Logf("known: %d", c.BestKnown) t.Logf("delta: %+d", length-c.BestKnown) } // Ensure the recorded best length and algorithm name are correct. if c.Length != length { t.Errorf("incorrect best value %d; expect %d", length, c.Length) } if c.AlgorithmName != b.Algorithm.String() { t.Errorf("incorrect algorithm name %q; expect %q", c.AlgorithmName, b.Algorithm) } // Compare to golden file. golden, err := acc.LoadFile(test.GoldenName(c.Slug)) if err != nil { t.Logf("failed to load golden file: %s", err) } save := test.Golden() switch { case golden == nil: t.Errorf("missing golden file") save = true case len(golden.Program) < length: t.Errorf("regression from golden: %d to %d", len(golden.Program), length) case len(golden.Program) > len(b.Program): t.Logf("improvement: %d to %d", len(golden.Program), length) save = true } if save { t.Log("saving golden file") r, err := acc.Decompile(b.Program) if err != nil { t.Fatal(err) } if err := acc.Save(test.GoldenName(c.Slug), r); err != nil { t.Fatal(err) } } }) } } addchain-0.4.0/internal/results/testdata/000077500000000000000000000000001514305256600204035ustar00rootroot00000000000000addchain-0.4.0/internal/results/testdata/curve25519_field.golden000066400000000000000000000005721514305256600244760ustar00rootroot00000000000000_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 addchain-0.4.0/internal/results/testdata/curve25519_scalar.golden000066400000000000000000000017221514305256600246560ustar00rootroot00000000000000_10 = 2*1 _11 = 1 + _10 _100 = 1 + _11 _1000 = 2*_100 _1010 = _10 + _1000 _1011 = 1 + _1010 _10000 = 2*_1000 _10110 = 2*_1011 _100000 = _1010 + _10110 _100110 = _10000 + _10110 _1000000 = 2*_100000 _1010000 = _10000 + _1000000 _1010011 = _11 + _1010000 _1100011 = _10000 + _1010011 _1100111 = _100 + _1100011 _1101011 = _100 + _1100111 _10010011 = _1000000 + _1010011 _10010111 = _100 + _10010011 _10111101 = _100110 + _10010111 _11010011 = _10110 + _10111101 _11100111 = _1010000 + _10010111 _11101011 = _100 + _11100111 _11110101 = _1010 + _11101011 i161 = ((_1011 + _11110101) << 126 + _1010011) << 9 + _10 i180 = ((_11110101 + i161) << 7 + _1100111) << 9 + _11110101 i210 = ((i180 << 11 + _10111101) << 8 + _11100111) << 9 i233 = ((_1101011 + i210) << 6 + _1011) << 14 + _10010011 i264 = ((i233 << 10 + _1100011) << 9 + _10010111) << 10 return ((_11110101 + i264) << 8 + _11010011) << 8 + _11101011 addchain-0.4.0/internal/results/testdata/goldilocks_field.golden000066400000000000000000000005741514305256600251000ustar00rootroot00000000000000_10 = 2*1 _11 = 1 + _10 _110 = 2*_11 _111 = 1 + _110 _111000 = _111 << 3 _111111 = _111 + _111000 x12 = _111111 << 6 + _111111 x24 = x12 << 12 + x12 i34 = x24 << 6 x30 = _111111 + i34 x48 = i34 << 18 + x24 x96 = x48 << 48 + x48 x192 = x96 << 96 + x96 x222 = x192 << 30 + x30 x223 = 2*x222 + 1 return (x223 << 223 + x222) << 2 + 1 addchain-0.4.0/internal/results/testdata/p192_field.golden000066400000000000000000000005231514305256600234330ustar00rootroot00000000000000_10 = 2*1 _11 = 1 + _10 _110 = 2*_11 _111 = 1 + _110 _111000 = _111 << 3 _111111 = _111 + _111000 x12 = _111111 << 6 + _111111 x15 = x12 << 3 + _111 x30 = x15 << 15 + x15 x60 = x30 << 30 + x30 x62 = x60 << 2 + _11 x124 = x62 << 62 + x62 x127 = x124 << 3 + _111 return (x127 << 63 + x62) << 2 + 1 addchain-0.4.0/internal/results/testdata/p2213_field.golden000066400000000000000000000005221514305256600235060ustar00rootroot00000000000000_10 = 2*1 _11 = 1 + _10 _1100 = _11 << 2 _1111 = _11 + _1100 _111100 = _1111 << 2 _111111 = _11 + _111100 x10 = _111111 << 4 + _1111 x20 = x10 << 10 + x10 x26 = x20 << 6 + _111111 x52 = x26 << 26 + x26 x104 = x52 << 52 + x52 x208 = x104 << 104 + x104 x218 = x208 << 10 + x10 return x218 << 3 + _11 addchain-0.4.0/internal/results/testdata/p222117_field.golden000066400000000000000000000005711514305256600236610ustar00rootroot00000000000000_10 = 2*1 _11 = 1 + _10 _110 = 2*_11 _111 = 1 + _110 _111000 = _111 << 3 _111111 = _111 + _111000 _1111110 = 2*_111111 _1111111 = 1 + _1111110 x13 = _1111111 << 6 + _111111 x26 = x13 << 13 + x13 x52 = x26 << 26 + x26 x104 = x52 << 52 + x52 x208 = x104 << 104 + x104 x215 = x208 << 7 + _1111111 return (x215 << 4 + 1) << 3 + 1 addchain-0.4.0/internal/results/testdata/p224_field.golden000066400000000000000000000005071514305256600234310ustar00rootroot00000000000000_10 = 2*1 _11 = 1 + _10 _110 = 2*_11 _111 = 1 + _110 _111000 = _111 << 3 _111111 = _111 + _111000 x12 = _111111 << 6 + _111111 x14 = x12 << 2 + _11 x17 = x14 << 3 + _111 x31 = x17 << 14 + x14 x48 = x31 << 17 + x17 x96 = x48 << 48 + x48 x127 = x96 << 31 + x31 return x127 << 97 + x96 addchain-0.4.0/internal/results/testdata/p2519_field.golden000066400000000000000000000006171514305256600235240ustar00rootroot00000000000000_10 = 2*1 _11 = 1 + _10 _110 = 2*_11 _111 = 1 + _110 _111000 = _111 << 3 _111111 = _111 + _111000 _1111110 = 2*_111111 _1111111 = 1 + _1111110 x14 = _1111111 << 7 + _1111111 x15 = 2*x14 + 1 x30 = x15 << 15 + x15 x60 = x30 << 30 + x30 x120 = x60 << 60 + x60 x240 = x120 << 120 + x120 x247 = x240 << 7 + _1111111 return (x247 << 2 + 1) << 2 + 1 addchain-0.4.0/internal/results/testdata/p256_field.golden000066400000000000000000000005001514305256600234270ustar00rootroot00000000000000_10 = 2*1 _11 = 1 + _10 _1100 = _11 << 2 _1111 = _11 + _1100 _111100 = _1111 << 2 _111111 = _11 + _111100 x12 = _111111 << 6 + _111111 x24 = x12 << 12 + x12 x30 = x24 << 6 + _111111 x32 = x30 << 2 + _11 i232 = ((x32 << 32 + 1) << 128 + x32) << 32 return ((x32 + i232) << 30 + x30) << 2 addchain-0.4.0/internal/results/testdata/p256_scalar.golden000066400000000000000000000022301514305256600236130ustar00rootroot00000000000000_10 = 2*1 _100 = 2*_10 _101 = 1 + _100 _110 = 1 + _101 _1001 = _100 + _101 _1111 = _110 + _1001 _10010 = 2*_1001 _10101 = _110 + _1111 _11000 = _110 + _10010 _11010 = _10 + _11000 _101111 = _10101 + _11010 _111000 = _1001 + _101111 _111101 = _101 + _111000 _111111 = _10 + _111101 _1001111 = _10010 + _111101 _1100001 = _10010 + _1001111 _1100011 = _10 + _1100001 _1110011 = _10010 + _1100001 _1110111 = _100 + _1110011 _1111101 = _110 + _1110111 _10010101 = _11000 + _1111101 _10100111 = _10010 + _10010101 _10101101 = _110 + _10100111 _11100101 = _111000 + _10101101 _11111111 = _11010 + _11100101 x16 = _11111111 << 8 + _11111111 x32 = x16 << 16 + x16 i133 = ((x32 << 48 + x16) << 16 + x16) << 16 i158 = ((x16 + i133) << 16 + x16) << 6 + _101111 i186 = ((i158 << 9 + _1110011) << 8 + _1111101) << 9 i206 = ((_10101101 + i186) << 8 + _10100111) << 9 + _101111 i236 = ((i206 << 8 + _111101) << 11 + _1001111) << 9 i257 = ((_1110111 + i236) << 10 + _11100101) << 8 + _1100001 i286 = ((i257 << 7 + _111111) << 10 + _1100011) << 10 return (_10010101 + i286) << 6 + _1111 addchain-0.4.0/internal/results/testdata/p382105_field.golden000066400000000000000000000007571514305256600236730ustar00rootroot00000000000000_10 = 2*1 _11 = 1 + _10 _110 = 2*_11 _111 = 1 + _110 _1110 = 2*_111 _10101 = _111 + _1110 _101010 = 2*_10101 _111111 = _10101 + _101010 _1111110 = 2*_111111 _11111100 = 2*_1111110 i11 = 2*_11111100 i25 = (i11 << 5 + _11111100) << 7 + i11 i51 = (i25 << 5 + _11111100) << 19 + i25 i101 = (i51 << 5 + _11111100) << 43 + i51 i199 = (i101 << 4 + _1111110) << 92 + i101 x375 = i199 << 186 + i199 + _111 return x375 << 7 + _10101 addchain-0.4.0/internal/results/testdata/p383187_field.golden000066400000000000000000000006631514305256600237020ustar00rootroot00000000000000_10 = 2*1 _11 = 1 + _10 _1100 = _11 << 2 _1111 = _11 + _1100 _11110000 = _1111 << 4 _11111111 = _1111 + _11110000 x16 = _11111111 << 8 + _11111111 x20 = x16 << 4 + _1111 x22 = x20 << 2 + _11 x44 = x22 << 22 + x22 x88 = x44 << 44 + x44 x176 = x88 << 88 + x88 x352 = x176 << 176 + x176 x374 = x352 << 22 + x22 x375 = 2*x374 + 1 return (x375 << 2 + 1) << 6 + _11 addchain-0.4.0/internal/results/testdata/p384_field.golden000066400000000000000000000006141514305256600234370ustar00rootroot00000000000000_10 = 2*1 _11 = 1 + _10 _110 = 2*_11 _111 = 1 + _110 _111000 = _111 << 3 _111111 = _111 + _111000 x12 = _111111 << 6 + _111111 x24 = x12 << 12 + x12 x30 = x24 << 6 + _111111 x31 = 2*x30 + 1 x32 = 2*x31 + 1 x63 = x32 << 31 + x31 x126 = x63 << 63 + x63 x252 = x126 << 126 + x126 x255 = x252 << 3 + _111 return ((x255 << 33 + x32) << 94 + x30) << 2 addchain-0.4.0/internal/results/testdata/p384_scalar.golden000066400000000000000000000022341514305256600236210ustar00rootroot00000000000000_10 = 2*1 _11 = 1 + _10 _101 = _10 + _11 _111 = _10 + _101 _1001 = _10 + _111 _1011 = _10 + _1001 _1101 = _10 + _1011 _1111 = _10 + _1101 _11110 = 2*_1111 _11111 = 1 + _11110 _1111100 = _11111 << 2 i14 = _1111100 << 2 i26 = (i14 << 3 + _1111100) << 7 + i14 i42 = i26 << 15 + i26 x64 = i42 << 30 + i42 + _1111 x128 = x64 << 64 + x64 x192 = x128 << 64 + x64 x194 = x192 << 2 + _11 i225 = ((x194 << 6 + _111) << 3 + _11) << 7 i235 = 2*((_1101 + i225) << 6 + _1101) + 1 i258 = ((i235 << 11 + _11111) << 2 + 1) << 8 i269 = ((_1101 + i258) << 2 + _11) << 6 + _1011 i286 = ((i269 << 4 + _111) << 6 + _11111) << 5 i308 = ((_1011 + i286) << 10 + _1101) << 9 + _1101 i323 = ((i308 << 4 + _1011) << 6 + _1001) << 3 i340 = ((1 + i323) << 7 + _1011) << 7 + _101 i357 = ((i340 << 5 + _111) << 5 + _1111) << 5 i369 = ((_1011 + i357) << 4 + _1011) << 5 + _111 i387 = ((i369 << 3 + _11) << 7 + _11) << 6 i397 = ((_1011 + i387) << 4 + _101) << 3 + _11 i413 = ((i397 << 4 + _11) << 4 + _11) << 6 i427 = ((_101 + i413) << 5 + _101) << 6 + _1011 return (2*i427 + 1) << 4 + 1 addchain-0.4.0/internal/results/testdata/p41417_field.golden000066400000000000000000000005611514305256600236020ustar00rootroot00000000000000_10 = 2*1 _11 = 1 + _10 _1100 = _11 << 2 _1111 = _11 + _1100 _111100 = _1111 << 2 _111111 = _11 + _111100 x12 = _111111 << 6 + _111111 x24 = x12 << 12 + x12 x48 = x24 << 24 + x24 x96 = x48 << 48 + x48 x192 = x96 << 96 + x96 x384 = x192 << 192 + x192 x408 = x384 << 24 + x24 x409 = 2*x408 + 1 return (x409 << 3 + _11) << 2 + 1 addchain-0.4.0/internal/results/testdata/p511187_field.golden000066400000000000000000000007571514305256600236770ustar00rootroot00000000000000_10 = 2*1 _11 = 1 + _10 _1100 = _11 << 2 _1111 = _11 + _1100 _111100 = _1111 << 2 _111111 = _11 + _111100 _11111100 = _111111 << 2 _11111111 = _11 + _11111100 x16 = _11111111 << 8 + _11111111 x22 = x16 << 6 + _111111 x30 = x22 << 8 + _11111111 x60 = x30 << 30 + x30 x120 = x60 << 60 + x60 x240 = x120 << 120 + x120 x480 = x240 << 240 + x240 x502 = x480 << 22 + x22 x503 = 2*x502 + 1 return (x503 << 2 + 1) << 6 + _11 addchain-0.4.0/internal/results/testdata/secp192k1_field.golden000066400000000000000000000006541514305256600243670ustar00rootroot00000000000000_10 = 2*1 _11 = 1 + _10 _101 = _10 + _11 _111 = _10 + _101 _11100 = _111 << 2 _11111 = _11 + _11100 _1111100 = _11111 << 2 _1111111 = _11 + _1111100 i15 = _1111111 << 5 x19 = i15 << 7 + i15 + _11111 i31 = x19 << 7 i51 = i31 << 19 + i31 i90 = i51 << 38 + i51 x159 = i90 << 76 + i90 + _1111111 i199 = ((x159 << 20 + x19) << 4 + _111) << 5 return (_11 + i199) << 4 + _101 addchain-0.4.0/internal/results/testdata/secp224k1_field.golden000066400000000000000000000006631514305256600243630ustar00rootroot00000000000000_100 = 1 << 2 _101 = 1 + _100 _10100 = _101 << 2 _10101 = 1 + _10100 _101010 = 2*_10101 _111111 = _10101 + _101010 _1111110 = 2*_111111 x12 = _1111110 << 5 + _111111 x19 = x12 << 7 + _1111110 + 1 i25 = 2*x19 i45 = i25 << 19 + i25 x57 = i45 << 18 + x19 i104 = x57 << 39 + i45 x191 = i104 << 95 + i104 + 1 i235 = ((x191 << 20 + x19) << 7 + _10101) << 5 return 2*(_10101 + i235) + 1 addchain-0.4.0/internal/results/testdata/secp256k1_field.golden000066400000000000000000000006771514305256600243750ustar00rootroot00000000000000_10 = 2*1 _11 = 1 + _10 _1100 = _11 << 2 _1111 = _11 + _1100 _11110 = 2*_1111 _11111 = 1 + _11110 _1111100 = _11111 << 2 _1111111 = _11 + _1111100 x11 = _1111111 << 4 + _1111 x22 = x11 << 11 + x11 x27 = x22 << 5 + _11111 x54 = x27 << 27 + x27 x108 = x54 << 54 + x54 x216 = x108 << 108 + x108 x223 = x216 << 7 + _1111111 i266 = ((x223 << 23 + x22) << 5 + 1) << 3 return (_11 + i266) << 2 addchain-0.4.0/internal/results/testdata/secp256k1_scalar.golden000066400000000000000000000017741514305256600245560ustar00rootroot00000000000000_10 = 2*1 _11 = 1 + _10 _101 = _10 + _11 _111 = _10 + _101 _1001 = _10 + _111 _1011 = _10 + _1001 _1101 = _10 + _1011 _110100 = _1101 << 2 _111111 = _1011 + _110100 _1111110 = 2*_111111 _1111111 = 1 + _1111110 _11111110 = 2*_1111111 _11111111 = 1 + _11111110 i17 = _11111111 << 3 i19 = i17 << 2 i21 = i19 << 2 i39 = (i21 << 6 + i19) << 10 + i21 x63 = (i39 << 4 + i17) << 28 + i39 + _1111111 x64 = 2*x63 + 1 x127 = x64 << 63 + x63 i154 = ((x127 << 5 + _1011) << 3 + _101) << 4 i166 = ((_101 + i154) << 4 + _111) << 5 + _1101 i181 = ((i166 << 2 + _11) << 5 + _111) << 6 i193 = ((_1101 + i181) << 5 + _1011) << 4 + _1101 i214 = ((i193 << 3 + 1) << 6 + _101) << 10 i230 = ((_111 + i214) << 4 + _111) << 9 + _11111111 i247 = ((i230 << 5 + _1001) << 6 + _1011) << 4 i261 = ((_1101 + i247) << 5 + _11) << 6 + _1101 i283 = ((i261 << 10 + _1101) << 4 + _1001) << 6 return (1 + i283) << 8 + _111111 addchain-0.4.0/internal/test/000077500000000000000000000000001514305256600160505ustar00rootroot00000000000000addchain-0.4.0/internal/test/doc.go000066400000000000000000000000711514305256600171420ustar00rootroot00000000000000// Package test provides testing utilities. package test addchain-0.4.0/internal/test/golden.go000066400000000000000000000006441514305256600176530ustar00rootroot00000000000000package test import ( "flag" "path/filepath" ) // Flags controlling whether to write testdata files. var golden = flag.Bool("golden", false, "write golden testdata files") // Golden reports whether to write golden testdata files. func Golden() bool { return *golden } // GoldenName returns a path to the named golden file. func GoldenName(name string) string { return filepath.Join("testdata", name+".golden") } addchain-0.4.0/internal/test/trials.go000066400000000000000000000033431514305256600177000ustar00rootroot00000000000000package test import ( "flag" "testing" "time" ) // Custom test command line flags. var ( long = flag.Bool("long", false, "enable long running tests") stress = flag.Bool("stress", false, "enable stress tests (implies -long)") ) // timeallowed returns how long a single test is allowed to take. func timeallowed() time.Duration { switch { case testing.Short(): return time.Second / 10 case *long: return 30 * time.Second case *stress: return 2 * time.Minute default: return time.Second } } // Long reports whether long tests are enabled. func Long() bool { return *long || *stress } // Stress reports whether stress tests are enabled. func Stress() bool { return *stress } // RequireLong marks this test as a long test. Test will be skipped if long // tests are not enabled. func RequireLong(t *testing.T) { if !Long() { t.Skipf("long test: use -long or -stress to enable") } } // RequireStress marks this test as a stress test. Test will be skipped if stress // tests are not enabled. func RequireStress(t *testing.T) { if !Stress() { t.Skipf("stress test: use -stress to enable") } } // Repeat the given trial function. The duration is controlled by custom // command-line flags. The trial function returns whether it wants to continue // testing. // // -short run for less time than usual // -long allow more time // -stress run for an extremely long time func Repeat(t *testing.T, trial func(t *testing.T) bool) { start := time.Now() d := timeallowed() n := 1 for time.Since(start) < d && trial(t) { n++ } t.Logf("%d trials in %s", n, time.Since(start)) } // Trials returns a function that repeats f. func Trials(f func(t *testing.T) bool) func(t *testing.T) { return func(t *testing.T) { Repeat(t, f) } } addchain-0.4.0/internal/tools/000077500000000000000000000000001514305256600162315ustar00rootroot00000000000000addchain-0.4.0/internal/tools/docgen/000077500000000000000000000000001514305256600174705ustar00rootroot00000000000000addchain-0.4.0/internal/tools/docgen/bibliography.tmpl000066400000000000000000000005201514305256600230360ustar00rootroot00000000000000// Code generated by bib. DO NOT EDIT. package main var bibliography = []struct{ CiteName string URL string Formatted string }{ {{ range .Entries }} { CiteName: {{ printf "%q" .CiteName }}, URL: {{ printf "%q" .Fields.url }}, Formatted: {{ printf "%q" .Formatted }}, }, {{ end }} } addchain-0.4.0/internal/tools/docgen/main.go000066400000000000000000000132531514305256600207470ustar00rootroot00000000000000package main import ( "bufio" "bytes" "embed" "errors" "flag" "fmt" "io/ioutil" "log" "net/url" "os" "path" "path/filepath" "regexp" "strings" "text/template" "github.com/mmcloughlin/addchain/internal/gen" "github.com/mmcloughlin/addchain/internal/results" "github.com/mmcloughlin/addchain/meta" ) //go:generate bib generate -bib ../../../doc/references.bib -tmpl bibliography.tmpl -output zbibliography.go func main() { log.SetPrefix("docgen: ") log.SetFlags(0) if err := mainerr(); err != nil { log.Fatal(err) } } var ( typ = flag.String("type", "", "documentation type") tmpl = flag.String("tmpl", "", "explicit template file (overrides -type)") output = flag.String("output", "", "path to output file (default stdout)") tocmin = flag.Int("tocmin", 2, "table of contents minimum heading level") tocmax = flag.Int("tocmax", 4, "table of contents maximum heading level") ) func mainerr() (err error) { flag.Parse() // Initialize template. t := template.New("doc") t.Funcs(template.FuncMap{ "link": rellink(*output), "include": include, "snippet": snippet, "anchor": anchor, "bibentry": bibentry, "biburl": biburl, "toc": toc, "oplus": symbol('\u2295'), "otimes": symbol('\u2297'), "sum": symbol('\u2211'), }) t.Funcs(pkgfuncs("", meta.Meta.Module())) t.Funcs(pkgfuncs("std", "")) // Load template. s, err := load() if err != nil { return err } if _, err := t.Parse(s); err != nil { return err } // Prepare template data. data := map[string]interface{}{ "Meta": meta.Meta, "Results": results.Results, "Bibliography": bibliography, "BuiltinTemplateNames": gen.BuiltinTemplateNames(), "TemplateFunctions": gen.Functions, } // Execute. var buf bytes.Buffer if err := t.Execute(&buf, data); err != nil { return err } // Insert table of contents. body, err := generateTOC(buf.Bytes(), *tocmin, *tocmax) if err != nil { return err } // Output. if *output != "" { err = ioutil.WriteFile(*output, body, 0640) } else { _, err = os.Stdout.Write(body) } if err != nil { return err } return nil } //go:embed templates var templates embed.FS // load template. func load() (string, error) { // Prefer explicit filename, if provided. if *tmpl != "" { b, err := ioutil.ReadFile(*tmpl) if err != nil { return "", err } return string(b), nil } // Otherwise expect a named type. if *typ == "" { return "", errors.New("missing documentation type") } path := fmt.Sprintf("templates/%s.tmpl", *typ) b, err := templates.ReadFile(path) if err != nil { return "", fmt.Errorf("unknown documentation type %q", *typ) } return string(b), nil } // link to a file in the repository. func rellink(output string) func(string) (string, error) { base := filepath.Dir(output) return func(filename string) (string, error) { if _, err := os.Stat(filename); err != nil { return "", err } return filepath.Rel(base, filename) } } // include template function. func include(filename string) (string, error) { b, err := ioutil.ReadFile(filename) if err != nil { return "", err } return string(b), nil } // snippet of a file between start and end regular expressions. func snippet(filename, start, end string) (string, error) { // Parse regular expressions. startx, err := regexp.Compile(start) if err != nil { return "", err } endx, err := regexp.Compile(end) if err != nil { return "", err } // Read the full file. data, err := include(filename) if err != nil { return "", err } // Collect matched lines. var buf bytes.Buffer output := false s := bufio.NewScanner(strings.NewReader(data)) for s.Scan() { line := s.Text() if startx.MatchString(line) { output = true } if output { fmt.Fprintln(&buf, line) } if endx.MatchString(line) { output = false } } return buf.String(), nil } // anchor returns the anchor for a heading in Github. func anchor(heading string) string { r := strings.NewReplacer(" ", "-", "(", "", ")", "", "/", "") return r.Replace(strings.ToLower((heading))) } // pkgfuncs builds template functions for references to packages linked to // documentation. func pkgfuncs(prefix, mod string) template.FuncMap { return template.FuncMap{ // pkgurl returns url to package documentation. prefix + "pkgurl": func(pkg string) string { return pkgurl(mod, pkg, "") }, // pkg returns markdown for a package with a link to documentation. prefix + "pkg": func(pkg string) string { return fmt.Sprintf("[`%s`](%s)", pkg, pkgurl(mod, pkg, "")) }, // sym returns markdown for a symbol with a link to documentation. prefix + "sym": func(pkg, name string) string { return fmt.Sprintf("[`%s.%s`](%s)", path.Base(pkg), name, pkgurl(mod, pkg, name)) }, } } // pkgurl returns url to go.dev documentation for a given package. func pkgurl(mod, pkg, fragment string) string { u := url.URL{ Scheme: "https", Host: "pkg.go.dev", Path: path.Join(mod, pkg), Fragment: fragment, } return u.String() } // bibentry returns formatted bibliography entry for the given citation name. func bibentry(name string) (string, error) { for _, entry := range bibliography { if entry.CiteName == name { return entry.Formatted, nil } } return "", fmt.Errorf("unknown citation %q", name) } // biburl returns URL for the bibliography entry with the given citation name. func biburl(name string) (string, error) { for _, entry := range bibliography { if entry.CiteName == name { return entry.URL, nil } } return "", fmt.Errorf("unknown citation %q", name) } // symbol builds a template function that expands to the given unicode symbol. func symbol(r rune) func() string { return func() string { return string([]rune{r}) } } addchain-0.4.0/internal/tools/docgen/templates/000077500000000000000000000000001514305256600214665ustar00rootroot00000000000000addchain-0.4.0/internal/tools/docgen/templates/bibtex.tmpl000066400000000000000000000000261514305256600236370ustar00rootroot00000000000000{{ .Meta.Citation -}} addchain-0.4.0/internal/tools/docgen/templates/cff.tmpl000066400000000000000000000012551514305256600231250ustar00rootroot00000000000000cff-version: 1.2.0 message: "If you use addchain in your work, a citation would be appreciated using the following metadata." title: "{{ .Meta.Title }}" authors: - family-names: "McLoughlin" given-names: "Michael Ben" orcid: "https://orcid.org/0000-0003-2347-6258" version: "{{ .Meta.ReleaseVersion }}" date-released: "{{ .Meta.ReleaseDate }}" license: BSD-3-Clause repository-code: {{ .Meta.RepositoryURL }} doi: "{{ .Meta.DOI }}" identifiers: - type: doi value: "{{ .Meta.ConceptDOI }}" description: "The concept DOI of the work." - type: doi value: "{{ .Meta.DOI }}" description: "The versioned DOI for version {{ .Meta.ReleaseVersion }} of the work." addchain-0.4.0/internal/tools/docgen/templates/gen.tmpl000066400000000000000000000057231514305256600231440ustar00rootroot00000000000000# Output Generation {{ toc }} {{- $templatereference := "Template Reference" -}} {{- $builtins := "Builtin Templates" }} ## Example Let's show an example of generating code for curve25519 field inversion. Search for the best addition chain and save the result: ```sh {{ include "internal/examples/fp25519/00-search.sh" -}} ``` Now we can use the `{{ .Meta.Name }}` generate command to generate code to execute the addition chain. By default, the generate command will show us a concise listing of the instructions required to compute the addition chain. ```sh {{ include "internal/examples/fp25519/01-listing.sh" -}} ``` Output: ``` {{ include "internal/examples/fp25519/01-listing.out" -}} ``` This listing is intended to be a simple text format that could directly be turned into code. The directives mean: * `tmp v ...`: declare temporary variables `v ...` * `add z x y`: execute addition `z = x+y` * `double z x`: execute doubling `z = 2*x` * `shift z x n`: execute repeated doubling z = 2n*x Under the hood, `{{ .Meta.Name }}` has processed the addition chain into the {{ sym "acc/ir" "Program" }} intermediate representation and used an allocation pass to assign the minimum number of temporary variables. The listing format is intended be a convient and easy-to-parse text format to use as input to other tools. In addition, `{{ .Meta.Name }}` also offers templated output. In fact, the listing is actually produced by the [listing](#listing) builtin template. See below for details of the [templating language](#{{ anchor $templatereference }}) and [builtin template examples](#{{ anchor $builtins }}). The following template can be used to directly produce Go code to execute the inversion chain: ``` {{ include "internal/examples/fp25519/inv.tmpl" -}} ``` Generate code by passing the template to `{{ .Meta.Name }}`: ```sh {{ include "internal/examples/fp25519/02-generate.sh" -}} ``` The end product: ```go {{ include "internal/examples/fp25519/inv.go" -}} ``` This code is part of a [full working example]({{ link "internal/examples/fp25519" }}) that passes tests. ## {{ $templatereference }} Templates use Go {{ stdpkg "text/template" }} syntax. The data structure passed to the template is: ```go {{ snippet "internal/gen/gen.go" "type Data" "^}" -}} ``` In addition to the [builtin functions]({{ stdpkgurl "text/template" }}#hdr-Functions), templates may use: | Name | Signature | Description | | ---- | --------- | ----------- | {{ range .TemplateFunctions -}} | **`{{ .Name }}`** | `{{ .Signature }}` | {{ .Description }} | {{ end }} ## {{ $builtins }} Example output for each builtin template is generated from the chain: ``` {{ include "internal/gen/testdata/input.acc" -}} ``` {{ range .BuiltinTemplateNames }} ### {{ . }} ``` {{ include (printf "internal/gen/templates/%s.tmpl" .) -}} ```
Output of {{ . }} template ``` {{ include (printf "internal/gen/testdata/builtin/%s.golden" .) -}} ```
{{ end }} addchain-0.4.0/internal/tools/docgen/templates/readme.tmpl000066400000000000000000000323761514305256600236340ustar00rootroot00000000000000

addchain
Build Status go.dev Go Report Card DOI: {{ .Meta.DOI }}

{{ .Meta.Description }}

`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 {{ toc }} ## 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]({{ biburl "curvechains" }}), and the delta from the library result. | Name | This Library | Best Known | Delta | | ---- | -----------: | ---------: | ----: | {{ range .Results -}} {{- if gt .BestKnown 0 -}} | [{{ .Name }}]({{ link "doc/results.md" }}#{{ anchor .Name }}) | {{ .Length }} | {{ .BestKnown }} | {{ if le .Delta 0 }}**{{ printf "%+d" .Delta }}**{{ else }}{{ printf "%+d" .Delta }}{{ end }} | {{ end -}} {{ end }} See [full results listing]({{ link "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]({{ .Meta.RepositoryURL }}/releases): ``` curl -sSfL https://git.io/addchain | sh -s -- -b /usr/local/bin ``` Alternatively build from source: ``` go install {{ .Meta.Module }}/cmd/addchain@latest ``` Search for a curve25519 field inversion addition chain with: ```sh {{ include "internal/examples/search/cmd.sh" -}} ``` Output: ``` {{ include "internal/examples/search/cmd.out" -}} ``` Next, you can [generate code from this addition chain]({{ link "doc/gen.md" }}). ### Library Install: ``` go get -u {{ .Meta.Module }} ``` Algorithms all conform to the {{ sym "alg" "ChainAlgorithm" }} or {{ sym "alg" "SequenceAlgorithm" }} interfaces and can be used directly. However the most user-friendly method uses the {{ pkg "alg/ensemble" }} package to instantiate a sensible default set of algorithms and the {{ pkg "alg/exec" }} helper to execute them in parallel. The following code uses this method to find an addition chain for curve25519 field inversion: ```go {{ snippet "alg/exec/example_test.go" "func Example" "^}" -}} ``` ## 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 {{ pkg "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 {{ pkg "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) {{ otimes }} (1,..., n/k) {{ oplus }} (n mod k). ``` for certain special operators {{ otimes }} and {{ oplus }}. 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 {{ pkg "alg/contfrac" }} package provides a laundry list of strategies from the literature: binary, co-binary, dichotomic, dyadic, fermat, square-root and total. #### References * {{ bibentry "contfrac" }} * {{ bibentry "efficientcompaddchain" }} * {{ bibentry "gencontfrac" }} * {{ bibentry "hehcc:exp" }} ### 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]({{ biburl "boscoster" }}) defined four heuristics: Approximation, Divison, Halving and Lucas. Package {{ pkg "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]({{ .Meta.RepositoryURL }}/issues/26). #### References * {{ bibentry "boscoster" }} * {{ bibentry "github:kwantam/addchain" }} * {{ bibentry "hehcc:exp" }} * {{ bibentry "modboscoster" }} * {{ bibentry "mpnt" }} * {{ bibentry "speedsubgroup" }} ### 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 = {{ sum }} 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 {{ pkg "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 * {{ bibentry "braueraddsubchains" }} * {{ bibentry "genshortchains" }} * {{ bibentry "hehcc:exp" }} ### 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 {{ sym "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 {{ pkg "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]({{ .Meta.RepositoryURL }}/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]({{ .Meta.ConceptDOIURL }}) and assigned a DOI. Please use the following BibTeX to cite the most recent [{{ .Meta.ReleaseVersion }} release]({{ .Meta.ReleaseURL }}). ```bib {{ .Meta.Citation -}} ``` If you need to cite a currently unreleased version please consider [filing an issue]({{ .Meta.RepositoryURL }}/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]({{ .Meta.RepositoryURL }}/issues/new) to the issues page. * Suggest [test cases]({{ .Meta.RepositoryURL }}/blob/e6c070065205efcaa02627ab1b23e8ce6aeea1db/internal/results/results.go#L62) or update best-known hand-optimized results. * Pull requests accepted. Please discuss in the [issues section]({{ .Meta.RepositoryURL }}/issues) before starting significant work. ## License `addchain` is available under the [BSD 3-Clause License](LICENSE). addchain-0.4.0/internal/tools/docgen/templates/results.tmpl000066400000000000000000000010451514305256600240650ustar00rootroot00000000000000# Results {{ range .Results -}} * [{{ .Name }}](#{{ anchor .Name }}) {{ end }} {{ range .Results -}} ## {{ .Name }} | Property | Value | | --- | ----- | | _N_ | `{{ .N.String }}` | | _d_ | `{{ .D }}` | | _N_-_d_ | `{{ printf "%x" .Target }}` | | Length | {{ .Length }} | | Algorithm | `{{ .AlgorithmName }}` | {{- if gt .BestKnown 0 }} | Best Known | {{ .BestKnown }} | | Delta | {{ printf "%+d" .Delta }} | {{ end }} Addition chain produced by `addchain`: ```go {{ include (printf "internal/results/testdata/%s.golden" .Slug) }}``` {{ end }} addchain-0.4.0/internal/tools/docgen/templates/zenodo.tmpl000066400000000000000000000015031514305256600236610ustar00rootroot00000000000000{ "title": "{{ .Meta.FullName }}: {{ .Meta.ReleaseTag }}", "description": "{{ .Meta.Description }}", "version": "{{ .Meta.ReleaseVersion }}", "publication_date": "{{ .Meta.ReleaseDate }}", "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/{{ .Meta.ReleaseTag }}", "relation": "isSupplementTo", "scheme": "url" } ], "references": [ {{ range $i, $entry := .Bibliography -}} {{- if $i }}, {{ end -}} {{- printf "%q" $entry.Formatted -}} {{- end }} ] } addchain-0.4.0/internal/tools/docgen/toc.go000066400000000000000000000031031514305256600206010ustar00rootroot00000000000000package main import ( "bufio" "bytes" "fmt" "io" "regexp" "strings" ) // tocMarker is a marker placed in the output to indicate where the table of // contents should be inserted. const tocMarker = `` // heading in a markdown file. type heading struct { level int text string } var headingx = regexp.MustCompile(`^(#+)\s+(.+)$`) // headings extracts headings from the markdown stream. func headings(r io.Reader) ([]heading, error) { var hs []heading s := bufio.NewScanner(r) for s.Scan() { match := headingx.FindStringSubmatch(s.Text()) if match != nil { hs = append(hs, heading{ level: len(match[1]), text: match[2], }) } } if err := s.Err(); err != nil { return nil, err } return hs, nil } // generateTOC inserts a table of contents into body. Table of contents includes // headings with the given range of levels. func generateTOC(body []byte, minlevel, maxlevel int) ([]byte, error) { r := bytes.NewReader(body) // Extract headings. hs, err := headings(r) if err != nil { return nil, err } // Build table of contents. var buf bytes.Buffer fmt.Fprint(&buf, "## Table of Contents\n\n") for _, h := range hs { if h.level >= minlevel && h.level <= maxlevel { indent := strings.Repeat(" ", h.level-minlevel) fmt.Fprintf(&buf, "%s* [%s](#%s)\n", indent, h.text, anchor(h.text)) } } // Replace marker. body = bytes.ReplaceAll(body, []byte(tocMarker), buf.Bytes()) return body, nil } // toc is a template function that leaves a marker which can later be replaced. func toc() string { return tocMarker } addchain-0.4.0/internal/tools/docgen/zbibliography.go000066400000000000000000000214641514305256600226730ustar00rootroot00000000000000// Code generated by bib. DO NOT EDIT. package main var bibliography = []struct{ CiteName string URL string Formatted string }{ { CiteName: "addchainreview", URL: "https://thescipub.com/pdf/10.3844/jcssp.2017.275.289.pdf", Formatted: "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", }, { CiteName: "aranha", URL: "https://eprint.iacr.org/2013/647", Formatted: "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", }, { CiteName: "boscoster", URL: "https://link.springer.com/content/pdf/10.1007/0-387-34805-0_37.pdf", Formatted: "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", }, { CiteName: "braueraddsubchains", URL: "http://www.martin-otto.de/publications/docs/2001_MartinOtto_Diplom_BrauerAddition-SubtractionChains.pdf", Formatted: "Martin Otto. Brauer addition-subtraction chains. PhD thesis, Universitat Paderborn. 2001. http://www.martin-otto.de/publications/docs/2001_MartinOtto_Diplom_BrauerAddition-SubtractionChains.pdf", }, { CiteName: "contfrac", URL: "http://www-igm.univ-mlv.fr/~berstel/Articles/1989AdditionChainDuboc.pdf", Formatted: "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", }, { CiteName: "crandallprime", URL: "https://patents.google.com/patent/US5159632A", Formatted: "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", }, { CiteName: "curve25519", URL: "https://cr.yp.to/ecdh/curve25519-20060209.pdf", Formatted: "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", }, { CiteName: "curvechains", URL: "https://briansmith.org/ecc-inversion-addition-chains-01", Formatted: "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)", }, { CiteName: "efficientcompaddchain", URL: "http://www.numdam.org/item/JTNB_1994__6_1_21_0", Formatted: "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", }, { CiteName: "elligator", URL: "https://eprint.iacr.org/2013/325", Formatted: "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", }, { CiteName: "fips186-2", URL: "https://csrc.nist.gov/csrc/media/publications/fips/186/2/archive/2000-01-27/documents/fips186-2.pdf", Formatted: "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", }, { CiteName: "gencontfrac", URL: "https://eprint.iacr.org/2013/466", Formatted: "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", }, { CiteName: "genshortchains", URL: "https://pdfs.semanticscholar.org/b398/d10faca35af9ce5a6026458b251fd0a5640c.pdf", Formatted: "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", }, { CiteName: "github:kwantam/addchain", URL: "https://github.com/kwantam/addchain", Formatted: "Riad S. Wahby. kwantam/addchain. Github Repository. Apache License, Version 2.0. 2018. https://github.com/kwantam/addchain", }, { CiteName: "goldilocks", URL: "https://eprint.iacr.org/2015/625", Formatted: "Mike Hamburg. Ed448-Goldilocks, a new elliptic curve. Cryptology ePrint Archive, Report 2015/625. 2015. https://eprint.iacr.org/2015/625", }, { CiteName: "hashbls12-381", URL: "https://eprint.iacr.org/2019/403", Formatted: "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", }, { CiteName: "hehcc:exp", URL: "http://koclab.cs.ucsb.edu/teaching/ecc/eccPapers/Doche-ch09.pdf", Formatted: "Christophe Doche. Exponentiation. Handbook of Elliptic and Hyperelliptic Curve Cryptography, chapter 9. 2006. http://koclab.cs.ucsb.edu/teaching/ecc/eccPapers/Doche-ch09.pdf", }, { CiteName: "knuth", URL: "https://www-cs-faculty.stanford.edu/~knuth/taocp.html", Formatted: "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", }, { CiteName: "modboscoster", URL: "http://library.isical.ac.in:8080/jspui/bitstream/10263/6441/1/DISS-285.pdf", Formatted: "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", }, { CiteName: "mpnt", URL: "https://profs.info.uaic.ro/~tr/tr03-02.pdf", Formatted: "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", }, { CiteName: "nistdanger", URL: "https://cr.yp.to/talks/2013.09.16/slides-djb-20130916-a4.pdf", Formatted: "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", }, { CiteName: "pairingsfinalexp", URL: "https://eprint.iacr.org/2008/490", Formatted: "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", }, { CiteName: "safecurves", URL: "https://safecurves.cr.yp.to", Formatted: "Daniel J. Bernstein and Tanja Lange. SafeCurves: choosing safe curves for elliptic-curve cryptography. https://safecurves.cr.yp.to", }, { CiteName: "sec2", URL: "https://safecurves.cr.yp.to/www.secg.org/sec2-v2.pdf", Formatted: "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", }, { CiteName: "solinasprime", URL: "http://cacr.uwaterloo.ca/techreports/1999/corr99-39.pdf", Formatted: "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", }, { CiteName: "speedsubgroup", URL: "https://cr.yp.to/bib/2003/stam-thesis.pdf", Formatted: "Stam, Martijn. Speeding up subgroup cryptosystems. PhD thesis, Technische Universiteit Eindhoven. 2003. https://cr.yp.to/bib/2003/stam-thesis.pdf", }, } addchain-0.4.0/internal/tools/release/000077500000000000000000000000001514305256600176515ustar00rootroot00000000000000addchain-0.4.0/internal/tools/release/bump.go000066400000000000000000000022671514305256600211520ustar00rootroot00000000000000package main import ( "context" "flag" "time" "github.com/google/subcommands" "github.com/mmcloughlin/addchain/internal/cli" ) // bump subcommand. type bump struct { cli.Command varsfile VarsFile releasedate string } func (*bump) Name() string { return "bump" } func (*bump) Synopsis() string { return "bump version" } func (*bump) Usage() string { return `Usage: bump Bump version and update related files. ` } func (cmd *bump) SetFlags(f *flag.FlagSet) { cmd.varsfile.SetFlags(f) f.StringVar(&cmd.releasedate, "date", time.Now().UTC().Format("2006-01-02"), "release date") } func (cmd *bump) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus { // Read arguments. if f.NArg() < 1 { return cmd.UsageError("missing version argument") } version := f.Arg(0) if err := ValidateVersion(version); err != nil { return cmd.Error(err) } // Set the version meta variable. if err := cmd.varsfile.Set("releaseversion", version); err != nil { return cmd.Error(err) } // Set the release date. if err := cmd.varsfile.Set("releasedate", cmd.releasedate); err != nil { return cmd.Error(err) } return subcommands.ExitSuccess } addchain-0.4.0/internal/tools/release/check.go000066400000000000000000000034371514305256600212640ustar00rootroot00000000000000package main import ( "context" "flag" "time" "github.com/google/subcommands" "github.com/mmcloughlin/addchain/internal/cli" ) // check subcommand. type check struct { cli.Command httpclient HTTPClient zenodo Zenodo varsfile VarsFile } func (*check) Name() string { return "check" } func (*check) Synopsis() string { return "check release is ready to be tagged" } func (*check) Usage() string { return `Usage: check Perform some final checks to confirm release can be tagged. ` } func (cmd *check) SetFlags(f *flag.FlagSet) { cmd.httpclient.SetFlags(f) cmd.zenodo.SetFlags(f) cmd.varsfile.SetFlags(f) } func (cmd *check) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus { // Validate the version field. version, err := cmd.varsfile.Get("releaseversion") if err != nil { return cmd.Error(err) } if err := ValidateVersion(version); err != nil { return cmd.Error(err) } // Check the release date. releasedate, err := cmd.varsfile.Get("releasedate") if err != nil { return cmd.Error(err) } if _, err := time.Parse("2006-01-02", releasedate); err != nil { return cmd.Fail("release date should be in format YYYY-MM-DD") } // Check that a Zenodo deposit has been allocated. httpclient, err := cmd.httpclient.Client() if err != nil { return cmd.Error(err) } client, err := cmd.zenodo.Client(httpclient) if err != nil { return cmd.Error(err) } id, err := cmd.varsfile.Get("zenodoid") if err != nil { return cmd.Error(err) } d, err := client.DepositionRetrieve(ctx, id) if err != nil { return cmd.Error(err) } if d.State != "unsubmitted" { return cmd.Fail("zenodo deposit in %q state", d.State) } if d.Submitted { return cmd.Fail("zenodo deposit has been published") } return subcommands.ExitSuccess } addchain-0.4.0/internal/tools/release/flags.go000066400000000000000000000071661514305256600213060ustar00rootroot00000000000000package main import ( "crypto/tls" "crypto/x509" "errors" "flag" "fmt" "io/ioutil" "net/http" "os" "github.com/mmcloughlin/addchain/internal/metavars" "github.com/mmcloughlin/addchain/internal/zenodo" ) // VarsFile represents a meta variables file. type VarsFile struct { path string } // SetFlags registers command-line flags to configure the meta variables file. func (v *VarsFile) SetFlags(f *flag.FlagSet) { f.StringVar(&v.path, "vars", v.DefaultPath(), "path to meta variables file") } // DefaultPath returns the path to the default variables file in the meta // package. Returns the empty string if the path cannot be determined. func (v *VarsFile) DefaultPath() string { return RepoPath("meta/vars.go") } // Get variable from the meta variables file. func (v *VarsFile) Get(name string) (string, error) { f, err := metavars.ReadFile(v.path) if err != nil { return "", err } value, ok := f.Get(name) if !ok { return "", fmt.Errorf("unknown property %q", name) } return value, nil } // Set variable in the meta variables file. func (v *VarsFile) Set(name, value string) error { f, err := metavars.ReadFile(v.path) if err != nil { return err } if err := f.Set(name, value); err != nil { return err } if err := metavars.WriteFile(v.path, f); err != nil { return err } return nil } // Zenodo configures a zenodo client. type Zenodo struct { base string sandbox bool token string } const zenodoTokenEnvVar = "ZENODO_TOKEN" // SetFlags registers command-line flags to configure the zenodo client. func (z *Zenodo) SetFlags(f *flag.FlagSet) { f.StringVar(&z.base, "url", zenodo.BaseURL, "zenodo api base url") f.BoolVar(&z.sandbox, "sandbox", false, "use zenodo sandbox") f.StringVar(&z.token, "token", "", fmt.Sprintf("zenodo token (uses %q environment variable if empty)", zenodoTokenEnvVar)) } // Token returns the configured zenodo token, either from the command-line or // environment variable. func (z *Zenodo) Token() (string, error) { if z.token != "" { return z.token, nil } if token, ok := os.LookupEnv(zenodoTokenEnvVar); ok { return token, nil } return "", errors.New("zenodo token not specified") } // URL to connect to. func (z *Zenodo) URL() string { if z.sandbox { return zenodo.SandboxBaseURL } return z.base } // Client builds the configured client. func (z *Zenodo) Client(c *http.Client) (*zenodo.Client, error) { // Token. token, err := z.Token() if err != nil { return nil, err } // Zenodo client. return zenodo.NewClient(c, z.URL(), token), nil } // HTTPClient configures a HTTP client. type HTTPClient struct { cert string } // SetFlags registers command-line flags to configure the HTTP client. func (h *HTTPClient) SetFlags(f *flag.FlagSet) { f.StringVar(&h.cert, "cert", "", "trust additional certificate authority certificate") } // Client builds a HTTP client according to configuration. func (h *HTTPClient) Client() (*http.Client, error) { // CAs. roots, err := h.RootCAs() if err != nil { return nil, err } // Transport. tr := &http.Transport{ Proxy: http.ProxyFromEnvironment, TLSClientConfig: &tls.Config{ MinVersion: tls.VersionTLS12, RootCAs: roots, }, } // Client. return &http.Client{ Transport: tr, }, nil } // RootCAs returns the configured certificate pool. func (h *HTTPClient) RootCAs() (*x509.CertPool, error) { roots, err := x509.SystemCertPool() if err != nil { return nil, err } if h.cert == "" { return roots, nil } data, err := ioutil.ReadFile(h.cert) if err != nil { return nil, err } cert, err := x509.ParseCertificate(data) if err != nil { return nil, err } roots.AddCert(cert) return roots, nil } addchain-0.4.0/internal/tools/release/main.go000066400000000000000000000010171514305256600211230ustar00rootroot00000000000000package main import ( "context" "flag" "os" "github.com/google/subcommands" "github.com/mmcloughlin/addchain/internal/cli" ) func main() { base := cli.NewBaseCommand("release") subcommands.Register(&bump{Command: base}, "") subcommands.Register(&reservedoi{Command: base}, "") subcommands.Register(&check{Command: base}, "") subcommands.Register(&upload{Command: base}, "") subcommands.Register(subcommands.HelpCommand(), "") flag.Parse() ctx := context.Background() os.Exit(int(subcommands.Execute(ctx))) } addchain-0.4.0/internal/tools/release/reservedoi.go000066400000000000000000000031741514305256600223540ustar00rootroot00000000000000package main import ( "context" "flag" "strconv" "github.com/google/subcommands" "github.com/mmcloughlin/addchain/internal/cli" ) // reservedoi subcommand. type reservedoi struct { cli.Command httpclient HTTPClient zenodo Zenodo varsfile VarsFile } func (*reservedoi) Name() string { return "reservedoi" } func (*reservedoi) Synopsis() string { return "reserve zenodo doi for a new version" } func (*reservedoi) Usage() string { return `Usage: reservedoi Reserve DOI on Zenodo for a new release. ` } func (cmd *reservedoi) SetFlags(f *flag.FlagSet) { cmd.httpclient.SetFlags(f) cmd.zenodo.SetFlags(f) cmd.varsfile.SetFlags(f) } func (cmd *reservedoi) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus { // Zenodo client. httpclient, err := cmd.httpclient.Client() if err != nil { return cmd.Error(err) } c, err := cmd.zenodo.Client(httpclient) if err != nil { return cmd.Error(err) } // Fetch existing Zenodo ID. id, err := cmd.varsfile.Get("zenodoid") if err != nil { return cmd.Error(err) } cmd.Log.Printf("current zenodo id %s", id) // Start a new deposit. newid, err := c.DepositionNewVersion(ctx, id) if err != nil { return cmd.Error(err) } cmd.Log.Printf("new version id %s", newid) // Fetch the new version. d, err := c.DepositionRetrieve(ctx, newid) if err != nil { return cmd.Error(err) } // Write back to variables file. if err := cmd.varsfile.Set("zenodoid", strconv.Itoa(d.ID)); err != nil { return cmd.Error(err) } if err := cmd.varsfile.Set("doi", d.DOI); err != nil { return cmd.Error(err) } return subcommands.ExitSuccess } addchain-0.4.0/internal/tools/release/upload.go000066400000000000000000000071451514305256600214730ustar00rootroot00000000000000package main import ( "bytes" "context" "encoding/json" "flag" "fmt" "io" "io/ioutil" "net/http" "github.com/google/subcommands" "github.com/mmcloughlin/addchain/internal/cli" "github.com/mmcloughlin/addchain/internal/zenodo" ) // upload subcommand. type upload struct { cli.Command httpclient HTTPClient zenodo Zenodo varsfile VarsFile metadata string publish bool } func (*upload) Name() string { return "upload" } func (*upload) Synopsis() string { return "upload version" } func (*upload) Usage() string { return `Usage: upload Bump version and update related files. ` } func (cmd *upload) SetFlags(f *flag.FlagSet) { cmd.httpclient.SetFlags(f) cmd.zenodo.SetFlags(f) cmd.varsfile.SetFlags(f) f.StringVar(&cmd.metadata, "metadata", RepoPath(".zenodo.json"), "path to zenodo metadata") f.BoolVar(&cmd.publish, "publish", false, "publish the zenodo record") } func (cmd *upload) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus { // Fetch version. version, err := cmd.varsfile.Get("releaseversion") if err != nil { return cmd.Error(err) } // HTTP Client. httpclient, err := cmd.httpclient.Client() if err != nil { return cmd.Error(err) } // Download archive from github. archive := bytes.NewBuffer(nil) url := "https://api.github.com/repos/mmcloughlin/addchain/zipball/v" + version if err := Download(ctx, archive, httpclient, url); err != nil { return cmd.Error(err) } cmd.Log.Printf("downloaded zip archive bytes %d", archive.Len()) // Zenodo client. client, err := cmd.zenodo.Client(httpclient) if err != nil { return cmd.Error(err) } // Load zenodo metadata. metadata, err := LoadZenodoMetadata(cmd.metadata) if err != nil { return cmd.Error(err) } cmd.Log.Printf("loaded zenodo metadata from %q", cmd.metadata) // Set metadata. id, err := cmd.varsfile.Get("zenodoid") if err != nil { return cmd.Error(err) } d, err := client.DepositionUpdate(ctx, id, metadata) if err != nil { return cmd.Error(err) } cmd.Log.Printf("updated zenodo metadata") // Clear Zenodo files. if err := client.DepositionFilesDeleteAll(ctx, id); err != nil { return cmd.Error(err) } cmd.Log.Printf("cleared all files from zenodo deposit") // Upload new Zenodo file. archivefilename := fmt.Sprintf("addchain_%s.zip", version) file, err := client.DepositionFilesCreate(ctx, id, archivefilename, "application/zip", archive) if err != nil { return cmd.Error(err) } cmd.Log.Printf("uploaded file %q", file.Filename) // Optionally publish zenodo deposit. if cmd.publish { if _, err := client.DepositionPublish(ctx, id); err != nil { return cmd.Error(err) } cmd.Log.Printf("published zenodo record") } else { cmd.Log.Printf("publish skipped: review and publish at %q", d.Links["html"]) } return subcommands.ExitSuccess } // Download a file over HTTP. func Download(ctx context.Context, w io.Writer, c *http.Client, url string) (err error) { // Issue GET request. req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) if err != nil { return err } res, err := c.Do(req) if err != nil { return err } defer func() { if errc := res.Body.Close(); errc != nil && err == nil { err = errc } }() // Copy to writer. _, err = io.Copy(w, res.Body) return } // LoadZenodoMetadata reads and parses a Zenodo metadata file. func LoadZenodoMetadata(filename string) (*zenodo.DepositionMetadata, error) { b, err := ioutil.ReadFile(filename) if err != nil { return nil, err } m := new(zenodo.DepositionMetadata) if err := json.Unmarshal(b, m); err != nil { return nil, err } return m, nil } addchain-0.4.0/internal/tools/release/util.go000066400000000000000000000014151514305256600211560ustar00rootroot00000000000000package main import ( "errors" "path/filepath" "regexp" "runtime" ) // ValidateVersion checks if version is of the form "MAJOR.MINOR.PATCH". That // is, a simple semver format without "v" prefix, pre-release or build suffixes. func ValidateVersion(version string) error { if !versionrx.MatchString(version) { return errors.New("version must be of the form MAJOR.MINOR.PATCH") } return nil } var versionrx = regexp.MustCompile(`^\d+\.\d+\.\d+$`) // RepoPath returns a full file path given a path relative to the repository // root. Returns empty string if it cannot be determined. func RepoPath(rel string) string { _, self, _, ok := runtime.Caller(0) if !ok { return "" } path := filepath.Join(filepath.Dir(self), "../../..", rel) return filepath.Clean(path) } addchain-0.4.0/internal/zenodo/000077500000000000000000000000001514305256600163675ustar00rootroot00000000000000addchain-0.4.0/internal/zenodo/client.go000066400000000000000000000153311514305256600201770ustar00rootroot00000000000000// Package zenodo provides a client for the Zendodo API. package zenodo import ( "bytes" "context" "encoding/json" "errors" "fmt" "io" "mime/multipart" "net/http" "net/textproto" "regexp" ) // Default API base URLs. const ( BaseURL = "https://zenodo.org" SandboxBaseURL = "https://sandbox.zenodo.org" ) // Client for the Zenodo API. type Client struct { client *http.Client base string token string } // NewClient builds a new Zenodo client. Uses the given HTTP client, base URL // and access token. func NewClient(c *http.Client, base, token string) *Client { return &Client{ client: c, base: base, token: token, } } // DepositionRetrieve retrieves a deposit. func (c *Client) DepositionRetrieve(ctx context.Context, id string) (*Deposition, error) { path := fmt.Sprintf("api/deposit/depositions/%s", id) // Build request. u := c.base + "/" + path req, err := http.NewRequestWithContext(ctx, http.MethodGet, u, nil) if err != nil { return nil, err } // Execute. d := &Deposition{} if err := c.request(req, d); err != nil { return nil, err } return d, nil } // DepositionCreate creates a new empty deposit. func (c *Client) DepositionCreate(ctx context.Context) (*Deposition, error) { path := "api/deposit/depositions" empty := &Deposition{} d := &Deposition{} if err := c.requestjson(ctx, http.MethodPost, path, &empty, d); err != nil { return nil, err } return d, nil } // DepositionUpdate updates deposit metadata. func (c *Client) DepositionUpdate(ctx context.Context, id string, meta *DepositionMetadata) (*Deposition, error) { path := fmt.Sprintf("api/deposit/depositions/%s", id) input := &Deposition{Metadata: meta} d := &Deposition{} if err := c.requestjson(ctx, http.MethodPut, path, input, d); err != nil { return nil, err } return d, nil } // DepositionNewVersion creates a new version of an existing deposit. Returns // the ID of the new version. func (c *Client) DepositionNewVersion(ctx context.Context, id string) (string, error) { // Create new version. d, err := c.action(ctx, id, "newversion") if err != nil { return "", err } // Parse out the new ID from the latest_draft link. field := "latest_draft" u, ok := d.Links["latest_draft"] if !ok { return "", fmt.Errorf("expected %q link", field) } match := newidrx.FindStringSubmatch(u) if match == nil { return "", fmt.Errorf("could not parse ID from %q link", field) } newid := match[1] return newid, nil } var newidrx = regexp.MustCompile(`/api/deposit/depositions/(\d+)$`) // DepositionPublish publishes a deposit. func (c *Client) DepositionPublish(ctx context.Context, id string) (*Deposition, error) { return c.action(ctx, id, "publish") } func (c *Client) action(ctx context.Context, id, name string) (*Deposition, error) { path := fmt.Sprintf("api/deposit/depositions/%s/actions/%s", id, name) // Build request. u := c.base + "/" + path req, err := http.NewRequestWithContext(ctx, http.MethodPost, u, nil) if err != nil { return nil, err } // Execute. d := &Deposition{} if err := c.request(req, d); err != nil { return nil, err } return d, nil } // DepositionFilesList lists all files attached to a deposit. func (c *Client) DepositionFilesList(ctx context.Context, id string) ([]*DepositionFile, error) { path := fmt.Sprintf("api/deposit/depositions/%s/files", id) // Build request. u := c.base + "/" + path req, err := http.NewRequestWithContext(ctx, http.MethodGet, u, nil) if err != nil { return nil, err } // Execute. var fs []*DepositionFile if err := c.request(req, &fs); err != nil { return nil, err } return fs, nil } // DepositionFilesCreate uploads a new file to a deposit. func (c *Client) DepositionFilesCreate(ctx context.Context, id, filename, mimetype string, r io.Reader) (*DepositionFile, error) { path := fmt.Sprintf("api/deposit/depositions/%s/files", id) // Build multipart body. body := &bytes.Buffer{} w := multipart.NewWriter(body) if err := w.WriteField("name", filename); err != nil { return nil, err } // Add file. hdr := make(textproto.MIMEHeader) hdr.Set("Content-Disposition", fmt.Sprintf(`form-data; name="file"; filename=%q`, filename)) hdr.Set("Content-Type", mimetype) part, err := w.CreatePart(hdr) if err != nil { return nil, err } if _, err := io.Copy(part, r); err != nil { return nil, err } // Finalize body. if err := w.Close(); err != nil { return nil, err } // Build request. u := c.base + "/" + path req, err := http.NewRequestWithContext(ctx, http.MethodPost, u, body) if err != nil { return nil, err } req.Header.Set("Content-Type", w.FormDataContentType()) // Execute request. f := &DepositionFile{} if err := c.request(req, f); err != nil { return nil, err } return f, nil } // DepositionFilesDelete deletes a file from a deposit. func (c *Client) DepositionFilesDelete(ctx context.Context, did, fid string) error { path := fmt.Sprintf("api/deposit/depositions/%s/files/%s", did, fid) // Build request. u := c.base + "/" + path req, err := http.NewRequestWithContext(ctx, http.MethodDelete, u, nil) if err != nil { return err } // Execute. return c.request(req, nil) } // DepositionFilesDeleteAll deletes all files from a deposit. This requires // multiple API calls. func (c *Client) DepositionFilesDeleteAll(ctx context.Context, id string) error { fs, err := c.DepositionFilesList(ctx, id) if err != nil { return fmt.Errorf("list files: %w", err) } for _, f := range fs { if err := c.DepositionFilesDelete(ctx, id, f.ID); err != nil { return fmt.Errorf("delete file: %w", err) } } return nil } func (c *Client) requestjson(ctx context.Context, method, path string, data, payload interface{}) error { // Encode request data. body, err := json.Marshal(data) if err != nil { return err } // Build request. u := c.base + "/" + path req, err := http.NewRequestWithContext(ctx, method, u, bytes.NewReader(body)) if err != nil { return err } req.Header.Set("Content-Type", "application/json") return c.request(req, payload) } func (c *Client) request(req *http.Request, payload interface{}) (err error) { // Add common headers. req.Header.Set("Authorization", "Bearer "+c.token) req.Header.Set("Accept", "application/json") // Execute the request. res, err := c.client.Do(req) if err != nil { return err } defer func() { if errc := res.Body.Close(); errc != nil && err == nil { err = errc } }() // Parse response body. if payload != nil { if err := decodejson(res.Body, payload); err != nil { return err } } return nil } func decodejson(r io.Reader, v interface{}) error { d := json.NewDecoder(r) if err := d.Decode(v); err != nil { return err } // Should not have trailing data. if d.More() { return errors.New("unexpected extra data after JSON") } return nil } addchain-0.4.0/internal/zenodo/models.go000066400000000000000000000057571514305256600202170ustar00rootroot00000000000000package zenodo import "time" // Deposition represents a work-in-progress deposit. type Deposition struct { ConceptDOI string `json:"conceptdoi,omitempty"` ConceptRecordID string `json:"conceptrecid,omitempty"` Created *time.Time `json:"created,omitempty"` DOI string `json:"doi,omitempty"` DOIURL string `json:"doi_url,omitempty"` Files []*DepositionFile `json:"files,omitempty"` ID int `json:"id,omitempty"` Links map[string]string `json:"links,omitempty"` Metadata *DepositionMetadata `json:"metadata,omitempty"` Modified *time.Time `json:"modified,omitempty"` Owner int `json:"owner,omitempty"` RecordID int `json:"record_id,omitempty"` State string `json:"state,omitempty"` Submitted bool `json:"submitted,omitempty"` Title string `json:"title,omitempty"` } // DepositionFile represents a file attached to a deposit. type DepositionFile struct { Checksum string `json:"checksum"` Filename string `json:"filename"` Filesize int `json:"filesize"` ID string `json:"id"` Links map[string]string `json:"links"` } // DepositionMetadata represents metadata for a deposit. type DepositionMetadata struct { AccessRight string `json:"access_right,omitempty"` Communities []*Community `json:"communities,omitempty"` Creators []*Creator `json:"creators,omitempty"` Description string `json:"description,omitempty"` DOI string `json:"doi,omitempty"` License string `json:"license,omitempty"` PrereserveDOI *PrereserveDOI `json:"prereserve_doi,omitempty"` PublicationDate string `json:"publication_date,omitempty"` Title string `json:"title,omitempty"` UploadType string `json:"upload_type,omitempty"` RelatedIdentifiers []*RelatedIdentifier `json:"related_identifiers,omitempty"` References []string `json:"references,omitempty"` Version string `json:"version,omitempty"` } // Community associated with a deposit. type Community struct { Identifier string `json:"identifier"` } // Creator of a deposit. type Creator struct { Name string `json:"name"` Affiliation string `json:"affiliation"` ORCID string `json:"orcid"` } // PrereserveDOI represents a DOI pre-reserved for a deposit. type PrereserveDOI struct { DOI string `json:"doi"` RecordID int `json:"recid"` } // RelatedIdentifier is a persistent identifiers of a related publications or // dataset. type RelatedIdentifier struct { Relation string `json:"relation"` Identifier string `json:"identifier"` Scheme string `json:"scheme"` } addchain-0.4.0/logo.svg000066400000000000000000000135571514305256600147510ustar00rootroot00000000000000 addchain-0.4.0/meta/000077500000000000000000000000001514305256600142035ustar00rootroot00000000000000addchain-0.4.0/meta/cite.go000066400000000000000000000027621514305256600154650ustar00rootroot00000000000000package 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 } addchain-0.4.0/meta/meta.go000066400000000000000000000055031514305256600154630ustar00rootroot00000000000000// 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 } addchain-0.4.0/meta/meta_test.go000066400000000000000000000002211514305256600165120ustar00rootroot00000000000000package meta import ( "testing" ) func TestMetaReleaseTime(t *testing.T) { _, err := Meta.ReleaseTime() if err != nil { t.Fatal(err) } } addchain-0.4.0/meta/vars.go000066400000000000000000000003261514305256600155060ustar00rootroot00000000000000package meta var ( buildversion = "" releaseversion = "0.4.0" releasedate = "2021-10-30" conceptdoi = "10.5281/zenodo.4625263" doi = "10.5281/zenodo.5622943" zenodoid = "5622943" ) addchain-0.4.0/program.go000066400000000000000000000061061514305256600152560ustar00rootroot00000000000000package 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 } addchain-0.4.0/program_test.go000066400000000000000000000007651514305256600163220ustar00rootroot00000000000000package addchain import ( "testing" "github.com/mmcloughlin/addchain/internal/assert" ) func TestProgramEvaluateDoublings(t *testing.T) { // Build a chain of doublings. p := Program{} n := 17 for i := 0; i < n; i++ { _, err := p.Double(i) assert.NoError(t, err) } // Evaluate. c := p.Evaluate() for i, got := range c { if !got.IsUint64() { t.Fatal("expected to be representable as uint64") } expect := uint64(1) << uint(i) if got.Uint64() != expect { t.Fail() } } } addchain-0.4.0/rand/000077500000000000000000000000001514305256600142015ustar00rootroot00000000000000addchain-0.4.0/rand/rand.go000066400000000000000000000034131514305256600154550ustar00rootroot00000000000000// Package rand provides random addition chain generators. package rand import ( "fmt" "math/big" "math/rand" "time" "github.com/mmcloughlin/addchain" "github.com/mmcloughlin/addchain/alg" "github.com/mmcloughlin/addchain/internal/bigint" "github.com/mmcloughlin/addchain/internal/bigints" ) // Generator can generate random chains. type Generator interface { GenerateChain() (addchain.Chain, error) String() string } // AddsGenerator generates a random chain by making N random adds. type AddsGenerator struct { N int } func (a AddsGenerator) String() string { return fmt.Sprintf("random_adds(%d)", a.N) } // GenerateChain generates a random chain based on N random adds. func (a AddsGenerator) GenerateChain() (addchain.Chain, error) { c := addchain.New() for len(c) < a.N { i, j := rand.Intn(len(c)), rand.Intn(len(c)) sum := new(big.Int).Add(c[i], c[j]) c = bigints.InsertSortedUnique(c, sum) } return c, nil } // SolverGenerator generates random N-bit values and uses an algorithm to build // a chain for them. type SolverGenerator struct { N uint Algorithm alg.ChainAlgorithm rand *rand.Rand } // NewSolverGenerator constructs a solver generator based on n-bit targets solved with a. func NewSolverGenerator(n uint, a alg.ChainAlgorithm) SolverGenerator { return SolverGenerator{ N: n, Algorithm: a, rand: rand.New(rand.NewSource(time.Now().UnixNano())), } } func (s SolverGenerator) String() string { return fmt.Sprintf("random_solver(%d,%s)", s.N, s.Algorithm) } // GenerateChain generates a random n-bit value and builds a chain for it using // the configured chain algorithm. func (s SolverGenerator) GenerateChain() (addchain.Chain, error) { target := bigint.RandBits(s.rand, s.N) return s.Algorithm.FindChain(target) } addchain-0.4.0/script/000077500000000000000000000000001514305256600145615ustar00rootroot00000000000000addchain-0.4.0/script/bootstrap000077500000000000000000000023531514305256600165270ustar00rootroot00000000000000#!/usr/bin/env bash set -exuo pipefail # Install golangci-lint curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b "${GOPATH}/bin" v1.38.0 # Install goreleaser. go install github.com/goreleaser/goreleaser@v0.177.0 # Install godownloader. # # This doesn't have an install script like the others and can't be installed # with `go install` like below because the go.mod has a replace directive. So # we install it the old-fashioned way by cloning and installing from the # repository. workdir="$(mktemp -d)" projectdir="${workdir}/godownloader" git clone --depth 1 --branch v0.1.0 https://github.com/goreleaser/godownloader.git "${projectdir}" (cd "${projectdir}" && go install .) # gofumports for stricter formatting. go install mvdan.cc/gofumpt/gofumports@v0.0.0-20200412215918-a91da47f375c # pigeon for PEG parser generation. go install github.com/mna/pigeon@v1.0.1-0.20200224192238-18953b277063 # mathfmt for unicode math formatting. go install github.com/mmcloughlin/mathfmt@v0.0.0-20200207041814-4064651798f4 # bib for bibliography references. go install github.com/mmcloughlin/bib@v0.4.0 # covertool for merging coverage reports. go install github.com/dlespiau/covertool@v0.0.0-20180314162135-b0c4c6d0583a addchain-0.4.0/script/bump000077500000000000000000000007161514305256600154560ustar00rootroot00000000000000#!/usr/bin/env bash set -exuo pipefail # Parse options. version="$1" # Check repo is not dirty. git diff test -z "$(git status --porcelain)" # Start new branch. branch="release-${version}" git checkout -b "${branch}" # Bump version. go run ./internal/tools/release bump "${version}" # Reserve DOI. go run ./internal/tools/release reservedoi # Rerun code generation. ./script/generate # Create a commit. git add -u git commit -m "all: release ${version}" addchain-0.4.0/script/fmt000077500000000000000000000010351514305256600152740ustar00rootroot00000000000000#!/usr/bin/env bash set -exuo pipefail repo="github.com/mmcloughlin/addchain" # Find files. mapfile -t files < <(find . -name '*.go' -print0 | xargs -0 grep -L '// Code generated') # Go formatting. sed -i.fmtbackup '/^import (/,/)/ { /^$$/ d; }' "${files[@]}" find . -name '*.fmtbackup' -delete gofumports -w -local "${repo}" "${files[@]}" # Math formatting. mathfmt -w "${files[@]}" # Bibliography references. bib process -bib doc/references.bib -w "${files[@]}" # Format the bibliography itself. bib fmt -bib doc/references.bib -w addchain-0.4.0/script/generate000077500000000000000000000020531514305256600163010ustar00rootroot00000000000000#!/usr/bin/env bash set -exuo pipefail # Run examples. go install ./cmd/addchain for example in ./internal/examples/*; do cd "${example}" for script in *.sh; do root="${script%.sh}" bash "${script}" > "${root}.out" 2>&1 done cd - done # go generate go generate -x ./... # Bibliography. bib generate -bib doc/references.bib -type markdown -output doc/bibliography.md # Documentation. go run ./internal/tools/docgen -type readme -tocmax 3 -output README.md go run ./internal/tools/docgen -type results -output doc/results.md go run ./internal/tools/docgen -type gen -tocmax 3 -output doc/gen.md go run ./internal/tools/docgen -type cff -output CITATION.cff go run ./internal/tools/docgen -type bibtex -output CITATION.bib go run ./internal/tools/docgen -type zenodo -output .zenodo.json # Install script. (Post-processed to remove timestamp for repeatability.) godownloader --repo=mmcloughlin/addchain .goreleaser.yml \ | sed 's/\(Code generated by godownloader\).*\(\. DO NOT EDIT\.\)/\1\2/' > install.sh chmod +x install.sh addchain-0.4.0/script/lint000077500000000000000000000000731514305256600154550ustar00rootroot00000000000000#!/usr/bin/env bash set -exuo pipefail golangci-lint run addchain-0.4.0/script/stress000077500000000000000000000015071514305256600160350ustar00rootroot00000000000000#!/usr/bin/env bash set -exuo pipefail # Parse options. output_cover_profile="/dev/null" while getopts "c:" opt; do case "${opt}" in c) output_cover_profile="${OPTARG}" ;; esac done # Packages with stress test mode. pkgs=( "alg" "alg/contfrac" "alg/dict" "alg/ensemble" "alg/heuristic" "acc" ) # Test each package individually. This is required since custom test arguments # do not work when calling "go test" on multiple packages. cover_profiles=() for pkg in "${pkgs[@]}"; do pushd "${pkg}" cover_profile=$(mktemp) go test -stress -timeout=0 -coverprofile="${cover_profile}" -covermode=set cover_profiles+=("${cover_profile}") popd done # Merge profiles. covertool merge --output "${output_cover_profile}" "${cover_profiles[@]}" # Clean up. rm -rf "${cover_profiles[@]}"