longfellow 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CODE_OF_CONDUCT.md +10 -0
- data/LICENSE.txt +21 -0
- data/README.md +152 -0
- data/ext/longfellow/CMakeLists.txt +76 -0
- data/ext/longfellow/extconf.rb +77 -0
- data/lib/longfellow/attribute.rb +65 -0
- data/lib/longfellow/c.rb +105 -0
- data/lib/longfellow/errors.rb +78 -0
- data/lib/longfellow/version.rb +5 -0
- data/lib/longfellow/zk_spec.rb +40 -0
- data/lib/longfellow.rb +162 -0
- data/sig/longfellow.rbs +74 -0
- data/vendor/longfellow-zk/LICENSE +203 -0
- data/vendor/longfellow-zk/lib/algebra/blas.h +121 -0
- data/vendor/longfellow-zk/lib/algebra/bogorng.h +68 -0
- data/vendor/longfellow-zk/lib/algebra/compare.h +40 -0
- data/vendor/longfellow-zk/lib/algebra/convolution.h +219 -0
- data/vendor/longfellow-zk/lib/algebra/crt.cc +42 -0
- data/vendor/longfellow-zk/lib/algebra/crt.h +299 -0
- data/vendor/longfellow-zk/lib/algebra/crt_convolution.h +114 -0
- data/vendor/longfellow-zk/lib/algebra/crt_test.cc +371 -0
- data/vendor/longfellow-zk/lib/algebra/fft.h +104 -0
- data/vendor/longfellow-zk/lib/algebra/fft_interpolation.h +304 -0
- data/vendor/longfellow-zk/lib/algebra/fft_interpolation_test.cc +168 -0
- data/vendor/longfellow-zk/lib/algebra/fft_test.cc +257 -0
- data/vendor/longfellow-zk/lib/algebra/fp.h +59 -0
- data/vendor/longfellow-zk/lib/algebra/fp2.h +240 -0
- data/vendor/longfellow-zk/lib/algebra/fp24.h +342 -0
- data/vendor/longfellow-zk/lib/algebra/fp24_6.h +305 -0
- data/vendor/longfellow-zk/lib/algebra/fp24_6_test.cc +197 -0
- data/vendor/longfellow-zk/lib/algebra/fp2_test.cc +280 -0
- data/vendor/longfellow-zk/lib/algebra/fp_generic.h +533 -0
- data/vendor/longfellow-zk/lib/algebra/fp_p128.h +91 -0
- data/vendor/longfellow-zk/lib/algebra/fp_p256.h +68 -0
- data/vendor/longfellow-zk/lib/algebra/fp_p256k1.h +123 -0
- data/vendor/longfellow-zk/lib/algebra/fp_p384.h +65 -0
- data/vendor/longfellow-zk/lib/algebra/fp_p521.h +62 -0
- data/vendor/longfellow-zk/lib/algebra/fp_test.cc +522 -0
- data/vendor/longfellow-zk/lib/algebra/hash.h +39 -0
- data/vendor/longfellow-zk/lib/algebra/interpolation.h +117 -0
- data/vendor/longfellow-zk/lib/algebra/interpolation_test.cc +74 -0
- data/vendor/longfellow-zk/lib/algebra/limb.h +153 -0
- data/vendor/longfellow-zk/lib/algebra/limb_test.cc +75 -0
- data/vendor/longfellow-zk/lib/algebra/nat.cc +32 -0
- data/vendor/longfellow-zk/lib/algebra/nat.h +212 -0
- data/vendor/longfellow-zk/lib/algebra/nat_test.cc +183 -0
- data/vendor/longfellow-zk/lib/algebra/nussbaumer.h +400 -0
- data/vendor/longfellow-zk/lib/algebra/nussbaumer_test.cc +138 -0
- data/vendor/longfellow-zk/lib/algebra/nussbaumerfp2_test.cc +139 -0
- data/vendor/longfellow-zk/lib/algebra/permutations.h +79 -0
- data/vendor/longfellow-zk/lib/algebra/poly.h +240 -0
- data/vendor/longfellow-zk/lib/algebra/poly_test.cc +123 -0
- data/vendor/longfellow-zk/lib/algebra/reed_solomon.h +150 -0
- data/vendor/longfellow-zk/lib/algebra/reed_solomon_extension.h +108 -0
- data/vendor/longfellow-zk/lib/algebra/reed_solomon_extension_test.cc +76 -0
- data/vendor/longfellow-zk/lib/algebra/reed_solomon_test.cc +473 -0
- data/vendor/longfellow-zk/lib/algebra/rfft.h +400 -0
- data/vendor/longfellow-zk/lib/algebra/rfft_test.cc +102 -0
- data/vendor/longfellow-zk/lib/algebra/static_string.h +29 -0
- data/vendor/longfellow-zk/lib/algebra/sysdep.h +495 -0
- data/vendor/longfellow-zk/lib/algebra/sysdep_test.cc +41 -0
- data/vendor/longfellow-zk/lib/algebra/twiddle.h +59 -0
- data/vendor/longfellow-zk/lib/algebra/utility.h +86 -0
- data/vendor/longfellow-zk/lib/algebra/utility_test.cc +86 -0
- data/vendor/longfellow-zk/lib/arrays/affine.h +56 -0
- data/vendor/longfellow-zk/lib/arrays/affine_test.cc +220 -0
- data/vendor/longfellow-zk/lib/arrays/dense.h +210 -0
- data/vendor/longfellow-zk/lib/arrays/eq.h +75 -0
- data/vendor/longfellow-zk/lib/arrays/eqs.h +137 -0
- data/vendor/longfellow-zk/lib/arrays/eqs_test.cc +151 -0
- data/vendor/longfellow-zk/lib/arrays/sparse.h +192 -0
- data/vendor/longfellow-zk/lib/cbor/host_decoder.h +323 -0
- data/vendor/longfellow-zk/lib/cbor/host_decoder_test.cc +541 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor.h +594 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_byte_decoder.h +150 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_byte_decoder_test.cc +147 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_constants.h +27 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_pluck.h +110 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_pluck_test.cc +55 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_test.cc +174 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_testing.h +98 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_witness.h +312 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/mso2_test.cc +662 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/mso_test.cc +485 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/scan.h +104 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/scan_test.cc +137 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/cbor.h +640 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/cbor_byte_decoder.h +150 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/cbor_byte_decoder_test.cc +147 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/cbor_constants.h +27 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/cbor_testing.h +99 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/cbor_witness.h +319 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/lexer_test.cc +120 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/mdoc_examples_test.cc +89 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/parser_circuit_test.cc +506 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/parser_size_test.cc +79 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/parser_test.cc +473 -0
- data/vendor/longfellow-zk/lib/circuits/compiler/canonicalization_test.cc +185 -0
- data/vendor/longfellow-zk/lib/circuits/compiler/circuit_dump.h +65 -0
- data/vendor/longfellow-zk/lib/circuits/compiler/compiler.h +471 -0
- data/vendor/longfellow-zk/lib/circuits/compiler/compiler_test.cc +110 -0
- data/vendor/longfellow-zk/lib/circuits/compiler/node.h +176 -0
- data/vendor/longfellow-zk/lib/circuits/compiler/pdqhash.h +127 -0
- data/vendor/longfellow-zk/lib/circuits/compiler/schedule.h +435 -0
- data/vendor/longfellow-zk/lib/circuits/ecdsa/verify_circuit.h +371 -0
- data/vendor/longfellow-zk/lib/circuits/ecdsa/verify_external_test.cc +246 -0
- data/vendor/longfellow-zk/lib/circuits/ecdsa/verify_test.cc +587 -0
- data/vendor/longfellow-zk/lib/circuits/ecdsa/verify_witness.h +201 -0
- data/vendor/longfellow-zk/lib/circuits/logic/bit_adder.h +140 -0
- data/vendor/longfellow-zk/lib/circuits/logic/bit_adder_test.cc +64 -0
- data/vendor/longfellow-zk/lib/circuits/logic/bit_plucker.h +247 -0
- data/vendor/longfellow-zk/lib/circuits/logic/bit_plucker_constants.h +35 -0
- data/vendor/longfellow-zk/lib/circuits/logic/bit_plucker_encoder.h +72 -0
- data/vendor/longfellow-zk/lib/circuits/logic/bit_plucker_test.cc +183 -0
- data/vendor/longfellow-zk/lib/circuits/logic/compiler_backend.h +62 -0
- data/vendor/longfellow-zk/lib/circuits/logic/counter.h +171 -0
- data/vendor/longfellow-zk/lib/circuits/logic/counter_test.cc +102 -0
- data/vendor/longfellow-zk/lib/circuits/logic/evaluation_backend.h +94 -0
- data/vendor/longfellow-zk/lib/circuits/logic/logic.h +1232 -0
- data/vendor/longfellow-zk/lib/circuits/logic/logic_circuit_test.cc +310 -0
- data/vendor/longfellow-zk/lib/circuits/logic/logic_test.cc +521 -0
- data/vendor/longfellow-zk/lib/circuits/logic/memcmp.h +68 -0
- data/vendor/longfellow-zk/lib/circuits/logic/memcmp_test.cc +148 -0
- data/vendor/longfellow-zk/lib/circuits/logic/polynomial.h +94 -0
- data/vendor/longfellow-zk/lib/circuits/logic/polynomial_test.cc +62 -0
- data/vendor/longfellow-zk/lib/circuits/logic/routing.h +445 -0
- data/vendor/longfellow-zk/lib/circuits/logic/routing_test.cc +241 -0
- data/vendor/longfellow-zk/lib/circuits/logic/unary.h +55 -0
- data/vendor/longfellow-zk/lib/circuits/logic/unary_plucker.h +77 -0
- data/vendor/longfellow-zk/lib/circuits/logic/unary_plucker_constants.h +37 -0
- data/vendor/longfellow-zk/lib/circuits/logic/unary_plucker_test.cc +53 -0
- data/vendor/longfellow-zk/lib/circuits/logic/unary_size_test.cc +69 -0
- data/vendor/longfellow-zk/lib/circuits/logic/unary_test.cc +62 -0
- data/vendor/longfellow-zk/lib/circuits/mac/mac_circuit.h +193 -0
- data/vendor/longfellow-zk/lib/circuits/mac/mac_circuit_test.cc +223 -0
- data/vendor/longfellow-zk/lib/circuits/mac/mac_reference.h +72 -0
- data/vendor/longfellow-zk/lib/circuits/mac/mac_witness.h +94 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/circuit_maker.cc +242 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_attribute_ids.h +311 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_attribute_test.cc +64 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_circuit_id.cc +85 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_constants.h +85 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_decompress.cc +41 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_decompress.h +27 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_examples.h +5232 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_generate_circuit.cc +199 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_hash.h +554 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_signature.h +143 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_signature_test.cc +444 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_test_attributes.h +157 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_witness.h +863 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_zk.cc +693 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_zk.h +216 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_zk_test.cc +724 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/zk_spec.cc +100 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/zk_spec_test.cc +155 -0
- data/vendor/longfellow-zk/lib/circuits/sha/flatsha256_circuit.h +330 -0
- data/vendor/longfellow-zk/lib/circuits/sha/flatsha256_circuit_test.cc +607 -0
- data/vendor/longfellow-zk/lib/circuits/sha/flatsha256_io.h +26 -0
- data/vendor/longfellow-zk/lib/circuits/sha/flatsha256_witness.cc +163 -0
- data/vendor/longfellow-zk/lib/circuits/sha/flatsha256_witness.h +47 -0
- data/vendor/longfellow-zk/lib/circuits/sha/sha256_constants.cc +34 -0
- data/vendor/longfellow-zk/lib/circuits/sha/sha256_constants.h +27 -0
- data/vendor/longfellow-zk/lib/circuits/sha/sha256_test_values.h +389 -0
- data/vendor/longfellow-zk/lib/circuits/tests/anoncred/ptrcred.h +171 -0
- data/vendor/longfellow-zk/lib/circuits/tests/anoncred/small.h +218 -0
- data/vendor/longfellow-zk/lib/circuits/tests/anoncred/small_examples.h +118 -0
- data/vendor/longfellow-zk/lib/circuits/tests/anoncred/small_io.h +25 -0
- data/vendor/longfellow-zk/lib/circuits/tests/anoncred/small_test.cc +208 -0
- data/vendor/longfellow-zk/lib/circuits/tests/anoncred/small_witness.h +130 -0
- data/vendor/longfellow-zk/lib/circuits/tests/base64/decode.h +508 -0
- data/vendor/longfellow-zk/lib/circuits/tests/base64/decode_circuit_test.cc +95 -0
- data/vendor/longfellow-zk/lib/circuits/tests/base64/decode_test.cc +119 -0
- data/vendor/longfellow-zk/lib/circuits/tests/base64/decode_util.cc +47 -0
- data/vendor/longfellow-zk/lib/circuits/tests/base64/decode_util.h +29 -0
- data/vendor/longfellow-zk/lib/circuits/tests/ec/pk_circuit.h +231 -0
- data/vendor/longfellow-zk/lib/circuits/tests/ec/pk_circuit_test.cc +428 -0
- data/vendor/longfellow-zk/lib/circuits/tests/ec/pk_witness.h +102 -0
- data/vendor/longfellow-zk/lib/circuits/tests/jwt/jwt.h +190 -0
- data/vendor/longfellow-zk/lib/circuits/tests/jwt/jwt_constants.h +26 -0
- data/vendor/longfellow-zk/lib/circuits/tests/jwt/jwt_test.cc +559 -0
- data/vendor/longfellow-zk/lib/circuits/tests/jwt/jwt_witness.h +315 -0
- data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_1f.h +411 -0
- data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_1f_io.h +32 -0
- data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_1f_test.cc +364 -0
- data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_1f_witness.h +278 -0
- data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_revocation.h +146 -0
- data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_revocation_constants.h +25 -0
- data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_revocation_test.cc +315 -0
- data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_revocation_witness.h +136 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/bitaddr/bitaddr.h +250 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/bitaddr/bitaddr_test.cc +333 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/bitaddr/bitaddr_witness.h +152 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44.h +903 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_circuit_test.cc +274 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_eval_test.cc +440 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_examples.cc +8851 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_examples.h +93 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_types.cc +24 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_types.h +118 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_witness.h +453 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_witness_test.cc +49 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_ref.cc +458 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_ref.h +150 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_ref_test.cc +398 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_ref_test_vectors.inc +3618 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_ref_test_vectors_pkdecode.inc +689 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_ref_test_vectors_sigdecode.inc +1501 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/sigdecode_test_vectors.inc +540 -0
- data/vendor/longfellow-zk/lib/circuits/tests/ripemd/ripemd_circuit.h +394 -0
- data/vendor/longfellow-zk/lib/circuits/tests/ripemd/ripemd_circuit_test.cc +577 -0
- data/vendor/longfellow-zk/lib/circuits/tests/ripemd/ripemd_constants.h +90 -0
- data/vendor/longfellow-zk/lib/circuits/tests/ripemd/ripemd_witness.cc +174 -0
- data/vendor/longfellow-zk/lib/circuits/tests/ripemd/ripemd_witness.h +140 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_circuit.h +351 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_circuit_test.cc +466 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_reference.cc +207 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_reference.h +59 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_reference_test.cc +153 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_round_constants.cc +39 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_round_constants.h +29 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_slicing.h +31 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_witness.cc +83 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_witness.h +72 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/shake_test_vectors.h +477 -0
- data/vendor/longfellow-zk/lib/ec/elliptic_curve.h +596 -0
- data/vendor/longfellow-zk/lib/ec/elliptic_curve_test.cc +548 -0
- data/vendor/longfellow-zk/lib/ec/p256.cc +36 -0
- data/vendor/longfellow-zk/lib/ec/p256.h +60 -0
- data/vendor/longfellow-zk/lib/ec/p256k1.cc +34 -0
- data/vendor/longfellow-zk/lib/ec/p256k1.h +60 -0
- data/vendor/longfellow-zk/lib/gf2k/gf2_128.h +503 -0
- data/vendor/longfellow-zk/lib/gf2k/gf2_128_bench.cc +48 -0
- data/vendor/longfellow-zk/lib/gf2k/gf2_128_test.cc +416 -0
- data/vendor/longfellow-zk/lib/gf2k/gf2poly.h +74 -0
- data/vendor/longfellow-zk/lib/gf2k/lch14.h +242 -0
- data/vendor/longfellow-zk/lib/gf2k/lch14_bench.cc +75 -0
- data/vendor/longfellow-zk/lib/gf2k/lch14_reed_solomon.h +127 -0
- data/vendor/longfellow-zk/lib/gf2k/lch14_reed_solomon_test.cc +110 -0
- data/vendor/longfellow-zk/lib/gf2k/lch14_test.cc +246 -0
- data/vendor/longfellow-zk/lib/gf2k/sysdep.h +329 -0
- data/vendor/longfellow-zk/lib/ligero/ligero_param.h +449 -0
- data/vendor/longfellow-zk/lib/ligero/ligero_prover.h +354 -0
- data/vendor/longfellow-zk/lib/ligero/ligero_test.cc +136 -0
- data/vendor/longfellow-zk/lib/ligero/ligero_transcript.h +67 -0
- data/vendor/longfellow-zk/lib/ligero/ligero_verifier.h +272 -0
- data/vendor/longfellow-zk/lib/merkle/merkle_commitment.h +104 -0
- data/vendor/longfellow-zk/lib/merkle/merkle_tree.h +216 -0
- data/vendor/longfellow-zk/lib/merkle/merkle_tree_test.cc +240 -0
- data/vendor/longfellow-zk/lib/proto/circuit.h +354 -0
- data/vendor/longfellow-zk/lib/proto/circuit_test.cc +202 -0
- data/vendor/longfellow-zk/lib/random/random.h +119 -0
- data/vendor/longfellow-zk/lib/random/random_test.cc +189 -0
- data/vendor/longfellow-zk/lib/random/secure_random_engine.h +37 -0
- data/vendor/longfellow-zk/lib/random/transcript.h +193 -0
- data/vendor/longfellow-zk/lib/random/transcript_test.cc +344 -0
- data/vendor/longfellow-zk/lib/sumcheck/circuit.h +148 -0
- data/vendor/longfellow-zk/lib/sumcheck/circuit_id.h +71 -0
- data/vendor/longfellow-zk/lib/sumcheck/equad.h +126 -0
- data/vendor/longfellow-zk/lib/sumcheck/hquad.h +115 -0
- data/vendor/longfellow-zk/lib/sumcheck/prover.h +59 -0
- data/vendor/longfellow-zk/lib/sumcheck/prover_layers.h +362 -0
- data/vendor/longfellow-zk/lib/sumcheck/quad.h +227 -0
- data/vendor/longfellow-zk/lib/sumcheck/quad_builder.h +211 -0
- data/vendor/longfellow-zk/lib/sumcheck/quad_test.cc +169 -0
- data/vendor/longfellow-zk/lib/sumcheck/sumcheck_test.cc +324 -0
- data/vendor/longfellow-zk/lib/sumcheck/testing.h +69 -0
- data/vendor/longfellow-zk/lib/sumcheck/transcript_sumcheck.h +85 -0
- data/vendor/longfellow-zk/lib/sumcheck/verifier.h +84 -0
- data/vendor/longfellow-zk/lib/sumcheck/verifier_layers.h +221 -0
- data/vendor/longfellow-zk/lib/testing/test_main.cc +50 -0
- data/vendor/longfellow-zk/lib/util/ceildiv.h +164 -0
- data/vendor/longfellow-zk/lib/util/ceildiv_test.cc +152 -0
- data/vendor/longfellow-zk/lib/util/crc64.h +45 -0
- data/vendor/longfellow-zk/lib/util/crypto.cc +39 -0
- data/vendor/longfellow-zk/lib/util/crypto.h +108 -0
- data/vendor/longfellow-zk/lib/util/log.cc +110 -0
- data/vendor/longfellow-zk/lib/util/log.h +33 -0
- data/vendor/longfellow-zk/lib/util/panic.h +40 -0
- data/vendor/longfellow-zk/lib/util/readbuffer.h +67 -0
- data/vendor/longfellow-zk/lib/util/serialization.h +54 -0
- data/vendor/longfellow-zk/lib/zk/zk_common.h +455 -0
- data/vendor/longfellow-zk/lib/zk/zk_proof.h +378 -0
- data/vendor/longfellow-zk/lib/zk/zk_prover.h +202 -0
- data/vendor/longfellow-zk/lib/zk/zk_test.cc +340 -0
- data/vendor/longfellow-zk/lib/zk/zk_testing.h +154 -0
- data/vendor/longfellow-zk/lib/zk/zk_verifier.h +109 -0
- metadata +347 -0
|
@@ -0,0 +1,1232 @@
|
|
|
1
|
+
// Copyright 2026 Google LLC.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
|
|
15
|
+
#ifndef PRIVACY_PROOFS_ZK_LIB_CIRCUITS_LOGIC_LOGIC_H_
|
|
16
|
+
#define PRIVACY_PROOFS_ZK_LIB_CIRCUITS_LOGIC_LOGIC_H_
|
|
17
|
+
|
|
18
|
+
#include <stddef.h>
|
|
19
|
+
|
|
20
|
+
#include <array>
|
|
21
|
+
#include <cstdint>
|
|
22
|
+
#include <functional>
|
|
23
|
+
#include <vector>
|
|
24
|
+
|
|
25
|
+
#include "algebra/fp_generic.h"
|
|
26
|
+
#include "gf2k/gf2_128.h"
|
|
27
|
+
#include "util/panic.h"
|
|
28
|
+
|
|
29
|
+
namespace proofs {
|
|
30
|
+
/*
|
|
31
|
+
Arithmetization of boolean logic in a field.
|
|
32
|
+
This class builds logical and arithmetic operations such as add, sub, mul,
|
|
33
|
+
and, or, xor, etc. over bits in the arithmetic circuit model.
|
|
34
|
+
The class utilizes several optimizations, including changing from the {0,1}
|
|
35
|
+
basis to the {-1,1} basis for representing bits.
|
|
36
|
+
*/
|
|
37
|
+
template <typename Field_, class Backend>
|
|
38
|
+
class Logic {
|
|
39
|
+
public:
|
|
40
|
+
using Field = Field_; /* this class export Field, Elt, and EltW */
|
|
41
|
+
using Elt = typename Field::Elt;
|
|
42
|
+
// an "Elt Wire", a wire carrying an Elt.
|
|
43
|
+
using EltW = typename Backend::V;
|
|
44
|
+
|
|
45
|
+
const Field& f_;
|
|
46
|
+
|
|
47
|
+
explicit Logic(const Backend* bk, const Field& F) : f_(F), bk_(bk) {}
|
|
48
|
+
|
|
49
|
+
//------------------------------------------------------------
|
|
50
|
+
// Arithmetic.
|
|
51
|
+
|
|
52
|
+
//
|
|
53
|
+
// Re-export field operations
|
|
54
|
+
Elt addf(const Elt& a, const Elt& b) const { return f_.addf(a, b); }
|
|
55
|
+
Elt mulf(const Elt& a, const Elt& b) const { return f_.mulf(a, b); }
|
|
56
|
+
Elt invertf(const Elt& a) const { return f_.invertf(a); }
|
|
57
|
+
Elt negf(const Elt& a) const { return f_.negf(a); }
|
|
58
|
+
Elt zero() const { return f_.zero(); }
|
|
59
|
+
Elt one() const { return f_.one(); }
|
|
60
|
+
Elt mone() const { return f_.mone(); }
|
|
61
|
+
Elt elt(uint64_t a) const { return f_.of_scalar(a); }
|
|
62
|
+
|
|
63
|
+
template <size_t N>
|
|
64
|
+
Elt elt(const char (&s)[N]) const {
|
|
65
|
+
return f_.of_string(s);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Historical note: All functions in this file were defined so that the last
|
|
69
|
+
// argument was a const reference and all other arguments were by const
|
|
70
|
+
// pointer, as in add(const EltW* a, const EltW& b). This funny convention
|
|
71
|
+
// forced the caller to create explicit temporaries for subexpressions, which
|
|
72
|
+
// in turn forced the wire ids to be deterministic. For example add(add(a,b),
|
|
73
|
+
// add(c,d)) may assign nondeterministic wire ids to the two subexpressions
|
|
74
|
+
// depending on the order of function calls. We have since modified the
|
|
75
|
+
// compiler to renumber wires in a deterministic way independent of the
|
|
76
|
+
// original wire numbering, and in fact this feature has been present in all
|
|
77
|
+
// open source versions of longfellow-zk. We have now removed this funny
|
|
78
|
+
// calling convention, and changed the code to use standard C++ idioms.
|
|
79
|
+
|
|
80
|
+
// Re-export backend operations
|
|
81
|
+
EltW assert0(const EltW& a) const { return bk_->assert0(a); }
|
|
82
|
+
EltW add(const EltW& a, const EltW& b) const { return bk_->add(a, b); }
|
|
83
|
+
|
|
84
|
+
EltW sub(const EltW& a, const EltW& b) const { return bk_->sub(a, b); }
|
|
85
|
+
|
|
86
|
+
EltW mul(const EltW& a, const EltW& b) const { return bk_->mul(a, b); }
|
|
87
|
+
EltW mul(const Elt& k, const EltW& b) const { return bk_->mul(k, b); }
|
|
88
|
+
EltW mul(const Elt& k, const EltW& a, const EltW& b) const {
|
|
89
|
+
return bk_->mul(k, a, b);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
EltW ax(const Elt& a, const EltW& x) const { return bk_->ax(a, x); }
|
|
93
|
+
EltW axy(const Elt& a, const EltW& x, const EltW& y) const {
|
|
94
|
+
return bk_->axy(a, x, y);
|
|
95
|
+
}
|
|
96
|
+
EltW axpy(const EltW& y, const Elt& a, const EltW& x) const {
|
|
97
|
+
return bk_->axpy(y, a, x);
|
|
98
|
+
}
|
|
99
|
+
EltW apy(const EltW& y, const Elt& a) const { return bk_->apy(y, a); }
|
|
100
|
+
|
|
101
|
+
EltW konst(const Elt& a) const { return bk_->konst(a); }
|
|
102
|
+
EltW konst(uint64_t a) const { return konst(elt(a)); }
|
|
103
|
+
|
|
104
|
+
template <size_t N>
|
|
105
|
+
std::array<EltW, N> konst(const std::array<Elt, N>& a) const {
|
|
106
|
+
std::array<EltW, N> r;
|
|
107
|
+
for (size_t i = 0; i < N; ++i) {
|
|
108
|
+
r[i] = konst(a[i]);
|
|
109
|
+
}
|
|
110
|
+
return r;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
//------------------------------------------------------------
|
|
114
|
+
// Boolean logic.
|
|
115
|
+
//
|
|
116
|
+
// We map TRUE to one() and FALSE to zero(). We call this convention
|
|
117
|
+
// the "standard basis".
|
|
118
|
+
//
|
|
119
|
+
// However, actual values on wires may use different conventions,
|
|
120
|
+
// e.g. -1 for TRUE and 1 for FALSE. To keep track of these changes,
|
|
121
|
+
// we represent boolean values as (c0, c1, x) where c0+c1*x is
|
|
122
|
+
// the value in the standard basis. c0 and c1
|
|
123
|
+
// are compile-time constants that can be manipulated, and
|
|
124
|
+
// x is a runtime value not known in advance.
|
|
125
|
+
//
|
|
126
|
+
// For example, let the "xor basis" denote the mapping FALSE -> 1,
|
|
127
|
+
// TRUE -> -1. In the xor basis, xor(a,b)=a*b. The output of the
|
|
128
|
+
// xor gate in the standard basis would be represented as 1/2 + (-1/2)*x
|
|
129
|
+
// where x=a*b is the wire value in the xor basis.
|
|
130
|
+
|
|
131
|
+
// a "bit Wire", a wire carrying a bit
|
|
132
|
+
struct BitW {
|
|
133
|
+
Elt c0, c1;
|
|
134
|
+
EltW x;
|
|
135
|
+
BitW() = default;
|
|
136
|
+
|
|
137
|
+
// constructor in the standard basis
|
|
138
|
+
explicit BitW(const EltW& bv, const Field& F)
|
|
139
|
+
: BitW(F.zero(), F.one(), bv) {}
|
|
140
|
+
|
|
141
|
+
BitW(Elt c0_, Elt c1_, const EltW& x_) : c0(c0_), c1(c1_), x(x_) {}
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
// vectors of N bits
|
|
145
|
+
template <size_t N>
|
|
146
|
+
class bitvec : public std::array<BitW, N> {
|
|
147
|
+
public:
|
|
148
|
+
bitvec() = default;
|
|
149
|
+
|
|
150
|
+
// Allow explicit copies only.
|
|
151
|
+
//
|
|
152
|
+
// There is nothing wrong with copying bitvecs, but it seems
|
|
153
|
+
// like clang on armv7 (at least) generates incorrect code at
|
|
154
|
+
// least in some cases when passing bitvecs by value. Thus, the
|
|
155
|
+
// goal is to force us to write const bv & in all function
|
|
156
|
+
// arguments, unless we explicitly opt-in to a copy via v32(x).
|
|
157
|
+
//
|
|
158
|
+
// bitvecs are only used by the compiler, and we don't ship
|
|
159
|
+
// 32-bit compilers. We do however care about the ability of
|
|
160
|
+
// running 32 bit tests that compile a circuit and run it,
|
|
161
|
+
// so this nuisance is still worth it.
|
|
162
|
+
//
|
|
163
|
+
// The Google3 style guide says that copy constructors SHOULD NOT be
|
|
164
|
+
// explicit, which defeats the whole point of this exercise. Oh well.
|
|
165
|
+
explicit bitvec(const bitvec&) = default;
|
|
166
|
+
bitvec& operator=(const bitvec&) = default;
|
|
167
|
+
bitvec(bitvec&&) = default;
|
|
168
|
+
bitvec& operator=(bitvec&&) = default;
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
// View for bitvec, used for clean initialization syntax.
|
|
172
|
+
template <size_t N>
|
|
173
|
+
struct bitvec_view {
|
|
174
|
+
const bitvec<N>* ptr;
|
|
175
|
+
// The Google3 style guide says that one-argument constructors MUST be
|
|
176
|
+
// explicit, which again defeats the whole point of this exercise.
|
|
177
|
+
bitvec_view(const bitvec<N>& v) : ptr(&v) {}
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
// Common sizes, publicly exported for convenience. The type names are
|
|
181
|
+
// intentionally lower-case to capture the spirit of basic "intx_t" types.
|
|
182
|
+
using v1 = bitvec<1>;
|
|
183
|
+
using v4 = bitvec<4>;
|
|
184
|
+
using v8 = bitvec<8>;
|
|
185
|
+
using v16 = bitvec<16>;
|
|
186
|
+
using v32 = bitvec<32>;
|
|
187
|
+
using v64 = bitvec<64>;
|
|
188
|
+
using v128 = bitvec<128>;
|
|
189
|
+
using v129 = bitvec<129>;
|
|
190
|
+
using v256 = bitvec<256>;
|
|
191
|
+
|
|
192
|
+
// Let v(x)=c0+c1*x. Return a representation of
|
|
193
|
+
// d0+d1*v(x)=(d0+d1*c0)+(d1*c1)*x without changing x.
|
|
194
|
+
// Does not involve the backend at all.
|
|
195
|
+
BitW rebase(const Elt& d0, const Elt& d1, const BitW& v) const {
|
|
196
|
+
return BitW(addf(d0, mulf(d1, v.c0)), mulf(d1, v.c1), v.x);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
EltW eval(const BitW& v) const {
|
|
200
|
+
EltW r = ax(v.c1, v.x);
|
|
201
|
+
if (v.c0 != zero()) {
|
|
202
|
+
r = add(konst(v.c0), r);
|
|
203
|
+
}
|
|
204
|
+
return r;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// compute in the circuit what F.of_scalar(sum_i v[i] 2^i) would compute
|
|
208
|
+
// outside the circuit
|
|
209
|
+
template <size_t N>
|
|
210
|
+
EltW as_scalar(const bitvec<N>& v) const {
|
|
211
|
+
EltW r = konst(zero());
|
|
212
|
+
uint64_t s = 0;
|
|
213
|
+
for (size_t i = 0; i < N; ++i) {
|
|
214
|
+
r = axpy(r, f_.beta(i), eval(v[i]));
|
|
215
|
+
s += static_cast<uint64_t>(1) << i;
|
|
216
|
+
}
|
|
217
|
+
// Check that the worst case all-1 bitvec can be represented
|
|
218
|
+
// in the field.
|
|
219
|
+
(void)f_.of_scalar(s);
|
|
220
|
+
return r;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// return an EltW which is 0 iff v is 0
|
|
224
|
+
EltW assert0(const BitW& v) const { return assert0(eval(v)); }
|
|
225
|
+
// return an EltW which is 0 iff v is 1
|
|
226
|
+
EltW assert1(const BitW& v) const { return assert0(lnot(v)); }
|
|
227
|
+
|
|
228
|
+
// 0 iff a==b
|
|
229
|
+
EltW assert_eq(const EltW& a, const EltW& b) const {
|
|
230
|
+
return assert0(sub(a, b));
|
|
231
|
+
}
|
|
232
|
+
EltW assert_eq(const BitW& a, const BitW& b) const {
|
|
233
|
+
return assert0(lxor(a, b));
|
|
234
|
+
}
|
|
235
|
+
EltW assert_implies(const BitW& a, const BitW& b) const {
|
|
236
|
+
return assert1(limplies(a, b));
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// special test for asserting that b \in {0,1} (i.e.,
|
|
240
|
+
// not some other field element).
|
|
241
|
+
EltW assert_is_bit(const BitW& b) const {
|
|
242
|
+
// b - b*b
|
|
243
|
+
// Seems to work better than b*(1-b)
|
|
244
|
+
// Equivalent to land(b,lnot(b)) but does not rely
|
|
245
|
+
// on the specific arithmetization.
|
|
246
|
+
return assert_is_bit(eval(b));
|
|
247
|
+
}
|
|
248
|
+
EltW assert_is_bit(const EltW& v) const {
|
|
249
|
+
auto vvmv = sub(v, mul(v, v));
|
|
250
|
+
return assert0(vvmv);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// bits in their own basis b + 0*1, to allow for some
|
|
254
|
+
// compile-time constant folding
|
|
255
|
+
BitW bit(size_t b) const {
|
|
256
|
+
return BitW((b == 0) ? zero() : one(), zero(), konst(one()));
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
void bits(size_t n, BitW a[/*n*/], uint64_t x) const {
|
|
260
|
+
for (size_t i = 0; i < n; ++i) {
|
|
261
|
+
a[i] = bit((x >> i) & 1u);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// gates
|
|
266
|
+
BitW lnot(const BitW& x) const {
|
|
267
|
+
// lnot() is a pure representation change that does not
|
|
268
|
+
// involve actual circuit gates
|
|
269
|
+
|
|
270
|
+
// 1 - x in the standard basis
|
|
271
|
+
return rebase(one(), mone(), x);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
BitW land(const BitW& a, const BitW& b) const {
|
|
275
|
+
// a * b in the standard basis
|
|
276
|
+
return mulv(a, b);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// special case of product of a logic value by a field
|
|
280
|
+
// element
|
|
281
|
+
EltW lmul(const BitW& a, const EltW& b) const {
|
|
282
|
+
// a * b in the standard basis
|
|
283
|
+
return eval(mulv(a, BitW(b, f_)));
|
|
284
|
+
}
|
|
285
|
+
EltW lmul(const EltW& b, const BitW& a) const { return lmul(a, b); }
|
|
286
|
+
|
|
287
|
+
BitW lxor(const BitW& a, const BitW& b) const {
|
|
288
|
+
return lxor_aux(a, b, typename Field::TypeTag());
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
BitW lor(const BitW& a, const BitW& b) const {
|
|
292
|
+
return lnot(land(lnot(a), lnot(b)));
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// a => b
|
|
296
|
+
BitW limplies(const BitW& a, const BitW& b) const { return lor(lnot(a), b); }
|
|
297
|
+
|
|
298
|
+
// OR of two quantities known to be mutually exclusive
|
|
299
|
+
BitW lor_exclusive(const BitW& a, const BitW& b) const { return addv(a, b); }
|
|
300
|
+
|
|
301
|
+
BitW lxor3(const BitW& a, const BitW& b, const BitW& c) const {
|
|
302
|
+
return lxor(lxor(a, b), c);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// sha256 Ch(): (x & y) ^ (~x & z);
|
|
306
|
+
BitW lCh(const BitW& x, const BitW& y, const BitW& z) const {
|
|
307
|
+
return lor_exclusive(land(x, y), land(lnot(x), z));
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// sha256 Maj(): (x & y) ^ (x & z) ^ (y & z);
|
|
311
|
+
BitW lMaj(const BitW& x, const BitW& y, const BitW& z) const {
|
|
312
|
+
// Interpret as x + y + z >= 2 and compute the carry
|
|
313
|
+
// for an adder in the (p, g) basis
|
|
314
|
+
return lor_exclusive(land(x, y), land(lxor(x, y), z));
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// mux over logic values
|
|
318
|
+
BitW mux(const BitW& control, const BitW& iftrue, const BitW& iffalse) const {
|
|
319
|
+
return lor_exclusive(land(control, iftrue), land(lnot(control), iffalse));
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// mux over backend values
|
|
323
|
+
EltW mux(const BitW& control, const EltW& iftrue, const EltW& iffalse) const {
|
|
324
|
+
return add(lmul(control, iftrue), lmul(lnot(control), iffalse));
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// sum_{i0 <= i < i1} f(i)
|
|
328
|
+
EltW add(size_t i0, size_t i1, const std::function<EltW(size_t)>& f) const {
|
|
329
|
+
if (i1 <= i0) {
|
|
330
|
+
return konst(0);
|
|
331
|
+
} else if (i1 == i0 + 1) {
|
|
332
|
+
return f(i0);
|
|
333
|
+
} else {
|
|
334
|
+
size_t im = i0 + (i1 - i0) / 2;
|
|
335
|
+
return add(add(i0, im, f), add(im, i1, f));
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// lor_exclusive_{i0 <= i < i1} f(i)
|
|
340
|
+
BitW lor_exclusive(size_t i0, size_t i1,
|
|
341
|
+
const std::function<BitW(size_t)>& f) const {
|
|
342
|
+
if (i1 <= i0) {
|
|
343
|
+
return bit(0);
|
|
344
|
+
} else if (i1 == i0 + 1) {
|
|
345
|
+
return f(i0);
|
|
346
|
+
} else {
|
|
347
|
+
size_t im = i0 + (i1 - i0) / 2;
|
|
348
|
+
return lor_exclusive(lor_exclusive(i0, im, f), lor_exclusive(im, i1, f));
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// and_{i0 <= i < i1} f(i)
|
|
353
|
+
BitW land(size_t i0, size_t i1, const std::function<BitW(size_t)>& f) const {
|
|
354
|
+
if (i1 <= i0) {
|
|
355
|
+
return bit(1);
|
|
356
|
+
} else if (i1 == i0 + 1) {
|
|
357
|
+
return f(i0);
|
|
358
|
+
} else {
|
|
359
|
+
size_t im = i0 + (i1 - i0) / 2;
|
|
360
|
+
return land(land(i0, im, f), land(im, i1, f));
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// or_{i0 <= i < i1} f(i)
|
|
365
|
+
BitW lor(size_t i0, size_t i1, const std::function<BitW(size_t)>& f) const {
|
|
366
|
+
if (i1 <= i0) {
|
|
367
|
+
return bit(0);
|
|
368
|
+
} else if (i1 == i0 + 1) {
|
|
369
|
+
return f(i0);
|
|
370
|
+
} else {
|
|
371
|
+
size_t im = i0 + (i1 - i0) / 2;
|
|
372
|
+
return lor(lor(i0, im, f), lor(im, i1, f));
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
BitW or_of_and(std::vector<std::vector<BitW>> clauses_of_ands) const {
|
|
377
|
+
std::vector<BitW> ands(clauses_of_ands.size());
|
|
378
|
+
for (size_t i = 0; i < clauses_of_ands.size(); ++i) {
|
|
379
|
+
auto ai = clauses_of_ands[i];
|
|
380
|
+
BitW res = land(0, ai.size(), [&](size_t i) { return ai[i]; });
|
|
381
|
+
ands[i] = res;
|
|
382
|
+
}
|
|
383
|
+
return lor(0, ands.size(), [&](size_t i) { return ands[i]; });
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// prod_{i0 <= i < i1} f(i)
|
|
387
|
+
EltW mul(size_t i0, size_t i1, const std::function<EltW(size_t)>& f) const {
|
|
388
|
+
if (i1 <= i0) {
|
|
389
|
+
return konst(1);
|
|
390
|
+
} else if (i1 == i0 + 1) {
|
|
391
|
+
return f(i0);
|
|
392
|
+
} else {
|
|
393
|
+
size_t im = i0 + (i1 - i0) / 2;
|
|
394
|
+
return mul(mul(i0, im, f), mul(im, i1, f));
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// assert that a + b = c in constant depth
|
|
399
|
+
void assert_sum(size_t w, const BitW c[/*w*/], const BitW a[/*w*/],
|
|
400
|
+
const BitW b[/*w*/]) const {
|
|
401
|
+
// first step of generic_gp_add(): change the basis from
|
|
402
|
+
// (a, b) to (g, p):
|
|
403
|
+
std::vector<BitW> g(w), p(w), cy(w);
|
|
404
|
+
for (size_t i = 0; i < w; ++i) {
|
|
405
|
+
g[i] = land(a[i], b[i]);
|
|
406
|
+
p[i] = lxor(a[i], b[i]);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// invert the last step of generic_gp_add(): derive
|
|
410
|
+
// cy[i - 1] (called g[i - 1] there) from
|
|
411
|
+
// c[i] and p[i].
|
|
412
|
+
assert_eq(c[0], p[0]);
|
|
413
|
+
for (size_t i = 1; i < w; ++i) {
|
|
414
|
+
cy[i - 1] = lxor(c[i], p[i]);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// Verify that applying ripple_scan to g[] produces cy[].
|
|
418
|
+
// Note that ripple_scan() operates in-place on g[]. Here, however, g[] is
|
|
419
|
+
// the input to ripple_scan(), and cy[] is the output.
|
|
420
|
+
assert_eq(cy[0], g[0]);
|
|
421
|
+
for (size_t i = 1; i + 1 < w; ++i) {
|
|
422
|
+
assert_eq(cy[i], lor_exclusive(g[i], land(cy[i - 1], p[i])));
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// (carry, c) = a + b, returning the carry.
|
|
427
|
+
BitW ripple_carry_add(size_t w, BitW c[/*w*/], const BitW a[/*w*/],
|
|
428
|
+
const BitW b[/*w*/]) const {
|
|
429
|
+
return generic_gp_add(w, c, a, b, &Logic::ripple_scan);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// (carry, c) = a - b, returning the carry.
|
|
433
|
+
BitW ripple_carry_sub(size_t w, BitW c[/*w*/], const BitW a[/*w*/],
|
|
434
|
+
const BitW b[/*w*/]) const {
|
|
435
|
+
return generic_gp_sub(w, c, a, b, &Logic::ripple_scan);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
BitW parallel_prefix_add(size_t w, BitW c[/*w*/], const BitW a[/*w*/],
|
|
439
|
+
const BitW b[/*w*/]) const {
|
|
440
|
+
return generic_gp_add(w, c, a, b, &Logic::sklansky_scan);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
BitW parallel_prefix_sub(size_t w, BitW c[/*w*/], const BitW a[/*w*/],
|
|
444
|
+
const BitW b[/*w*/]) const {
|
|
445
|
+
return generic_gp_sub(w, c, a, b, &Logic::sklansky_scan);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// w x w -> 2w-bit multiplier c = a * b
|
|
449
|
+
void multiplier(size_t w, BitW c[/*2*w*/], const BitW a[/*w*/],
|
|
450
|
+
const BitW b[/*w*/]) const {
|
|
451
|
+
std::vector<BitW> t(w);
|
|
452
|
+
for (size_t i = 0; i < w; ++i) {
|
|
453
|
+
if (i == 0) {
|
|
454
|
+
for (size_t j = 0; j < w; ++j) {
|
|
455
|
+
c[j] = land(a[0], b[j]);
|
|
456
|
+
}
|
|
457
|
+
c[w] = bit(0);
|
|
458
|
+
} else {
|
|
459
|
+
for (size_t j = 0; j < w; ++j) {
|
|
460
|
+
t[j] = land(a[i], b[j]);
|
|
461
|
+
}
|
|
462
|
+
BitW carry = ripple_carry_add(w, c + i, t.data(), c + i);
|
|
463
|
+
c[i + w] = carry;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
// w x w -> 2w-bit polynomial multiplier over gf2. c(x) = a(x) * b(x)
|
|
469
|
+
void gf2_polynomial_multiplier(size_t w, BitW c[/*2*w*/], const BitW a[/*w*/],
|
|
470
|
+
const BitW b[/*w*/]) const {
|
|
471
|
+
std::vector<BitW> t(w);
|
|
472
|
+
for (size_t k = 0; k < 2 * w; ++k) {
|
|
473
|
+
size_t n = 0;
|
|
474
|
+
for (size_t i = 0; i < w; ++i) {
|
|
475
|
+
if (k >= i && k - i < w) {
|
|
476
|
+
t[n++] = land(a[i], b[k - i]);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
c[k] = parity(0, n, t.data());
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// w x w -> 2w-bit polynomial multiplier over gf2. c(x) = a(x) * b(x)
|
|
484
|
+
// via the Karatsuba recurrence. Only works for w = 2^k.
|
|
485
|
+
void gf2_polynomial_multiplier_karat(size_t w, BitW c[/*2*w*/],
|
|
486
|
+
const BitW a[/*w*/],
|
|
487
|
+
const BitW b[/*w*/]) const {
|
|
488
|
+
check(w == 128 || w == 64 || w < 64, "input length is not a power of 2");
|
|
489
|
+
if (w < 64) {
|
|
490
|
+
gf2_polynomial_multiplier(w, c, a, b);
|
|
491
|
+
return;
|
|
492
|
+
} else {
|
|
493
|
+
// We only run this look on w=128 bits. To support odd w,
|
|
494
|
+
std::vector<BitW> a01(w / 2); /* a0 plus a1 */
|
|
495
|
+
std::vector<BitW> b01(w / 2); /* b0 plus b1 */
|
|
496
|
+
std::vector<BitW> ab01(w);
|
|
497
|
+
std::vector<BitW> a0b0(w);
|
|
498
|
+
std::vector<BitW> a1b1(w);
|
|
499
|
+
|
|
500
|
+
for (size_t i = 0; i < w / 2; ++i) {
|
|
501
|
+
a01[i] = lxor(a[i], a[i + w / 2]);
|
|
502
|
+
b01[i] = lxor(b[i], b[i + w / 2]);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
gf2_polynomial_multiplier_karat(w / 2, &ab01[0], &a01[0], &b01[0]);
|
|
506
|
+
gf2_polynomial_multiplier_karat(w / 2, &a0b0[0], a, b);
|
|
507
|
+
gf2_polynomial_multiplier_karat(w / 2, &a1b1[0], a + w / 2, b + w / 2);
|
|
508
|
+
|
|
509
|
+
for (size_t i = 0; i < w; ++i) {
|
|
510
|
+
ab01[i] = lxor3(ab01[i], a0b0[i], a1b1[i]);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
for (size_t i = 0; i < w / 2; ++i) {
|
|
514
|
+
c[i] = a0b0[i];
|
|
515
|
+
c[i + w / 2] = lxor(a0b0[i + w / 2], ab01[i]);
|
|
516
|
+
c[i + w] = lxor(ab01[i + w / 2], a1b1[i]);
|
|
517
|
+
c[i + 3 * w / 2] = a1b1[i + w / 2];
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// Performs field multiplication in GF2^128 defined by the irreducible
|
|
523
|
+
// x^128 + x^7 + x^2 + x + 1. This routine is generated in a sage script that
|
|
524
|
+
// computes a sparse matrix-vector mult via the powers of x^k mod p(x).
|
|
525
|
+
//
|
|
526
|
+
// def make_mulmod(F, n):
|
|
527
|
+
// r = F(1)
|
|
528
|
+
// gen = F.gen()
|
|
529
|
+
// nl = [[] for _ in range(n)]
|
|
530
|
+
// terms = 0
|
|
531
|
+
// for i in range(0, 2*n-1):
|
|
532
|
+
// for j, var in enumerate(r.polynomial().list()):
|
|
533
|
+
// if var == 1:
|
|
534
|
+
// nl[j].append(i)
|
|
535
|
+
// r = r * gen
|
|
536
|
+
// print(nl)
|
|
537
|
+
void gf2_128_mul(v128& c, const v128& a, const v128& b) const {
|
|
538
|
+
const std::vector<uint16_t> taps[128] = {
|
|
539
|
+
{0, 128, 249, 254},
|
|
540
|
+
{1, 128, 129, 249, 250, 254},
|
|
541
|
+
{2, 128, 129, 130, 249, 250, 251, 254},
|
|
542
|
+
{3, 129, 130, 131, 250, 251, 252},
|
|
543
|
+
{4, 130, 131, 132, 251, 252, 253},
|
|
544
|
+
{5, 131, 132, 133, 252, 253, 254},
|
|
545
|
+
{6, 132, 133, 134, 253, 254},
|
|
546
|
+
{7, 128, 133, 134, 135, 249},
|
|
547
|
+
{8, 129, 134, 135, 136, 250},
|
|
548
|
+
{9, 130, 135, 136, 137, 251},
|
|
549
|
+
{10, 131, 136, 137, 138, 252},
|
|
550
|
+
{11, 132, 137, 138, 139, 253},
|
|
551
|
+
{12, 133, 138, 139, 140, 254},
|
|
552
|
+
{13, 134, 139, 140, 141},
|
|
553
|
+
{14, 135, 140, 141, 142},
|
|
554
|
+
{15, 136, 141, 142, 143},
|
|
555
|
+
{16, 137, 142, 143, 144},
|
|
556
|
+
{17, 138, 143, 144, 145},
|
|
557
|
+
{18, 139, 144, 145, 146},
|
|
558
|
+
{19, 140, 145, 146, 147},
|
|
559
|
+
{20, 141, 146, 147, 148},
|
|
560
|
+
{21, 142, 147, 148, 149},
|
|
561
|
+
{22, 143, 148, 149, 150},
|
|
562
|
+
{23, 144, 149, 150, 151},
|
|
563
|
+
{24, 145, 150, 151, 152},
|
|
564
|
+
{25, 146, 151, 152, 153},
|
|
565
|
+
{26, 147, 152, 153, 154},
|
|
566
|
+
{27, 148, 153, 154, 155},
|
|
567
|
+
{28, 149, 154, 155, 156},
|
|
568
|
+
{29, 150, 155, 156, 157},
|
|
569
|
+
{30, 151, 156, 157, 158},
|
|
570
|
+
{31, 152, 157, 158, 159},
|
|
571
|
+
{32, 153, 158, 159, 160},
|
|
572
|
+
{33, 154, 159, 160, 161},
|
|
573
|
+
{34, 155, 160, 161, 162},
|
|
574
|
+
{35, 156, 161, 162, 163},
|
|
575
|
+
{36, 157, 162, 163, 164},
|
|
576
|
+
{37, 158, 163, 164, 165},
|
|
577
|
+
{38, 159, 164, 165, 166},
|
|
578
|
+
{39, 160, 165, 166, 167},
|
|
579
|
+
{40, 161, 166, 167, 168},
|
|
580
|
+
{41, 162, 167, 168, 169},
|
|
581
|
+
{42, 163, 168, 169, 170},
|
|
582
|
+
{43, 164, 169, 170, 171},
|
|
583
|
+
{44, 165, 170, 171, 172},
|
|
584
|
+
{45, 166, 171, 172, 173},
|
|
585
|
+
{46, 167, 172, 173, 174},
|
|
586
|
+
{47, 168, 173, 174, 175},
|
|
587
|
+
{48, 169, 174, 175, 176},
|
|
588
|
+
{49, 170, 175, 176, 177},
|
|
589
|
+
{50, 171, 176, 177, 178},
|
|
590
|
+
{51, 172, 177, 178, 179},
|
|
591
|
+
{52, 173, 178, 179, 180},
|
|
592
|
+
{53, 174, 179, 180, 181},
|
|
593
|
+
{54, 175, 180, 181, 182},
|
|
594
|
+
{55, 176, 181, 182, 183},
|
|
595
|
+
{56, 177, 182, 183, 184},
|
|
596
|
+
{57, 178, 183, 184, 185},
|
|
597
|
+
{58, 179, 184, 185, 186},
|
|
598
|
+
{59, 180, 185, 186, 187},
|
|
599
|
+
{60, 181, 186, 187, 188},
|
|
600
|
+
{61, 182, 187, 188, 189},
|
|
601
|
+
{62, 183, 188, 189, 190},
|
|
602
|
+
{63, 184, 189, 190, 191},
|
|
603
|
+
{64, 185, 190, 191, 192},
|
|
604
|
+
{65, 186, 191, 192, 193},
|
|
605
|
+
{66, 187, 192, 193, 194},
|
|
606
|
+
{67, 188, 193, 194, 195},
|
|
607
|
+
{68, 189, 194, 195, 196},
|
|
608
|
+
{69, 190, 195, 196, 197},
|
|
609
|
+
{70, 191, 196, 197, 198},
|
|
610
|
+
{71, 192, 197, 198, 199},
|
|
611
|
+
{72, 193, 198, 199, 200},
|
|
612
|
+
{73, 194, 199, 200, 201},
|
|
613
|
+
{74, 195, 200, 201, 202},
|
|
614
|
+
{75, 196, 201, 202, 203},
|
|
615
|
+
{76, 197, 202, 203, 204},
|
|
616
|
+
{77, 198, 203, 204, 205},
|
|
617
|
+
{78, 199, 204, 205, 206},
|
|
618
|
+
{79, 200, 205, 206, 207},
|
|
619
|
+
{80, 201, 206, 207, 208},
|
|
620
|
+
{81, 202, 207, 208, 209},
|
|
621
|
+
{82, 203, 208, 209, 210},
|
|
622
|
+
{83, 204, 209, 210, 211},
|
|
623
|
+
{84, 205, 210, 211, 212},
|
|
624
|
+
{85, 206, 211, 212, 213},
|
|
625
|
+
{86, 207, 212, 213, 214},
|
|
626
|
+
{87, 208, 213, 214, 215},
|
|
627
|
+
{88, 209, 214, 215, 216},
|
|
628
|
+
{89, 210, 215, 216, 217},
|
|
629
|
+
{90, 211, 216, 217, 218},
|
|
630
|
+
{91, 212, 217, 218, 219},
|
|
631
|
+
{92, 213, 218, 219, 220},
|
|
632
|
+
{93, 214, 219, 220, 221},
|
|
633
|
+
{94, 215, 220, 221, 222},
|
|
634
|
+
{95, 216, 221, 222, 223},
|
|
635
|
+
{96, 217, 222, 223, 224},
|
|
636
|
+
{97, 218, 223, 224, 225},
|
|
637
|
+
{98, 219, 224, 225, 226},
|
|
638
|
+
{99, 220, 225, 226, 227},
|
|
639
|
+
{100, 221, 226, 227, 228},
|
|
640
|
+
{101, 222, 227, 228, 229},
|
|
641
|
+
{102, 223, 228, 229, 230},
|
|
642
|
+
{103, 224, 229, 230, 231},
|
|
643
|
+
{104, 225, 230, 231, 232},
|
|
644
|
+
{105, 226, 231, 232, 233},
|
|
645
|
+
{106, 227, 232, 233, 234},
|
|
646
|
+
{107, 228, 233, 234, 235},
|
|
647
|
+
{108, 229, 234, 235, 236},
|
|
648
|
+
{109, 230, 235, 236, 237},
|
|
649
|
+
{110, 231, 236, 237, 238},
|
|
650
|
+
{111, 232, 237, 238, 239},
|
|
651
|
+
{112, 233, 238, 239, 240},
|
|
652
|
+
{113, 234, 239, 240, 241},
|
|
653
|
+
{114, 235, 240, 241, 242},
|
|
654
|
+
{115, 236, 241, 242, 243},
|
|
655
|
+
{116, 237, 242, 243, 244},
|
|
656
|
+
{117, 238, 243, 244, 245},
|
|
657
|
+
{118, 239, 244, 245, 246},
|
|
658
|
+
{119, 240, 245, 246, 247},
|
|
659
|
+
{120, 241, 246, 247, 248},
|
|
660
|
+
{121, 242, 247, 248, 249},
|
|
661
|
+
{122, 243, 248, 249, 250},
|
|
662
|
+
{123, 244, 249, 250, 251},
|
|
663
|
+
{124, 245, 250, 251, 252},
|
|
664
|
+
{125, 246, 251, 252, 253},
|
|
665
|
+
{126, 247, 252, 253, 254},
|
|
666
|
+
{127, 248, 253, 254},
|
|
667
|
+
};
|
|
668
|
+
gf2k_mul(c.data(), a.data(), b.data(), taps, 128);
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
// Performs field multiplication in GF2^k using a sparse matrix datastructure.
|
|
672
|
+
void gf2k_mul(BitW c[/*w*/], const BitW a[/*w*/], const BitW b[/*w*/],
|
|
673
|
+
const std::vector<uint16_t> M[], size_t w) const {
|
|
674
|
+
std::vector<BitW> t(w * 2);
|
|
675
|
+
gf2_polynomial_multiplier_karat(w, t.data(), a, b);
|
|
676
|
+
|
|
677
|
+
std::vector<BitW> tmp(w);
|
|
678
|
+
for (size_t i = 0; i < w; ++i) {
|
|
679
|
+
size_t n = 0;
|
|
680
|
+
for (auto ti : M[i]) {
|
|
681
|
+
tmp[n++] = t[ti];
|
|
682
|
+
}
|
|
683
|
+
c[i] = parity(0, n, tmp.data());
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
// a == 0
|
|
688
|
+
BitW eq0(size_t w, const BitW a[/*w*/]) const { return eq0(0, w, a); }
|
|
689
|
+
|
|
690
|
+
// a == b
|
|
691
|
+
BitW eq(size_t w, const BitW a[/*w*/], const BitW b[/*w*/]) const {
|
|
692
|
+
return eq_reduce(0, w, a, b);
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
// a < b.
|
|
696
|
+
// Specialization of the subtractor for the case (a - b) < 0
|
|
697
|
+
BitW lt(size_t w, const BitW a[/*w*/], const BitW b[/*w*/]) const {
|
|
698
|
+
if (w == 0) {
|
|
699
|
+
return bit(0);
|
|
700
|
+
} else {
|
|
701
|
+
BitW xeq, xlt;
|
|
702
|
+
lt_reduce(0, w, &xeq, &xlt, a, b);
|
|
703
|
+
return xlt;
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
// a <= b
|
|
708
|
+
BitW leq(size_t w, const BitW a[/*w*/], const BitW b[/*w*/]) const {
|
|
709
|
+
auto blt = lt(w, b, a);
|
|
710
|
+
return lnot(blt);
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
// Parallel prefix of various kinds
|
|
714
|
+
template <class T>
|
|
715
|
+
void scan(const std::function<void(T*, const T&, const T&)>& op, T x[],
|
|
716
|
+
size_t i0, size_t i1, bool backward = false) const {
|
|
717
|
+
// generic Sklansky scan
|
|
718
|
+
if (i1 - i0 > 1) {
|
|
719
|
+
size_t im = i0 + (i1 - i0) / 2;
|
|
720
|
+
scan(op, x, i0, im, backward);
|
|
721
|
+
scan(op, x, im, i1, backward);
|
|
722
|
+
if (backward) {
|
|
723
|
+
for (size_t i = i0; i < im; ++i) {
|
|
724
|
+
op(&x[i], x[i], x[im]);
|
|
725
|
+
}
|
|
726
|
+
} else {
|
|
727
|
+
for (size_t i = im; i < i1; ++i) {
|
|
728
|
+
op(&x[i], x[im - 1], x[i]);
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
void scan_and(BitW x[], size_t i0, size_t i1, bool backward = false) const {
|
|
735
|
+
scan<BitW>(
|
|
736
|
+
[&](BitW* out, const BitW& l, const BitW& r) { *out = land(l, r); }, x,
|
|
737
|
+
i0, i1, backward);
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
void scan_or(BitW x[], size_t i0, size_t i1, bool backward = false) const {
|
|
741
|
+
scan<BitW>(
|
|
742
|
+
[&](BitW* out, const BitW& l, const BitW& r) { *out = lor(l, r); }, x,
|
|
743
|
+
i0, i1, backward);
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
void scan_xor(BitW x[], size_t i0, size_t i1, bool backward = false) const {
|
|
747
|
+
scan<BitW>(
|
|
748
|
+
[&](BitW* out, const BitW& l, const BitW& r) { *out = lxor(l, r); }, x,
|
|
749
|
+
i0, i1, backward);
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
template <size_t I0, size_t I1, size_t N>
|
|
753
|
+
bitvec<I1 - I0> slice(const bitvec<N>& a) const {
|
|
754
|
+
bitvec<I1 - I0> r;
|
|
755
|
+
for (size_t i = I0; i < I1; ++i) {
|
|
756
|
+
r[i - I0] = a[i];
|
|
757
|
+
}
|
|
758
|
+
return r;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
// Little-endian append of A and B. A[0] is the LSB, B starts at
|
|
762
|
+
// position [NA].
|
|
763
|
+
template <size_t NA, size_t NB>
|
|
764
|
+
bitvec<NA + NB> vappend(const bitvec<NA>& a, const bitvec<NB>& b) const {
|
|
765
|
+
bitvec<NA + NB> r;
|
|
766
|
+
for (size_t i = 0; i < NA; ++i) {
|
|
767
|
+
r[i] = a[i];
|
|
768
|
+
}
|
|
769
|
+
for (size_t i = 0; i < NB; ++i) {
|
|
770
|
+
r[i + NA] = b[i];
|
|
771
|
+
}
|
|
772
|
+
return r;
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
template <size_t N>
|
|
776
|
+
bitvec<N> vbit(uint64_t x) const {
|
|
777
|
+
bitvec<N> r;
|
|
778
|
+
bits(N, r.data(), x);
|
|
779
|
+
return r;
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
// shorthands for the silly "template" notation
|
|
783
|
+
v8 vbit8(uint64_t x) const { return vbit<8>(x); }
|
|
784
|
+
v32 vbit32(uint64_t x) const { return vbit<32>(x); }
|
|
785
|
+
|
|
786
|
+
template <size_t N>
|
|
787
|
+
bitvec<N> vnot(const bitvec<N>& x) const {
|
|
788
|
+
bitvec<N> r;
|
|
789
|
+
for (size_t i = 0; i < N; ++i) {
|
|
790
|
+
r[i] = lnot(x[i]);
|
|
791
|
+
}
|
|
792
|
+
return r;
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
template <size_t N>
|
|
796
|
+
bitvec<N> vand(const bitvec<N>& a, const bitvec<N>& b) const {
|
|
797
|
+
bitvec<N> r;
|
|
798
|
+
for (size_t i = 0; i < N; ++i) {
|
|
799
|
+
r[i] = land(a[i], b[i]);
|
|
800
|
+
}
|
|
801
|
+
return r;
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
template <size_t N>
|
|
805
|
+
bitvec<N> vand(const BitW& a, const bitvec<N>& b) const {
|
|
806
|
+
bitvec<N> r;
|
|
807
|
+
for (size_t i = 0; i < N; ++i) {
|
|
808
|
+
r[i] = land(a, b[i]);
|
|
809
|
+
}
|
|
810
|
+
return r;
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
template <size_t N>
|
|
814
|
+
bitvec<N> vor(const bitvec<N>& a, const bitvec<N>& b) const {
|
|
815
|
+
bitvec<N> r;
|
|
816
|
+
for (size_t i = 0; i < N; ++i) {
|
|
817
|
+
r[i] = lor(a[i], b[i]);
|
|
818
|
+
}
|
|
819
|
+
return r;
|
|
820
|
+
}
|
|
821
|
+
template <size_t N>
|
|
822
|
+
bitvec<N> vor_exclusive(const bitvec<N>& a, const bitvec<N>& b) const {
|
|
823
|
+
bitvec<N> r;
|
|
824
|
+
for (size_t i = 0; i < N; ++i) {
|
|
825
|
+
r[i] = lor_exclusive(a[i], b[i]);
|
|
826
|
+
}
|
|
827
|
+
return r;
|
|
828
|
+
}
|
|
829
|
+
template <size_t N>
|
|
830
|
+
bitvec<N> vxor(const bitvec<N>& a, const bitvec<N>& b) const {
|
|
831
|
+
bitvec<N> r;
|
|
832
|
+
for (size_t i = 0; i < N; ++i) {
|
|
833
|
+
r[i] = lxor(a[i], b[i]);
|
|
834
|
+
}
|
|
835
|
+
return r;
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
template <size_t N>
|
|
839
|
+
bitvec<N> vCh(const bitvec<N>& x, const bitvec<N>& y,
|
|
840
|
+
const bitvec<N>& z) const {
|
|
841
|
+
bitvec<N> r;
|
|
842
|
+
for (size_t i = 0; i < N; ++i) {
|
|
843
|
+
r[i] = lCh(x[i], y[i], z[i]);
|
|
844
|
+
}
|
|
845
|
+
return r;
|
|
846
|
+
}
|
|
847
|
+
template <size_t N>
|
|
848
|
+
bitvec<N> vMaj(const bitvec<N>& x, const bitvec<N>& y,
|
|
849
|
+
const bitvec<N>& z) const {
|
|
850
|
+
bitvec<N> r;
|
|
851
|
+
for (size_t i = 0; i < N; ++i) {
|
|
852
|
+
r[i] = lMaj(x[i], y[i], z[i]);
|
|
853
|
+
}
|
|
854
|
+
return r;
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
template <size_t N>
|
|
858
|
+
bitvec<N> vxor3(const bitvec<N>& x, const bitvec<N>& y,
|
|
859
|
+
const bitvec<N>& z) const {
|
|
860
|
+
bitvec<N> r;
|
|
861
|
+
for (size_t i = 0; i < N; ++i) {
|
|
862
|
+
r[i] = lxor3(x[i], y[i], z[i]);
|
|
863
|
+
}
|
|
864
|
+
return r;
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
template <size_t N>
|
|
868
|
+
bitvec<N> vshr(const bitvec<N>& a, size_t shift, size_t b = 0) const {
|
|
869
|
+
bitvec<N> r;
|
|
870
|
+
for (size_t i = 0; i < N; ++i) {
|
|
871
|
+
if (i + shift < N) {
|
|
872
|
+
r[i] = a[i + shift];
|
|
873
|
+
} else {
|
|
874
|
+
r[i] = bit(b);
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
return r;
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
template <size_t N>
|
|
881
|
+
bitvec<N> vshl(const bitvec<N>& a, size_t shift, size_t b = 0) const {
|
|
882
|
+
bitvec<N> r;
|
|
883
|
+
for (size_t i = 0; i < N; ++i) {
|
|
884
|
+
if (i >= shift) {
|
|
885
|
+
r[i] = a[i - shift];
|
|
886
|
+
} else {
|
|
887
|
+
r[i] = bit(b);
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
return r;
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
template <size_t N>
|
|
894
|
+
bitvec<N> vrotr(const bitvec<N>& a, size_t b) const {
|
|
895
|
+
bitvec<N> r;
|
|
896
|
+
for (size_t i = 0; i < N; ++i) {
|
|
897
|
+
r[i] = a[(i + b) % N];
|
|
898
|
+
}
|
|
899
|
+
return r;
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
template <size_t N>
|
|
903
|
+
bitvec<N> vrotl(const bitvec<N>& a, size_t b) const {
|
|
904
|
+
bitvec<N> r;
|
|
905
|
+
for (size_t i = 0; i < N; ++i) {
|
|
906
|
+
r[(i + b) % N] = a[i];
|
|
907
|
+
}
|
|
908
|
+
return r;
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
template <size_t N>
|
|
912
|
+
bitvec<N> vadd(const bitvec<N>& a, const bitvec<N>& b) const {
|
|
913
|
+
bitvec<N> r;
|
|
914
|
+
(void)parallel_prefix_add(N, &r[0], &a[0], &b[0]);
|
|
915
|
+
return r;
|
|
916
|
+
}
|
|
917
|
+
template <size_t N>
|
|
918
|
+
bitvec<N> vadd(const bitvec<N>& a, uint64_t val) const {
|
|
919
|
+
return vadd(a, vbit<N>(val));
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
template <size_t N>
|
|
923
|
+
BitW veq(const bitvec<N>& a, const bitvec<N>& b) const {
|
|
924
|
+
return eq(N, a.data(), b.data());
|
|
925
|
+
}
|
|
926
|
+
template <size_t N>
|
|
927
|
+
BitW veq(const bitvec<N>& a, uint64_t val) const {
|
|
928
|
+
auto v = vbit<N>(val);
|
|
929
|
+
return veq(a, v);
|
|
930
|
+
}
|
|
931
|
+
template <size_t N>
|
|
932
|
+
BitW vlt(const bitvec<N>& a, const bitvec<N>& b) const {
|
|
933
|
+
return lt(N, a.data(), b.data());
|
|
934
|
+
}
|
|
935
|
+
template <size_t N>
|
|
936
|
+
BitW vlt(const bitvec<N>& a, uint64_t val) const {
|
|
937
|
+
auto v = vbit<N>(val);
|
|
938
|
+
return vlt(a, v);
|
|
939
|
+
}
|
|
940
|
+
template <size_t N>
|
|
941
|
+
BitW vlt(uint64_t a, const bitvec<N>& b) const {
|
|
942
|
+
auto va = vbit<N>(a);
|
|
943
|
+
return vlt(va, b);
|
|
944
|
+
}
|
|
945
|
+
template <size_t N>
|
|
946
|
+
BitW vleq(const bitvec<N>& a, const bitvec<N>& b) const {
|
|
947
|
+
return leq(N, a.data(), b.data());
|
|
948
|
+
}
|
|
949
|
+
template <size_t N>
|
|
950
|
+
BitW vleq(const bitvec<N>& a, uint64_t val) const {
|
|
951
|
+
auto v = vbit<N>(val);
|
|
952
|
+
return vleq(a, v);
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
// (a ^ val) & mask == 0
|
|
956
|
+
template <size_t N>
|
|
957
|
+
BitW veqmask(const bitvec<N>& a, uint64_t mask, const bitvec<N>& val) const {
|
|
958
|
+
auto r = vxor(a, val);
|
|
959
|
+
size_t n = pack(mask, N, &r[0]);
|
|
960
|
+
return eq0(0, n, &r[0]);
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
template <size_t N>
|
|
964
|
+
BitW veqmask(const bitvec<N>& a, uint64_t mask, uint64_t val) const {
|
|
965
|
+
auto v = vbit<N>(val);
|
|
966
|
+
return veqmask(a, mask, v);
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
// I/O. This is a hack which only works if the backend supports
|
|
970
|
+
// bk_->{input,output}. Because C++ templates are lazily expanded,
|
|
971
|
+
// this class compiles even with backends that do not support I/O,
|
|
972
|
+
// as long as you don't expand vinput(), voutput().
|
|
973
|
+
EltW eltw_input() const { return bk_->input_wire(); }
|
|
974
|
+
BitW input() const {
|
|
975
|
+
BitW x(bk_->input_wire(), f_);
|
|
976
|
+
assert_is_bit(x);
|
|
977
|
+
return x;
|
|
978
|
+
}
|
|
979
|
+
void output(const EltW& x, size_t i) const { bk_->output_wire(x, i); }
|
|
980
|
+
void output(const BitW& x, size_t i) const { output(eval(x), i); }
|
|
981
|
+
|
|
982
|
+
template <size_t N>
|
|
983
|
+
bitvec<N> vinput() const {
|
|
984
|
+
bitvec<N> r;
|
|
985
|
+
for (size_t i = 0; i < N; ++i) {
|
|
986
|
+
r[i] = input();
|
|
987
|
+
}
|
|
988
|
+
return r;
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
template <size_t N>
|
|
992
|
+
void voutput(const bitvec<N>& x, size_t i0) const {
|
|
993
|
+
for (size_t i = 0; i < N; ++i) {
|
|
994
|
+
output(x[i], i + i0);
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
template <size_t N>
|
|
999
|
+
void vassert0(const bitvec<N>& x) const {
|
|
1000
|
+
for (size_t i = 0; i < N; ++i) {
|
|
1001
|
+
(void)assert0(x[i]);
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
template <size_t N>
|
|
1006
|
+
void vassert_eq(const bitvec<N>& x, const bitvec<N>& y) const {
|
|
1007
|
+
for (size_t i = 0; i < N; ++i) {
|
|
1008
|
+
(void)assert_eq(x[i], y[i]);
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
template <size_t N>
|
|
1013
|
+
void vassert_eq(const bitvec<N>& x, uint64_t y) const {
|
|
1014
|
+
auto v = vbit<N>(y);
|
|
1015
|
+
vassert_eq(x, v);
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
template <size_t N>
|
|
1019
|
+
void vassert_is_bit(const bitvec<N>& a) const {
|
|
1020
|
+
for (size_t i = 0; i < N; ++i) {
|
|
1021
|
+
(void)assert_is_bit(a[i]);
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
template <size_t N>
|
|
1026
|
+
void vmux(const BitW& sel, bitvec<N>& dst, const bitvec<N>& v1,
|
|
1027
|
+
const bitvec<N>& v0) const {
|
|
1028
|
+
for (size_t i = 0; i < N; ++i) {
|
|
1029
|
+
dst[i] = mux(sel, v1[i], v0[i]);
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
private:
|
|
1034
|
+
// return one quad gate for the product eval(a)*eval(b),
|
|
1035
|
+
// optimizing some "obvious" cases.
|
|
1036
|
+
BitW mulv(const BitW& a, const BitW& b) const {
|
|
1037
|
+
if (a.c1 == zero()) {
|
|
1038
|
+
return rebase(zero(), a.c0, b);
|
|
1039
|
+
} else if (b.c1 == zero()) {
|
|
1040
|
+
return mulv(b, a);
|
|
1041
|
+
} else {
|
|
1042
|
+
// Avoid creating the intermediate term 1 * a.x * b.x which is
|
|
1043
|
+
// likely a useless node. Moreover, two nodes (k1 * a.x * b.x)
|
|
1044
|
+
// and (k2 * a.x * b.x) will detect the common subexpression
|
|
1045
|
+
// (a.x * b.x), which will confusingly increment the
|
|
1046
|
+
// common-subexpression counter.
|
|
1047
|
+
EltW x = axy(mulf(a.c1, b.c1), a.x, b.x);
|
|
1048
|
+
x = axpy(x, mulf(a.c0, b.c1), b.x);
|
|
1049
|
+
x = axpy(x, mulf(a.c1, b.c0), a.x);
|
|
1050
|
+
x = apy(x, mulf(a.c0, b.c0));
|
|
1051
|
+
return BitW(x, f_);
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
BitW addv(const BitW& a, const BitW& b) const {
|
|
1056
|
+
if (a.c1 == zero()) {
|
|
1057
|
+
return BitW(addf(a.c0, b.c0), b.c1, b.x);
|
|
1058
|
+
} else if (b.c1 == zero()) {
|
|
1059
|
+
return addv(b, a);
|
|
1060
|
+
} else {
|
|
1061
|
+
EltW x = ax(a.c1, a.x);
|
|
1062
|
+
auto axb = ax(b.c1, b.x);
|
|
1063
|
+
x = add(x, axb);
|
|
1064
|
+
x = apy(x, addf(a.c0, b.c0));
|
|
1065
|
+
return BitW(x, f_);
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
BitW lxor_aux(const BitW& a, const BitW& b, PrimeFieldTypeTag tt) const {
|
|
1070
|
+
// a * b in the xor basis TRUE -> -1, FALSE -> 1
|
|
1071
|
+
// map a, b from standard basis to xor basis
|
|
1072
|
+
Elt mtwo = f_.negf(f_.two());
|
|
1073
|
+
Elt half = f_.half();
|
|
1074
|
+
Elt mhalf = f_.negf(half);
|
|
1075
|
+
|
|
1076
|
+
BitW a1 = rebase(one(), mtwo, a);
|
|
1077
|
+
BitW b1 = rebase(one(), mtwo, b);
|
|
1078
|
+
BitW p = mulv(a1, b1);
|
|
1079
|
+
return rebase(half, mhalf, p);
|
|
1080
|
+
}
|
|
1081
|
+
BitW lxor_aux(const BitW& a, const BitW& b, BinaryFieldTypeTag tt) const {
|
|
1082
|
+
return addv(a, b);
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
size_t pack(uint64_t mask, size_t n, BitW a[/*n*/]) const {
|
|
1086
|
+
size_t j = 0;
|
|
1087
|
+
for (size_t i = 0; i < n; ++i) {
|
|
1088
|
+
if (mask & 1) {
|
|
1089
|
+
a[j++] = a[i];
|
|
1090
|
+
}
|
|
1091
|
+
mask >>= 1;
|
|
1092
|
+
}
|
|
1093
|
+
return j;
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
// carry-propagation equations
|
|
1097
|
+
// (g0, p0) + (g1, p1) = (g1 | (g0 & p1), p0 & p1)
|
|
1098
|
+
// Accumulate in-place into (g1, p1).
|
|
1099
|
+
//
|
|
1100
|
+
// We use the property that g1 and p1 are mutually exclusive (g1&p1
|
|
1101
|
+
// is false), and therefore g1 and (g0 & p1) are also mutually
|
|
1102
|
+
// exclusive.
|
|
1103
|
+
void gp_reduce(const BitW& g0, const BitW& p0, BitW* g1, BitW* p1) const {
|
|
1104
|
+
*g1 = lor_exclusive(*g1, land(g0, *p1));
|
|
1105
|
+
*p1 = land(p0, *p1);
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
// ripple carry propagation
|
|
1109
|
+
void ripple_scan(std::vector<BitW>& g, std::vector<BitW>& p, size_t i0,
|
|
1110
|
+
size_t i1) const {
|
|
1111
|
+
for (size_t i = i0 + 1; i < i1; ++i) {
|
|
1112
|
+
gp_reduce(g[i - 1], p[i - 1], &g[i], &p[i]);
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
// parallel-prefix carry propagation, Sklansky-style [1960]
|
|
1117
|
+
void sklansky_scan(std::vector<BitW>& g, std::vector<BitW>& p, size_t i0,
|
|
1118
|
+
size_t i1) const {
|
|
1119
|
+
if (i1 - i0 > 1) {
|
|
1120
|
+
size_t im = i0 + (i1 - i0) / 2;
|
|
1121
|
+
sklansky_scan(g, p, i0, im);
|
|
1122
|
+
sklansky_scan(g, p, im, i1);
|
|
1123
|
+
for (size_t i = im; i < i1; ++i) {
|
|
1124
|
+
gp_reduce(g[im - 1], p[im - 1], &g[i], &p[i]);
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
// generic add in generate/propagate form, parametrized
|
|
1130
|
+
// by the scan primitive.
|
|
1131
|
+
//
|
|
1132
|
+
// (carry, c) = a + b
|
|
1133
|
+
BitW generic_gp_add(size_t w, BitW c[/*w*/], const BitW a[/*w*/],
|
|
1134
|
+
const BitW b[/*w*/],
|
|
1135
|
+
void (Logic::*scan)(std::vector<BitW>& /*g*/,
|
|
1136
|
+
std::vector<BitW>& /*p*/,
|
|
1137
|
+
size_t /*i0*/, size_t /*i1*/)
|
|
1138
|
+
const) const {
|
|
1139
|
+
if (w == 0) {
|
|
1140
|
+
return bit(0);
|
|
1141
|
+
} else {
|
|
1142
|
+
std::vector<BitW> g(w), p(w);
|
|
1143
|
+
for (size_t i = 0; i < w; ++i) {
|
|
1144
|
+
g[i] = land(a[i], b[i]);
|
|
1145
|
+
p[i] = lxor(a[i], b[i]);
|
|
1146
|
+
c[i] = p[i];
|
|
1147
|
+
}
|
|
1148
|
+
(this->*scan)(g, p, 0, w);
|
|
1149
|
+
for (size_t i = 1; i < w; ++i) {
|
|
1150
|
+
c[i] = lxor(c[i], g[i - 1]);
|
|
1151
|
+
}
|
|
1152
|
+
return g[w - 1];
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
BitW generic_gp_sub(size_t w, BitW c[/*w*/], const BitW a[/*w*/],
|
|
1157
|
+
const BitW b[/*w*/],
|
|
1158
|
+
void (Logic::*scan)(std::vector<BitW>& /*g*/,
|
|
1159
|
+
std::vector<BitW>& /*p*/,
|
|
1160
|
+
size_t /*i0*/, size_t /*i1*/)
|
|
1161
|
+
const) const {
|
|
1162
|
+
// implement as ~(~a + b)
|
|
1163
|
+
std::vector<BitW> t(w);
|
|
1164
|
+
for (size_t j = 0; j < w; ++j) {
|
|
1165
|
+
t[j] = lnot(a[j]);
|
|
1166
|
+
}
|
|
1167
|
+
BitW carry = generic_gp_add(w, c, t.data(), b, scan);
|
|
1168
|
+
for (size_t j = 0; j < w; ++j) {
|
|
1169
|
+
c[j] = lnot(c[j]);
|
|
1170
|
+
}
|
|
1171
|
+
return carry;
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
// Recursion for the a < b comparison.
|
|
1175
|
+
// Let a = (a1, a0) and b = (b1, b0). Then:
|
|
1176
|
+
//
|
|
1177
|
+
// a == b iff a1 == b1 && a0 == b0
|
|
1178
|
+
// a < b iff a1 < b1 || (a1 == b1 && a0 < b0)
|
|
1179
|
+
void lt_reduce(size_t i0, size_t i1, BitW* xeq, BitW* xlt,
|
|
1180
|
+
const BitW a[/*w*/], const BitW b[/*w*/]) const {
|
|
1181
|
+
if (i1 - i0 > 1) {
|
|
1182
|
+
BitW eq0, eq1, lt0, lt1;
|
|
1183
|
+
size_t im = i0 + (i1 - i0) / 2;
|
|
1184
|
+
lt_reduce(i0, im, &eq0, <0, a, b);
|
|
1185
|
+
lt_reduce(im, i1, &eq1, <1, a, b);
|
|
1186
|
+
*xeq = land(eq1, eq0);
|
|
1187
|
+
*xlt = lor_exclusive(lt1, land(eq1, lt0));
|
|
1188
|
+
} else {
|
|
1189
|
+
*xeq = lnot(lxor(a[i0], b[i0]));
|
|
1190
|
+
*xlt = land(lnot(a[i0]), b[i0]);
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
BitW parity(size_t i0, size_t i1, const BitW a[]) const {
|
|
1195
|
+
if (i1 <= i0) {
|
|
1196
|
+
return bit(0);
|
|
1197
|
+
} else if (i1 == i0 + 1) {
|
|
1198
|
+
return a[i0];
|
|
1199
|
+
} else {
|
|
1200
|
+
size_t im = i0 + (i1 - i0) / 2;
|
|
1201
|
+
return lxor(parity(i0, im, a), parity(im, i1, a));
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
BitW eq0(size_t i0, size_t i1, const BitW a[]) const {
|
|
1206
|
+
if (i1 <= i0) {
|
|
1207
|
+
return bit(1);
|
|
1208
|
+
} else if (i1 == i0 + 1) {
|
|
1209
|
+
return lnot(a[i0]);
|
|
1210
|
+
} else {
|
|
1211
|
+
size_t im = i0 + (i1 - i0) / 2;
|
|
1212
|
+
return land(eq0(i0, im, a), eq0(im, i1, a));
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
BitW eq_reduce(size_t i0, size_t i1, const BitW a[], const BitW b[]) const {
|
|
1217
|
+
if (i1 <= i0) {
|
|
1218
|
+
return bit(1);
|
|
1219
|
+
} else if (i1 == i0 + 1) {
|
|
1220
|
+
return lnot(lxor(a[i0], b[i0]));
|
|
1221
|
+
} else {
|
|
1222
|
+
size_t im = i0 + (i1 - i0) / 2;
|
|
1223
|
+
return land(eq_reduce(i0, im, a, b), eq_reduce(im, i1, a, b));
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
const Backend* bk_;
|
|
1228
|
+
};
|
|
1229
|
+
|
|
1230
|
+
} // namespace proofs
|
|
1231
|
+
|
|
1232
|
+
#endif // PRIVACY_PROOFS_ZK_LIB_CIRCUITS_LOGIC_LOGIC_H_
|