mirror of
https://github.com/odin-lang/Odin.git
synced 2026-07-12 10:59:33 +00:00
core/crypto/_bigint: Initial import
This commit is contained in:
@@ -13,10 +13,11 @@ constant-time byte comparison.
|
||||
- The crypto packages are not thread-safe.
|
||||
- Best-effort is make to mitigate timing side-channels on reasonable
|
||||
architectures. Architectures that are known to be unreasonable include
|
||||
but are not limited to i386, i486, and WebAssembly.
|
||||
but are not limited to i386, i486, VIA Nano 2000, ARM7T/ARM9T/Cortex-M3,
|
||||
and WASM.
|
||||
- Implementations assume a 64-bit architecture (64-bit integer arithmetic
|
||||
is fast, and includes add-with-carry, sub-with-borrow, and full-result
|
||||
multiply).
|
||||
is fast, and includes contant-time add-with-carry, sub-with-borrow, and
|
||||
full-result multiply).
|
||||
- Hardware sidechannels are explicitly out of scope for this package.
|
||||
Notable examples include but are not limited to:
|
||||
- Power/RF side-channels etc.
|
||||
@@ -29,4 +30,4 @@ constant-time byte comparison.
|
||||
|
||||
## License
|
||||
|
||||
This library is made available under the zlib license.
|
||||
This library is made available under the zlib license.
|
||||
|
||||
904
core/crypto/_bigint/i31.odin
Normal file
904
core/crypto/_bigint/i31.odin
Normal file
@@ -0,0 +1,904 @@
|
||||
// Constant time Big Integers
|
||||
package _bigint
|
||||
|
||||
// Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
// 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.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHORS “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 AUTHORS 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.
|
||||
|
||||
import "base:intrinsics"
|
||||
import "core:crypto"
|
||||
import subtle "core:crypto/_subtle"
|
||||
import "core:slice"
|
||||
|
||||
// Integers 'i31'
|
||||
// --------------
|
||||
//
|
||||
// The 'i31' functions implement computations on big integers using
|
||||
// an internal representation as an array of 32-bit integers. For
|
||||
// an array `x`:
|
||||
// -- x[0] encodes the array length and the "announced bit length"
|
||||
// of the integer: namely, if the announced bit length is k,
|
||||
// then x[0] = ((k / 31) << 5) + (k % 31).
|
||||
// -- x[1], x[2]... contain the value in little-endian order, 31
|
||||
// bits per word (x[1] contains the least significant 31 bits).
|
||||
// The upper bit of each word is 0.
|
||||
//
|
||||
// Multiplications rely on the elementary 32x32->64 multiplication.
|
||||
//
|
||||
// The announced bit length specifies the number of bits that are
|
||||
// significant in the subsequent 32-bit words. Unused bits in the
|
||||
// last (most significant) word are set to 0; subsequent words are
|
||||
// uninitialized and need not exist at all.
|
||||
//
|
||||
// The execution time and memory access patterns of all computations
|
||||
// depend on the announced bit length, but not on the actual word
|
||||
// values. For modular integers, the announced bit length of any integer
|
||||
// modulo `n` is equal to the actual bit length of `n`; thus, computations
|
||||
// on modular integers are "constant-time" (only the modulus length may leak).
|
||||
|
||||
I31_MASK :: 0x7fff_ffff
|
||||
|
||||
// Compute the bit length of a 32-bit integer.
|
||||
// Returned value is between 0 and 32 (inclusive).
|
||||
@(require_results)
|
||||
_u32_bit_length :: proc "contextless" (x: u32) -> (length: u32) {
|
||||
x := x
|
||||
k := subtle.neq(x, 0)
|
||||
c := subtle.gt(x, 0xFFFF); x = subtle.csel(x, x >> 16, c); k += c << 4
|
||||
c = subtle.gt(x, 0x00FF); x = subtle.csel(x, x >> 8, c); k += c << 3
|
||||
c = subtle.gt(x, 0x000F); x = subtle.csel(x, x >> 4, c); k += c << 2
|
||||
c = subtle.gt(x, 0x0003); x = subtle.csel(x, x >> 2, c); k += c << 1
|
||||
k += subtle.gt(x, 0x0001)
|
||||
return k
|
||||
}
|
||||
|
||||
// Multiply two 31-bit integers, with a 62-bit result. This default
|
||||
// implementation assumes that the basic multiplication operator
|
||||
// yields constant-time code.
|
||||
//
|
||||
// The mul31_lo() returns only the low 31 bits of the product.
|
||||
//
|
||||
// Note/Odin:
|
||||
// The original BearSSL code provides alternative implemenetations
|
||||
// of these routines gated behind `BR_CT_MUL31`, however that macro
|
||||
// is only useful on Intel 80386/80486, VIA Nano 2000, and ARM7T/ARM9T.
|
||||
@(require_results)
|
||||
_mul31 :: #force_inline proc "contextless" (x, y: u32) -> (res: u64) {
|
||||
return u64(x) * u64(y)
|
||||
}
|
||||
|
||||
@(private="file", require_results)
|
||||
_mul31_lo :: #force_inline proc "contextless" (x, y: u32) -> (res: u32) {
|
||||
return (x * y) & I31_MASK
|
||||
}
|
||||
|
||||
// Wrapper for `div_rem`; the remainder is returned, and the quotient is
|
||||
// discarded.
|
||||
@(private, require_results)
|
||||
_rem_u32 :: #force_inline proc "contextless" (hi: u32, lo: u32, d: u32) -> (res: u32) {
|
||||
_, rem := div_rem_u32(hi, lo, d)
|
||||
return rem
|
||||
}
|
||||
|
||||
// Wrapper for `div_rem`; the quotient is returned, and the remainder is
|
||||
// discarded.
|
||||
@(private="file", require_results)
|
||||
_div_u32 :: #force_inline proc "contextless" (hi: u32, lo: u32, d: u32) -> (quo: u32) {
|
||||
q, _ := div_rem_u32(hi, lo, d)
|
||||
return q
|
||||
}
|
||||
|
||||
// Constant-time division. The dividend `hi:lo` is divided by the divisor `d`;
|
||||
// the quotient and remainder are returned.
|
||||
//
|
||||
// If `hi == d`, then the quotient does not fit on 32 bits; returned value is thus truncated.
|
||||
// If `hi > d`, returned values are indeterminate.
|
||||
@(require_results)
|
||||
div_rem_u32 :: proc "contextless" (hi: u32, lo: u32, d: u32) -> (quo: u32, rem: u32) {
|
||||
// TODO: optimize this
|
||||
hi := hi
|
||||
lo := lo
|
||||
ch := subtle.eq(hi, d)
|
||||
hi = subtle.csel(hi, 0, ch)
|
||||
for k := uint(31); k > 0; k -= 1 {
|
||||
j := 32 - k
|
||||
w := (hi << j) | (lo >> k)
|
||||
ctl := subtle.ge(w, d) | (hi >> k)
|
||||
hi2 := (w - d) >> j
|
||||
lo2 := lo - (d << k)
|
||||
hi = subtle.csel(hi, hi2, ctl)
|
||||
lo = subtle.csel(lo, lo2, ctl)
|
||||
quo |= ctl << k
|
||||
}
|
||||
cf := subtle.ge(lo, d) | hi
|
||||
quo |= cf
|
||||
rem = subtle.csel(lo, lo - d, cf)
|
||||
return
|
||||
}
|
||||
|
||||
// i31_rem computes x / y and returns the remainder.
|
||||
@(require_results)
|
||||
i31_rem :: proc "contextless" (x: []u32, y: u32) -> u32 {
|
||||
words := uint(x[0] + 31) >> 5
|
||||
x_ := x[1:]
|
||||
|
||||
r: u32
|
||||
for i := int(words-1); i >= 0; i -= 1 {
|
||||
r = _rem_u32(r, x_[i], y)
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
// Test whether an integer `x` is zero.
|
||||
@(optimization_mode="none", require_results)
|
||||
i31_is_zero :: proc "contextless" (x: []u32) -> (res: u32) {
|
||||
z: u32
|
||||
|
||||
for u := (x[0] + 31) >> 5; u > 0; u -= 1 {
|
||||
z |= x[u]
|
||||
}
|
||||
return ~(z | -z) >> 31
|
||||
}
|
||||
|
||||
// Add `b` to `a` and return the `carry` (`0` or `1`). if `ctl` is `1`.
|
||||
// If `ctl` is `0`, `a` is left alone but the `carry` will still be computed.
|
||||
//
|
||||
// The slices `a` and `b` MUST have the same announced bit length (in subscript `0`)
|
||||
//
|
||||
// `a` and `b` MAY be the same array, but partial overlap is not allowed.
|
||||
@(require_results)
|
||||
i31_add :: proc "contextless" (a: []u32, b: []u32, ctl: u32) -> (carry: u32) {
|
||||
words := uint(a[0] + 63) >> 5
|
||||
for u in 1..<words {
|
||||
aw := a[u]
|
||||
bw := b[u]
|
||||
naw := aw + bw + carry
|
||||
carry = naw >> 31
|
||||
a[u] = subtle.csel(aw, naw & I31_MASK, ctl)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Subtract `b` from `a` and return the `carry` (`0` or `1`), if `ctl` is `1`.
|
||||
// If `ctl` is `0`, then `a` is unmodified, but the carry is still computed
|
||||
// and returned.
|
||||
//
|
||||
// The slices `a` and `b` MUST have the same announced bit length (in subscript `0`)
|
||||
//
|
||||
// `a` and `b` MAY be the same array, but partial overlap is not allowed.
|
||||
@(require_results)
|
||||
i31_sub :: proc "contextless" (a: []u32, b: []u32, ctl: u32) -> (carry: u32) {
|
||||
words := uint(a[0] + 63) >> 5
|
||||
for u in 1..<words {
|
||||
aw := a[u]
|
||||
bw := b[u]
|
||||
naw := aw - bw - carry
|
||||
carry = naw >> 31
|
||||
a[u] = subtle.csel(aw, naw & I31_MASK, ctl)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Compute the ENCODED actual bit length of an integer `x`.
|
||||
// The argument `x` should point to the first (least significant)
|
||||
// value word of the integer.
|
||||
//
|
||||
// The upper bit of each value word MUST be `0`.
|
||||
//
|
||||
// Returned value is `((k / 31) << 5) + (k % 31)` if the bit length is `k`.
|
||||
//
|
||||
// CT: value or length of `x` does not leak.
|
||||
@(require_results)
|
||||
i31_bit_length :: proc "contextless" (x: []u32) -> (res: u32) {
|
||||
tw, twk: u32
|
||||
|
||||
xlen := len(x)
|
||||
for xlen > 0 {
|
||||
xlen -= 1
|
||||
c := subtle.eq(tw, 0)
|
||||
w := x[xlen]
|
||||
|
||||
tw = subtle.csel(tw, w, c)
|
||||
twk = subtle.csel(twk, u32(xlen), c)
|
||||
}
|
||||
return (twk << 5) + _u32_bit_length(tw)
|
||||
}
|
||||
|
||||
// Decode an integer from its big-endian unsigned representation. The
|
||||
// "true" bit length of the integer is computed and set in the encoded
|
||||
// announced bit length (`x[0]`), but all words of `x` corresponding to
|
||||
// the full slice of source bytes.
|
||||
//
|
||||
// `x` needs to have a minimum length of: `1 + ((len(src) * 8) + 31) / 31`
|
||||
//
|
||||
// CT: value or length of `x` does not leak.
|
||||
i31_decode :: proc "contextless" (x: []u32, src: []byte) {
|
||||
u := len(src) - 1
|
||||
v := 1
|
||||
acc := u32(0)
|
||||
acc_len := uint(0)
|
||||
for u >= 0 {
|
||||
b := u32(src[u])
|
||||
acc |= b << acc_len
|
||||
acc_len += 8
|
||||
if acc_len >= 31 {
|
||||
x[v] = acc & I31_MASK
|
||||
acc_len -= 31
|
||||
acc = b >> (8 - acc_len)
|
||||
v += 1
|
||||
}
|
||||
u -= 1
|
||||
}
|
||||
if acc_len != 0 {
|
||||
x[v] = acc
|
||||
v += 1
|
||||
}
|
||||
x[0] = i31_bit_length(x[1:])
|
||||
}
|
||||
|
||||
// Decode an integer from its big-endian unsigned representation.
|
||||
// The integer MUST be lower than `m`; the (encoded) announced bit length
|
||||
// written in `x` will be equal to that of `m`. All bytes from the
|
||||
// `src` slice are read.
|
||||
//
|
||||
// Returned value is `1` if the decode value fits within the modulus, `0`
|
||||
// otherwise. In the latter case, the `x` buffer will be set to `0` (but
|
||||
// still with the announced bit length of `m`).
|
||||
//
|
||||
// CT: value or length of `x` does not leak. Memory access pattern depends
|
||||
// only `src`'s length and the announced bit length of `m`. Whether `x` fits or
|
||||
// not does not leak either.
|
||||
@(require_results)
|
||||
i31_decode_mod :: proc "contextless" (x: []u32, src: []byte, m: []u32) -> (res: u32) {
|
||||
// Two-pass algorithm: in the first pass, we determine whether the
|
||||
// value fits; in the second pass, we do the actual write.
|
||||
//
|
||||
// During the first pass, `res` contains the comparison result so far:
|
||||
// 0x00000000 value is equal to the modulus
|
||||
// 0x00000001 value is greater than the modulus
|
||||
// 0xFFFFFFFF value is lower than the modulus
|
||||
//
|
||||
// Since we iterate starting with the least significant bytes (at
|
||||
// the end of `src`), each new comparison overrides the previous
|
||||
// except when the comparison yields 0 (equal).
|
||||
//
|
||||
// During the second pass, `res` is either 0xFFFFFFFF (value fits) 0x00000000 (value does not fit).
|
||||
// We must iterate over all bytes of the source, _and_ possibly
|
||||
// some extra virtual bytes (with value 0) so as to cover the
|
||||
// complete modulus as well. We also add 4 such extra bytes beyond
|
||||
// the modulus length because it then guarantees that no accumulated
|
||||
// partial word remains to be processed.
|
||||
_len := uint(len(src))
|
||||
mlen := uint((m[0] + 31) >> 5)
|
||||
tlen := uint(mlen << 2)
|
||||
if tlen < _len {
|
||||
tlen = _len
|
||||
}
|
||||
tlen += 4
|
||||
|
||||
for pass in 0..<2 {
|
||||
v := uint(1)
|
||||
acc := u32(0)
|
||||
acc_len := u32(0)
|
||||
|
||||
for u in uint(0)..<tlen {
|
||||
b: u32 = ---
|
||||
|
||||
if u < _len {
|
||||
b = u32(src[_len - 1 - u])
|
||||
} else {
|
||||
b = 0
|
||||
}
|
||||
|
||||
acc |= (b << acc_len)
|
||||
acc_len += 8
|
||||
if acc_len >= 31 {
|
||||
xw := acc & I31_MASK
|
||||
acc_len -= 31
|
||||
|
||||
acc = b >> (8 - acc_len)
|
||||
if v <= mlen {
|
||||
if pass == 1 {
|
||||
x[v] = res & xw
|
||||
} else {
|
||||
cc := u32(subtle.cmp(xw, m[v]))
|
||||
res = subtle.csel(cc, res, subtle.eq(cc, 0))
|
||||
}
|
||||
} else {
|
||||
if pass == 0 {
|
||||
res = subtle.csel(1, res, subtle.eq(xw, 0))
|
||||
}
|
||||
}
|
||||
v += 1
|
||||
}
|
||||
}
|
||||
|
||||
// When we reach this point at the end of the first pass:
|
||||
// r is either 0, 1 or -1; we want to set r to 0 if it
|
||||
// is equal to 0 or 1, and leave it to -1 otherwise.
|
||||
//
|
||||
// When we reach this point at the end of the second pass:
|
||||
// r is either 0 or -1; we want to leave that value
|
||||
// untouched. This is a subcase of the previous.
|
||||
res >>= 1
|
||||
res |= (res << 1)
|
||||
}
|
||||
|
||||
x[0] = m[0]
|
||||
|
||||
return res & 1
|
||||
}
|
||||
|
||||
// Zeroize integer `x`. The announced bit length is set to the provided value,
|
||||
// and the corresponding words are set to 0. The ENCODED bit length is expected
|
||||
//here.
|
||||
i31_zero :: proc "contextless" (x: []u32, bit_len: u32) {
|
||||
x[0] = bit_len
|
||||
intrinsics.mem_zero(raw_data(x[1:]), ((bit_len + 31) >> 5) * size_of(u32))
|
||||
}
|
||||
|
||||
// Make a random integer of the provided size. The size is encoded.
|
||||
// The header word is untouched.
|
||||
i31_mkrand :: proc(x: []u32, esize: u32) {
|
||||
_len := (esize + 31) >> 5
|
||||
x_ := slice.reinterpret([]byte, x)
|
||||
crypto.rand_bytes(x_[4:4 + _len * size_of(u32)])
|
||||
for u in 1..<_len {
|
||||
x[u] &= I31_MASK
|
||||
}
|
||||
m := _len & 31
|
||||
if m == 0 {
|
||||
x[_len] &= I31_MASK
|
||||
} else {
|
||||
x[_len] &= I31_MASK >> (31 - m)
|
||||
}
|
||||
}
|
||||
|
||||
// Right-shift an integer. The shift amount must be lower than 31 bits.
|
||||
i31_rshift :: proc "contextless" (x: []u32, shift_amount: i32) {
|
||||
_len := uint(x[0] + 31) >> 5
|
||||
if _len == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
count := uint(shift_amount)
|
||||
|
||||
r := x[1] >> count
|
||||
for u in 2..= _len {
|
||||
w := u32(x[u])
|
||||
|
||||
x[u - 1] = ((w << (31 - count)) | r) & I31_MASK
|
||||
r = w >> count
|
||||
}
|
||||
x[_len] = r
|
||||
}
|
||||
|
||||
// Reduce integer `a` modulo `m`. The result is written to `x`,
|
||||
// and its announced bit length is set to be equal to that of `m`.
|
||||
//
|
||||
// `x` MUST be distinct from `a` and `m`.
|
||||
//
|
||||
// CT: only announced bit lengths leak, not values of `x`, `a` or `m`.
|
||||
i31_reduce :: proc "contextless" (x: []u32, a: []u32, m: []u32) {
|
||||
m_bitlen := m[0]
|
||||
mlen := uint(m_bitlen + 31) >> 5
|
||||
|
||||
x[0] = m_bitlen
|
||||
if m_bitlen == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// If the source is shorter, then simply copy all words from a[]
|
||||
// and zero out the upper words.
|
||||
a_bitlen := a[0]
|
||||
alen := uint(a_bitlen + 31) >> 5
|
||||
if a_bitlen < m_bitlen {
|
||||
copy(x[1:], a[1:][:alen])
|
||||
for u in alen..<mlen {
|
||||
x[u + 1] = 0
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// The source length is at least equal to that of the modulus.
|
||||
// We must thus copy N-1 words, and input the remaining words one
|
||||
// by one.
|
||||
copy(x[1:], a[2 + (alen - mlen):][:mlen - 1])
|
||||
x[mlen] = 0
|
||||
for u := 1 + alen - mlen; u > 0; u -= 1 {
|
||||
i31_muladd_small(x, a[u], m)
|
||||
}
|
||||
}
|
||||
|
||||
// Decode an integer from its big-endian unsigned representation, and
|
||||
// reduce it modulo the provided modulus `m`. The announced bit length
|
||||
// of the result is set to be equal to that of the modulus.
|
||||
//
|
||||
// `x` MUST be distinct from `m`.
|
||||
i31_decode_reduce :: proc "contextless" (x: []u32, src: []byte, m: []u32) {
|
||||
// Get the encoded bit length.
|
||||
m_ebitlen := m[0]
|
||||
|
||||
// Special case for an invalid (null) modulus.
|
||||
if m_ebitlen == 0 {
|
||||
x[0] = 0
|
||||
return
|
||||
}
|
||||
|
||||
// Clear the destination.
|
||||
i31_zero(x, m_ebitlen)
|
||||
|
||||
// First decode directly as many bytes as possible.
|
||||
// This requires computing the actual bit length.
|
||||
m_rbitlen := m_ebitlen >> 5
|
||||
m_rbitlen = (m_ebitlen & 31) + (m_rbitlen << 5) - m_rbitlen
|
||||
|
||||
mblen := uint(m_rbitlen + 7) >> 3
|
||||
k := mblen - 1
|
||||
_len := uint(len(src))
|
||||
|
||||
if k >= _len {
|
||||
i31_decode(x, src)
|
||||
x[0] = m_ebitlen
|
||||
return
|
||||
}
|
||||
|
||||
i31_decode(x, src[:k])
|
||||
x[0] = m_ebitlen
|
||||
|
||||
// Input remaining bytes, using 31-bit words.
|
||||
acc := u32(0)
|
||||
acc_len := uint(0)
|
||||
|
||||
for {
|
||||
v := u32(src[k])
|
||||
|
||||
if acc_len >= 23 {
|
||||
acc_len -= 23
|
||||
acc <<= (8 - acc_len)
|
||||
acc |= v >> acc_len
|
||||
i31_muladd_small(x, acc, m)
|
||||
acc = v & (0xFF >> (8 - acc_len))
|
||||
} else {
|
||||
acc = (acc << 8) | v
|
||||
acc_len += 8
|
||||
}
|
||||
|
||||
if k += 1; k >= _len {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// We may have some bits accumulated. We then perform a shift to
|
||||
// be able to inject these bits as a full 31-bit word.
|
||||
if acc_len != 0 {
|
||||
acc = (acc | (x[1] << acc_len)) & I31_MASK
|
||||
i31_rshift(x, i32(31 - acc_len))
|
||||
i31_muladd_small(x, acc, m)
|
||||
}
|
||||
}
|
||||
|
||||
// Multiply `x` by 2^31 and then add integer `z`, modulo `m`.
|
||||
// This function assumes that `x` and `m` have the same announced bit
|
||||
// length, the announced bit length of `m` matches its true bit length.
|
||||
//
|
||||
// `x` and `m` MUST be distinct arrays.
|
||||
// `z` MUST fit in 31 bits (upper bit set to 0).
|
||||
//
|
||||
// CT: only the common announced bit length of `x` and `m` leaks, not
|
||||
// the values of `x`, `z` or `m`.
|
||||
i31_muladd_small :: proc "contextless" (x: []u32, z: u32, m: []u32) {
|
||||
// We can test on the modulus bit length since we accept to leak
|
||||
// that length.
|
||||
m_bitlen := m[0]
|
||||
if m_bitlen == 0 {
|
||||
return
|
||||
}
|
||||
hi: u32
|
||||
if m_bitlen <= 31 {
|
||||
hi = x[1] >> 1
|
||||
lo := (x[1] << 31) | z
|
||||
x[1] = _rem_u32(hi, lo, m[1])
|
||||
return
|
||||
}
|
||||
mlen := uint(m_bitlen + 31) >> 5
|
||||
mblr := uint(m_bitlen) & 31
|
||||
|
||||
// Principle: we estimate the quotient (x*2^31+z)/m by
|
||||
// doing a 64/32 division with the high words.
|
||||
//
|
||||
// Let:
|
||||
// w = 2^31
|
||||
// a = (w*a0 + a1) * w^N + a2
|
||||
// b = b0 * w^N + b2
|
||||
// such that:
|
||||
// 0 <= a0 < w
|
||||
// 0 <= a1 < w
|
||||
// 0 <= a2 < w^N
|
||||
// w/2 <= b0 < w
|
||||
// 0 <= b2 < w^N
|
||||
// a < w*b
|
||||
// I.e. the two top words of a are a0:a1, the top word of b is
|
||||
// b0, we ensured that b0 is "full" (high bit set), and a is
|
||||
// such that the quotient q = a/b fits on one word (0 <= q < w).
|
||||
//
|
||||
// If a = b*q + r (with 0 <= r < q), we can estimate q by
|
||||
// doing an Euclidean division on the top words:
|
||||
// a0*w+a1 = b0*u + v (with 0 <= v < b0)
|
||||
// Then the following holds:
|
||||
// 0 <= u <= w
|
||||
// u-2 <= q <= u
|
||||
hi = x[mlen]
|
||||
a0, a1, b0: u32
|
||||
if mblr == 0 {
|
||||
a0 = x[mlen]
|
||||
intrinsics.mem_copy(raw_data(x[2:]), raw_data(x[1:]), (mlen - 1) * size_of(u32))
|
||||
x[1] = z
|
||||
a1 = x[mlen]
|
||||
b0 = m[mlen]
|
||||
} else {
|
||||
a0 = ((x[mlen] << (31 - mblr)) | (x[mlen - 1] >> mblr)) & I31_MASK
|
||||
intrinsics.mem_copy(raw_data(x[2:]), raw_data(x[1:]), (mlen - 1) * size_of(u32))
|
||||
x[1] = z
|
||||
a1 = ((x[mlen] << (31 - mblr)) | (x[mlen - 1] >> mblr)) & I31_MASK
|
||||
b0 = ((m[mlen] << (31 - mblr)) | (m[mlen - 1] >> mblr)) & I31_MASK
|
||||
}
|
||||
|
||||
// We estimate a divisor q. If the quotient returned by div()
|
||||
// is g:
|
||||
// -- If a0 == b0 then g == 0; we want q = 0x7FFFFFFF.
|
||||
// -- Otherwise:
|
||||
// -- if g == 0 then we set q = 0;
|
||||
// -- otherwise, we set q = g - 1.
|
||||
// The properties described above then ensure that the true
|
||||
// quotient is q-1, q or q+1.
|
||||
//
|
||||
// Take care that a0, a1 and b0 are 31-bit words, not 32-bit. We
|
||||
// must adjust the parameters to br_div() accordingly.
|
||||
g := _div_u32(a0 >> 1, a1 | (a0 << 31), b0)
|
||||
q := subtle.csel(subtle.csel(g - 1, 0, subtle.eq(g, 0)), I31_MASK, subtle.eq(a0, b0))
|
||||
|
||||
// We subtract q*m from x (with the extra high word of value 'hi').
|
||||
// Since q may be off by 1 (in either direction), we may have to
|
||||
// add or subtract m afterwards.
|
||||
//
|
||||
// The 'tb' flag will be true (1) at the end of the loop if the
|
||||
// result is greater than or equal to the modulus (not counting
|
||||
// 'hi' or the carry).
|
||||
cc := u32(0)
|
||||
tb := u32(1)
|
||||
for u in 1..= mlen {
|
||||
mw := m[u]
|
||||
zl := _mul31(mw, q) + u64(cc)
|
||||
cc = u32(zl >> 31)
|
||||
zw := u32(zl) & I31_MASK
|
||||
xw := x[u]
|
||||
nxw := xw - zw
|
||||
cc += nxw >> 31
|
||||
nxw &= I31_MASK
|
||||
x[u] = nxw
|
||||
tb = subtle.csel(subtle.gt(nxw, mw), tb, subtle.eq(nxw, mw))
|
||||
}
|
||||
|
||||
// If we underestimated q, then either cc < hi (one extra bit
|
||||
// beyond the top array word), or cc == hi and tb is true (no
|
||||
// extra bit, but the result is not lower than the modulus). In
|
||||
// these cases we must subtract m once.
|
||||
//
|
||||
// Otherwise, we may have overestimated, which will show as
|
||||
// cc > hi (thus a negative result). Correction is adding m once.
|
||||
over := subtle.gt(cc, hi)
|
||||
under := ~over & (tb | subtle.lt(cc, hi))
|
||||
_ = i31_add(x, m, over)
|
||||
_ = i31_sub(x, m, under)
|
||||
}
|
||||
|
||||
// Encode an integer into its big-endian unsigned representation. The
|
||||
// output length in bytes is provided (parameter 'len'); if the length
|
||||
// is too short then the integer is appropriately truncated; if it is
|
||||
// too long then the extra bytes are set to 0.
|
||||
i31_encode :: proc "contextless" (dst: []byte, x: []u32) {
|
||||
xlen := uint(x[0] + 31) >> 5
|
||||
if xlen == 0 {
|
||||
intrinsics.mem_zero(raw_data(dst[:]), len(dst) * size_of(u32))
|
||||
return
|
||||
}
|
||||
_len := uint(len(dst))
|
||||
k := uint(1)
|
||||
acc := u32(0)
|
||||
acc_len := uint(0)
|
||||
for _len != 0 {
|
||||
w := (k <= xlen) ? x[k] : 0
|
||||
k += 1
|
||||
if (acc_len == 0) {
|
||||
acc = w
|
||||
acc_len = 31
|
||||
} else {
|
||||
z := acc | (w << acc_len)
|
||||
acc_len -= 1
|
||||
acc = w >> (31 - acc_len)
|
||||
if _len >= 4 {
|
||||
_len -= 4
|
||||
ptr := (^u32be)(raw_data(dst[_len:]))
|
||||
intrinsics.unaligned_store(ptr, u32be(z))
|
||||
} else {
|
||||
switch _len {
|
||||
case 3:
|
||||
dst[_len - 3] = byte(z >> 16)
|
||||
fallthrough
|
||||
case 2:
|
||||
dst[_len - 2] = byte(z >> 8)
|
||||
fallthrough
|
||||
case 1:
|
||||
dst[_len - 1] = byte(z)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compute `-(1/x) % 2^31`. If `x` is even, then this function returns `0`.
|
||||
i31_ninv31 :: proc "contextless" (x: u32) -> (y: u32) {
|
||||
y = 2 - x
|
||||
y *= 2 - y * x
|
||||
y *= 2 - y * x
|
||||
y *= 2 - y * x
|
||||
y *= 2 - y * x
|
||||
return subtle.csel(0, -y, x & 1) & I31_MASK
|
||||
}
|
||||
|
||||
// Compute a modular Montgomery multiplication. `d` is filled with the
|
||||
// value of `x*y/R % m` (where `R` is the Montgomery factor).
|
||||
//
|
||||
// The array `d` MUST be distinct from `x`, `y` and `m`[].
|
||||
// `x` and `y` MUST be numerically lower than `m`.
|
||||
//
|
||||
// `x` and `y` MAY be the same array.
|
||||
//
|
||||
// The `m0i` parameter is equal to `-(1/m0) mod 2^31`, where `m0` is the least
|
||||
// significant value word of `m` (this works only if `m` is an odd integer).
|
||||
i31_montymul :: proc "contextless" (d: []u32, x: []u32, y: []u32, m: []u32, m0i: u32) {
|
||||
// Each outer loop iteration computes:
|
||||
// `d <- (d + xu*y + f*m) / 2^31`
|
||||
// We have `xu <= 2^31-1` and `f <= 2^31-1`.
|
||||
// Thus, if `d <= 2*m-1` on input, then:
|
||||
// `2*m-1 + 2*(2^31-1)*m <= (2^32)*m-1`
|
||||
// and the new `d` value is less than `2*m`.
|
||||
//
|
||||
// We represent `d` over 31-bit words, with an extra word `dh`,
|
||||
// which can thus be only 0 or 1.
|
||||
_len := uint((m[0] + 31) >> 5)
|
||||
len4 := _len & ~uint(3)
|
||||
i31_zero(d, m[0])
|
||||
dh := u32(0)
|
||||
for u in 0..<_len {
|
||||
// The carry for each operation fits on 32 bits:
|
||||
// `d[v+1] <= 2^31-1`
|
||||
// `xu*y[v+1] <= (2^31-1)*(2^31-1)`
|
||||
// `f*m[v+1] <= (2^31-1)*(2^31-1)`
|
||||
// `r <= 2^32-1`
|
||||
// `(2^31-1) + 2*(2^31-1)*(2^31-1) + (2^32-1) = 2^63 - 2^31`
|
||||
//
|
||||
// After division by `2^31`, the new `r` is then at most `2^32-1`
|
||||
//
|
||||
// Using a 32-bit carry has performance benefits on 32-bit
|
||||
// systems; however, on 64-bit architectures, we prefer to
|
||||
// keep the carry (r) in a 64-bit register, thus avoiding some
|
||||
// "clear high bits" operations.
|
||||
xu := x[u + 1]
|
||||
f := _mul31_lo((d[1] + _mul31_lo(xu, y[1])), m0i)
|
||||
|
||||
r := u64(0)
|
||||
v := uint(0)
|
||||
for ; v < len4; v += 4 {
|
||||
z := u64(d[v + 1]) + _mul31(xu, y[v + 1]) + _mul31(f, m[v + 1]) + r
|
||||
r = z >> 31
|
||||
d[v + 0] = u32(z) & I31_MASK
|
||||
z = u64(d[v + 2]) + _mul31(xu, y[v + 2]) + _mul31(f, m[v + 2]) + r
|
||||
r = z >> 31
|
||||
d[v + 1] = u32(z) & I31_MASK
|
||||
z = u64(d[v + 3]) + _mul31(xu, y[v + 3]) + _mul31(f, m[v + 3]) + r
|
||||
r = z >> 31
|
||||
d[v + 2] = u32(z) & I31_MASK
|
||||
z = u64(d[v + 4]) + _mul31(xu, y[v + 4]) + _mul31(f, m[v + 4]) + r
|
||||
r = z >> 31
|
||||
d[v + 3] = u32(z) & I31_MASK
|
||||
}
|
||||
for ; v < _len; v += 1 {
|
||||
z := u64(d[v + 1]) + _mul31(xu, y[v + 1]) + _mul31(f, m[v + 1]) + r
|
||||
r = z >> 31
|
||||
d[v] = u32(z) & I31_MASK
|
||||
}
|
||||
|
||||
// Since the new `dh` can only be `0` or `1`, the addition of
|
||||
// the old dh with the carry MUST fit on 32 bits, and
|
||||
// thus can be done into dh itself.
|
||||
dh += u32(r)
|
||||
d[_len] = dh & I31_MASK
|
||||
dh >>= 31
|
||||
}
|
||||
|
||||
// We must write back the bit length because it was overwritten in
|
||||
// the loop (not overwriting it would require a test in the loop,
|
||||
// which would yield bigger and slower code).
|
||||
d[0] = m[0]
|
||||
|
||||
// `d` may still be greater than `m` at that point; notably, the `dh`
|
||||
// word may be non-zero.
|
||||
_ = i31_sub(d, m, subtle.neq(dh, 0) | subtle.not(i31_sub(d, m, 0)))
|
||||
}
|
||||
|
||||
// Convert a modular integer to Montgomery representation.
|
||||
//
|
||||
// The integer `x` MUST be lower than `m`, but with the same announced bit length.
|
||||
i31_to_monty :: proc "contextless" (x: []u32, m: []u32) {
|
||||
// uint32_t k;
|
||||
for k := (m[0] + 31) >> 5; k > 0; k -= 1 {
|
||||
i31_muladd_small(x, 0, m)
|
||||
}
|
||||
}
|
||||
|
||||
// Convert a modular integer back from Montgomery representation.
|
||||
//
|
||||
// The integer `x` MUST be lower than `m`[], but with the same announced bit
|
||||
// length.
|
||||
//
|
||||
// The `m0i` parameter is equal to `-(1/m0) mod 2^32`, where `m0` is the least
|
||||
// significant value word of `m` (this works only if `m` is an odd integer).
|
||||
i31_from_monty :: proc "contextless" (x: []u32, m: []u32, m0i: u32) {
|
||||
_len := uint(m[0] + 31) >> 5
|
||||
for _ in 0..<_len {
|
||||
f := _mul31_lo(x[1], m0i)
|
||||
cc := u64(0)
|
||||
for v in 0..<_len {
|
||||
z := u64(x[v + 1]) + _mul31(f, m[v + 1]) + cc
|
||||
cc = z >> 31
|
||||
if v != 0 {
|
||||
x[v] = u32(z & I31_MASK)
|
||||
}
|
||||
}
|
||||
x[_len] = u32(cc)
|
||||
}
|
||||
|
||||
// We may have to do an extra subtraction, but only if the value in `x`
|
||||
// is indeed greater than or equal to that of `m`, which is why we must
|
||||
// do two calls:
|
||||
// - First call computes the carry
|
||||
// - Second call performs the subtraction only if the carry is 0).
|
||||
_ = i31_sub(x, m, subtle.not(i31_sub(x, m, 0)))
|
||||
}
|
||||
|
||||
// Compute a modular exponentiation.
|
||||
//
|
||||
// `x` MUST be an integer modulo `m` (same announced bit length, lower value).
|
||||
// `m` MUST be odd.
|
||||
//
|
||||
// The exponent `e` is in big-endian unsigned notation.
|
||||
//
|
||||
// The `m0i` parameter is equal to `-(1/m0) mod 2^31`, where `m0` is the least
|
||||
// significant value word of `m` (this works only if `m` is an odd integer).
|
||||
//
|
||||
// The `t1` and `t2` parameters must be temporary arrays, each large enough to
|
||||
// accommodate an integer with the same size as `m`.
|
||||
i31_modpow :: proc "contextless" (x: []u32, e: []byte, m: []u32, m0i: u32, t1: []u32, t2: []u32) {
|
||||
// `mlen` is the length of `m` expressed in `u32`'s (including the
|
||||
// "bit length" first field).
|
||||
mlen := uint((m[0] + 63) >> 5)
|
||||
elen := u32(len(e))
|
||||
|
||||
// Throughout the algorithm:
|
||||
// -- `t1` is in Montgomery representation; it contains x, x^2, x^4, x^8...
|
||||
// -- The result is accumulated, in normal representation, in the `x` array.
|
||||
// -- `t2` is used as destination buffer for each multiplication.
|
||||
//
|
||||
// Note that there is no need to call `i32_from_monty()`.
|
||||
copy(t1[:mlen], x[:mlen])
|
||||
i31_to_monty(t1, m)
|
||||
i31_zero(x, m[0])
|
||||
x[1] = 1
|
||||
for k := u32(0); k < (elen << 3); k += 1 {
|
||||
ctl := (e[elen - 1 - (k >> 3)] >> (k & 7)) & 1
|
||||
|
||||
i31_montymul(t2, x, t1, m, m0i)
|
||||
|
||||
for &d, i in x[:mlen] {
|
||||
d = subtle.csel(d, t2[i], ctl)
|
||||
}
|
||||
|
||||
i31_montymul(t2, t1, t1, m, m0i)
|
||||
copy(t1[:mlen], t2[:mlen])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Compute a modular exponentiation.
|
||||
//
|
||||
// `x` MUST be an integer modulo `m` (same announced bit length, lower value).
|
||||
// `m` MUST be odd.
|
||||
//
|
||||
// The exponent `e` is in big-endian unsigned notation.
|
||||
//
|
||||
// The `m0i` parameter is equal to `-(1/m0) mod 2^31`, where `m0` is the least
|
||||
// significant value word of `m`[] (this works only if m[] is an odd integer).
|
||||
//
|
||||
// The `tmp` array is used for temporaries; it must be large enough to accommodate
|
||||
// at least two temporary values with the same size as `m` (including the leading
|
||||
// "bit length" word).
|
||||
//
|
||||
// If there is room for more temporaries, then this function may use the extra
|
||||
// room for window-based optimisation, resulting in faster computations.
|
||||
//
|
||||
// Returned value is `true` on success, `false` on error. An error is reported if
|
||||
// the provided `tmp`array is too short.
|
||||
i31_modpow_opt :: proc "contextless" (x: []u32, e: []byte, m: []u32, m0i: u32, tmp: []u32) -> u32 {
|
||||
// NOTE/yawning: This is only used by the rsa_i31 code, with the key
|
||||
// generation taking a function pointer to either this routine,
|
||||
// or the i62 variant.
|
||||
//
|
||||
// If we ever need to support the i32 version, it is used extensively,
|
||||
// but non e-waste architecutures will all do the right thing with
|
||||
// the i62 version, albeit with a perforance hit on 32-bit CPUs.
|
||||
|
||||
unimplemented_contextless()
|
||||
|
||||
// i31_mod_pow(x, e, m, m0i, tmp[:len(m)], tmp[len(m):])
|
||||
// return 1
|
||||
}
|
||||
|
||||
// Compute `d+a*b`, result in `d`.
|
||||
//
|
||||
// The initial announced bit length of `d` MUST match that of `a`[].
|
||||
//
|
||||
// The `d` array MUST be large enough to accommodate the full result,
|
||||
// plus (possibly) an extra word. The resulting announced bit length
|
||||
// of `d` will be the sum of the announced bit lengths of `a` and `b`
|
||||
// (therefore, it may be larger than the actual bit length of the numerical result).
|
||||
//
|
||||
// `a` and `b` may be the same array. `d` must be disjoint from both `a` and `b`.
|
||||
i31_mulacc :: proc "contextless" (d: []u32, a: []u32, b: []u32) {
|
||||
a_len := uint((a[0] + 31) >> 5)
|
||||
b_len := uint((b[0] + 31) >> 5)
|
||||
|
||||
// We want to add the two bit lengths, but these are encoded,
|
||||
// which requires some extra care.
|
||||
d_l := (a[0] & 31) + (b[0] & 31)
|
||||
d_h := (a[0] >> 5) + (b[0] >> 5)
|
||||
d[0] = (d_h << 5) + d_l + (~u32(d_l - 31) >> 31)
|
||||
|
||||
for u in 0..<b_len {
|
||||
// Carry always fits on 31 bits; we want to keep it in a
|
||||
// 32-bit register on 32-bit architectures (on a 64-bit
|
||||
// architecture, cast down from 64 to 32 bits means
|
||||
// clearing the high bits, which is not free; on a 32-bit
|
||||
// architecture, the same operation really means ignoring
|
||||
// the top register, which has negative or zero cost).
|
||||
f := b[1 + u]
|
||||
cc := u64(0)
|
||||
for v in 0..<a_len {
|
||||
z := u64(d[1 + u + v]) + _mul31(f, a[1 + v]) + cc
|
||||
cc = z >> 31
|
||||
d[1 + u + v] = u32(z) & I31_MASK
|
||||
}
|
||||
d[1 + u + a_len] = u32(cc)
|
||||
}
|
||||
}
|
||||
361
core/crypto/_bigint/i62.odin
Normal file
361
core/crypto/_bigint/i62.odin
Normal file
@@ -0,0 +1,361 @@
|
||||
package _bigint
|
||||
|
||||
// Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
// 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.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHORS “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 AUTHORS 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.
|
||||
|
||||
import "base:intrinsics"
|
||||
import "core:math/bits"
|
||||
import subtle "core:crypto/_subtle"
|
||||
import "core:slice"
|
||||
|
||||
@(private="file")
|
||||
I62_MASK :: 0x3fff_ffff_ffff_ffff
|
||||
|
||||
// Compute x*y+v1+v2. Operands are 64-bit, and result is 128-bit, with
|
||||
// high word in "hi" and low word in "lo".
|
||||
@(private="file", require_results)
|
||||
_fma1 :: #force_inline proc "contextless" (x, y, v1, v2: u64) -> (hi, lo: u64) {
|
||||
hi, lo = bits.mul_u64(x, y)
|
||||
|
||||
carry: u64
|
||||
lo, carry = bits.add_u64(lo, v1, 0)
|
||||
hi += carry
|
||||
|
||||
lo, carry = bits.add_u64(lo, v2, 0)
|
||||
hi += carry
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Compute x1*y1+x2*y2+v1+v2. Operands are 64-bit, and result is 128-bit,
|
||||
// with high word in "hi" and low word in "lo".
|
||||
//
|
||||
// Callers should ensure that the two inner products, and the v1 and v2
|
||||
// operands, are multiple of 4 (this is not used by this specific definition
|
||||
// but may help other implementations).
|
||||
@(private="file", require_results)
|
||||
_fma2 :: #force_inline proc "contextless" (x1, y1, x2, y2, v1, v2: u64) -> (hi, lo: u64) {
|
||||
hi_1, lo_1 := bits.mul_u64(x1, y1)
|
||||
hi_2, lo_2 := bits.mul_u64(x2, y2)
|
||||
|
||||
carry: u64
|
||||
lo, carry = bits.add_u64(lo_1, lo_2, 0)
|
||||
hi, _ = bits.add_u64(hi_1, hi_2, carry)
|
||||
|
||||
lo, carry = bits.add_u64(lo, v1, 0)
|
||||
hi += carry
|
||||
|
||||
lo, carry = bits.add_u64(lo, v2, 0)
|
||||
hi += carry
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@(private="file", require_results)
|
||||
_mul62_lo :: #force_inline proc "contextless" (x, y: u64) -> u64 {
|
||||
return (x * y) & I62_MASK
|
||||
}
|
||||
|
||||
// Subtract b from a, and return the final carry. If 'ctl32' is 0, then
|
||||
// a[] is kept unmodified, but the final carry is still computed and
|
||||
// returned.
|
||||
@(private="file", require_results)
|
||||
_i62_sub :: proc "contextless" (a, b: []u64, num: int, ctl32: u32) -> u32 {
|
||||
cc: u64
|
||||
|
||||
ctl := -ctl32
|
||||
mask := u64(ctl) | (u64(ctl) << 32)
|
||||
for u in 0..<num {
|
||||
aw := a[u]
|
||||
bw := b[u]
|
||||
dw := aw - bw - cc
|
||||
cc = dw >> 63
|
||||
dw &= I62_MASK
|
||||
a[u] = aw ~ (mask & (dw ~ aw))
|
||||
}
|
||||
|
||||
return u32(cc)
|
||||
}
|
||||
|
||||
// Montgomery multiplication, over arrays of 62-bit values. The
|
||||
// destination array (d) must be distinct from the other operands
|
||||
// (x, y and m). All arrays are in little-endian format (least
|
||||
// significant word comes first) over 'num' words.
|
||||
@(private="file")
|
||||
_i62_montymul :: proc "contextless" (d, x, y, m: []u64, num: int, m0i: u64) {
|
||||
dh: u64
|
||||
|
||||
num4 := 1 + u64((num - 1) & ~int(3))
|
||||
intrinsics.mem_zero(raw_data(d), num * size_of(u64))
|
||||
for u in 0..<num {
|
||||
xu := x[u] << 2
|
||||
f := _mul62_lo(d[0] + _mul62_lo(x[u], y[0]), m0i) << 2
|
||||
|
||||
hi, lo := _fma2(xu, y[0], f, m[0], d[0] << 2, 0)
|
||||
r := hi
|
||||
|
||||
v: int
|
||||
for v = 1; v < int(num4); v += 4 {
|
||||
hi, lo = _fma2(xu, y[v + 0], f, m[v + 0], d[v + 0] << 2, r << 2)
|
||||
r = hi + (r >> 62)
|
||||
d[v - 1] = lo >> 2
|
||||
hi, lo = _fma2(xu, y[v + 1], f, m[v + 1], d[v + 1] << 2, r << 2)
|
||||
r = hi + (r >> 62)
|
||||
d[v + 0] = lo >> 2
|
||||
hi, lo = _fma2(xu, y[v + 2], f, m[v + 2], d[v + 2] << 2, r << 2)
|
||||
r = hi + (r >> 62)
|
||||
d[v + 1] = lo >> 2
|
||||
hi, lo = _fma2(xu, y[v + 3], f, m[v + 3], d[v + 3] << 2, r << 2)
|
||||
r = hi + (r >> 62)
|
||||
d[v + 2] = lo >> 2
|
||||
}
|
||||
for ; v < num; v += 1 {
|
||||
hi, lo = _fma2(xu, y[v], f, m[v], d[v] << 2, r << 2)
|
||||
r = hi + (r >> 62)
|
||||
d[v - 1] = lo >> 2
|
||||
}
|
||||
|
||||
zh := dh + r
|
||||
d[num - 1] = zh & I62_MASK
|
||||
dh = zh >> 62
|
||||
}
|
||||
_ = _i62_sub(d, m, num, u32(dh) | subtle.not(_i62_sub(d, m, num, 0)))
|
||||
}
|
||||
|
||||
// Conversion back from Montgomery representation.
|
||||
@(private="file")
|
||||
_i62_frommonty :: proc "contextless" (x, m: []u64, num: int, m0i: u64) {
|
||||
for _ in 0..<num {
|
||||
cc: u64
|
||||
f := _mul62_lo(x[0], m0i) << 2
|
||||
for v in 0..<num {
|
||||
hi, lo := _fma1(f, m[v], x[v] << 2, cc)
|
||||
cc = hi << 2
|
||||
if (v != 0) {
|
||||
x[v - 1] = lo >> 2
|
||||
}
|
||||
}
|
||||
x[num - 1] = cc >> 2
|
||||
}
|
||||
_ = _i62_sub(x, m, num, subtle.not(_i62_sub(x, m, num, 0)))
|
||||
}
|
||||
|
||||
// Variant of i31_modpow_opt() that internally uses 64x64->128
|
||||
// multiplications. It expects the same parameters as i31_modpow_opt(),
|
||||
// except that the temporaries should be 64-bit integers, not 32-bit
|
||||
// integers.
|
||||
i62_modpow_opt :: proc "contextless" (x31: []u32, e: []byte, m31: []u32, m0i31: u32, tmp: []u64) -> u32 {
|
||||
twlen := len(tmp)
|
||||
|
||||
// Get modulus size, in words.
|
||||
mw31num := int((m31[0] + 31) >> 5)
|
||||
mw62num := int((mw31num + 1) >> 1)
|
||||
|
||||
// In order to apply this function, we must have enough room to
|
||||
// copy the operand and modulus into the temporary array, along
|
||||
// with at least two temporaries. If there is not enough room,
|
||||
// switch to br_i31_modpow(). We also use br_i31_modpow() if the
|
||||
// modulus length is not at least four words (94 bits or more).
|
||||
if mw31num < 4 || mw62num << 2 > twlen {
|
||||
// We assume here that we can split an aligned uint64_t
|
||||
// into two properly aligned uint32_t. Since both types
|
||||
// are supposed to have an exact width with no padding,
|
||||
// then this property must hold.
|
||||
|
||||
txlen := mw31num + 1
|
||||
if twlen < txlen {
|
||||
return 0
|
||||
}
|
||||
|
||||
tmp_as_u32s := slice.reinterpret([]u32, tmp)
|
||||
t1, t2 := tmp_as_u32s[:txlen], tmp_as_u32s[txlen:]
|
||||
|
||||
i31_modpow(x31, e, m31, m0i31, t1, t2)
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
// Convert x to Montgomery representation: this means that
|
||||
// we replace x with x*2^z mod m, where z is the smallest multiple
|
||||
// of the word size such that 2^z >= m. We want to reuse the 31-bit
|
||||
// functions here (for constant-time operation), but we need z
|
||||
// for a 62-bit word size.
|
||||
for _ in 0..<mw62num {
|
||||
i31_muladd_small(x31, 0, m31)
|
||||
i31_muladd_small(x31, 0, m31)
|
||||
}
|
||||
|
||||
// Assemble operands into arrays of 62-bit words. Note that
|
||||
// all the arrays of 62-bit words that we will handle here
|
||||
// are without any leading size word.
|
||||
//
|
||||
// We also adjust tmp and twlen to account for the words used
|
||||
// for these extra arrays.
|
||||
m := tmp[:mw62num]
|
||||
x := tmp[mw62num:mw62num*2]
|
||||
tmp_ := tmp[mw62num << 1:]
|
||||
twlen -= mw62num << 1
|
||||
for u := 0; u < mw31num; u += 2 {
|
||||
v := u >> 1
|
||||
if u + 1 == mw31num {
|
||||
m[v] = u64(m31[u + 1])
|
||||
x[v] = u64(x31[u + 1])
|
||||
} else {
|
||||
m[v] = u64(m31[u + 1]) + (u64(m31[u + 2]) << 31)
|
||||
x[v] = u64(x31[u + 1]) + (u64(x31[u + 2]) << 31)
|
||||
}
|
||||
}
|
||||
|
||||
// Compute window size. We support windows up to 5 bits; for a
|
||||
// window of size k bits, we need 2^k+1 temporaries (for k = 1,
|
||||
// we use special code that uses only 2 temporaries).
|
||||
win_len: int
|
||||
for win_len = 5; win_len > 1; win_len -= 1 {
|
||||
if (1 << uint(win_len) + 1) * mw62num <= twlen {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
t1 := tmp_[:mw62num]
|
||||
t2 := tmp_[mw62num:]
|
||||
|
||||
// Compute m0i, which is equal to -(1/m0) mod 2^62. We were
|
||||
// provided with m0i31, which already fulfills this property
|
||||
// modulo 2^31; the single expression below is then sufficient.
|
||||
m0i := u64(m0i31)
|
||||
m0i = _mul62_lo(m0i, 2 + _mul62_lo(m0i, m[0]))
|
||||
|
||||
// Compute window contents. If the window has size one bit only,
|
||||
// then t2 is set to x; otherwise, t2[0] is left untouched, and
|
||||
// t2[k] is set to x^k (for k >= 1).
|
||||
if win_len == 1 {
|
||||
copy(t2, x)
|
||||
} else {
|
||||
copy(t2[mw62num:], x)
|
||||
|
||||
base := t2[mw62num:]
|
||||
for u := 2; u < 1 << uint(win_len); u += 1 {
|
||||
_i62_montymul(base[mw62num:], base, x, m, mw62num, m0i)
|
||||
base = base[mw62num:]
|
||||
}
|
||||
}
|
||||
|
||||
// Set x to 1, in Montgomery representation. We again use the
|
||||
// 31-bit code.
|
||||
i31_zero(x31, m31[0])
|
||||
x31[(m31[0] + 31) >> 5] = 1
|
||||
i31_muladd_small(x31, 0, m31)
|
||||
if mw31num & 1 != 0 {
|
||||
i31_muladd_small(x31, 0, m31)
|
||||
}
|
||||
for u := 0; u < mw31num; u+= 2 {
|
||||
v := u >> 1
|
||||
if u + 1 == mw31num {
|
||||
x[v] = u64(x31[u + 1])
|
||||
} else {
|
||||
x[v] = u64(x31[u + 1]) + (u64(x31[u + 2]) << 31)
|
||||
}
|
||||
}
|
||||
|
||||
e_, e_len := e, len(e)
|
||||
// We process bits from most to least significant. At each
|
||||
// loop iteration, we have acc_len bits in acc.
|
||||
acc: u32
|
||||
acc_len: uint
|
||||
for acc_len > 0 || e_len > 0 {
|
||||
// Get the next bits.
|
||||
k := uint(win_len)
|
||||
if acc_len < uint(win_len) {
|
||||
if e_len > 0 {
|
||||
acc = (acc << 8) | u32(e_[0])
|
||||
e_ = e_[1:]
|
||||
e_len -= 1
|
||||
acc_len += 8
|
||||
} else {
|
||||
k = acc_len
|
||||
}
|
||||
}
|
||||
bits := (acc >> (acc_len - k)) & ((u32(1) << k) - 1)
|
||||
acc_len -= k
|
||||
|
||||
// We could get exactly k bits. Compute k squarings.
|
||||
for _ in 0..<k {
|
||||
_i62_montymul(t1, x, x, m, mw62num, m0i)
|
||||
copy(x, t1)
|
||||
}
|
||||
|
||||
// Window lookup: we want to set t2 to the window
|
||||
// lookup value, assuming the bits are non-zero. If
|
||||
// the window length is 1 bit only, then t2 is
|
||||
// already set; otherwise, we do a constant-time lookup.
|
||||
if win_len > 1 {
|
||||
intrinsics.mem_zero(raw_data(t2), mw62num * size_of(u64))
|
||||
|
||||
base := t2[mw62num:]
|
||||
for u := u32(1); u < u32(1) << k; u += 1 {
|
||||
mask := -u64(subtle.eq(u, bits))
|
||||
for v in 0..<mw62num {
|
||||
t2[v] |= mask & base[v]
|
||||
}
|
||||
base = base[mw62num:]
|
||||
}
|
||||
}
|
||||
|
||||
// Multiply with the looked-up value. We keep the product
|
||||
// only if the exponent bits are not all-zero.
|
||||
_i62_montymul(t1, x, t2, m, mw62num, m0i)
|
||||
mask1 := -u64(subtle.eq(bits, 0))
|
||||
mask2 := ~mask1
|
||||
for u in 0..<mw62num {
|
||||
x[u] = (mask1 & x[u]) | (mask2 & t1[u])
|
||||
}
|
||||
}
|
||||
|
||||
// Convert back from Montgomery representation.
|
||||
_i62_frommonty(x, m, mw62num, m0i)
|
||||
|
||||
// Convert result into 31-bit words.
|
||||
for u := 0; u < mw31num; u += 2 {
|
||||
zw := u64(x[u >> 1])
|
||||
x31[u + 1] = u32(zw) & I31_MASK
|
||||
if u + 1 < mw31num {
|
||||
x31[u + 2] = u32(zw >> 31)
|
||||
}
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
// Wrapper for i62_modpow_opt() that uses the same type as
|
||||
// i31_modpow_opt(); however, it requires its 'tmp' argument to the
|
||||
// 64-bit aligned.
|
||||
i62_modpow_opt_as_i31 :: proc "contextless" (x31: []u32, e: []byte, m31: []u32, m0i31: u32, tmp: []u32) -> u32 {
|
||||
// As documented, this function expects the 'tmp' argument to be
|
||||
// 64-bit aligned. This is OK since this function is internal (it
|
||||
// is not part of BearSSL's public API).
|
||||
ensure_contextless(uintptr(raw_data(tmp)) & 7 == 0)
|
||||
ensure_contextless(len(tmp) & 1 == 0) // Length MUST be even.
|
||||
|
||||
tmp_as_u64s := slice.reinterpret([]u64, tmp)
|
||||
|
||||
return i62_modpow_opt(x31, e, m31, m0i31, tmp_as_u64s)
|
||||
}
|
||||
265
core/crypto/_bigint/i62_primes.odin
Normal file
265
core/crypto/_bigint/i62_primes.odin
Normal file
@@ -0,0 +1,265 @@
|
||||
package _bigint
|
||||
|
||||
// Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
// 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.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHORS “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 AUTHORS 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.
|
||||
|
||||
import subtle "core:crypto/_subtle"
|
||||
import "core:math/big"
|
||||
import "core:slice"
|
||||
|
||||
// Perform trial divisions on a candidate prime. We opt for the simple
|
||||
// route and "just" compute a series of trial divisions.
|
||||
//
|
||||
// Returned value is 1 on success (none of the small primes
|
||||
// divides x), 0 on error (a non-trivial GCD is obtained).
|
||||
@(private="file", require_results)
|
||||
trial_divisions :: proc "contextless" (x: []u32) -> u32 {
|
||||
for factor in big._private_prime_table {
|
||||
if factor <= 11 {
|
||||
continue
|
||||
}
|
||||
if i31_rem(x, u32(factor)) == 0 {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
// Perform n rounds of Miller-Rabin on the candidate prime x. This
|
||||
// function assumes that x = 3 mod 4.
|
||||
//
|
||||
// WARNING: t MUST be 64-bit aligned, and be large enough such that
|
||||
// it can hold 4 encoded integers that have the same number of limbs
|
||||
// as x.
|
||||
//
|
||||
// Returned value is 1 on success (all rounds completed successfully),
|
||||
// 0 otherwise.
|
||||
@(private="file", require_results)
|
||||
i62_miller_rabin :: proc(x: []u32, n: int, t: []u32) -> u32 {
|
||||
// Since x = 3 mod 4, the Miller-Rabin test is simple:
|
||||
// - get a random base a (such that 1 < a < x-1)
|
||||
// - compute z = a^((x-1)/2) mod x
|
||||
// - if z != 1 and z != x-1, the number x is composite
|
||||
//
|
||||
// We generate bases 'a' randomly with a size which is
|
||||
// one bit less than x, which ensures that a < x-1. It
|
||||
// is not useful to verify that a > 1 because the probability
|
||||
// that we get a value a equal to 0 or 1 is much smaller
|
||||
// than the probability of our Miller-Rabin tests not to
|
||||
// detect a composite, which is already quite smaller than the
|
||||
// probability of the hardware misbehaving and return a
|
||||
// composite integer because of some glitch (e.g. bad RAM
|
||||
// or ill-timed cosmic ray).
|
||||
|
||||
// Compute (x-1)/2 (encoded).
|
||||
xm1d2 := slice.reinterpret([]byte, t)
|
||||
xm1d2_len := ((x[0] - (x[0] >> 5)) + 7) >> 3
|
||||
i31_encode(xm1d2[:xm1d2_len], x)
|
||||
cc: u32
|
||||
for u in 0..<xm1d2_len {
|
||||
w := u32(xm1d2[u])
|
||||
xm1d2[u] = byte((w >> 1) | cc)
|
||||
cc = w << 7
|
||||
}
|
||||
|
||||
// We used some words of the provided buffer for (x-1)/2.
|
||||
xm1d2_len_u32 := (xm1d2_len + 3) >> 2
|
||||
t_ := t[xm1d2_len_u32:]
|
||||
tlen := len(t_)
|
||||
|
||||
xlen := (x[0] + 31) >> 5
|
||||
asize := x[0] - 1 - subtle.eq0(x[0] & 31)
|
||||
x0i := i31_ninv31(x[1])
|
||||
for _ in 0..<n {
|
||||
// Generate a random base. We don't need the base to be
|
||||
// really uniform modulo x, so we just get a random
|
||||
// number which is one bit shorter than x.
|
||||
a := t_
|
||||
a[0] = x[0]
|
||||
a[xlen] = 0
|
||||
i31_mkrand(a, asize)
|
||||
|
||||
// Compute a^((x-1)/2) mod x. We assume here that the
|
||||
// function will not fail (the temporary array is large
|
||||
// enough).
|
||||
t2 := t_[1 + xlen:]
|
||||
t2len := tlen - 1 - int(xlen)
|
||||
if (t2len & 1) != 0 {
|
||||
// Since the source array is 64-bit aligned and
|
||||
// has an even number of elements (TEMPS), we
|
||||
// can use the parity of the remaining length to
|
||||
// detect and adjust alignment.
|
||||
t2 = t2[1:]
|
||||
t2len -= 1
|
||||
}
|
||||
i62_modpow_opt_as_i31(a, xm1d2[:xm1d2_len], x, x0i, t2[:t2len])
|
||||
|
||||
// We must obtain either 1 or x-1. Note that x is odd,
|
||||
// hence x-1 differs from x only in its low word (no
|
||||
// carry).
|
||||
eq1 := a[1] ~ 1
|
||||
eqm1 := a[1] ~ (x[1] - 1)
|
||||
for u in 2..=xlen {
|
||||
eq1 |= a[u]
|
||||
eqm1 |= a[u] ~ x[u]
|
||||
}
|
||||
|
||||
if ((subtle.eq0(eq1) | subtle.eq0(eqm1)) == 0) {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
||||
// Create a random prime of the provided size. 'esize' is the _encoded_
|
||||
// bit length. The two top bits and the two bottom bits are set to 1.
|
||||
i62_mkprime :: proc(x: []u32, esize: u32, pubexp: u32, t: []u32) {
|
||||
x[0] = esize
|
||||
_len := (esize + 31) >> 5
|
||||
|
||||
for {
|
||||
// Generate random bits. We force the two top bits and the
|
||||
// two bottom bits to 1.
|
||||
i31_mkrand(x, esize)
|
||||
if (esize & 31) == 0 {
|
||||
x[_len] |= 0x60000000
|
||||
} else if (esize & 31) == 1 {
|
||||
x[_len] |= 0x00000001
|
||||
x[_len - 1] |= 0x40000000
|
||||
} else {
|
||||
x[_len] |= 0x00000003 << ((esize & 31) - 2)
|
||||
}
|
||||
x[1] |= 0x00000003
|
||||
|
||||
// Trial division with low primes (3, 5, 7 and 11). We
|
||||
// use the following properties:
|
||||
//
|
||||
// 2^2 = 1 mod 3
|
||||
// 2^4 = 1 mod 5
|
||||
// 2^3 = 1 mod 7
|
||||
// 2^10 = 1 mod 11
|
||||
m3, m5, m7, m11: u32
|
||||
s7, s11: uint
|
||||
for u in 0..<_len {
|
||||
w := x[1 + u]
|
||||
w3 := (w & 0xFFFF) + (w >> 16) // max: 98302
|
||||
w5 := (w & 0xFFFF) + (w >> 16) // max: 98302
|
||||
w7 := (w & 0x7FFF) + (w >> 15) // max: 98302
|
||||
w11 := (w & 0xFFFFF) + (w >> 20) // max: 1050622
|
||||
|
||||
m3 += w3 << (u & 1)
|
||||
m3 = (m3 & 0xFF) + (m3 >> 8) // max: 1025
|
||||
|
||||
m5 += w5 << ((4 - u) & 3)
|
||||
m5 = (m5 & 0xFFF) + (m5 >> 12) // max: 4479
|
||||
|
||||
m7 += w7 << s7
|
||||
m7 = (m7 & 0x1FF) + (m7 >> 9) // max: 1280
|
||||
s7 += 1
|
||||
if s7 == 3 {
|
||||
s7 = 0
|
||||
}
|
||||
|
||||
m11 += w11 << s11
|
||||
s11 += 1
|
||||
if s11 == 10 {
|
||||
s11 = 0
|
||||
}
|
||||
m11 = (m11 & 0x3FF) + (m11 >> 10) // max: 526847
|
||||
}
|
||||
|
||||
m3 = (m3 & 0x3F) + (m3 >> 6) // max: 78
|
||||
m3 = (m3 & 0x0F) + (m3 >> 4) // max: 18
|
||||
m3 = ((m3 * 43) >> 5) & 3
|
||||
|
||||
m5 = (m5 & 0xFF) + (m5 >> 8) // max: 271
|
||||
m5 = (m5 & 0x0F) + (m5 >> 4) // max: 31
|
||||
m5 -= 20 & -subtle.gt(m5, 19)
|
||||
m5 -= 10 & -subtle.gt(m5, 9)
|
||||
m5 -= 5 & -subtle.gt(m5, 4)
|
||||
|
||||
m7 = (m7 & 0x3F) + (m7 >> 6) // max: 82
|
||||
m7 = (m7 & 0x07) + (m7 >> 3) // max: 16
|
||||
m7 = ((m7 * 147) >> 7) & 7
|
||||
|
||||
// 2^5 = 32 = -1 mod 11.
|
||||
m11 = (m11 & 0x3FF) + (m11 >> 10) // max: 1536
|
||||
m11 = (m11 & 0x3FF) + (m11 >> 10) // max: 1023
|
||||
m11 = (m11 & 0x1F) + 33 - (m11 >> 5) // max: 64
|
||||
m11 -= 44 & -subtle.gt(m11, 43)
|
||||
m11 -= 22 & -subtle.gt(m11, 21)
|
||||
m11 -= 11 & -subtle.gt(m11, 10)
|
||||
|
||||
// If any of these modulo is 0, then the candidate is
|
||||
// not prime. Also, if pubexp is 3, 5, 7 or 11, and the
|
||||
// corresponding modulus is 1, then the candidate must
|
||||
// be rejected, because we need e to be invertible
|
||||
// modulo p-1. We can use simple comparisons here
|
||||
// because they won't leak information on a candidate
|
||||
// that we keep, only on one that we reject (and is thus
|
||||
// not secret).
|
||||
if m3 == 0 || m5 == 0 || m7 == 0 || m11 == 0 {
|
||||
continue
|
||||
}
|
||||
if (pubexp == 3 && m3 == 1) || (pubexp == 5 && m5 == 1) || (pubexp == 7 && m7 == 1) || (pubexp == 11 && m11 == 1) {
|
||||
continue
|
||||
}
|
||||
|
||||
// More trial divisions.
|
||||
if trial_divisions(x) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// Miller-Rabin algorithm. Since we selected a random
|
||||
// integer, not a maliciously crafted integer, we can use
|
||||
// relatively few rounds to lower the risk of a false
|
||||
// positive (i.e. declaring prime a non-prime) under
|
||||
// 2^(-80). It is not useful to lower the probability much
|
||||
// below that, since that would be substantially below
|
||||
// the probability of the hardware misbehaving. Sufficient
|
||||
// numbers of rounds are extracted from the Handbook of
|
||||
// Applied Cryptography, note 4.49 (page 149).
|
||||
//
|
||||
// Since we work on the encoded size (esize), we need to
|
||||
// compare with encoded thresholds.
|
||||
rounds: int
|
||||
switch {
|
||||
case esize < 309:
|
||||
rounds = 12
|
||||
case esize < 464:
|
||||
rounds = 9
|
||||
case esize < 670:
|
||||
rounds = 6
|
||||
case esize < 877:
|
||||
rounds = 4
|
||||
case esize < 1341:
|
||||
rounds = 3
|
||||
case:
|
||||
rounds = 2
|
||||
}
|
||||
|
||||
if i62_miller_rabin(x, rounds, t) == 1 {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
310
tests/core/crypto/bigint/int.odin
Normal file
310
tests/core/crypto/bigint/int.odin
Normal file
@@ -0,0 +1,310 @@
|
||||
// Tests for the constant time RSA primitives
|
||||
package test_core_crypto_bigint
|
||||
|
||||
import "base:runtime"
|
||||
import "core:crypto/_bigint"
|
||||
import "core:log"
|
||||
import "core:slice"
|
||||
import "core:testing"
|
||||
|
||||
ROUNDS :: 100_000
|
||||
|
||||
i31_equal :: proc(a, b: []u32) -> bool {
|
||||
if a[0] != b[0] { return false }
|
||||
|
||||
bits := uint(a[0])
|
||||
idx := 1
|
||||
for bits > 0 {
|
||||
ex := min(bits, 31)
|
||||
mask := u32(1<<ex) - 1
|
||||
|
||||
if a[idx] & mask != b[idx] & mask { return false }
|
||||
|
||||
bits -= ex
|
||||
idx += 1
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@(test)
|
||||
i31_is_zero :: proc(t: ^testing.T) {
|
||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||
arr := make([][5]u32, ROUNDS, context.temp_allocator)
|
||||
for i in 0..<len(arr) {
|
||||
_bigint.i31_mkrand(arr[i][:], u32((len(arr[i])-1) * 32))
|
||||
}
|
||||
|
||||
for &v in arr {
|
||||
v[0] = _bigint.i31_bit_length(v[1:])
|
||||
sum: u64
|
||||
for w in v[1:] {
|
||||
sum += u64(w)
|
||||
}
|
||||
testing.expect_value(t, _bigint.i31_is_zero(v[:]), 1 if sum == 0 else 0)
|
||||
|
||||
slice.zero(v[1:])
|
||||
testing.expect_value(t, _bigint.i31_is_zero(v[:]), 1)
|
||||
}
|
||||
}
|
||||
|
||||
@(test)
|
||||
i31_add :: proc(t: ^testing.T) {
|
||||
N :: 5
|
||||
res: [N]u32
|
||||
|
||||
for v in i31_add_test_vectors {
|
||||
if len(v.a) > N || len(v.b) > N || len(v.res) > N {
|
||||
log.infof("Skipped %v, not enough scratch space", v)
|
||||
continue
|
||||
}
|
||||
if !(len(v.a) == len(v.b) && len(v.b) == len(v.res)) {
|
||||
log.infof("Skipped %v, expected `a`, `b` and `res` lengths to be equal", v)
|
||||
continue
|
||||
}
|
||||
|
||||
// Copy into writable memory
|
||||
copy(res[:], v.a[:])
|
||||
|
||||
// Add b to "a" in place
|
||||
cc := _bigint.i31_add(res[:], v.b[:], 1)
|
||||
|
||||
testing.expect(t, slice.equal(res[:len(v.res)], v.res))
|
||||
testing.expect_value(t, cc, v.carry)
|
||||
}
|
||||
}
|
||||
|
||||
@(test)
|
||||
i31_sub :: proc(t: ^testing.T) {
|
||||
N :: 5
|
||||
res: [N]u32
|
||||
|
||||
for v in i31_sub_test_vectors {
|
||||
if len(v.a) > N || len(v.b) > N || len(v.res) > N {
|
||||
log.infof("Skipped %v, not enough scratch space", v)
|
||||
continue
|
||||
}
|
||||
if !(len(v.a) == len(v.b) && len(v.b) == len(v.res)) {
|
||||
log.infof("Skipped %v, expected `a`, `b` and `res` lengths to be equal", v)
|
||||
continue
|
||||
}
|
||||
|
||||
// Copy into writable memory
|
||||
copy(res[:], v.a[:])
|
||||
|
||||
// Add b to "a" in place
|
||||
cc := _bigint.i31_sub(res[:], v.b[:], 1)
|
||||
|
||||
testing.expect(t, slice.equal(res[:len(v.res)], v.res))
|
||||
testing.expect_value(t, cc, v.carry)
|
||||
}
|
||||
}
|
||||
|
||||
@(test)
|
||||
i31_bit_length :: proc (t: ^testing.T) {
|
||||
for v in i31_add_test_vectors {
|
||||
a_len := _bigint.i31_bit_length(v.a[1:])
|
||||
b_len := _bigint.i31_bit_length(v.b[1:])
|
||||
|
||||
testing.expect_value(t, a_len, v.a[0])
|
||||
testing.expect_value(t, b_len, v.b[0])
|
||||
}
|
||||
}
|
||||
|
||||
@(test)
|
||||
i31_decode :: proc(t: ^testing.T) {
|
||||
N :: 10
|
||||
res: [N]u32
|
||||
|
||||
mod := []u32{42, 0x7fff_fffe, 0x3ff, 0}
|
||||
|
||||
for v in i31_decode_test_vectors {
|
||||
if len(v.decode) > N || len(v.mod) > N {
|
||||
log.infof("Skipped %v, not enough scratch space", v)
|
||||
continue
|
||||
}
|
||||
|
||||
_bigint.i31_decode(res[:], v.src)
|
||||
testing.expect(t, slice.equal(res[:len(v.decode)], v.decode))
|
||||
|
||||
slice.zero(res[:])
|
||||
|
||||
mod_res := _bigint.i31_decode_mod(res[:], v.src, mod)
|
||||
testing.expect(t, slice.equal(res[:len(v.mod)], v.mod))
|
||||
testing.expect_value(t, mod_res, v.mod_res)
|
||||
|
||||
encoded: [32]u8 = 0
|
||||
_bigint.i31_encode(encoded[:], v.decode)
|
||||
testing.expect(t, slice.equal(encoded[32 - len(v.src):], v.src))
|
||||
}
|
||||
}
|
||||
|
||||
@(test)
|
||||
i31_rshift :: proc(t: ^testing.T) {
|
||||
N :: 4
|
||||
res: [N]u32
|
||||
for v in i31_rshift_test_vectors {
|
||||
if len(v.orig) > N || len(v.res) > N {
|
||||
log.infof("Skipped %v, not enough scratch space", v)
|
||||
continue
|
||||
}
|
||||
|
||||
if v.shift < 0 || v.shift > 31 {
|
||||
log.infof("Skipped %v, invalid shift amount", v)
|
||||
continue
|
||||
}
|
||||
|
||||
copy(res[:], v.orig)
|
||||
_bigint.i31_rshift(res[:], v.shift)
|
||||
testing.expect(t, slice.equal(res[:len(v.res)], v.res))
|
||||
}
|
||||
}
|
||||
|
||||
@(test)
|
||||
i31_reduce :: proc(t: ^testing.T) {
|
||||
N :: 12
|
||||
res: [N]u32 = ---
|
||||
mod := []u32{42, 0x7fff_fffe, 0x3ff, 0}
|
||||
|
||||
for v in i31_reduce_test_vectors {
|
||||
if len(v.orig) > N || len(v.res) > N {
|
||||
log.infof("Skipped %v, not enough scratch space", v)
|
||||
continue
|
||||
}
|
||||
|
||||
slice.zero(res[:])
|
||||
_bigint.i31_reduce(res[:], v.orig, mod)
|
||||
testing.expect(t, i31_equal(res[:], v.res))
|
||||
}
|
||||
}
|
||||
|
||||
@(test)
|
||||
i31_decode_reduce :: proc(t: ^testing.T) {
|
||||
N :: 4
|
||||
res: [N]u32 = 0
|
||||
mod := []u32{42, 0x7fff_fffe, 0x3ff, 0}
|
||||
|
||||
for v in i31_decode_reduce_test_vectors {
|
||||
if len(v.decode) > N {
|
||||
log.infof("Skipped %v, not enough scratch space", v)
|
||||
continue
|
||||
}
|
||||
|
||||
res = 0
|
||||
_bigint.i31_decode_reduce(res[:], v.src, mod)
|
||||
testing.expect(t, i31_equal(res[:], v.decode))
|
||||
}
|
||||
}
|
||||
|
||||
@(test)
|
||||
i31_muladd_small :: proc(t: ^testing.T) {
|
||||
mod := []u32{42, 0x7fff_fffe, 0x3ff, 0}
|
||||
|
||||
for v in i31_mul_add_test_vectors {
|
||||
if len(v.orig) > len(mod) || len(v.res) > len(mod) {
|
||||
log.infof("Skipped %v, not enough scratch space", v)
|
||||
continue
|
||||
}
|
||||
|
||||
res: [3]u32 = 0
|
||||
copy(res[:], v.orig)
|
||||
|
||||
_bigint.i31_muladd_small(res[:], v.z, mod)
|
||||
l := len(v.res)
|
||||
testing.expect(t, slice.equal(res[:l], v.res[:l]))
|
||||
}
|
||||
}
|
||||
|
||||
@(test)
|
||||
i31_encode :: proc(t: ^testing.T) {
|
||||
for v in i31_encode_test_vectors {
|
||||
decoded: [10]u32 = 0
|
||||
_bigint.i31_decode(decoded[:], v.encoded)
|
||||
|
||||
l := len(v.orig)
|
||||
testing.expect(t, slice.equal(decoded[:l], v.orig[:l]))
|
||||
|
||||
encoded: [32]u8 = 0
|
||||
_bigint.i31_encode(encoded[:], v.orig)
|
||||
|
||||
testing.expect(t, slice.equal(encoded[:], v.encoded))
|
||||
}
|
||||
}
|
||||
|
||||
@(test)
|
||||
i31_monty_mul :: proc(t: ^testing.T) {
|
||||
for v in i31_monty_mul_test_vectors {
|
||||
res: [6]u32 = 0
|
||||
|
||||
m0i := _bigint.i31_ninv31(v.m[1])
|
||||
if m0i == 0 {
|
||||
log.infof("Expected _bigint.i31_ninv31(%v) to not be 0, m[1] must be even. Skipped.", v.m[1])
|
||||
continue
|
||||
}
|
||||
|
||||
_bigint.i31_montymul(res[:], v.x, v.y, v.m, m0i)
|
||||
testing.expect(t, slice.equal(res[:], v.res))
|
||||
}
|
||||
}
|
||||
|
||||
@(test)
|
||||
i31_to_monty :: proc(t: ^testing.T) {
|
||||
for v in i31_to_monty_test_vectors {
|
||||
res: [6]u32 = 0
|
||||
copy(res[:], v.orig)
|
||||
|
||||
_bigint.i31_to_monty(res[:], v.m)
|
||||
testing.expect(t, slice.equal(res[:], v.x))
|
||||
|
||||
m0i := _bigint.i31_ninv31(v.m[1])
|
||||
if m0i == 0 {
|
||||
log.infof("Expected _bigint.i31_ninv31(%v) to not be 0, m[1] must be even. Skipped.", v.m[1])
|
||||
continue
|
||||
}
|
||||
|
||||
_bigint.i31_from_monty(res[:], v.m, m0i)
|
||||
testing.expect(t, slice.equal(res[:], v.orig))
|
||||
}
|
||||
}
|
||||
|
||||
@(test)
|
||||
i31_modpow :: proc(t: ^testing.T) {
|
||||
for v in i31_mod_pow_test_vectors {
|
||||
x_out: [6]u32
|
||||
temp: [100]u32
|
||||
|
||||
copy(x_out[:], v.orig)
|
||||
|
||||
m0i := _bigint.i31_ninv31(v.m[1])
|
||||
assert(m0i != 0)
|
||||
_bigint.i31_modpow(x_out[:], v.e, v.m, m0i, temp[:6], temp[6:][:6])
|
||||
|
||||
testing.expect(t, slice.equal(x_out[:], v.x))
|
||||
}
|
||||
}
|
||||
|
||||
@(test)
|
||||
i31_mulacc :: proc(t: ^testing.T) {
|
||||
for v in i31_mul_acc_test_vectors {
|
||||
res: [12]u32 = 0
|
||||
copy(res[:], v.d)
|
||||
|
||||
assert(v.d[0] == v.a[0])
|
||||
|
||||
_bigint.i31_mulacc(res[:], v.a, v.b)
|
||||
|
||||
testing.expect(t, slice.equal(res[:], v.res))
|
||||
}
|
||||
}
|
||||
|
||||
@(test)
|
||||
internal_div_rem_u32 :: proc(t: ^testing.T) {
|
||||
for v in i31_div_rem_test_vectors {
|
||||
den := u64(v.hi) << 32 + u64(v.lo)
|
||||
res := u64(v.quo) * u64(v.div) + u64(v.rem)
|
||||
assert(den == res)
|
||||
|
||||
quo, rem := _bigint.div_rem_u32(v.hi, v.lo, v.div)
|
||||
testing.expect_value(t, quo, v.quo)
|
||||
testing.expect_value(t, rem, v.rem)
|
||||
}
|
||||
}
|
||||
577
tests/core/crypto/bigint/test_vectors.odin
Normal file
577
tests/core/crypto/bigint/test_vectors.odin
Normal file
@@ -0,0 +1,577 @@
|
||||
package test_core_crypto_bigint
|
||||
|
||||
// Generated using BearSSL bindings.
|
||||
|
||||
I31_Test_Vector_Binary :: struct {
|
||||
a: []u32,
|
||||
b: []u32,
|
||||
res: []u32,
|
||||
carry: u32,
|
||||
}
|
||||
|
||||
@(rodata)
|
||||
i31_add_test_vectors := []I31_Test_Vector_Binary {
|
||||
{a = {127, 0x051558fb, 0x578cb6cf, 0x3d2097aa, 0x7512fbf6}, b = {127, 0x6b2123f1, 0x4ad77a17, 0x705c1500, 0x508d965d}, res = {127, 0x70367cec, 0x226430e6, 0x2d7cacab, 0x45a09254}, carry = 1},
|
||||
{a = {127, 0x0248fd90, 0x7825baae, 0x6de2183c, 0x4f5d0505}, b = {125, 0x492ba26a, 0x1bc7df54, 0x5114950e, 0x1ae989b2}, res = {127, 0x4b749ffa, 0x13ed9a02, 0x3ef6ad4b, 0x6a468eb8}, carry = 0},
|
||||
{a = {126, 0x4833d6ef, 0x37a112d4, 0x2f71a920, 0x3093d1c3}, b = {127, 0x20574627, 0x39305532, 0x20b76825, 0x6e2eeea3}, res = {126, 0x688b1d16, 0x70d16806, 0x50291145, 0x1ec2c066}, carry = 1},
|
||||
{a = {127, 0x55fb7b29, 0x21bef5c8, 0x67fe29e8, 0x798dabac}, b = {127, 0x274221db, 0x562cbe9c, 0x785bf5dc, 0x7058bbfa}, res = {127, 0x7d3d9d04, 0x77ebb464, 0x605a1fc4, 0x69e667a7}, carry = 1},
|
||||
{a = {127, 0x2ffa533d, 0x59e20331, 0x59323704, 0x42cf6e75}, b = {127, 0x7ac812c0, 0x32ca1723, 0x15abc385, 0x410265b0}, res = {127, 0x2ac265fd, 0x0cac1a55, 0x6eddfa8a, 0x03d1d425}, carry = 1},
|
||||
{a = {126, 0x789b52f9, 0x6535ff6a, 0x2744cf6e, 0x2e4342a6}, b = {127, 0x32dd2f41, 0x64d80309, 0x1ae80d4b, 0x405d1799}, res = {126, 0x2b78823a, 0x4a0e0274, 0x422cdcba, 0x6ea05a3f}, carry = 0},
|
||||
{a = {127, 0x62003ba4, 0x2b58e836, 0x4587aced, 0x760bdb36}, b = {126, 0x0201e795, 0x50230e49, 0x30039ab5, 0x36f17032}, res = {127, 0x64022339, 0x7b7bf67f, 0x758b47a2, 0x2cfd4b68}, carry = 1},
|
||||
{a = {124, 0x4ef8170f, 0x65e714cc, 0x5500f2a4, 0x090fac28}, b = {127, 0x0a03290f, 0x0d3fafb1, 0x74ebb1b5, 0x7a30e9c6}, res = {124, 0x58fb401e, 0x7326c47d, 0x49eca459, 0x034095ef}, carry = 1},
|
||||
{a = {127, 0x34995a2f, 0x58f39080, 0x376ab5ef, 0x555b4fdf}, b = {122, 0x1c0928d9, 0x037fc1ea, 0x35c6d9b0, 0x0206ff68}, res = {127, 0x50a28308, 0x5c73526a, 0x6d318f9f, 0x57624f47}, carry = 0},
|
||||
{a = {127, 0x7029eb02, 0x465899f5, 0x71ab22fc, 0x604f1ccf}, b = {124, 0x703e163c, 0x50f72eb1, 0x0a0f0bae, 0x0a2028fe}, res = {127, 0x6068013e, 0x174fc8a7, 0x7bba2eab, 0x6a6f45cd}, carry = 0},
|
||||
{a = {125, 0x70cc03f6, 0x4d984b06, 0x4b990b9d, 0x16dd5097}, b = {125, 0x6eed2b72, 0x6001ddd2, 0x12c50807, 0x14f176cb}, res = {125, 0x5fb92f68, 0x2d9a28d9, 0x5e5e13a5, 0x2bcec762}, carry = 0},
|
||||
{a = {127, 0x5e6a99af, 0x3ffc66eb, 0x31e47de6, 0x5bcd2f4b}, b = {124, 0x0f6f4335, 0x07d4bf78, 0x61e99233, 0x0fe21745}, res = {127, 0x6dd9dce4, 0x47d12663, 0x13ce1019, 0x6baf4691}, carry = 0},
|
||||
{a = {127, 0x45de8b13, 0x010684b5, 0x01c77d90, 0x7464b4c8}, b = {127, 0x672a5a37, 0x33cb5670, 0x4ccc9e85, 0x7c0b88e1}, res = {127, 0x2d08e54a, 0x34d1db26, 0x4e941c15, 0x70703da9}, carry = 1},
|
||||
{a = {127, 0x012fe1a4, 0x741e0733, 0x44d3fb4a, 0x79d78453}, b = {126, 0x66d849d4, 0x427b3ff0, 0x5b2b72e8, 0x3c88987d}, res = {127, 0x68082b78, 0x36994723, 0x1fff6e33, 0x36601cd1}, carry = 1},
|
||||
{a = {125, 0x3ee54e09, 0x6bc71a68, 0x53cb44c8, 0x1f803699}, b = {124, 0x506ff07c, 0x63b155a0, 0x2c87590f, 0x0c7347e4}, res = {125, 0x0f553e85, 0x4f787009, 0x00529dd8, 0x2bf37e7e}, carry = 0},
|
||||
{a = {125, 0x4847d126, 0x4c6af2f2, 0x663970b3, 0x11d97a24}, b = {126, 0x67c8e79a, 0x313d0fc2, 0x786fdac1, 0x23c16f5c}, res = {125, 0x3010b8c0, 0x7da802b5, 0x5ea94b74, 0x359ae981}, carry = 0},
|
||||
{a = {127, 0x035a5f5c, 0x5fad2c0b, 0x6df6c2f3, 0x6cf28780}, b = {125, 0x09719328, 0x6adec2fa, 0x07d51f17, 0x1467d4f6}, res = {127, 0x0ccbf284, 0x4a8bef05, 0x75cbe20b, 0x015a5c76}, carry = 1},
|
||||
{a = {127, 0x48a484fe, 0x4a2eb1e7, 0x04a04363, 0x52dd3789}, b = {126, 0x136b08b1, 0x4d63762d, 0x52072be9, 0x2f4ef42b}, res = {127, 0x5c0f8daf, 0x17922814, 0x56a76f4d, 0x022c2bb4}, carry = 1},
|
||||
{a = {123, 0x119e8d05, 0x36510131, 0x38c3b084, 0x07bfe00d}, b = {127, 0x2ecdd4e9, 0x0afaddad, 0x77058092, 0x6b9f72dd}, res = {123, 0x406c61ee, 0x414bdede, 0x2fc93116, 0x735f52eb}, carry = 0},
|
||||
{a = {126, 0x459b051a, 0x6cfaeee6, 0x461ccc17, 0x36a7eb37}, b = {126, 0x53726a35, 0x34443d10, 0x2d29d052, 0x27d37b9d}, res = {126, 0x190d6f4f, 0x213f2bf7, 0x73469c6a, 0x5e7b66d4}, carry = 0},
|
||||
{a = {126, 0x73ccf104, 0x352c20d6, 0x580eeeca, 0x28ffb3bc}, b = {126, 0x1aba27fc, 0x31a85479, 0x05e9d689, 0x338a99a8}, res = {126, 0x0e871900, 0x66d47550, 0x5df8c553, 0x5c8a4d64}, carry = 0},
|
||||
{a = {127, 0x0220ed88, 0x4ccecbb5, 0x31016917, 0x7bc75c14}, b = {127, 0x19d9b7b6, 0x763136a7, 0x783931cf, 0x58fec945}, res = {127, 0x1bfaa53e, 0x4300025c, 0x293a9ae7, 0x54c6255a}, carry = 1},
|
||||
{a = {127, 0x14696b6a, 0x63348532, 0x71d09a50, 0x77ec660c}, b = {126, 0x67251ffd, 0x1f9606e1, 0x1205eb43, 0x32c3b9f7}, res = {127, 0x7b8e8b67, 0x02ca8c13, 0x03d68594, 0x2ab02004}, carry = 1},
|
||||
{a = {127, 0x570637d9, 0x22723669, 0x77a7b284, 0x4e1e69ac}, b = {127, 0x32c70945, 0x072c2f80, 0x7ef86c2f, 0x595e375a}, res = {127, 0x09cd411e, 0x299e65ea, 0x76a01eb3, 0x277ca107}, carry = 1},
|
||||
{a = {126, 0x47ab18d6, 0x4918a98b, 0x51c48283, 0x39a6cb59}, b = {127, 0x2430ac5b, 0x5328674a, 0x1fdffc7d, 0x69dced9b}, res = {126, 0x6bdbc531, 0x1c4110d5, 0x71a47f01, 0x2383b8f4}, carry = 1},
|
||||
{a = {127, 0x30e85990, 0x65afbf0b, 0x3a20ce3d, 0x5a014c71}, b = {127, 0x27d0d3a9, 0x2483d56f, 0x7e96f8e9, 0x54c679f8}, res = {127, 0x58b92d39, 0x0a33947a, 0x38b7c727, 0x2ec7c66a}, carry = 1},
|
||||
{a = {127, 0x6ec2ebc5, 0x2fe87e6e, 0x5c214f86, 0x46ce9354}, b = {127, 0x7b6b78e3, 0x0de8a5eb, 0x1cf27da3, 0x43d7077f}, res = {127, 0x6a2e64a8, 0x3dd1245a, 0x7913cd29, 0x0aa59ad3}, carry = 1},
|
||||
{a = {127, 0x532479dc, 0x38cb5eb9, 0x6b8afdb8, 0x624a0f13}, b = {127, 0x74ab8b56, 0x27e5b9da, 0x62e7b771, 0x50f115a6}, res = {127, 0x47d00532, 0x60b11894, 0x4e72b529, 0x333b24ba}, carry = 1},
|
||||
{a = {126, 0x7fe1b477, 0x4477a7c5, 0x04b0164d, 0x31d00838}, b = {125, 0x321ef997, 0x579ab7cf, 0x54fb3455, 0x133928f5}, res = {126, 0x3200ae0e, 0x1c125f95, 0x59ab4aa3, 0x4509312d}, carry = 0},
|
||||
{a = {127, 0x0dd79881, 0x120bcfae, 0x73cc2c5d, 0x43b522e7}, b = {126, 0x0b81b7af, 0x3c00816c, 0x5658e7d3, 0x30483552}, res = {127, 0x19595030, 0x4e0c511a, 0x4a251430, 0x73fd583a}, carry = 0},
|
||||
{a = {126, 0x0c52d45e, 0x698fd6df, 0x29a362fc, 0x3b6b5882}, b = {127, 0x5e851c19, 0x72428920, 0x417745c0, 0x437e8c53}, res = {126, 0x6ad7f077, 0x5bd25fff, 0x6b1aa8bd, 0x7ee9e4d5}, carry = 0},
|
||||
{a = {126, 0x5d82d3a5, 0x328636c2, 0x175e0f86, 0x270f7afa}, b = {126, 0x7c06e395, 0x21b77837, 0x5fb98ab1, 0x225d6181}, res = {126, 0x5989b73a, 0x543daefa, 0x77179a37, 0x496cdc7b}, carry = 0},
|
||||
{a = {127, 0x16be1fea, 0x48971493, 0x4a8f5617, 0x6b2a9968}, b = {127, 0x47387295, 0x2cecd451, 0x59abfdc3, 0x40028930}, res = {127, 0x5df6927f, 0x7583e8e4, 0x243b53da, 0x2b2d2299}, carry = 1},
|
||||
{a = {127, 0x3cea792f, 0x62a42211, 0x18aa6284, 0x4ca7e07f}, b = {127, 0x5ea60937, 0x5e7c6b69, 0x5bd789bd, 0x774ddc8e}, res = {127, 0x1b908266, 0x41208d7b, 0x7481ec42, 0x43f5bd0d}, carry = 1},
|
||||
{a = {127, 0x0e21cb57, 0x34087c35, 0x7bcad13b, 0x59c8dc35}, b = {125, 0x08a0ae9f, 0x145d8ebb, 0x1bcb683a, 0x1caefdbd}, res = {127, 0x16c279f6, 0x48660af0, 0x17963975, 0x7677d9f3}, carry = 0},
|
||||
{a = {127, 0x0b0dd998, 0x1210d9cc, 0x01074e0a, 0x762996da}, b = {126, 0x3c80570a, 0x00fbed3c, 0x77bb5d04, 0x258d2213}, res = {127, 0x478e30a2, 0x130cc708, 0x78c2ab0e, 0x1bb6b8ed}, carry = 1},
|
||||
{a = {127, 0x4e88ee76, 0x335e5d85, 0x634e3d26, 0x56cff5de}, b = {126, 0x15f3b966, 0x1c0a3f86, 0x1da6a59b, 0x35edda6f}, res = {127, 0x647ca7dc, 0x4f689d0b, 0x00f4e2c1, 0x0cbdd04e}, carry = 1},
|
||||
{a = {127, 0x374f8369, 0x00230d40, 0x76f627a4, 0x45cb7dff}, b = {127, 0x0e437bcd, 0x5524b249, 0x6aa80d40, 0x578666e8}, res = {127, 0x4592ff36, 0x5547bf89, 0x619e34e4, 0x1d51e4e8}, carry = 1},
|
||||
{a = {126, 0x7804142f, 0x66b7d326, 0x2f6fbe1b, 0x340e91e8}, b = {127, 0x5650e768, 0x22201fc5, 0x1a849718, 0x608b4950}, res = {126, 0x4e54fb97, 0x08d7f2ec, 0x49f45534, 0x1499db38}, carry = 1},
|
||||
{a = {127, 0x409a9e5d, 0x6b53d3a4, 0x284aa18f, 0x60899852}, b = {126, 0x340a5074, 0x05dc9720, 0x6c400c75, 0x2c0a2e6d}, res = {127, 0x74a4eed1, 0x71306ac4, 0x148aae04, 0x0c93c6c0}, carry = 1},
|
||||
{a = {127, 0x484f4d07, 0x45bf1a9a, 0x7679ef61, 0x58da55e9}, b = {125, 0x1672599a, 0x25b9fde9, 0x1dd52ce2, 0x1b792755}, res = {127, 0x5ec1a6a1, 0x6b791883, 0x144f1c43, 0x74537d3f}, carry = 0},
|
||||
{a = {127, 0x46f0b919, 0x258efe9f, 0x25ac2909, 0x7ee35251}, b = {126, 0x26292ec9, 0x052799f6, 0x26e8cd9f, 0x2a91ea77}, res = {127, 0x6d19e7e2, 0x2ab69895, 0x4c94f6a8, 0x29753cc8}, carry = 1},
|
||||
{a = {127, 0x662c1549, 0x7d1d8413, 0x2820005b, 0x640fa366}, b = {127, 0x1a1c703a, 0x7c960a8a, 0x0468ab46, 0x76636006}, res = {127, 0x00488583, 0x79b38e9e, 0x2c88aba2, 0x5a73036c}, carry = 1},
|
||||
{a = {127, 0x32c078a6, 0x09144c2e, 0x7216eb1e, 0x575eb4a5}, b = {127, 0x014b7cd8, 0x7374bc3f, 0x79bad310, 0x41c309b3}, res = {127, 0x340bf57e, 0x7c89086d, 0x6bd1be2e, 0x1921be59}, carry = 1},
|
||||
{a = {127, 0x5d152378, 0x0db3b779, 0x27cbd808, 0x729e2498}, b = {127, 0x639a2cac, 0x4e2dc8f3, 0x22846201, 0x538c5c6c}, res = {127, 0x40af5024, 0x5be1806d, 0x4a503a09, 0x462a8104}, carry = 1},
|
||||
{a = {126, 0x4f52ebe5, 0x2e2ce1fe, 0x740060a5, 0x2b602c28}, b = {127, 0x23613e9d, 0x5236ec37, 0x744c1397, 0x6a0e964f}, res = {126, 0x72b42a82, 0x0063ce35, 0x684c743d, 0x156ec278}, carry = 1},
|
||||
{a = {126, 0x7cab43a4, 0x7b2c3d9d, 0x44c551d5, 0x3e795426}, b = {127, 0x25f21ad6, 0x50b3905d, 0x4477f701, 0x64063b12}, res = {126, 0x229d5e7a, 0x4bdfcdfb, 0x093d48d7, 0x227f8f39}, carry = 1},
|
||||
{a = {126, 0x54d5908a, 0x4db32799, 0x4e170b52, 0x32d0557d}, b = {126, 0x24f21022, 0x0e431da5, 0x52beb40c, 0x2e5eada4}, res = {126, 0x79c7a0ac, 0x5bf6453e, 0x20d5bf5e, 0x612f0322}, carry = 0},
|
||||
{a = {127, 0x2fd0c679, 0x429d2164, 0x3b7d1340, 0x478c197e}, b = {126, 0x5b9f625b, 0x15cfdd9b, 0x0eb39653, 0x3f2a9e1a}, res = {127, 0x0b7028d4, 0x586cff00, 0x4a30a993, 0x06b6b798}, carry = 1},
|
||||
{a = {127, 0x47e483cd, 0x635dad05, 0x334178a6, 0x5be2703c}, b = {127, 0x12487678, 0x0b47445a, 0x2b468da6, 0x5cf39115}, res = {127, 0x5a2cfa45, 0x6ea4f15f, 0x5e88064c, 0x38d60151}, carry = 1},
|
||||
{a = {127, 0x16bd1190, 0x6f358b1b, 0x43fef060, 0x57246c18}, b = {125, 0x52f9efe3, 0x1d8e35d7, 0x45422cbc, 0x1e9a7d06}, res = {127, 0x69b70173, 0x0cc3c0f2, 0x09411d1d, 0x75bee91f}, carry = 0},
|
||||
{a = {124, 0x300566bd, 0x4043d1da, 0x07083a42, 0x0ac4490a}, b = {126, 0x7bc7aaa4, 0x089b207d, 0x7d73159e, 0x20475102}, res = {124, 0x2bcd1161, 0x48def258, 0x047b4fe0, 0x2b0b9a0d}, carry = 0},
|
||||
{a = {127, 0x1879a134, 0x2d5dce4b, 0x4fb09e72, 0x6f409165}, b = {127, 0x224335a0, 0x20c2b717, 0x748b2f65, 0x738d9650}, res = {127, 0x3abcd6d4, 0x4e208562, 0x443bcdd7, 0x62ce27b6}, carry = 1},
|
||||
{a = {127, 0x49d61045, 0x5b207515, 0x2e191bd8, 0x64903107}, b = {127, 0x08359044, 0x2f1aff57, 0x730d9fb4, 0x7f03816e}, res = {127, 0x520ba089, 0x0a3b746c, 0x2126bb8d, 0x6393b276}, carry = 1},
|
||||
{a = {127, 0x623eb7a3, 0x4d52e07d, 0x4a90b87c, 0x4641403a}, b = {125, 0x08f857d7, 0x3761ae9d, 0x46ead119, 0x13a35973}, res = {127, 0x6b370f7a, 0x04b48f1a, 0x117b8996, 0x59e499ae}, carry = 0},
|
||||
{a = {126, 0x71b46b67, 0x1edc966c, 0x42558b0c, 0x29be2808}, b = {127, 0x666102d3, 0x573e7bfe, 0x65d18c72, 0x67b4562e}, res = {126, 0x58156e3a, 0x761b126b, 0x2827177e, 0x11727e37}, carry = 1},
|
||||
{a = {127, 0x50500966, 0x0c5234da, 0x3e8cf39e, 0x62fbe6ce}, b = {127, 0x6c96a29c, 0x0ffb4fc4, 0x5f3a488f, 0x60d3a913}, res = {127, 0x3ce6ac02, 0x1c4d849f, 0x1dc73c2d, 0x43cf8fe2}, carry = 1},
|
||||
{a = {125, 0x508f7e5a, 0x2a6c24f8, 0x7cb4ae59, 0x1816c2cd}, b = {126, 0x1e8cc9df, 0x16ed73e1, 0x5910fa15, 0x3a24b307}, res = {125, 0x6f1c4839, 0x415998d9, 0x55c5a86e, 0x523b75d5}, carry = 0},
|
||||
{a = {127, 0x510325a0, 0x1ded9a89, 0x51e31db4, 0x6ddc474b}, b = {127, 0x22f4ab1e, 0x6fb69633, 0x51a5308e, 0x6eb15ef6}, res = {127, 0x73f7d0be, 0x0da430bc, 0x23884e43, 0x5c8da642}, carry = 1},
|
||||
{a = {127, 0x12108d0c, 0x386688ec, 0x69d02125, 0x628e00f3}, b = {124, 0x11f211b8, 0x2a6ff08f, 0x33daa305, 0x0c610086}, res = {127, 0x24029ec4, 0x62d6797b, 0x1daac42a, 0x6eef017a}, carry = 0},
|
||||
{a = {126, 0x0c264fba, 0x0884a2d3, 0x20569035, 0x304b267d}, b = {126, 0x6ff360e6, 0x12c6ad2b, 0x33f44806, 0x21d94783}, res = {126, 0x7c19b0a0, 0x1b4b4ffe, 0x544ad83b, 0x52246e00}, carry = 0},
|
||||
{a = {127, 0x43ab14a8, 0x7c15842c, 0x636094f1, 0x53d57eea}, b = {126, 0x15682230, 0x35fc075d, 0x59910014, 0x23e605cb}, res = {127, 0x591336d8, 0x32118b89, 0x3cf19506, 0x77bb84b6}, carry = 0},
|
||||
{a = {126, 0x5a7805ff, 0x32dd0387, 0x75f7a085, 0x3ea23d06}, b = {127, 0x4c55c285, 0x26e33530, 0x03d565c7, 0x724d2fcb}, res = {126, 0x26cdc884, 0x59c038b8, 0x79cd064c, 0x30ef6cd1}, carry = 1},
|
||||
{a = {125, 0x1a9e1657, 0x1af68cda, 0x4602b940, 0x17acd817}, b = {127, 0x539ac7fe, 0x54adc300, 0x1fe07458, 0x403f5f12}, res = {125, 0x6e38de55, 0x6fa44fda, 0x65e32d98, 0x57ec3729}, carry = 0},
|
||||
{a = {127, 0x62b5821b, 0x2c747aa2, 0x49572e10, 0x691ea596}, b = {127, 0x2e8da32f, 0x1325dd52, 0x08bf290a, 0x7b103bf2}, res = {127, 0x1143254a, 0x3f9a57f5, 0x5216571a, 0x642ee188}, carry = 1},
|
||||
{a = {127, 0x215fb007, 0x0dfc51a6, 0x7014c1ee, 0x5e30b9d9}, b = {125, 0x52f164a9, 0x300a98d7, 0x2cab73e3, 0x132af275}, res = {127, 0x745114b0, 0x3e06ea7d, 0x1cc035d1, 0x715bac4f}, carry = 0},
|
||||
{a = {127, 0x4dfcc7e5, 0x10d63d11, 0x443f7365, 0x7eb2535a}, b = {127, 0x543fd063, 0x041977bb, 0x294f5562, 0x7fabe576}, res = {127, 0x223c9848, 0x14efb4cd, 0x6d8ec8c7, 0x7e5e38d0}, carry = 1},
|
||||
{a = {127, 0x1a8c810b, 0x49c32b54, 0x5dfbd7fe, 0x49ce1a98}, b = {127, 0x5166f071, 0x0bfea258, 0x3325555d, 0x7ebb7c16}, res = {127, 0x6bf3717c, 0x55c1cdac, 0x11212d5b, 0x488996af}, carry = 1},
|
||||
{a = {124, 0x4b8a34ea, 0x5b0935d4, 0x3568d516, 0x0d16387a}, b = {126, 0x620a0226, 0x65058ce5, 0x6dd1444f, 0x2f49abb0}, res = {124, 0x2d943710, 0x400ec2ba, 0x233a1966, 0x3c5fe42b}, carry = 0},
|
||||
{a = {126, 0x5e834973, 0x4242f578, 0x03a1e339, 0x2c61fc03}, b = {127, 0x04a255ce, 0x01ec5f4b, 0x4e56d825, 0x5d998057}, res = {126, 0x63259f41, 0x442f54c3, 0x51f8bb5e, 0x09fb7c5a}, carry = 1},
|
||||
{a = {127, 0x6cb09c4b, 0x293baae1, 0x7e2830b9, 0x4edf0b6b}, b = {127, 0x4a59137b, 0x4b516bec, 0x0e882e9a, 0x67fd68cb}, res = {127, 0x3709afc6, 0x748d16ce, 0x0cb05f53, 0x36dc7437}, carry = 1},
|
||||
{a = {126, 0x49d63bd1, 0x20f7d1ab, 0x78eec602, 0x21eea324}, b = {127, 0x4bf2e9c3, 0x55004234, 0x012195b5, 0x725e1f50}, res = {126, 0x15c92594, 0x75f813e0, 0x7a105bb7, 0x144cc274}, carry = 1},
|
||||
{a = {118, 0x009708e5, 0x0f6eae6a, 0x22717ea3, 0x0027f75e}, b = {125, 0x73b69ce9, 0x05c9d5e7, 0x079ce44c, 0x1e0e4b57}, res = {118, 0x744da5ce, 0x15388451, 0x2a0e62ef, 0x1e3642b5}, carry = 0},
|
||||
{a = {127, 0x7d5fcca1, 0x703581e8, 0x5ebea294, 0x6d59d7b6}, b = {127, 0x072dc186, 0x2556d525, 0x6550936e, 0x483050d7}, res = {127, 0x048d8e27, 0x158c570e, 0x440f3603, 0x358a288e}, carry = 1},
|
||||
{a = {125, 0x1ee5e478, 0x6cbc0fd8, 0x5a08ca0d, 0x160799a6}, b = {124, 0x20c5baa0, 0x6893f6b8, 0x2e615746, 0x08b55361}, res = {125, 0x3fab9f18, 0x55500690, 0x086a2154, 0x1ebced08}, carry = 0},
|
||||
{a = {126, 0x5ba7f924, 0x69e6da01, 0x7012307c, 0x257f31e9}, b = {124, 0x4f354878, 0x5c6c44df, 0x580de770, 0x088dc09c}, res = {126, 0x2add419c, 0x46531ee1, 0x482017ed, 0x2e0cf286}, carry = 0},
|
||||
{a = {126, 0x53c283ee, 0x19ddd382, 0x401fa681, 0x39b9198a}, b = {126, 0x3e9c90df, 0x3091f3aa, 0x1ec070d3, 0x2f2473fa}, res = {126, 0x125f14cd, 0x4a6fc72d, 0x5ee01754, 0x68dd8d84}, carry = 0},
|
||||
{a = {125, 0x2aab90f9, 0x0ee5a976, 0x4b5b0203, 0x1672068b}, b = {125, 0x53c43b94, 0x020d4782, 0x260b9c3a, 0x1faca98d}, res = {125, 0x7e6fcc8d, 0x10f2f0f8, 0x71669e3d, 0x361eb018}, carry = 0},
|
||||
{a = {127, 0x1741cb5d, 0x42adb37f, 0x16f4e290, 0x7c26149a}, b = {127, 0x5c12de2e, 0x77a67be5, 0x2ef8e62e, 0x4a9fdb63}, res = {127, 0x7354a98b, 0x3a542f64, 0x45edc8bf, 0x46c5effd}, carry = 1},
|
||||
{a = {125, 0x21437747, 0x41ce24dd, 0x70efb0ac, 0x1d4aac67}, b = {126, 0x1235886f, 0x7bc15966, 0x1097debf, 0x29249284}, res = {125, 0x3378ffb6, 0x3d8f7e43, 0x01878f6c, 0x466f3eec}, carry = 0},
|
||||
{a = {126, 0x0e70b5d5, 0x43bd3fd6, 0x1bdbe98b, 0x2033fc0b}, b = {127, 0x7ce4daf7, 0x16ace9f7, 0x073703bc, 0x5704964f}, res = {126, 0x0b5590cc, 0x5a6a29ce, 0x2312ed47, 0x7738925a}, carry = 0},
|
||||
{a = {120, 0x62a94a7e, 0x604154fa, 0x3deeb80c, 0x00df6634}, b = {125, 0x6fd3f3b5, 0x3cfc6cef, 0x63fd704a, 0x1678e57f}, res = {120, 0x527d3e33, 0x1d3dc1ea, 0x21ec2857, 0x17584bb4}, carry = 0},
|
||||
{a = {123, 0x7978a2ad, 0x5d491b8a, 0x71574e8a, 0x0663444b}, b = {126, 0x0bc05c34, 0x7c0f280f, 0x015a49fc, 0x38502a7f}, res = {123, 0x0538fee1, 0x5958439a, 0x72b19887, 0x3eb36eca}, carry = 0},
|
||||
{a = {125, 0x51d6b6f2, 0x079bd814, 0x6ce81e2d, 0x18c4c981}, b = {127, 0x54f420d0, 0x2dc663dc, 0x13bc81b9, 0x4060575c}, res = {125, 0x26cad7c2, 0x35623bf1, 0x00a49fe6, 0x592520de}, carry = 0},
|
||||
{a = {127, 0x36485bbe, 0x09796514, 0x63ee7f58, 0x5625e4e2}, b = {127, 0x21458fe6, 0x7c9fa294, 0x54b76a7e, 0x6d695c7f}, res = {127, 0x578deba4, 0x061907a8, 0x38a5e9d7, 0x438f4162}, carry = 1},
|
||||
{a = {127, 0x33d70ec2, 0x1f127a0b, 0x2717bb82, 0x5fd43cd2}, b = {125, 0x3f0797eb, 0x0d5c370b, 0x3d594b1d, 0x1752300b}, res = {127, 0x72dea6ad, 0x2c6eb116, 0x6471069f, 0x77266cdd}, carry = 0},
|
||||
{a = {127, 0x37eae763, 0x19004adb, 0x38b7eff2, 0x688fe1c5}, b = {127, 0x2cac471c, 0x37811110, 0x1f3987d5, 0x7fe15712}, res = {127, 0x64972e7f, 0x50815beb, 0x57f177c7, 0x687138d7}, carry = 1},
|
||||
{a = {126, 0x6c225971, 0x0437a4c8, 0x1bcb8b3e, 0x28ceb662}, b = {127, 0x48cd5436, 0x7e421cca, 0x29d44db3, 0x55711f42}, res = {126, 0x34efada7, 0x0279c193, 0x459fd8f2, 0x7e3fd5a4}, carry = 0},
|
||||
{a = {126, 0x2574a51d, 0x5de32cbd, 0x6c67c9cc, 0x376694a2}, b = {126, 0x138f84b7, 0x46f2b3f1, 0x47583471, 0x3b15472c}, res = {126, 0x390429d4, 0x24d5e0ae, 0x33bffe3e, 0x727bdbcf}, carry = 0},
|
||||
{a = {127, 0x588e6a4d, 0x03204eb0, 0x400a06ba, 0x469c62fd}, b = {127, 0x33609fc4, 0x65a624e4, 0x6111951d, 0x7648f1ae}, res = {127, 0x0bef0a11, 0x68c67395, 0x211b9bd7, 0x3ce554ac}, carry = 1},
|
||||
{a = {127, 0x03178062, 0x2c0793b9, 0x6b91ed2a, 0x436a75d5}, b = {127, 0x364e9acd, 0x20881e30, 0x609f019a, 0x5d437f92}, res = {127, 0x39661b2f, 0x4c8fb1e9, 0x4c30eec4, 0x20adf568}, carry = 1},
|
||||
{a = {126, 0x582502a7, 0x76d9bbd7, 0x6ec18736, 0x3d15fed5}, b = {127, 0x45e8a9e7, 0x0cfae275, 0x4c164029, 0x641d8e58}, res = {126, 0x1e0dac8e, 0x03d49e4d, 0x3ad7c760, 0x21338d2e}, carry = 1},
|
||||
{a = {127, 0x31a44c73, 0x4c970755, 0x433f481c, 0x63704395}, b = {127, 0x1a3979dc, 0x0e9d5437, 0x592a1251, 0x5cb4e212}, res = {127, 0x4bddc64f, 0x5b345b8c, 0x1c695a6d, 0x402525a8}, carry = 1},
|
||||
{a = {126, 0x31499a0a, 0x2df3b6ac, 0x4cf3e9b4, 0x3fdaa87e}, b = {126, 0x6749f6f2, 0x28c62023, 0x3e54e11b, 0x30a577bf}, res = {126, 0x189390fc, 0x56b9d6d0, 0x0b48cacf, 0x7080203e}, carry = 0},
|
||||
{a = {126, 0x2d6e6ed4, 0x3c9f5183, 0x27326fac, 0x35b95ad6}, b = {125, 0x28a46b0d, 0x4143c903, 0x182ab95c, 0x17b09437}, res = {126, 0x5612d9e1, 0x7de31a86, 0x3f5d2908, 0x4d69ef0d}, carry = 0},
|
||||
{a = {126, 0x26f20408, 0x2af94d52, 0x440bf192, 0x360df26a}, b = {127, 0x7b2198cb, 0x763bc4c5, 0x78ac7d5a, 0x5de9efc9}, res = {126, 0x22139cd3, 0x21351218, 0x3cb86eed, 0x13f7e234}, carry = 1},
|
||||
{a = {127, 0x47128b80, 0x670a3dbb, 0x63efbba7, 0x74a10d1e}, b = {124, 0x7f481747, 0x59187cd8, 0x51e741bc, 0x0a8ea0cd}, res = {127, 0x465aa2c7, 0x4022ba94, 0x35d6fd64, 0x7f2fadec}, carry = 0},
|
||||
{a = {127, 0x5a47d043, 0x052b9ec0, 0x401cbe7c, 0x49104294}, b = {127, 0x7427cee8, 0x06334bc8, 0x4528bd14, 0x741e6df6}, res = {127, 0x4e6f9f2b, 0x0b5eea89, 0x05457b90, 0x3d2eb08b}, carry = 1},
|
||||
{a = {127, 0x6520f6a0, 0x5b37902f, 0x31d3c910, 0x5f9fe4e6}, b = {127, 0x6aa5d0dc, 0x61ad0b30, 0x3b782608, 0x7dd0cd5f}, res = {127, 0x4fc6c77c, 0x3ce49b60, 0x6d4bef19, 0x5d70b245}, carry = 1},
|
||||
{a = {126, 0x34bdc731, 0x2de09f84, 0x3896e197, 0x3fee6ac9}, b = {127, 0x5b5d8627, 0x3c22bdb9, 0x5e7b4aaf, 0x555e4e2a}, res = {126, 0x101b4d58, 0x6a035d3e, 0x17122c46, 0x154cb8f4}, carry = 1},
|
||||
}
|
||||
|
||||
@(rodata)
|
||||
i31_sub_test_vectors := []I31_Test_Vector_Binary {
|
||||
{a = {126, 0x75832201, 0x72b1ddb3, 0x3e8d7744, 0x325d7cb5}, b = {127, 0x52a23cfc, 0x51a47476, 0x19fd5fa3, 0x5a5e5d48}, res = {126, 0x22e0e505, 0x210d693d, 0x249017a1, 0x57ff1f6d}, carry = 1},
|
||||
{a = {127, 0x02585014, 0x15b77a75, 0x66fa4e0f, 0x5368a27c}, b = {126, 0x1aaa3973, 0x288030e7, 0x51ede1ff, 0x37bbad71}, res = {127, 0x67ae16a1, 0x6d37498d, 0x150c6c0f, 0x1bacf50b}, carry = 0},
|
||||
{a = {125, 0x3b43d5aa, 0x3de09ea7, 0x18004f89, 0x113b0b5e}, b = {127, 0x3a318699, 0x10ee38f1, 0x6d8c06d8, 0x7ac6ef8f}, res = {125, 0x01124f11, 0x2cf265b6, 0x2a7448b1, 0x16741bce}, carry = 1},
|
||||
{a = {127, 0x047e69b6, 0x5455ee19, 0x012e5e13, 0x73a56c35}, b = {127, 0x10606c28, 0x33f1e053, 0x18f48327, 0x69bc2be6}, res = {127, 0x741dfd8e, 0x20640dc5, 0x6839daec, 0x09e9404e}, carry = 0},
|
||||
{a = {127, 0x02c391a7, 0x07feb24a, 0x3a32b686, 0x5ee14ddd}, b = {126, 0x3f3b74ff, 0x2c1596d7, 0x677a7df4, 0x2ce6395d}, res = {127, 0x43881ca8, 0x5be91b72, 0x52b83891, 0x31fb147f}, carry = 0},
|
||||
{a = {125, 0x4b26152d, 0x24f5c3a3, 0x6f1d3b6f, 0x1586f40a}, b = {125, 0x7380829e, 0x1bd90254, 0x382393b6, 0x1b85a0c5}, res = {125, 0x57a5928f, 0x091cc14e, 0x36f9a7b9, 0x7a015345}, carry = 1},
|
||||
{a = {126, 0x4fa59569, 0x643c2005, 0x72e9a332, 0x2e315696}, b = {121, 0x6de61d40, 0x6b932a39, 0x52568d6d, 0x01e8488c}, res = {126, 0x61bf7829, 0x78a8f5cb, 0x209315c4, 0x2c490e0a}, carry = 0},
|
||||
{a = {127, 0x5379b430, 0x467ac863, 0x297696ab, 0x70622b6f}, b = {127, 0x37aac8dc, 0x1adda229, 0x58df1d01, 0x505ee996}, res = {127, 0x1bceeb54, 0x2b9d263a, 0x509779aa, 0x200341d8}, carry = 0},
|
||||
{a = {127, 0x1ccf6e2c, 0x11dc002c, 0x561b6361, 0x46990123}, b = {127, 0x3e9f8554, 0x42397834, 0x4fdd5416, 0x7e39420f}, res = {127, 0x5e2fe8d8, 0x4fa287f7, 0x063e0f4a, 0x485fbf14}, carry = 1},
|
||||
{a = {126, 0x2150add9, 0x26e965d1, 0x5e4ac34d, 0x2a55c9de}, b = {127, 0x6669738d, 0x3d3ff599, 0x582b736f, 0x4dd82557}, res = {126, 0x3ae73a4c, 0x69a97037, 0x061f4fdd, 0x5c7da487}, carry = 1},
|
||||
{a = {127, 0x61a3eb42, 0x2796bb5e, 0x5b90dcd6, 0x78085440}, b = {127, 0x51c6a80f, 0x0a65c487, 0x6179dc58, 0x562966ef}, res = {127, 0x0fdd4333, 0x1d30f6d7, 0x7a17007e, 0x21deed50}, carry = 0},
|
||||
{a = {127, 0x51d4085f, 0x72b1daa2, 0x7560d03e, 0x47df6842}, b = {125, 0x27993d6b, 0x1b36ba5a, 0x78a56068, 0x1811037d}, res = {127, 0x2a3acaf4, 0x577b2048, 0x7cbb6fd6, 0x2fce64c4}, carry = 0},
|
||||
{a = {125, 0x2cb4937a, 0x48c3af52, 0x7c4e70a7, 0x1578b00c}, b = {127, 0x20263089, 0x3feb52a0, 0x1b877614, 0x4f5677bc}, res = {125, 0x0c8e62f1, 0x08d85cb2, 0x60c6fa93, 0x46223850}, carry = 1},
|
||||
{a = {126, 0x338493e9, 0x4ff90c99, 0x5dc3827f, 0x2a9898da}, b = {122, 0x588232b4, 0x1c53bb05, 0x17ef86ab, 0x03bce2b4}, res = {126, 0x5b026135, 0x33a55193, 0x45d3fbd4, 0x26dbb626}, carry = 0},
|
||||
{a = {124, 0x40625bc9, 0x204b059d, 0x48deea64, 0x0a019e61}, b = {127, 0x661bd15a, 0x48ead2c5, 0x2a0e651f, 0x7999457b}, res = {124, 0x5a468a6f, 0x576032d7, 0x1ed08544, 0x106858e6}, carry = 1},
|
||||
{a = {127, 0x5874a542, 0x71947250, 0x054ff642, 0x7d66c0f6}, b = {125, 0x780fcb4e, 0x290dc73d, 0x2687ab55, 0x107555db}, res = {127, 0x6064d9f4, 0x4886ab12, 0x5ec84aed, 0x6cf16b1a}, carry = 0},
|
||||
{a = {126, 0x6fd19206, 0x50f14417, 0x7f82f1ed, 0x2bbb502b}, b = {127, 0x0468cf8a, 0x67942b1c, 0x7c399be0, 0x6306501c}, res = {126, 0x6b68c27c, 0x695d18fb, 0x0349560c, 0x48b5000f}, carry = 1},
|
||||
{a = {124, 0x51a0623b, 0x7b984ebd, 0x0fb05efe, 0x0fd13b63}, b = {127, 0x2a6b91ec, 0x68eaf51b, 0x3265f0fd, 0x4a4f4fb3}, res = {124, 0x2734d04f, 0x12ad59a2, 0x5d4a6e01, 0x4581ebaf}, carry = 1},
|
||||
{a = {127, 0x0f1be1af, 0x76ef0418, 0x489dab08, 0x4998335f}, b = {127, 0x24c297f4, 0x6fabbbe8, 0x01529fff, 0x6c5b3c15}, res = {127, 0x6a5949bb, 0x0743482f, 0x474b0b09, 0x5d3cf74a}, carry = 1},
|
||||
{a = {125, 0x53a96664, 0x6e05147a, 0x1017a26d, 0x19d02282}, b = {127, 0x46f7e29b, 0x466f513b, 0x1c9bb1fc, 0x56817f94}, res = {125, 0x0cb183c9, 0x2795c33f, 0x737bf071, 0x434ea2ed}, carry = 1},
|
||||
{a = {127, 0x2fcad8be, 0x60aea5d7, 0x63f1ddde, 0x5e392547}, b = {127, 0x3006e08d, 0x560753cd, 0x7e2304f9, 0x48c18d08}, res = {127, 0x7fc3f831, 0x0aa75209, 0x65ced8e5, 0x1577983e}, carry = 0},
|
||||
{a = {125, 0x140a0bd3, 0x0af4e07b, 0x1d4d97a3, 0x12530f8a}, b = {124, 0x66378508, 0x26164d79, 0x0b3ff9ba, 0x0b94a13a}, res = {125, 0x2dd286cb, 0x64de9301, 0x120d9de8, 0x06be6e50}, carry = 0},
|
||||
{a = {127, 0x16d0c935, 0x6e1afbd1, 0x08ef273a, 0x694e551c}, b = {125, 0x0f34a643, 0x167cbfb7, 0x2c1977e7, 0x1bd4f3cc}, res = {127, 0x079c22f2, 0x579e3c1a, 0x5cd5af53, 0x4d79614f}, carry = 0},
|
||||
{a = {127, 0x3d62a534, 0x3c284b2d, 0x53524377, 0x6016b0bd}, b = {125, 0x7cf4d88b, 0x68fb44c3, 0x61c8f0ad, 0x10e57b36}, res = {127, 0x406dcca9, 0x532d0669, 0x718952c9, 0x4f313586}, carry = 0},
|
||||
{a = {127, 0x6f015d33, 0x536fbab1, 0x26915f4b, 0x562f74ee}, b = {122, 0x63e75212, 0x68694786, 0x3f82de9a, 0x02f4382a}, res = {127, 0x0b1a0b21, 0x6b06732b, 0x670e80b0, 0x533b3cc3}, carry = 0},
|
||||
{a = {127, 0x66a82756, 0x4025f122, 0x42ad0938, 0x58fbe956}, b = {123, 0x150d6a84, 0x23439905, 0x7f8687ac, 0x057badf7}, res = {127, 0x519abcd2, 0x1ce2581d, 0x4326818c, 0x53803b5e}, carry = 0},
|
||||
{a = {127, 0x1b0466bd, 0x69accc1e, 0x55da7183, 0x71f64927}, b = {126, 0x12a653b6, 0x4be3b926, 0x174ecdc5, 0x2e28e368}, res = {127, 0x085e1307, 0x1dc912f8, 0x3e8ba3be, 0x43cd65bf}, carry = 0},
|
||||
{a = {119, 0x119a6115, 0x130e1918, 0x4e2c62c0, 0x00586779}, b = {127, 0x7042f5f4, 0x6c596133, 0x0b8e23ed, 0x4fded5b4}, res = {119, 0x21576b21, 0x26b4b7e4, 0x429e3ed2, 0x307991c5}, carry = 1},
|
||||
{a = {127, 0x05b5cfd3, 0x2ae55120, 0x46abe106, 0x70b46cd4}, b = {127, 0x4a8e2790, 0x5557a5e9, 0x3e14dfb6, 0x62ff997b}, res = {127, 0x3b27a843, 0x558dab36, 0x0897014f, 0x0db4d359}, carry = 0},
|
||||
{a = {126, 0x40c5bd09, 0x1bc7d36e, 0x5787d3c1, 0x2dadafd4}, b = {127, 0x7d36195e, 0x67d20645, 0x384c8cf2, 0x7bc9c106}, res = {126, 0x438fa3ab, 0x33f5cd28, 0x1f3b46ce, 0x31e3eece}, carry = 1},
|
||||
{a = {121, 0x582c3425, 0x5e591a55, 0x64bc368c, 0x01171496}, b = {127, 0x7ff455d7, 0x1d082b60, 0x69a595c6, 0x7506f22f}, res = {121, 0x5837de4e, 0x4150eef4, 0x7b16a0c6, 0x0c102266}, carry = 1},
|
||||
{a = {126, 0x76e444c8, 0x5d162950, 0x0b4c9cb8, 0x350172ce}, b = {126, 0x6fae6b50, 0x457e2833, 0x22e790fd, 0x222f32e8}, res = {126, 0x0735d978, 0x1798011d, 0x68650bbb, 0x12d23fe5}, carry = 0},
|
||||
{a = {126, 0x0a94f6cb, 0x7e659900, 0x21e27381, 0x20898f13}, b = {125, 0x6c0e1d51, 0x26db9379, 0x4aa78374, 0x13e8525f}, res = {126, 0x1e86d97a, 0x578a0586, 0x573af00d, 0x0ca13cb3}, carry = 0},
|
||||
{a = {126, 0x2df85daa, 0x089e925f, 0x372ad1cd, 0x282da3da}, b = {126, 0x5f6eb57d, 0x666b94e8, 0x72523b11, 0x2e872674}, res = {126, 0x4e89a82d, 0x2232fd76, 0x44d896bb, 0x79a67d65}, carry = 1},
|
||||
{a = {127, 0x59c5b936, 0x14069767, 0x00e21797, 0x7ab2135d}, b = {127, 0x4a74250d, 0x65c5e230, 0x5562bf62, 0x5c25dec5}, res = {127, 0x0f519429, 0x2e40b537, 0x2b7f5834, 0x1e8c3497}, carry = 0},
|
||||
{a = {125, 0x74ce4c1e, 0x59cb9a18, 0x5e0560c1, 0x142bdb97}, b = {126, 0x0e08a60d, 0x4c39a45f, 0x0929589f, 0x22096dd5}, res = {125, 0x66c5a611, 0x0d91f5b9, 0x54dc0822, 0x72226dc2}, carry = 1},
|
||||
{a = {127, 0x65273636, 0x653e4647, 0x2cf1b1f4, 0x74f9fddd}, b = {122, 0x6e960ace, 0x7ea2dfda, 0x35a317bd, 0x0202a322}, res = {127, 0x76912b68, 0x669b666c, 0x774e9a36, 0x72f75aba}, carry = 0},
|
||||
{a = {126, 0x45582ae7, 0x6996c2bb, 0x09380ea2, 0x30b4897c}, b = {127, 0x246ce79f, 0x758393b5, 0x00926c53, 0x40dd24dc}, res = {126, 0x20eb4348, 0x74132f06, 0x08a5a24e, 0x6fd764a0}, carry = 1},
|
||||
{a = {127, 0x7face3b5, 0x4e099393, 0x1e3f7fe6, 0x50946a47}, b = {126, 0x50b06b20, 0x36db7586, 0x40ec226f, 0x33e64381}, res = {127, 0x2efc7895, 0x172e1e0d, 0x5d535d77, 0x1cae26c5}, carry = 0},
|
||||
{a = {124, 0x5bae9309, 0x23a74c8d, 0x4c7f0704, 0x0fd4a29c}, b = {127, 0x07e40cc7, 0x31e632d3, 0x1ae2cbd2, 0x6f8f930a}, res = {124, 0x53ca8642, 0x71c119ba, 0x319c3b31, 0x20450f92}, carry = 1},
|
||||
{a = {126, 0x69c3634b, 0x0c4ffbaa, 0x390a326e, 0x25e998b2}, b = {123, 0x4d164145, 0x6cf31f2c, 0x60273791, 0x05ea1210}, res = {126, 0x1cad2206, 0x1f5cdc7e, 0x58e2fadc, 0x1fff86a1}, carry = 0},
|
||||
{a = {124, 0x25a0c384, 0x38438ee6, 0x67b92d68, 0x0b8d4052}, b = {127, 0x65152a5c, 0x6af4d890, 0x78f3790f, 0x516ebf7b}, res = {124, 0x408b9928, 0x4d4eb655, 0x6ec5b458, 0x3a1e80d6}, carry = 1},
|
||||
{a = {120, 0x27e60366, 0x1158cd09, 0x7f574484, 0x00eb60e2}, b = {126, 0x5ee2ec9b, 0x17d9507a, 0x283fcdf8, 0x3d95a50e}, res = {120, 0x490316cb, 0x797f7c8e, 0x5717768b, 0x4355bbd4}, carry = 1},
|
||||
{a = {126, 0x7a6cfbf1, 0x3b47fde4, 0x1f96a1b0, 0x3415815d}, b = {127, 0x6db4865c, 0x68d15d67, 0x29492ffd, 0x55b34d59}, res = {126, 0x0cb87595, 0x5276a07d, 0x764d71b2, 0x5e623403}, carry = 1},
|
||||
{a = {126, 0x78bc926b, 0x06872ef9, 0x77dc59ee, 0x341e1fe5}, b = {127, 0x4aafbaf4, 0x0f29aa6c, 0x6e2dcd74, 0x5ae5ab56}, res = {126, 0x2e0cd777, 0x775d848d, 0x09ae8c79, 0x5938748f}, carry = 1},
|
||||
{a = {127, 0x5339599f, 0x6d388285, 0x1fb30e96, 0x653d70d1}, b = {127, 0x26e44c38, 0x360bdfc0, 0x317ed433, 0x4e44f71e}, res = {127, 0x2c550d67, 0x372ca2c5, 0x6e343a63, 0x16f879b2}, carry = 0},
|
||||
{a = {126, 0x5f57436e, 0x5d7b8fc4, 0x3b913a49, 0x289c171d}, b = {127, 0x63106f0e, 0x181ab5a1, 0x1a35ecdc, 0x4f6fd3de}, res = {126, 0x7c46d460, 0x4560da22, 0x215b4d6d, 0x592c433f}, carry = 1},
|
||||
{a = {125, 0x0a9e7523, 0x4011ed51, 0x573e92c1, 0x1465e918}, b = {125, 0x190d6359, 0x595c3a46, 0x76ee73b0, 0x1163ef5f}, res = {125, 0x719111ca, 0x66b5b30a, 0x60501f10, 0x0301f9b8}, carry = 0},
|
||||
{a = {126, 0x5b4c4e1c, 0x368e93d7, 0x1d7f383f, 0x3893cc55}, b = {126, 0x15361741, 0x192e05a0, 0x69808f62, 0x3d0b8de0}, res = {126, 0x461636db, 0x1d608e37, 0x33fea8dd, 0x7b883e74}, carry = 1},
|
||||
{a = {127, 0x711129f3, 0x1221b384, 0x75a6ce65, 0x75cc9dda}, b = {125, 0x05242048, 0x29449c5e, 0x299b4ec4, 0x1179eca2}, res = {127, 0x6bed09ab, 0x68dd1726, 0x4c0b7fa0, 0x6452b138}, carry = 0},
|
||||
{a = {126, 0x23d8928a, 0x6bc1710b, 0x4f1a2853, 0x3920c780}, b = {127, 0x3ed60b0f, 0x639f16e2, 0x26d5472a, 0x7a6d17fb}, res = {126, 0x6502877b, 0x08225a28, 0x2844e129, 0x3eb3af85}, carry = 1},
|
||||
{a = {127, 0x0d9cfe5d, 0x619328e7, 0x542c700d, 0x6997d292}, b = {127, 0x1cedd3b7, 0x5edfbdf6, 0x45d76cf4, 0x7357a00a}, res = {127, 0x70af2aa6, 0x02b36af0, 0x0e550319, 0x76403288}, carry = 1},
|
||||
{a = {127, 0x03e30b55, 0x4013c48f, 0x729f2a80, 0x58b486a3}, b = {126, 0x786328fe, 0x37cc20dc, 0x25a645e1, 0x27cf6abb}, res = {127, 0x0b7fe257, 0x0847a3b2, 0x4cf8e49f, 0x30e51be8}, carry = 0},
|
||||
{a = {125, 0x7ac1580f, 0x2c93cbec, 0x527026f9, 0x124b767e}, b = {127, 0x68ba663a, 0x4df0c1d0, 0x4a5c9da6, 0x5da272db}, res = {125, 0x1206f1d5, 0x5ea30a1c, 0x08138952, 0x34a903a3}, carry = 1},
|
||||
{a = {127, 0x56b6b76a, 0x3ece11a5, 0x296c5e68, 0x59ab3003}, b = {127, 0x6e69a755, 0x7099639a, 0x357c87d6, 0x4c9f33fd}, res = {127, 0x684d1015, 0x4e34ae0a, 0x73efd691, 0x0d0bfc05}, carry = 0},
|
||||
{a = {127, 0x4404fa8a, 0x5866a5c4, 0x0c22add4, 0x5ef97523}, b = {127, 0x1c21bae1, 0x256e56eb, 0x77662e5f, 0x7376f17a}, res = {127, 0x27e33fa9, 0x32f84ed9, 0x14bc7f75, 0x6b8283a8}, carry = 1},
|
||||
{a = {126, 0x2c0d6109, 0x3509e87e, 0x53519777, 0x3c09bbc0}, b = {127, 0x3a60646e, 0x3f868a8e, 0x461edbdd, 0x777a0c2c}, res = {126, 0x71acfc9b, 0x75835def, 0x0d32bb99, 0x448faf94}, carry = 1},
|
||||
{a = {126, 0x5f8c1f7a, 0x40041120, 0x463c5e66, 0x35a4cd6e}, b = {127, 0x08cf40d3, 0x2edbcf34, 0x784ab86d, 0x4de2eb71}, res = {126, 0x56bcdea7, 0x112841ec, 0x4df1a5f9, 0x67c1e1fc}, carry = 1},
|
||||
{a = {127, 0x2266e65d, 0x0553ee53, 0x0c667741, 0x4fd147e2}, b = {127, 0x3fb1e4a2, 0x7cb1c12a, 0x535dbe75, 0x67bfcc87}, res = {127, 0x62b501bb, 0x08a22d28, 0x3908b8cb, 0x68117b5a}, carry = 1},
|
||||
{a = {127, 0x76bfd2fb, 0x40e3235f, 0x7110f948, 0x55262313}, b = {126, 0x56f35745, 0x288792fc, 0x3759df43, 0x36acfcf9}, res = {127, 0x1fcc7bb6, 0x185b9063, 0x39b71a05, 0x1e79261a}, carry = 0},
|
||||
{a = {125, 0x79452908, 0x28cb7d35, 0x033fb36e, 0x1e3d1dc2}, b = {126, 0x625452fe, 0x6f0e270e, 0x4a783375, 0x21ed361b}, res = {125, 0x16f0d60a, 0x39bd5627, 0x38c77ff8, 0x7c4fe7a6}, carry = 1},
|
||||
{a = {126, 0x7372a659, 0x3cd43111, 0x79c40547, 0x2d1afece}, b = {127, 0x7f8726fd, 0x24d0aa04, 0x1f6ecb14, 0x4e053ba9}, res = {126, 0x73eb7f5c, 0x1803870c, 0x5a553a33, 0x5f15c325}, carry = 1},
|
||||
{a = {126, 0x2f15690a, 0x4de81324, 0x3e9f55fe, 0x373cfdd3}, b = {125, 0x02bb7d7f, 0x3f2d94bb, 0x769d851b, 0x10f5260a}, res = {126, 0x2c59eb8b, 0x0eba7e69, 0x4801d0e3, 0x2647d7c8}, carry = 0},
|
||||
{a = {125, 0x54d7b5c6, 0x3932181a, 0x53521bf5, 0x1c5cf5ee}, b = {125, 0x03d8109e, 0x4d5cbcea, 0x49faabc0, 0x1d3e3e9a}, res = {125, 0x50ffa528, 0x6bd55b30, 0x09577034, 0x7f1eb754}, carry = 1},
|
||||
{a = {125, 0x43482a38, 0x1ce74ab0, 0x624445b9, 0x176cc140}, b = {125, 0x202ec3d7, 0x1cdd0bba, 0x4493150c, 0x13241d43}, res = {125, 0x23196661, 0x000a3ef6, 0x1db130ad, 0x0448a3fd}, carry = 0},
|
||||
{a = {126, 0x63a9b9c1, 0x5557f9c9, 0x4a536191, 0x3c4994c8}, b = {127, 0x5ee2af7f, 0x7dda218e, 0x53e931bb, 0x4270e93f}, res = {126, 0x04c70a42, 0x577dd83b, 0x766a2fd5, 0x79d8ab88}, carry = 1},
|
||||
{a = {127, 0x4950f74f, 0x6aad0a67, 0x43e36683, 0x76afb633}, b = {127, 0x2213721e, 0x76557c01, 0x299aae91, 0x44c18e55}, res = {127, 0x273d8531, 0x74578e66, 0x1a48b7f1, 0x31ee27de}, carry = 0},
|
||||
{a = {126, 0x0935ca8f, 0x1200cc80, 0x2f3661fb, 0x23960e06}, b = {126, 0x4624b76e, 0x14091fd6, 0x6286cb7a, 0x3e1aa872}, res = {126, 0x43111321, 0x7df7aca9, 0x4caf9680, 0x657b6593}, carry = 1},
|
||||
{a = {124, 0x52ac128b, 0x45fa9e02, 0x6427aa53, 0x0feaf8b5}, b = {127, 0x18aa3cc4, 0x19e96b87, 0x6c0e4dcc, 0x45da3929}, res = {124, 0x3a01d5c7, 0x2c11327b, 0x78195c87, 0x4a10bf8b}, carry = 1},
|
||||
{a = {126, 0x4111b645, 0x1c825213, 0x2a8b75b3, 0x213c3a3e}, b = {126, 0x23f60c22, 0x490b2da9, 0x353a3844, 0x29d5dd47}, res = {126, 0x1d1baa23, 0x5377246a, 0x75513d6e, 0x77665cf6}, carry = 1},
|
||||
{a = {127, 0x09c853b4, 0x7541862d, 0x36e91f14, 0x6e89e67d}, b = {127, 0x21d3bfe2, 0x61403f04, 0x554b57fc, 0x76d413df}, res = {127, 0x67f493d2, 0x14014728, 0x619dc718, 0x77b5d29d}, carry = 1},
|
||||
{a = {127, 0x67761ecf, 0x3837a139, 0x335e0875, 0x79923e83}, b = {127, 0x76813044, 0x7c0f5491, 0x59acc858, 0x5a7a5795}, res = {127, 0x70f4ee8b, 0x3c284ca7, 0x59b1401c, 0x1f17e6ed}, carry = 0},
|
||||
{a = {126, 0x6429a8c8, 0x635056e0, 0x76e76b1d, 0x3837df4c}, b = {127, 0x531005db, 0x115acaa3, 0x69231eee, 0x43d19db2}, res = {126, 0x1119a2ed, 0x51f58c3d, 0x0dc44c2f, 0x7466419a}, carry = 1},
|
||||
{a = {127, 0x5014a598, 0x068dbb0f, 0x22fdc5bf, 0x6a670715}, b = {126, 0x7c4f94e9, 0x2e78116b, 0x224d3768, 0x2b95833a}, res = {127, 0x53c510af, 0x5815a9a3, 0x00b08e56, 0x3ed183db}, carry = 0},
|
||||
{a = {126, 0x75b94a38, 0x71d62d52, 0x6c557c79, 0x2d8cfb9f}, b = {127, 0x743c6840, 0x3b04bcff, 0x50744d2c, 0x608611a3}, res = {126, 0x017ce1f8, 0x36d17053, 0x1be12f4d, 0x4d06e9fc}, carry = 1},
|
||||
{a = {126, 0x04d24ee0, 0x37e1c03c, 0x50704c96, 0x2577ba6b}, b = {127, 0x6dd14735, 0x03c4f523, 0x379aa43a, 0x4fbfbf80}, res = {126, 0x170107ab, 0x341ccb18, 0x18d5a85c, 0x55b7faeb}, carry = 1},
|
||||
{a = {123, 0x572d0f53, 0x732fb14c, 0x7975e187, 0x05706d99}, b = {127, 0x51a90823, 0x707dd091, 0x2f6c63b4, 0x789adddf}, res = {123, 0x05840730, 0x02b1e0bb, 0x4a097dd3, 0x0cd58fba}, carry = 1},
|
||||
{a = {126, 0x68306d82, 0x51d883c8, 0x52a45e7f, 0x339e6fc7}, b = {127, 0x57da71c8, 0x72d5dd1c, 0x21a11ff7, 0x5d6ea34b}, res = {126, 0x1055fbba, 0x5f02a6ac, 0x31033e87, 0x562fcc7c}, carry = 1},
|
||||
{a = {125, 0x47b20e6e, 0x39411f59, 0x0324640b, 0x19996204}, b = {124, 0x4e55588b, 0x64846ee8, 0x57d16f9e, 0x0a3db8bc}, res = {125, 0x795cb5e3, 0x54bcb070, 0x2b52f46c, 0x0f5ba947}, carry = 0},
|
||||
{a = {127, 0x5a6ab51b, 0x0051b988, 0x1a192e89, 0x42b3d43a}, b = {125, 0x2daa3aa4, 0x063f37e9, 0x7ba7850f, 0x13dcea8c}, res = {127, 0x2cc07a77, 0x7a12819f, 0x1e71a979, 0x2ed6e9ad}, carry = 0},
|
||||
{a = {125, 0x46813953, 0x6920da78, 0x5b6db2f9, 0x12219a9c}, b = {126, 0x5666e4fb, 0x5458ccf2, 0x097952e7, 0x38f4e37f}, res = {125, 0x701a5458, 0x14c80d85, 0x51f46012, 0x592cb71d}, carry = 1},
|
||||
{a = {127, 0x47633dea, 0x6405989b, 0x1d019f24, 0x7dab4fa6}, b = {127, 0x686dbe43, 0x5715424a, 0x2027ac93, 0x70c8d29c}, res = {127, 0x5ef57fa7, 0x0cf05650, 0x7cd9f291, 0x0ce27d09}, carry = 0},
|
||||
{a = {127, 0x22705ca5, 0x2c180e47, 0x393c2083, 0x40d0fea1}, b = {124, 0x37ce1e5a, 0x17b2b88d, 0x49bd2a90, 0x0d5d9087}, res = {127, 0x6aa23e4b, 0x146555b9, 0x6f7ef5f3, 0x33736e19}, carry = 0},
|
||||
{a = {126, 0x5d61d089, 0x1391e7a4, 0x780aeb70, 0x3eb6e8e2}, b = {127, 0x7a54a013, 0x28f31254, 0x3d63ef25, 0x5d2cf7ff}, res = {126, 0x630d3076, 0x6a9ed54f, 0x3aa6fc4a, 0x6189f0e3}, carry = 1},
|
||||
{a = {126, 0x505f4672, 0x275eb845, 0x665c7a55, 0x31c26f48}, b = {127, 0x3af113f0, 0x6a0358aa, 0x009cd3d5, 0x551cd2f6}, res = {126, 0x156e3282, 0x3d5b5f9b, 0x65bfa67f, 0x5ca59c52}, carry = 1},
|
||||
{a = {126, 0x1a313b22, 0x04332012, 0x4cfb19fe, 0x3aa25e6c}, b = {127, 0x0525c494, 0x1a177649, 0x10bd52f2, 0x5d114ab1}, res = {126, 0x150b768e, 0x6a1ba9c9, 0x3c3dc70b, 0x5d9113bb}, carry = 1},
|
||||
{a = {126, 0x52981c2d, 0x4c46b130, 0x37b3c3cf, 0x231f6fc4}, b = {126, 0x76da8c93, 0x5e52130f, 0x7efb6a4f, 0x2e3c4907}, res = {126, 0x5bbd8f9a, 0x6df49e20, 0x38b8597f, 0x74e326bc}, carry = 1},
|
||||
{a = {127, 0x05600262, 0x0bb65331, 0x19f8d9cb, 0x5ddc2c62}, b = {127, 0x687b227e, 0x27348976, 0x072f2464, 0x4fbe7ebe}, res = {127, 0x1ce4dfe4, 0x6481c9ba, 0x12c9b566, 0x0e1dada4}, carry = 0},
|
||||
{a = {127, 0x6a2d2e4a, 0x1b8b56dd, 0x50946d73, 0x64b0886d}, b = {122, 0x68ceaba5, 0x5344cea7, 0x7aeae02f, 0x03444737}, res = {127, 0x015e82a5, 0x48468836, 0x55a98d43, 0x616c4135}, carry = 0},
|
||||
{a = {126, 0x2be80971, 0x7a1ffbd6, 0x7d5cd745, 0x310e6aa8}, b = {126, 0x31c62e38, 0x08a3a28d, 0x4d67f9a3, 0x30493db3}, res = {126, 0x7a21db39, 0x717c5948, 0x2ff4dda2, 0x00c52cf5}, carry = 0},
|
||||
{a = {125, 0x030ba3d3, 0x162c1b78, 0x3f878cb3, 0x1a5108ff}, b = {127, 0x1f37aec7, 0x01e1153a, 0x325aab1e, 0x4b9a6619}, res = {125, 0x63d3f50c, 0x144b063d, 0x0d2ce195, 0x4eb6a2e6}, carry = 1},
|
||||
{a = {126, 0x15a0528b, 0x29cbf0ad, 0x3048884b, 0x2c03d1c4}, b = {127, 0x5c32f40c, 0x192de971, 0x21a7f87d, 0x558c0542}, res = {126, 0x396d5e7f, 0x109e073b, 0x0ea08fce, 0x5677cc82}, carry = 1},
|
||||
{a = {126, 0x0b48d92b, 0x5b09cd3a, 0x73960e62, 0x3f0ed1cd}, b = {124, 0x7a3d70fe, 0x5ff9c6b1, 0x4bd0e555, 0x0cc51487}, res = {126, 0x110b682d, 0x7b100688, 0x27c5290c, 0x3249bd46}, carry = 0},
|
||||
{a = {127, 0x1bf5bd1c, 0x54104aef, 0x0c7ce316, 0x420fe407}, b = {126, 0x409409a2, 0x3d04fecd, 0x3e06417a, 0x3078c80b}, res = {127, 0x5b61b37a, 0x170b4c21, 0x4e76a19c, 0x11971bfb}, carry = 0},
|
||||
{a = {125, 0x33d00217, 0x1c394fa4, 0x574f8331, 0x1d57d174}, b = {127, 0x6630d00d, 0x666f444c, 0x1a90af22, 0x484d8ca0}, res = {125, 0x4d9f320a, 0x35ca0b57, 0x3cbed40e, 0x550a44d4}, carry = 1},
|
||||
{a = {127, 0x166e17c2, 0x1ecc3694, 0x1d8ad0ad, 0x5cfd9dd8}, b = {125, 0x130183de, 0x537699d8, 0x353fa45d, 0x114feeeb}, res = {127, 0x036c93e4, 0x4b559cbc, 0x684b2c4f, 0x4badaeec}, carry = 0},
|
||||
{a = {127, 0x2736ea4c, 0x34a77f3b, 0x5d62185c, 0x49f65789}, b = {126, 0x10ef92f4, 0x6d50c8cd, 0x3b2c8da0, 0x26d91a49}, res = {127, 0x16475758, 0x4756b66e, 0x22358abb, 0x231d3d40}, carry = 0},
|
||||
{a = {127, 0x7c90f6d6, 0x6e8c2441, 0x56303ec7, 0x648b71e2}, b = {127, 0x5efcffab, 0x35738e3f, 0x6a0010b5, 0x54fd6ef0}, res = {127, 0x1d93f72b, 0x39189602, 0x6c302e12, 0x0f8e02f1}, carry = 0},
|
||||
{a = {127, 0x09d4aa13, 0x39bee362, 0x48f85dfd, 0x54d4270d}, b = {121, 0x75609829, 0x5a20f480, 0x2a01c588, 0x0146be72}, res = {127, 0x147411ea, 0x5f9deee1, 0x1ef69874, 0x538d689b}, carry = 0},
|
||||
{a = {123, 0x5ca62e2f, 0x5bd68bd9, 0x009238b5, 0x04524739}, b = {126, 0x0f74d025, 0x68d0ff9b, 0x3cd174c2, 0x23b408c2}, res = {123, 0x4d315e0a, 0x73058c3e, 0x43c0c3f2, 0x609e3e76}, carry = 1},
|
||||
}
|
||||
|
||||
I31_Test_Vector_Decode :: struct {
|
||||
src: []byte,
|
||||
decode: []u32,
|
||||
mod: []u32,
|
||||
mod_res: u32,
|
||||
}
|
||||
|
||||
@(rodata)
|
||||
i31_decode_test_vectors := []I31_Test_Vector_Decode {
|
||||
{src = {0x49}, decode = {7, 0x00000049}, mod = {42, 0x00000049}, mod_res = 1},
|
||||
{src = {0x27, 0xdb}, decode = {14, 0x000027db}, mod = {42, 0x000027db}, mod_res = 1},
|
||||
{src = {0xb8, 0xd7, 0x72}, decode = {24, 0x00b8d772}, mod = {42, 0x00b8d772}, mod_res = 1},
|
||||
{src = {0xa0, 0x94, 0x6e, 0xac}, decode = {33, 0x20946eac, 0x00000001}, mod = {42, 0x20946eac, 0x00000001}, mod_res = 1},
|
||||
{src = {0xed, 0x8a, 0xc2, 0xe4, 0x45}, decode = {41, 0x0ac2e445, 0x000001db}, mod = {42, 0x0ac2e445, 0x000001db}, mod_res = 1},
|
||||
{src = {0xfb, 0x37, 0x36, 0x46, 0x28, 0x4e}, decode = {49, 0x3646284e, 0x0001f66e}, mod = {42, 0x00000000, 0x00000000}, mod_res = 0},
|
||||
{src = {0xd8, 0xcc, 0xbb, 0xf2, 0x13, 0x66, 0xdf}, decode = {57, 0x721366df, 0x01b19977}, mod = {42, 0x00000000, 0x00000000}, mod_res = 0},
|
||||
{src = {0xcb, 0xc3, 0xe2, 0xa8, 0x4c, 0xfd, 0x9e, 0x8a}, decode = {66, 0x4cfd9e8a, 0x1787c550, 0x00000003}, mod = {42, 0x00000000, 0x00000000, 0x00000000}, mod_res = 0},
|
||||
{src = {0x0d, 0xd5, 0x76, 0xc1, 0xb4, 0x02, 0xdb, 0xb4, 0xb9}, decode = {70, 0x02dbb4b9, 0x2aed8368, 0x00000037}, mod = {42, 0x00000000, 0x00000000, 0x00000000}, mod_res = 0},
|
||||
{src = {0xf6, 0xb6, 0x08, 0xb3, 0xfb, 0x0c, 0x7e, 0x8e, 0x58, 0xa7}, decode = {82, 0x7e8e58a7, 0x1167f618, 0x0003dad8}, mod = {42, 0x00000000, 0x00000000, 0x00000000}, mod_res = 0},
|
||||
{src = {0xf9, 0x51, 0xde, 0x6a, 0x29, 0x54, 0x48, 0xf5, 0x3c, 0x78, 0x85}, decode = {90, 0x753c7885, 0x5452a891, 0x03e54779}, mod = {42, 0x00000000, 0x00000000, 0x00000000}, mod_res = 0},
|
||||
{src = {0xb5, 0x5a, 0x92, 0x18, 0x67, 0x09, 0x6e, 0x21, 0x5d, 0x84, 0x10, 0xce}, decode = {99, 0x5d8410ce, 0x4e12dc42, 0x556a4861, 0x00000005}, mod = {42, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, mod_res = 0},
|
||||
{src = {0xd3, 0xa4, 0x7b, 0xa0, 0x90, 0x26, 0x36, 0x73, 0xa6, 0x7f, 0x28, 0x66, 0x4e}, decode = {107, 0x7f28664e, 0x4c6ce74c, 0x11ee8240, 0x0000069d}, mod = {42, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, mod_res = 0},
|
||||
{src = {0x23, 0xfa, 0xe7, 0x0c, 0x6a, 0x07, 0x00, 0x86, 0xa2, 0xcf, 0x22, 0xa1, 0x1f, 0x62}, decode = {113, 0x22a11f62, 0x010d459e, 0x1c31a81c, 0x00011fd7}, mod = {42, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, mod_res = 0},
|
||||
{src = {0x9c, 0x39, 0xf8, 0x67, 0x8a, 0x9f, 0x85, 0xb4, 0xdb, 0x92, 0x4b, 0xe6, 0xdc, 0x12, 0xa5}, decode = {123, 0x66dc12a5, 0x69b72497, 0x1e2a7e16, 0x04e1cfc3}, mod = {42, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, mod_res = 0},
|
||||
{src = {0x8f, 0xc7, 0xcc, 0xda, 0x43, 0x21, 0x0b, 0x39, 0x0e, 0xc3, 0x51, 0xb0, 0xbd, 0xce, 0xbb, 0x73}, decode = {132, 0x3dcebb73, 0x1d86a361, 0x0c842ce4, 0x7e3e66d2, 0x00000008}, mod = {42, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, mod_res = 0},
|
||||
{src = {0xc5, 0x8d, 0xd3, 0x1b, 0xda, 0x0d, 0x21, 0xfd, 0xb2, 0x69, 0xca, 0x12, 0xd4, 0x47, 0x44, 0x4e, 0x61}, decode = {140, 0x47444e61, 0x539425a8, 0x3487f6c9, 0x6e98ded0, 0x00000c58}, mod = {42, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, mod_res = 0},
|
||||
{src = {0x4f, 0x00, 0x7f, 0x9c, 0x00, 0x11, 0x29, 0x8d, 0x94, 0xd6, 0x7e, 0x1c, 0xc3, 0x26, 0x78, 0xb7, 0xfb, 0xbb}, decode = {147, 0x78b7fbbb, 0x7c39864c, 0x26365359, 0x7ce00089, 0x0004f007}, mod = {42, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, mod_res = 0},
|
||||
{src = {0xb8, 0x85, 0x3f, 0xe0, 0x03, 0x89, 0x20, 0x72, 0xf8, 0xa6, 0x66, 0x48, 0x0f, 0xdb, 0x63, 0x19, 0x8e, 0xbb, 0x00}, decode = {156, 0x198ebb00, 0x101fb6c6, 0x4be29999, 0x001c4903, 0x0b8853fe}, mod = {42, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, mod_res = 0},
|
||||
{src = {0x3c, 0x88, 0x99, 0xf2, 0x23, 0xc8, 0x65, 0x6d, 0x6a, 0x93, 0xa0, 0xf6, 0xef, 0x8d, 0x28, 0xd8, 0x85, 0x9e, 0x8f, 0x85}, decode = {163, 0x059e8f85, 0x5f1a51b1, 0x2a4e83db, 0x1e432b6b, 0x48899f22, 0x00000007}, mod = {42, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, mod_res = 0},
|
||||
{src = {0xd8, 0x28, 0x9e, 0xae, 0x7c, 0xc2, 0xf6, 0x9c, 0x72, 0xe7, 0x25, 0xf6, 0x0c, 0xec, 0xcc, 0x78, 0x5d, 0xf9, 0xb0, 0xe9, 0x9f}, decode = {173, 0x79b0e99f, 0x5998f0bb, 0x1c97d833, 0x17b4e397, 0x09eae7cc, 0x00001b05}, mod = {42, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, mod_res = 0},
|
||||
{src = {0xec, 0x5f, 0x68, 0xa7, 0xb6, 0xa4, 0x7d, 0x01, 0x88, 0x39, 0xeb, 0x88, 0x3a, 0x33, 0x60, 0x8a, 0x59, 0x67, 0xaa, 0xfe, 0x67, 0xc2}, decode = {181, 0x2afe67c2, 0x4114b2cf, 0x2e20e8cd, 0x680c41cf, 0x0a7b6a47, 0x001d8bed}, mod = {42, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, mod_res = 0},
|
||||
{src = {0x34, 0x8a, 0x87, 0xdb, 0xbf, 0x60, 0xa6, 0x58, 0x23, 0xe3, 0x99, 0x9a, 0x43, 0x5c, 0x43, 0x9e, 0xfe, 0xb2, 0xbd, 0xd7, 0xd2, 0xa3, 0x74}, decode = {187, 0x57d2a374, 0x3dfd657b, 0x690d710e, 0x411f1ccc, 0x3bf60a65, 0x069150fb}, mod = {42, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, mod_res = 0},
|
||||
{src = {0xe6, 0xe7, 0x48, 0x95, 0x31, 0x9e, 0xdb, 0x97, 0xd7, 0x37, 0x17, 0x1a, 0x9a, 0x51, 0xde, 0x02, 0xa4, 0x7f, 0x84, 0xbd, 0x25, 0x02, 0xc7, 0xe1}, decode = {198, 0x2502c7e1, 0x48ff097a, 0x6947780a, 0x39b8b8d4, 0x19edb97d, 0x5ce912a6, 0x00000039}, mod = {42, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, mod_res = 0},
|
||||
{src = {0x5c, 0xd5, 0xa2, 0x66, 0xf4, 0x01, 0x12, 0xba, 0xe8, 0x05, 0x63, 0xa0, 0xc0, 0xfa, 0xaf, 0xe1, 0x3d, 0xe4, 0xc5, 0x21, 0xab, 0xa9, 0x52, 0x99, 0x3f}, decode = {205, 0x2952993f, 0x498a4357, 0x6abf84f7, 0x2b1d0607, 0x112bae80, 0x344cde80, 0x00001735}, mod = {42, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, mod_res = 0},
|
||||
{src = {0x8f, 0x93, 0xfc, 0x0c, 0x73, 0x29, 0x7d, 0x28, 0xdc, 0x71, 0x7b, 0x01, 0x53, 0x4f, 0x87, 0xdd, 0xf5, 0x43, 0xe2, 0xb0, 0x97, 0x1d, 0xe1, 0xf7, 0x7f, 0xcf}, decode = {214, 0x61f77fcf, 0x45612e3b, 0x1f77d50f, 0x580a9a7c, 0x528dc717, 0x018e652f, 0x0023e4ff}, mod = {42, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, mod_res = 0},
|
||||
{src = {0xd7, 0x86, 0x9b, 0x8d, 0x91, 0x97, 0xff, 0x98, 0xbe, 0xa7, 0x67, 0x73, 0xda, 0x7a, 0x07, 0xe7, 0x07, 0xf3, 0x61, 0xc4, 0x2d, 0x01, 0x96, 0x68, 0xbf, 0xd6, 0x36}, decode = {222, 0x68bfd636, 0x085a032c, 0x1c1fcd87, 0x1ed3d03f, 0x0bea7677, 0x3232fff3, 0x35e1a6e3}, mod = {42, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, mod_res = 0},
|
||||
{src = {0xf7, 0xec, 0xfa, 0x44, 0x18, 0x5e, 0x6a, 0x51, 0x98, 0x3d, 0x3b, 0xc9, 0xcf, 0xb5, 0x9f, 0x97, 0xa8, 0x7d, 0xdd, 0xda, 0xf3, 0xf3, 0x1c, 0x02, 0x9c, 0x40, 0x5c, 0x8a}, decode = {231, 0x1c405c8a, 0x67e63805, 0x21f7776b, 0x7dacfcbd, 0x03d3bc9c, 0x0bcd4a33, 0x7b3e9106, 0x0000007b}, mod = {42, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, mod_res = 0},
|
||||
{src = {0xca, 0x32, 0x04, 0xef, 0xc8, 0x40, 0x55, 0xc9, 0x67, 0x2e, 0x3b, 0x1a, 0xbe, 0x2c, 0xf1, 0xdd, 0xe0, 0xaa, 0x46, 0x31, 0x40, 0xc5, 0xf6, 0xaa, 0x25, 0x88, 0x0d, 0x0f, 0x30}, decode = {239, 0x080d0f30, 0x0bed544b, 0x2918c503, 0x678eef05, 0x63b1abe2, 0x0ab92ce5, 0x013bf210, 0x00006519}, mod = {42, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, mod_res = 0},
|
||||
{src = {0x96, 0xb5, 0x62, 0x03, 0x50, 0x9f, 0x04, 0xfc, 0xc3, 0x06, 0x25, 0xc1, 0xa7, 0x21, 0x6d, 0xeb, 0x60, 0x8d, 0xb0, 0x02, 0x34, 0x18, 0xaf, 0xd1, 0xb0, 0x23, 0x0f, 0x6a, 0xe6, 0x63}, decode = {247, 0x0f6ae663, 0x5fa36046, 0x4008d062, 0x6f5b046d, 0x5c1a7216, 0x1f9860c4, 0x00d427c1, 0x004b5ab1}, mod = {42, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, mod_res = 0},
|
||||
{src = {0x5c, 0x00, 0x1a, 0x67, 0x07, 0x8e, 0x49, 0x72, 0x30, 0x6f, 0x2b, 0xa6, 0x93, 0x37, 0x6a, 0x2b, 0x5a, 0x8f, 0xb4, 0x30, 0x65, 0x89, 0xa1, 0x7b, 0xbc, 0xf9, 0x85, 0x3f, 0x44, 0x64, 0x48}, decode = {254, 0x3f446448, 0x7779f30a, 0x41962685, 0x5ad47da1, 0x693376a2, 0x460de574, 0x41e3925c, 0x2e000d33, 0x00000000}, mod = {42, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, mod_res = 0},
|
||||
}
|
||||
|
||||
I31_Test_RShift :: struct {
|
||||
orig: []u32,
|
||||
res: []u32,
|
||||
shift: i32,
|
||||
}
|
||||
|
||||
@(rodata)
|
||||
i31_rshift_test_vectors := []I31_Test_RShift {
|
||||
{orig = {92, 0x4b451fff, 0x2874869d, 0x0d1b97a7}, res = {92, 0x4b451fff, 0x2874869d, 0x0d1b97a7}, shift = 0},
|
||||
{orig = {94, 0x44709cd4, 0x60d36574, 0x3a587e31}, res = {94, 0x22384e6a, 0x7069b2ba, 0x1d2c3f18}, shift = 1},
|
||||
{orig = {94, 0x77ea5771, 0x78324ed5, 0x3d9ad39d}, res = {94, 0x3dfa95dc, 0x3e0c93b5, 0x0f66b4e7}, shift = 2},
|
||||
{orig = {94, 0x631db445, 0x248c243a, 0x3f1cc589}, res = {94, 0x2c63b688, 0x14918487, 0x07e398b1}, shift = 3},
|
||||
{orig = {95, 0x6f23a8ed, 0x7d5a3c91, 0x7e913a13}, res = {95, 0x0ef23a8e, 0x1fd5a3c9, 0x07e913a1}, shift = 4},
|
||||
{orig = {94, 0x03dd8abf, 0x5f02ee65, 0x249f3f58}, res = {94, 0x141eec55, 0x62f81773, 0x0124f9fa}, shift = 5},
|
||||
{orig = {94, 0x2927bee6, 0x4f308116, 0x3279228a}, res = {94, 0x2ca49efb, 0x153cc204, 0x00c9e48a}, shift = 6},
|
||||
{orig = {95, 0x22687024, 0x73cb5fd3, 0x52d71799}, res = {95, 0x5344d0e0, 0x19e796bf, 0x00a5ae2f}, shift = 7},
|
||||
{orig = {94, 0x71a3bca0, 0x27642d52, 0x23e2059f}, res = {94, 0x2971a3bc, 0x4fa7642d, 0x0023e205}, shift = 8},
|
||||
{orig = {95, 0x180d85aa, 0x12a8516d, 0x4797741e}, res = {95, 0x5b4c06c2, 0x07895428, 0x0023cbba}, shift = 9},
|
||||
{orig = {95, 0x7b30aeeb, 0x3ababf4f, 0x6a446aff}, res = {95, 0x69fecc2b, 0x5feeaeaf, 0x001a911a}, shift = 10},
|
||||
{orig = {94, 0x3b2d5f09, 0x7bde80e9, 0x33ed8ce0}, res = {94, 0x0e9765ab, 0x4e0f7bd0, 0x00067db1}, shift = 11},
|
||||
{orig = {93, 0x62c89828, 0x20d78d11, 0x14bbd081}, res = {93, 0x688e2c89, 0x040a0d78, 0x00014bbd}, shift = 12},
|
||||
{orig = {95, 0x102c28e6, 0x31f2a99f, 0x6c337ed1}, res = {95, 0x267c8161, 0x7b458f95, 0x0003619b}, shift = 13},
|
||||
{orig = {94, 0x78097c9b, 0x6b3f99c8, 0x2ea10fbb}, res = {94, 0x3391e025, 0x1f77acfe, 0x0000ba84}, shift = 14},
|
||||
{orig = {92, 0x4684f360, 0x56d54074, 0x0dd7bfa7}, res = {92, 0x40748d09, 0x3fa7adaa, 0x00001baf}, shift = 15},
|
||||
{orig = {93, 0x59e9b272, 0x1792ca1d, 0x134ce6d8}, res = {93, 0x650ed9e9, 0x736c1792, 0x0000134c}, shift = 16},
|
||||
{orig = {94, 0x2be2d592, 0x566508a1, 0x3a8622ab}, res = {94, 0x422855f1, 0x08aaeb32, 0x00001d43}, shift = 17},
|
||||
{orig = {95, 0x3082be20, 0x118cde6a, 0x57a1832c}, res = {95, 0x1bcd4c20, 0x30658463, 0x000015e8}, shift = 18},
|
||||
{orig = {95, 0x7b7ec9fc, 0x30304a84, 0x7cb524f7}, res = {95, 0x04a84f6f, 0x524f7606, 0x00000f96}, shift = 19},
|
||||
{orig = {94, 0x7a038786, 0x5902ae15, 0x2ee36b72}, res = {94, 0x1570afa0, 0x1b5b9590, 0x000002ee}, shift = 20},
|
||||
{orig = {95, 0x2a127f63, 0x5d1b323f, 0x7dc23bd7}, res = {95, 0x6cc8fd50, 0x08ef5ee8, 0x000003ee}, shift = 21},
|
||||
{orig = {95, 0x3cf76a47, 0x30310973, 0x69bc9430}, res = {95, 0x6212e6f3, 0x792860c0, 0x000001a6}, shift = 22},
|
||||
{orig = {94, 0x3ca70baa, 0x07747e80, 0x3a710be4}, res = {94, 0x747e8079, 0x710be40e, 0x00000074}, shift = 23},
|
||||
{orig = {95, 0x6bc0e3b9, 0x77b2972f, 0x5b9f893c}, res = {95, 0x594b97eb, 0x4fc49e77, 0x0000005b}, shift = 24},
|
||||
{orig = {90, 0x49e59ccc, 0x7d67d332, 0x02b4f127}, res = {90, 0x59f4cca4, 0x2d3c49fe, 0x00000001}, shift = 25},
|
||||
{orig = {94, 0x55e1b1d7, 0x7a1c0bdb, 0x217e8547}, res = {94, 0x43817b75, 0x2fd0a8fe, 0x00000008}, shift = 26},
|
||||
{orig = {94, 0x67fb980c, 0x20a9410b, 0x25de2ffd}, res = {94, 0x0a9410bc, 0x5de2ffd4, 0x00000004}, shift = 27},
|
||||
{orig = {92, 0x18363569, 0x0b492aba, 0x0a37f42c}, res = {92, 0x5a4955d1, 0x51bfa160, 0x00000000}, shift = 28},
|
||||
{orig = {95, 0x23bb0e53, 0x4bb6c3aa, 0x77932915}, res = {95, 0x2edb0ea9, 0x5e4ca456, 0x00000003}, shift = 29},
|
||||
{orig = {95, 0x725acb18, 0x1da81862, 0x6d6c306b}, res = {95, 0x3b5030c5, 0x5ad860d6, 0x00000001}, shift = 30},
|
||||
{orig = {95, 0x70d51c12, 0x44e8b652, 0x4a0d2a6b}, res = {95, 0x44e8b652, 0x4a0d2a6b, 0x00000000}, shift = 31},
|
||||
}
|
||||
|
||||
I31_Test_Reduce :: struct {
|
||||
orig: []u32,
|
||||
res: []u32,
|
||||
}
|
||||
|
||||
@(rodata)
|
||||
i31_reduce_test_vectors := []I31_Test_Reduce {
|
||||
{orig = {62, 0x27da8fd9, 0x2fea2339}, res = {42, 0x27f284e9, 0x00000339}},
|
||||
{orig = {95, 0x37856cc1, 0x54ad3e73, 0x718777f1}, res = {42, 0x33efdfc1, 0x0000022f, 0x718777f1}},
|
||||
{orig = {123, 0x4787b519, 0x47fa51cf, 0x11ef98ae, 0x058b1a99}, res = {42, 0x567ed6bd, 0x000002fe, 0x11ef98ae, 0x058b1a99}},
|
||||
{orig = {158, 0x328fbfb6, 0x6e9ec225, 0x0241df84, 0x4a3627d0, 0x3a79e4a4}, res = {42, 0x005f59f0, 0x000001aa, 0x0241df84, 0x4a3627d0, 0x3a79e4a4}},
|
||||
{orig = {191, 0x451321f5, 0x45f677b9, 0x2c43b0b8, 0x7cb722c1, 0x70e594e6, 0x4c81757c}, res = {42, 0x684ba25d, 0x0000008d, 0x2c43b0b8, 0x7cb722c1, 0x70e594e6, 0x4c81757c}},
|
||||
{orig = {222, 0x0749fe0b, 0x3c45795b, 0x21e6f14c, 0x265b264d, 0x37def307, 0x35019b6b, 0x25ab0a3e}, res = {42, 0x36c99d3d, 0x00000173, 0x21e6f14c, 0x265b264d, 0x37def307, 0x35019b6b, 0x25ab0a3e}},
|
||||
{orig = {255, 0x1c2630cd, 0x0c0d9a7e, 0x375154d0, 0x67249adf, 0x0df9ec39, 0x73b5ad9e, 0x396d0f52, 0x4ed9b56a}, res = {42, 0x79997cc9, 0x000002b4, 0x375154d0, 0x67249adf, 0x0df9ec39, 0x73b5ad9e, 0x396d0f52, 0x4ed9b56a}},
|
||||
{orig = {286, 0x35b7eae2, 0x033002a6, 0x149766aa, 0x5d4a5a16, 0x7d09704c, 0x380c8cf2, 0x249df2ff, 0x03caabad, 0x214fc645}, res = {42, 0x20f488ba, 0x000003e1, 0x149766aa, 0x5d4a5a16, 0x7d09704c, 0x380c8cf2, 0x249df2ff, 0x03caabad, 0x214fc645}},
|
||||
{orig = {315, 0x7a5813dc, 0x76309cbf, 0x03e432bc, 0x218df9a1, 0x1a0d0525, 0x793ad550, 0x280cbf6e, 0x18356492, 0x4b6f39a1, 0x04adeb0d}, res = {42, 0x0016ad0c, 0x000000a8, 0x03e432bc, 0x218df9a1, 0x1a0d0525, 0x793ad550, 0x280cbf6e, 0x18356492, 0x4b6f39a1, 0x04adeb0d}},
|
||||
{orig = {351, 0x0ded15c8, 0x3875535e, 0x4627ebc1, 0x101a8369, 0x7300acd4, 0x22113509, 0x2a441bc0, 0x25902fec, 0x230133c0, 0x7ecaa587, 0x439bfdcd}, res = {42, 0x60547c04, 0x00000144, 0x4627ebc1, 0x101a8369, 0x7300acd4, 0x22113509, 0x2a441bc0, 0x25902fec, 0x230133c0, 0x7ecaa587, 0x439bfdcd}},
|
||||
}
|
||||
|
||||
@(rodata)
|
||||
i31_decode_reduce_test_vectors := []I31_Test_Vector_Decode {
|
||||
{src = {171, 54, 46}, decode = {42, 0x00ab362e, 0x00000000, 0x00000000}},
|
||||
{src = {87, 80, 187, 242}, decode = {42, 0x5750bbf2, 0x00000000, 0x00000000}},
|
||||
{src = {181, 9, 43, 65, 203}, decode = {42, 0x092b41cb, 0x0000016a, 0x00000000}},
|
||||
{src = {196, 160, 88, 214, 25, 234}, decode = {42, 0x58d61aae, 0x00000140, 0x00000000}},
|
||||
{src = {223, 248, 213, 188, 56, 226, 125}, decode = {42, 0x3c39c275, 0x000001ab, 0x00000000}},
|
||||
{src = {252, 152, 213, 96, 59, 205, 38, 68}, decode = {42, 0x3cc9bf18, 0x000002c0, 0x00000000}},
|
||||
{src = {61, 151, 139, 227, 56, 129, 245, 7, 245}, decode = {42, 0x3f8c93d7, 0x00000271, 0x00000000}},
|
||||
{src = {50, 242, 36, 43, 28, 76, 75, 80, 191, 213}, decode = {42, 0x3d74eaf1, 0x000000fe, 0x00000000}},
|
||||
{src = {45, 174, 63, 171, 108, 66, 180, 223, 196, 24, 202}, decode = {42, 0x1f6f853a, 0x000000c6, 0x00000000}},
|
||||
{src = {106, 140, 119, 25, 145, 178, 50, 134, 118, 181, 241, 205}, decode = {42, 0x10480e8b, 0x000001fb, 0x00000000}},
|
||||
}
|
||||
|
||||
I31_Test_Mul_Add_Small :: struct {
|
||||
orig: []u32,
|
||||
res: []u32,
|
||||
z: u32,
|
||||
}
|
||||
|
||||
@(rodata)
|
||||
i31_mul_add_test_vectors := []I31_Test_Mul_Add_Small {
|
||||
{orig = {63, 0x157df37a, 0x5e97b10e}, res = {63, 0x438abf24, 0x7fffff7a}, z = 42},
|
||||
{orig = {63, 0x6c11d92a, 0x74b6b943}, res = {63, 0x50f60940, 0x0000012a}, z = 84},
|
||||
{orig = {63, 0x0bf17f5a, 0x756c85bb}, res = {63, 0x6ec5f93e, 0x7fffff5a}, z = 126},
|
||||
{orig = {63, 0x0d24e4eb, 0x5891203e}, res = {63, 0x0f86931a, 0x000000eb}, z = 168},
|
||||
{orig = {63, 0x41dda071, 0x6deb6411}, res = {63, 0x0460efa2, 0x00000071}, z = 210},
|
||||
{orig = {63, 0x29793d56, 0x4d5204e5}, res = {63, 0x3954bd9a, 0x00000156}, z = 252},
|
||||
{orig = {58, 0x40e72062, 0x039ba033}, res = {58, 0x0ce074b6, 0x00000062}, z = 294},
|
||||
{orig = {63, 0x6e9b147b, 0x60dcf3ef}, res = {63, 0x7bf74edc, 0x7ffffc7c}, z = 336},
|
||||
{orig = {62, 0x74572099, 0x3af8369a}, res = {62, 0x26ba2d0a, 0x0000009a}, z = 378},
|
||||
}
|
||||
|
||||
I31_Test_Vector_Encode :: struct {
|
||||
orig: []u32,
|
||||
encoded: []u8,
|
||||
}
|
||||
|
||||
@(rodata)
|
||||
i31_encode_test_vectors := []I31_Test_Vector_Encode {
|
||||
{orig = {30, 0x2003ca33}, encoded = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 3, 202, 51}},
|
||||
{orig = {61, 0x13d86a42, 0x1c0fc55a}, encoded = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 7, 226, 173, 19, 216, 106, 66}},
|
||||
{orig = {93, 0x0adffd1b, 0x3a03c1bc, 0x19682bb9}, encoded = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 90, 10, 238, 93, 1, 224, 222, 10, 223, 253, 27}},
|
||||
{orig = {127, 0x193841a2, 0x5cf0aa2f, 0x57594f6d, 0x4fc77899}, encoded = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 248, 239, 19, 53, 214, 83, 219, 110, 120, 85, 23, 153, 56, 65, 162}},
|
||||
{orig = {158, 0x219d0fd8, 0x623e21ae, 0x5c9ad413, 0x6dc292d4, 0x2b2f85fe}, encoded = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 178, 248, 95, 237, 184, 82, 90, 151, 38, 181, 4, 241, 31, 16, 215, 33, 157, 15, 216}},
|
||||
{orig = {189, 0x69363092, 0x4b751e5d, 0x663b4745, 0x2e93e19e, 0x1a3dabce, 0x1d4caa3f}, encoded = {0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 101, 81, 249, 163, 218, 188, 229, 210, 124, 51, 217, 142, 209, 209, 101, 186, 143, 46, 233, 54, 48, 146}},
|
||||
{orig = {222, 0x016b86ed, 0x29c31304, 0x15cca452, 0x6abefa4a, 0x7410f562, 0x450559df, 0x28ad9252}, encoded = {0, 0, 0, 0, 0, 162, 182, 73, 74, 40, 42, 206, 255, 65, 15, 86, 45, 87, 223, 73, 69, 115, 41, 20, 148, 225, 137, 130, 1, 107, 134, 237}},
|
||||
{orig = {253, 0x4b6d0cd3, 0x357f8b7d, 0x4bd86436, 0x5838a86c, 0x10280aa0, 0x22f9b902, 0x4bdb5c1c, 0x19a20f9e}, encoded = {0, 51, 68, 31, 61, 47, 109, 112, 113, 23, 205, 200, 17, 2, 128, 170, 11, 7, 21, 13, 146, 246, 25, 13, 154, 191, 197, 190, 203, 109, 12, 211}},
|
||||
}
|
||||
|
||||
I31_Test_Ninv :: struct {
|
||||
orig: []u32,
|
||||
ninv: []u32,
|
||||
}
|
||||
|
||||
@(rodata)
|
||||
i31_ninv_test_vectors := I31_Test_Ninv {
|
||||
orig = {0x00000c5c, 0x47faf728, 0x69a8e9d5, 0x49f5015c, 0x4ea9aea5, 0x164bcf32, 0x3fc395b4, 0x1c0a908a, 0x795f47f2, 0x79aa0c9a, 0x1a37680f, 0x2834cf17, 0x499235c8, 0x6d239632, 0x0560438b, 0x2cf4b82b, 0x5133fd25, 0x3b63a8b9, 0x45b66eca, 0x0213c13c, 0x6cd589f3, 0x4ed03f68, 0x722eb913, 0x670c76f4, 0x444d31d0, 0x1809da41, 0x3656a4af, 0x2ab43d09, 0x281c0e85, 0x426b3fd3, 0x680413c0, 0x065884c2, 0x55e4db17, 0x3839a23f, 0x3cc508b0, 0x3c492cda, 0x43325992, 0x5bc31283, 0x3891deaa, 0x5ddddd43, 0x64314225, 0x43a1c73b, 0x5e0ec431, 0x27f583bf, 0x491a73dc, 0x377982b8, 0x0b760791, 0x7835c61d, 0x0192b0f7, 0x129ca7ca, 0x16333e2d, 0x39c07864, 0x4d4b0d1b, 0x252fdb31, 0x2ca1bef8, 0x0358e216, 0x6aeda289, 0x201bca8f, 0x6ded1451, 0x5fbb04bb, 0x03d86c3b, 0x2f402c96, 0x4567a0ad, 0x6159d4de, 0x494f89b9, 0x7035fbdf, 0x5c3cfbd6, 0x40bfdbc8, 0x5e27b49c, 0x4fee508e, 0x76bd2f29, 0x45b49e47, 0x7da53921, 0x3d9380aa, 0x5d5bce86, 0x212b2912, 0x2e3e0a61, 0x218cfe04, 0x22ebe499, 0x70713a1c, 0x5b690632, 0x3f5c8dc1, 0x323815a5, 0x1f9f4c8f, 0x56a54a21, 0x469a2122, 0x6fb2beea, 0x643ac847, 0x01d2c5bc, 0x7dc51683, 0x0b876ebe, 0x214a069a, 0x535258ed, 0x529b3dce, 0x2760b2c2, 0x78cf5cd3, 0x19d1d3f2, 0x572ebc02, 0x1ab91604, 0x0b5f09a0},
|
||||
ninv = {0x00000000, 0x00000000, 0x66e2f883, 0x00000000, 0x210176d3, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x40ad7911, 0x3954a759, 0x00000000, 0x00000000, 0x657333dd, 0x11c1b97d, 0x1c122953, 0x40642277, 0x00000000, 0x00000000, 0x7f3dc8c5, 0x00000000, 0x166a06e5, 0x00000000, 0x00000000, 0x605cca3f, 0x3548cdb1, 0x35b19ec7, 0x681845b3, 0x1c438fa5, 0x00000000, 0x00000000, 0x2beff359, 0x79f2b241, 0x00000000, 0x00000000, 0x00000000, 0x6040b3d5, 0x00000000, 0x1ee96895, 0x1f18f653, 0x7f80860d, 0x3901eb2f, 0x56ff93c1, 0x00000000, 0x00000000, 0x562e668f, 0x72bad3cb, 0x3de0ef39, 0x00000000, 0x6be23e5b, 0x00000000, 0x3a327aed, 0x0fae622f, 0x00000000, 0x00000000, 0x004d8c47, 0x5a1feb91, 0x76f34b4f, 0x68675f8d, 0x7dec730d, 0x00000000, 0x5a953cdb, 0x00000000, 0x65605377, 0x7aa67fe1, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4eaf22e7, 0x4a585489, 0x3fa2751f, 0x00000000, 0x00000000, 0x00000000, 0x7107e65f, 0x00000000, 0x5f81d057, 0x00000000, 0x00000000, 0x2d7b7dbf, 0x0e2f35d3, 0x75e7ad91, 0x4ed7461f, 0x00000000, 0x00000000, 0x4a199e89, 0x00000000, 0x45bf97d5, 0x00000000, 0x00000000, 0x4ada3b1b, 0x00000000, 0x00000000, 0x7456a4a5, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
}
|
||||
|
||||
I31_Test_Monty_Mul :: struct {
|
||||
x: []u32,
|
||||
y: []u32,
|
||||
m: []u32,
|
||||
res: []u32,
|
||||
}
|
||||
|
||||
@(rodata)
|
||||
i31_monty_mul_test_vectors := []I31_Test_Monty_Mul {
|
||||
{x = {127, 0x7c5a766e, 0x6ce75a35, 0x1c64cb75, 0x51263ee0, 0x00000000}, y = {127, 0x75063ae3, 0x3f506a6f, 0x1d1ad6d5, 0x47a85d53, 0x00000000}, m = {159, 0x7e0a5a33, 0x41c36cc5, 0x065bfbbd, 0x4608e748, 0x69ac6740, 0x00000000}, res = {159, 0x3e2b1a07, 0x4990ba63, 0x15f1a1ea, 0x6e8ff678, 0x13ba5b66}},
|
||||
{x = {124, 0x5232b140, 0x341f2854, 0x3e6bde54, 0x092324e1, 0x00000000}, y = {127, 0x6c66ba58, 0x51577b9e, 0x72a600d4, 0x53bd0450, 0x00000000}, m = {159, 0x153010a5, 0x7d0ddec2, 0x13c7f180, 0x1cd216b3, 0x5818bdd7, 0x00000000}, res = {159, 0x6de73758, 0x21d8ff38, 0x69b18e1e, 0x5d1c7d47, 0x41c75523}},
|
||||
{x = {126, 0x176e0f5b, 0x0a98100a, 0x475e0a72, 0x348f9141, 0x00000000}, y = {127, 0x334e2dfe, 0x2c988363, 0x73e23cf8, 0x606dcc5f, 0x00000000}, m = {159, 0x7023de77, 0x54103e3b, 0x338cd291, 0x0e2c1e77, 0x6fa41147, 0x00000000}, res = {159, 0x488db6ba, 0x3ec6b26b, 0x0dddf8b5, 0x4e0334db, 0x2125e61c}},
|
||||
{x = {127, 0x1018738e, 0x233c04d7, 0x46a665c0, 0x79c84e0a, 0x00000000}, y = {127, 0x783e44fe, 0x14a1ea17, 0x31bea107, 0x66c49111, 0x00000000}, m = {158, 0x580ca6c1, 0x61ad5aad, 0x238b9bdb, 0x0ce14c93, 0x2749fc5c, 0x00000000}, res = {158, 0x37557af5, 0x5ca2f6fb, 0x7fdca455, 0x4d436f9b, 0x18d60f4f}},
|
||||
{x = {126, 0x45da293a, 0x1665982a, 0x0e8fc303, 0x231c2772, 0x00000000}, y = {126, 0x542485c1, 0x3f2f7d3f, 0x684047a6, 0x3abaed33, 0x00000000}, m = {159, 0x03d31fd1, 0x6f0c8ff3, 0x12825696, 0x199fda81, 0x76457daf, 0x00000000}, res = {159, 0x6c6852a3, 0x0d1fd2b0, 0x67e96590, 0x768c4fca, 0x3ad66382}},
|
||||
{x = {126, 0x21d23a0e, 0x5ba5d464, 0x29697487, 0x338d2cff, 0x00000000}, y = {125, 0x29e49a2c, 0x144564ae, 0x3d17958d, 0x101f7e41, 0x00000000}, m = {158, 0x4545452b, 0x6e68f705, 0x2302e752, 0x07b5d5d6, 0x3657a220, 0x00000000}, res = {158, 0x3e90a0ed, 0x457cb17b, 0x53b4f9f5, 0x7a6324ce, 0x35d2cdd7}},
|
||||
{x = {125, 0x4732d8b6, 0x45573e7d, 0x07f4963f, 0x12a290dd, 0x00000000}, y = {127, 0x39baf88d, 0x5d858830, 0x4580eb58, 0x6d196a63, 0x00000000}, m = {159, 0x0cb6812b, 0x482b08af, 0x4f1b863c, 0x3cef2e92, 0x50f7c7f1, 0x00000000}, res = {159, 0x6ad503c6, 0x27c67766, 0x5fca2845, 0x15bbcb6b, 0x46c3cb6c}},
|
||||
{x = {127, 0x354a4328, 0x651d0b7f, 0x43a452fb, 0x7bd74c98, 0x00000000}, y = {126, 0x3cfc2842, 0x71256a54, 0x3719176f, 0x34407271, 0x00000000}, m = {159, 0x306eba87, 0x772cb87d, 0x4907c954, 0x5dc5e91b, 0x74d5eb17, 0x00000000}, res = {159, 0x49e12a70, 0x7e89a281, 0x1ea3548a, 0x54711053, 0x713bfe04}},
|
||||
{x = {126, 0x4affb101, 0x52a6864d, 0x7152422e, 0x3cca5f4e, 0x00000000}, y = {126, 0x3f4b1e18, 0x32aaa89a, 0x635dcdc7, 0x3c44b1de, 0x00000000}, m = {158, 0x01432ccf, 0x2bcf7f6d, 0x7561291c, 0x7064f0cb, 0x3381e843, 0x00000000}, res = {158, 0x03895437, 0x6792e4bb, 0x68391714, 0x5a6104d6, 0x16bbc670}},
|
||||
{x = {127, 0x56c42650, 0x2723c136, 0x4d64beac, 0x5e656e91, 0x00000000}, y = {126, 0x1aa1d10f, 0x01fffab5, 0x44fd097e, 0x3483b271, 0x00000000}, m = {159, 0x2f77d067, 0x1f191f5b, 0x1a1a8568, 0x52026c09, 0x4692f6e6, 0x00000000}, res = {159, 0x1b1bfa15, 0x3726bd88, 0x1af57d8e, 0x2de30fb3, 0x3f96e86f}},
|
||||
}
|
||||
|
||||
I31_Test_To_Monty :: struct {
|
||||
orig: []u32,
|
||||
x: []u32,
|
||||
m: []u32,
|
||||
}
|
||||
|
||||
@(rodata)
|
||||
i31_to_monty_test_vectors := []I31_Test_To_Monty {
|
||||
{orig = {123, 0x3f3aff0e, 0x459fe053, 0x4bba523d, 0x04b91a78, 0x00000000}, x = {123, 0x2eab2260, 0x4d3d8e5d, 0x2943569d, 0x01d1c5f3, 0x00000000}, m = {123, 0x3f3aff1b, 0x459fe061, 0x4bba524b, 0x04b91a78, 0x00000000}},
|
||||
{orig = {127, 0x111641a2, 0x4fcfb2b4, 0x1cf1576b, 0x6b088658, 0x00000000}, x = {127, 0x25c08f99, 0x3bdc976a, 0x3a808f23, 0x5be48931, 0x00000000}, m = {127, 0x111641af, 0x4fcfb2c1, 0x1cf15779, 0x6b088658, 0x00000000}},
|
||||
{orig = {126, 0x03accd4a, 0x34a7e2d7, 0x749af3f3, 0x25febe05, 0x00000000}, x = {126, 0x763fca85, 0x61a5498c, 0x28eb0856, 0x1dab3aee, 0x00000000}, m = {126, 0x03accd57, 0x34a7e2e5, 0x749af401, 0x25febe05, 0x00000000}},
|
||||
{orig = {127, 0x6d8c4617, 0x01cffa24, 0x3475f32e, 0x7c9ba743, 0x00000000}, x = {127, 0x7304a0f6, 0x653ea916, 0x6c412db9, 0x427e57a8, 0x00000000}, m = {127, 0x6d8c4625, 0x01cffa31, 0x3475f33b, 0x7c9ba743, 0x00000000}},
|
||||
{orig = {127, 0x2da2a286, 0x152f4795, 0x3f383173, 0x6622cb58, 0x00000000}, x = {127, 0x1e118541, 0x63461082, 0x57a7e060, 0x3529988e, 0x00000000}, m = {127, 0x2da2a293, 0x152f47a3, 0x3f383181, 0x6622cb58, 0x00000000}},
|
||||
{orig = {127, 0x2a17a287, 0x52b707dd, 0x30d2b30f, 0x6334fa45, 0x00000000}, x = {127, 0x06823214, 0x2c2ddf09, 0x286443db, 0x231af948, 0x00000000}, m = {127, 0x2a17a295, 0x52b707eb, 0x30d2b31d, 0x6334fa45, 0x00000000}},
|
||||
{orig = {127, 0x41152b43, 0x0a898780, 0x5a517da6, 0x72eb605e, 0x00000000}, x = {127, 0x2761082a, 0x1e1ff23b, 0x3f2516a3, 0x0b165b25, 0x00000000}, m = {127, 0x41152b51, 0x0a89878d, 0x5a517db3, 0x72eb605e, 0x00000000}},
|
||||
{orig = {127, 0x6b29c7ff, 0x6297d9f9, 0x3225bebb, 0x71bc4932, 0x00000000}, x = {127, 0x4bb7368d, 0x12320331, 0x5cc9ce0e, 0x1eb2ad59, 0x00000000}, m = {127, 0x6b29c80d, 0x6297da07, 0x3225bec9, 0x71bc4932, 0x00000000}},
|
||||
{orig = {127, 0x6cb514c0, 0x3ff230d8, 0x6a6915f5, 0x73655603, 0x00000000}, x = {127, 0x1ebae285, 0x28f81b38, 0x37f80ed8, 0x21dc723e, 0x00000000}, m = {127, 0x6cb514cd, 0x3ff230e5, 0x6a691603, 0x73655603, 0x00000000}},
|
||||
{orig = {127, 0x632339fa, 0x30508879, 0x038d4f85, 0x4bff3ced, 0x00000000}, x = {127, 0x3a3502a9, 0x4364df08, 0x3c8b1fdc, 0x20b2fa04, 0x00000000}, m = {127, 0x63233a07, 0x30508887, 0x038d4f93, 0x4bff3ced, 0x00000000}},
|
||||
}
|
||||
|
||||
I31_Test_Mod_Pow :: struct {
|
||||
orig: []u32,
|
||||
x: []u32,
|
||||
e: []u8,
|
||||
m: []u32,
|
||||
}
|
||||
|
||||
@(rodata)
|
||||
i31_mod_pow_test_vectors := []I31_Test_Mod_Pow {
|
||||
{orig = {123, 0x2eab2260, 0x4d3d8e5d, 0x2943569d, 0x01d1c5f3, 0x00000000}, x = {123, 0x030692d4, 0x14836f1f, 0x7c343636, 0x014fdd77, 0x00000000}, e = {81, 188, 252, 55, 213, 144, 254, 197, 116, 215, 162}, m = {123, 0x3f3aff1b, 0x459fe061, 0x4bba524b, 0x04b91a78, 0x00000000}},
|
||||
{orig = {127, 0x25c08f99, 0x3bdc976a, 0x3a808f23, 0x5be48931, 0x00000000}, x = {127, 0x3cd4569e, 0x6474f743, 0x23fc7461, 0x05e72909, 0x00000000}, e = {145, 145, 164, 213, 254, 94, 63, 192, 72, 205, 16}, m = {127, 0x111641af, 0x4fcfb2c1, 0x1cf15779, 0x6b088658, 0x00000000}},
|
||||
{orig = {126, 0x763fca85, 0x61a5498c, 0x28eb0856, 0x1dab3aee, 0x00000000}, x = {126, 0x0eb01d51, 0x178d8313, 0x044cbdfa, 0x022d38b4, 0x00000000}, e = {254, 224, 156, 88, 224, 176, 213, 125, 112, 43, 72}, m = {126, 0x03accd57, 0x34a7e2e5, 0x749af401, 0x25febe05, 0x00000000}},
|
||||
{orig = {127, 0x7304a0f6, 0x653ea916, 0x6c412db9, 0x427e57a8, 0x00000000}, x = {127, 0x3b1cad0e, 0x15e996b3, 0x6ccc145e, 0x63b7aa04, 0x00000000}, e = {250, 142, 147, 53, 107, 204, 201, 168, 122, 147, 143}, m = {127, 0x6d8c4625, 0x01cffa31, 0x3475f33b, 0x7c9ba743, 0x00000000}},
|
||||
{orig = {127, 0x1e118541, 0x63461082, 0x57a7e060, 0x3529988e, 0x00000000}, x = {127, 0x3ed716f7, 0x09f828bb, 0x00840e9d, 0x19c59712, 0x00000000}, e = {244, 245, 26, 174, 174, 246, 9, 106, 176, 161, 120}, m = {127, 0x2da2a293, 0x152f47a3, 0x3f383181, 0x6622cb58, 0x00000000}},
|
||||
{orig = {127, 0x06823214, 0x2c2ddf09, 0x286443db, 0x231af948, 0x00000000}, x = {127, 0x79062be3, 0x5787887e, 0x59a8999f, 0x3f1c71f1, 0x00000000}, e = {212, 118, 203, 181, 125, 193, 238, 33, 133, 239, 12}, m = {127, 0x2a17a295, 0x52b707eb, 0x30d2b31d, 0x6334fa45, 0x00000000}},
|
||||
{orig = {127, 0x2761082a, 0x1e1ff23b, 0x3f2516a3, 0x0b165b25, 0x00000000}, x = {127, 0x7a632df1, 0x1775c47f, 0x30b8030b, 0x562da059, 0x00000000}, e = {139, 161, 176, 68, 175, 27, 137, 101, 59, 37, 210}, m = {127, 0x41152b51, 0x0a89878d, 0x5a517db3, 0x72eb605e, 0x00000000}},
|
||||
{orig = {127, 0x4bb7368d, 0x12320331, 0x5cc9ce0e, 0x1eb2ad59, 0x00000000}, x = {127, 0x00db078c, 0x078b7daf, 0x2c19dc27, 0x5e45284f, 0x00000000}, e = {154, 81, 208, 248, 214, 247, 12, 230, 127, 200, 184}, m = {127, 0x6b29c80d, 0x6297da07, 0x3225bec9, 0x71bc4932, 0x00000000}},
|
||||
{orig = {127, 0x1ebae285, 0x28f81b38, 0x37f80ed8, 0x21dc723e, 0x00000000}, x = {127, 0x1f004d80, 0x15576afe, 0x7dccb09d, 0x31928c9a, 0x00000000}, e = {164, 131, 3, 178, 189, 171, 249, 186, 241, 118, 179}, m = {127, 0x6cb514cd, 0x3ff230e5, 0x6a691603, 0x73655603, 0x00000000}},
|
||||
{orig = {127, 0x3a3502a9, 0x4364df08, 0x3c8b1fdc, 0x20b2fa04, 0x00000000}, x = {127, 0x13718bdd, 0x3ea119db, 0x1d2488e5, 0x02324bed, 0x00000000}, e = {107, 45, 140, 104, 190, 245, 72, 158, 102, 160, 168}, m = {127, 0x63233a07, 0x30508887, 0x038d4f93, 0x4bff3ced, 0x00000000}},
|
||||
}
|
||||
|
||||
I31_Test_Mul_Acc :: struct {
|
||||
res: []u32,
|
||||
d: []u32,
|
||||
a: []u32,
|
||||
b: []u32,
|
||||
}
|
||||
|
||||
@(rodata)
|
||||
i31_mul_acc_test_vectors := []I31_Test_Mul_Acc {
|
||||
{res = {317, 0x535a1b12, 0x44ccd6ec, 0x1fa7b212, 0x584b46e2, 0x222bf023, 0x4580794b, 0x67411ea6, 0x47b4ac1d, 0x229d50a9, 0x1818f1a8, 0x00000000}, d = {157, 0x79ef7e23, 0x4387243c, 0x0f107f29, 0x3567d945, 0x24e08c78, 0x00000000}, a = {157, 0x06deb1d1, 0x7bba988f, 0x46c80867, 0x490dafbc, 0x1f998ea4, 0x00000000}, b = {159, 0x1c1f52bf, 0x56cb5e69, 0x4f743315, 0x56bd7776, 0x619c427b, 0x00000000}},
|
||||
{res = {317, 0x3ef33eed, 0x50471631, 0x244d5b99, 0x3aace6d9, 0x3152bb58, 0x13b7c355, 0x0e321425, 0x567217ce, 0x31b3e5b9, 0x0d74845e, 0x00000000}, d = {157, 0x736962be, 0x7712398c, 0x7b098d1f, 0x43804b77, 0x3bd3f8bf, 0x00000000}, a = {157, 0x12a5d163, 0x4ae379f1, 0x1387fd7f, 0x1dec4842, 0x195d1d4c, 0x00000000}, b = {159, 0x6023c9c5, 0x3740c9c3, 0x612c755b, 0x6f3d0941, 0x43e704ff, 0x00000000}},
|
||||
{res = {318, 0x5c85ea39, 0x54f32864, 0x507dd4d4, 0x6250b7ce, 0x1334f373, 0x445b332d, 0x14557fc2, 0x7e1738be, 0x21bab745, 0x2f0aa313, 0x00000000}, d = {158, 0x77f935c9, 0x1e13e902, 0x43c028fd, 0x4937d854, 0x7e23bf79, 0x00000000}, a = {158, 0x1d618801, 0x79681bf4, 0x7f92559f, 0x2f1cccaf, 0x3faefa11, 0x00000000}, b = {159, 0x32413470, 0x5aff5bf1, 0x05f98105, 0x53055486, 0x5e8cf955, 0x00000000}},
|
||||
{res = {319, 0x3e013eac, 0x07fe4a8a, 0x65782090, 0x5b880ea5, 0x7408456c, 0x5bf575a0, 0x2a3cd440, 0x23d148fa, 0x418bc6d7, 0x31cc34a1, 0x00000000}, d = {159, 0x102ef9f4, 0x1bc81608, 0x02f901f1, 0x668b0bd6, 0x283c9d2b, 0x00000000}, a = {159, 0x7da4773e, 0x360df7cb, 0x2b3be4f2, 0x79faa607, 0x5e09cc20, 0x00000000}, b = {159, 0x57ef4024, 0x32c96c31, 0x4559d5d3, 0x3b4d08ae, 0x43c831a5, 0x00000000}},
|
||||
{res = {317, 0x2588c09a, 0x7a89223b, 0x41126c82, 0x321cdef0, 0x3faf4f56, 0x54b95fd5, 0x44abcdbd, 0x4c9acfbb, 0x5d732ab6, 0x1e44b843, 0x00000000}, d = {158, 0x524131a8, 0x6388c83c, 0x4a50e580, 0x0df9f5b8, 0x4fb833b3, 0x00000000}, a = {158, 0x523a18b9, 0x465a2251, 0x2dd0ebec, 0x7a14c3c3, 0x3caa78eb, 0x00000000}, b = {158, 0x30ec8982, 0x37707644, 0x7f244b46, 0x6f958529, 0x3fdd26db, 0x00000000}},
|
||||
{res = {318, 0x61bad587, 0x761aa039, 0x6ab9a7d4, 0x41f18ba1, 0x0f77af87, 0x557292c8, 0x3428f9a7, 0x7c028945, 0x405a01c3, 0x1f3c11e1, 0x00000000}, d = {159, 0x62a6cc33, 0x07c52956, 0x4b78094d, 0x0210300b, 0x59a0cc24, 0x00000000}, a = {159, 0x6538ecfc, 0x666ac7d2, 0x62ada152, 0x1b6f0537, 0x40b88005, 0x00000000}, b = {158, 0x4f69016b, 0x2b90ac7e, 0x547c3f0e, 0x2f1de4c9, 0x3dc60ec7, 0x00000000}},
|
||||
{res = {318, 0x7c1d72ed, 0x4c4d8e1f, 0x461bb74f, 0x38b75f85, 0x0c340951, 0x37882272, 0x5bb93d3e, 0x5f8ed31e, 0x7bd1add0, 0x258ae081, 0x00000000}, d = {158, 0x007d10b7, 0x7e03550f, 0x28189fea, 0x3407d2f0, 0x44f16726, 0x00000000}, a = {158, 0x152afd5f, 0x71ab1c22, 0x6fb41945, 0x522bd719, 0x3025871d, 0x00000000}, b = {159, 0x7272538a, 0x795fd146, 0x7111af44, 0x2b400ac9, 0x63cef8dc, 0x00000000}},
|
||||
{res = {317, 0x6ac9a927, 0x37bf839e, 0x72166cf4, 0x66e97192, 0x0f1010a8, 0x475dd251, 0x730eb0ff, 0x295b1515, 0x340bb235, 0x14da57c9, 0x00000000}, d = {157, 0x026ce5ab, 0x49a7c219, 0x7d86a513, 0x47701297, 0x56e7b169, 0x00000000}, a = {157, 0x6f6a9a0e, 0x7e018fa4, 0x23b35254, 0x2566e0a9, 0x158799e8, 0x00000000}, b = {159, 0x12e6bed2, 0x3b186bb1, 0x3bddcfc9, 0x75ca6013, 0x7bf9ee6e, 0x00000000}},
|
||||
{res = {317, 0x277fe2cd, 0x00e40ce6, 0x2c35b175, 0x59bd9a99, 0x2a53689e, 0x3972c269, 0x4db20926, 0x67d98c0d, 0x57bbbc3f, 0x0bf1a543, 0x00000000}, d = {159, 0x17d3efaf, 0x59a9c4ff, 0x69349a09, 0x535b0031, 0x677b2a0d, 0x00000000}, a = {159, 0x67e1ef0e, 0x7d1e406e, 0x5111e847, 0x321572bc, 0x547d3b3a, 0x00000000}, b = {157, 0x1c685fb9, 0x2f3d09a2, 0x6611e3c9, 0x25575675, 0x12184aec, 0x00000000}},
|
||||
{res = {317, 0x11c8df23, 0x0d48a117, 0x0a6b8c50, 0x0fef02e9, 0x3eb1ae96, 0x32cd060b, 0x0cdb0651, 0x2dc87323, 0x16ea6bb3, 0x09cf6776, 0x00000000}, d = {159, 0x53b8638b, 0x4e180172, 0x3a3cdcac, 0x614f28ca, 0x0f644498, 0x00000000}, a = {159, 0x72ac2c95, 0x196ed06f, 0x43412b53, 0x59441827, 0x4364974f, 0x00000000}, b = {157, 0x0e220f38, 0x02785026, 0x6566e3fe, 0x1a270c17, 0x12a1eeaa, 0x00000000}},
|
||||
}
|
||||
|
||||
I31_Test_Div_Rem :: struct {
|
||||
hi: u32,
|
||||
lo: u32,
|
||||
div: u32,
|
||||
quo: u32,
|
||||
rem: u32,
|
||||
}
|
||||
|
||||
@(rodata)
|
||||
i31_div_rem_test_vectors := []I31_Test_Div_Rem {
|
||||
{hi = 0x632c115c, lo = 0x4b2bf821, div = 0xb8481290, quo = 0x89c490d1, rem = 0x07a3d091},
|
||||
{hi = 0x1cb7e3aa, lo = 0x63e1d659, div = 0xd94a9eb0, quo = 0x21d58fe1, rem = 0x02380da9},
|
||||
{hi = 0xbe78690c, lo = 0x88cc1bd7, div = 0xbf1211a9, quo = 0xff32200f, rem = 0x4a85f2f0},
|
||||
{hi = 0xa91488a1, lo = 0x2f8f64ac, div = 0xb5027f82, quo = 0xef20d04a, rem = 0x86fce918},
|
||||
{hi = 0x074838b4, lo = 0xc1b7bbbe, div = 0x0cc1ef1e, quo = 0x92207a42, rem = 0x0c03ca02},
|
||||
{hi = 0x415c651d, lo = 0xe696b3e5, div = 0x5a782289, quo = 0xb8f37d3e, rem = 0x149671b7},
|
||||
{hi = 0x26454389, lo = 0x986fc51a, div = 0xebc02a27, quo = 0x298ec804, rem = 0x27dea47e},
|
||||
{hi = 0x5a3b3e87, lo = 0xf475705b, div = 0x5e6f1d1a, quo = 0xf49b708c, rem = 0x4c382623},
|
||||
{hi = 0x8b1580f2, lo = 0x4ca1db17, div = 0xafd69ac8, quo = 0xca7d730d, rem = 0x938c26ef},
|
||||
{hi = 0x0dd6f07e, lo = 0xde23b70c, div = 0x5bd60fda, quo = 0x26943342, rem = 0x05c332d8},
|
||||
{hi = 0xede68f1d, lo = 0x07813b19, div = 0xff2b167e, quo = 0xeead1023, rem = 0x1c0f47df},
|
||||
{hi = 0x5c5ec31f, lo = 0xd985218f, div = 0xae020a42, quo = 0x87e50b9b, rem = 0x6cce1599},
|
||||
{hi = 0x6639e3c0, lo = 0xe8690a35, div = 0x6c241512, quo = 0xf1ff7b0a, rem = 0x69f29181},
|
||||
{hi = 0x0a45fb42, lo = 0x113dd8cc, div = 0x2ee12611, quo = 0x3819d4aa, rem = 0x0c8b7d82},
|
||||
{hi = 0x3ea35d11, lo = 0x5e2a590f, div = 0xd465b470, quo = 0x4b7f3d2b, rem = 0x21865a3f},
|
||||
{hi = 0xcb7cee11, lo = 0x25cea707, div = 0xe191debc, quo = 0xe6f0751f, rem = 0x7218c243},
|
||||
{hi = 0x816b74f4, lo = 0xb66d7312, div = 0x83e048ef, quo = 0xfb3b4f1d, rem = 0x6b6e6eff},
|
||||
{hi = 0x4863d8a6, lo = 0x7de42a8b, div = 0x588fc2d3, quo = 0xd140fa7c, rem = 0x3c3fbe57},
|
||||
{hi = 0x2540246a, lo = 0xe24d9d05, div = 0x8320712a, quo = 0x48b98123, rem = 0x047dfa47},
|
||||
{hi = 0xc074131e, lo = 0xdc4d465e, div = 0xe1dc958c, quo = 0xda22448b, rem = 0x8d36e35a},
|
||||
{hi = 0xf6ef68bc, lo = 0xc22f3f3e, div = 0xfa5c4162, quo = 0xfc7f66e0, rem = 0x07cafd7e},
|
||||
{hi = 0x061d173b, lo = 0xeccf58ec, div = 0xb792ff7a, quo = 0x08869175, rem = 0x3a107c2a},
|
||||
{hi = 0xb2ee2b9d, lo = 0x7805c28d, div = 0xf610e48b, quo = 0xba276d3a, rem = 0xb7b5cc0f},
|
||||
{hi = 0x38849ac0, lo = 0x67df2bd4, div = 0xa314f95e, quo = 0x58b84824, rem = 0x0739aa9c},
|
||||
{hi = 0x32dc45d0, lo = 0x2c7f42e9, div = 0xfafc8a2a, quo = 0x33e05b19, rem = 0xa1f8d6cf},
|
||||
{hi = 0x4240d91f, lo = 0xec3b2dd8, div = 0x7a1bc3fe, quo = 0x8ae65d59, rem = 0x602cc48a},
|
||||
{hi = 0x3c0836b4, lo = 0x275cd2a6, div = 0x871c1085, quo = 0x71bf0a5e, rem = 0x6a2e8fd0},
|
||||
{hi = 0x49de09c7, lo = 0xf62ac65b, div = 0x9b7ae8a1, quo = 0x799f9edf, rem = 0x1587c41c},
|
||||
{hi = 0x3da17dbc, lo = 0xe4437bf3, div = 0xf64f9bca, quo = 0x400e1fa2, rem = 0x5cf9701f},
|
||||
{hi = 0x4e22607b, lo = 0xa8798c83, div = 0xfe90aa77, quo = 0x4e931fa6, rem = 0xedb19a59},
|
||||
{hi = 0x43dd8e64, lo = 0xd2aee2d3, div = 0xfa05bf14, quo = 0x457ceca2, rem = 0x5d35882b},
|
||||
{hi = 0x74ae120e, lo = 0x4a567457, div = 0x80e12b3b, quo = 0xe7c46e8b, rem = 0x3954a14e},
|
||||
{hi = 0x25c33e85, lo = 0xd4fe503d, div = 0xab5e1c7a, quo = 0x38698d75, rem = 0x4f421a7b},
|
||||
{hi = 0xba818477, lo = 0xf1edb77a, div = 0xf5028225, quo = 0xc2df32d7, rem = 0x472c3067},
|
||||
{hi = 0xce85c4d5, lo = 0xc1530b0c, div = 0xe5a6d9ab, quo = 0xe63795d9, rem = 0x94770219},
|
||||
{hi = 0x08adb5bb, lo = 0xa277cb09, div = 0xab1ee4c6, quo = 0x0cfbb916, rem = 0x045b0c05},
|
||||
{hi = 0x8dc1580e, lo = 0xe73d2e39, div = 0xadf26902, quo = 0xd09f833f, rem = 0x349b50bb},
|
||||
{hi = 0x4435ddf6, lo = 0x42a05702, div = 0x594f5cd1, quo = 0xc3850b8d, rem = 0x3d583ce5},
|
||||
{hi = 0x6cb4f9c6, lo = 0xcc9b6e48, div = 0xa7bbed72, quo = 0xa5e948ca, rem = 0x00c80254},
|
||||
{hi = 0x3cb3b260, lo = 0xf2f7a398, div = 0xecf16edf, quo = 0x419586bc, rem = 0x6ad67dd4},
|
||||
{hi = 0x1720b73c, lo = 0x347ff447, div = 0x1724839d, quo = 0xffd5fbb6, rem = 0x0ede73a9},
|
||||
{hi = 0xe3003f2c, lo = 0xe1cb1bdf, div = 0xf2298637, quo = 0xeff8ef99, rem = 0x04648c00},
|
||||
{hi = 0x558a5621, lo = 0x1f717ddc, div = 0xf03e2bca, quo = 0x5b269cff, rem = 0xa0d8c7a6},
|
||||
{hi = 0x949fb36a, lo = 0xce76c920, div = 0xd215ba56, quo = 0xb51b3884, rem = 0x456de4c8},
|
||||
{hi = 0xa0f2fc11, lo = 0xd0259ff1, div = 0xc8626cac, quo = 0xcd9ea15a, rem = 0xa90b3f79},
|
||||
{hi = 0x70c3fa84, lo = 0x74d29bb9, div = 0xf9e5a764, quo = 0x7384fbe9, rem = 0x9c1e35b5},
|
||||
{hi = 0x2da900de, lo = 0xcf74abff, div = 0x99abc1da, quo = 0x4c10ae3a, rem = 0x6b28949b},
|
||||
{hi = 0x3664397e, lo = 0x2ba486dc, div = 0x7ea469c9, quo = 0x6df304d3, rem = 0x39af3231},
|
||||
{hi = 0x095d67a6, lo = 0xe3b31742, div = 0xdbe7549c, quo = 0x0ae6ee14, rem = 0x88cf7312},
|
||||
{hi = 0x9a402804, lo = 0x462e5dcd, div = 0xa736e128, quo = 0xec272359, rem = 0x76399ee5},
|
||||
{hi = 0x12809274, lo = 0x09011d2f, div = 0xac4c1332, quo = 0x1b7d9f66, rem = 0x7d5b6943},
|
||||
{hi = 0x6a897aed, lo = 0x1d121571, div = 0xef42fe4b, quo = 0x71fd7b8c, rem = 0xa921fb6d},
|
||||
{hi = 0x55ed8b10, lo = 0x9090ea62, div = 0x9cd2c065, quo = 0x8c45083c, rem = 0x21efaab6},
|
||||
{hi = 0x3930a3f2, lo = 0x541cf31f, div = 0xa7c1fef1, quo = 0x5745c1d4, rem = 0x884d228b},
|
||||
{hi = 0xa7167582, lo = 0x0abb9b9f, div = 0xf63dc17e, quo = 0xadb5a66e, rem = 0x3ca4c37b},
|
||||
{hi = 0x74b72666, lo = 0x4abb1c94, div = 0x7ee27c4a, quo = 0xeb7b903b, rem = 0x0110d786},
|
||||
{hi = 0x88a89e33, lo = 0x2dada2d6, div = 0xe8725e91, quo = 0x9681856f, rem = 0x5be44cf7},
|
||||
{hi = 0x5affad0b, lo = 0x68c7b744, div = 0x8bf402e7, quo = 0xa6740fb8, rem = 0x6a8e183c},
|
||||
{hi = 0x18400a64, lo = 0x91c19fee, div = 0xececa37b, quo = 0x1a33df48, rem = 0xbd4a8056},
|
||||
{hi = 0x0ca1d509, lo = 0x5ace5b38, div = 0x405fe35b, quo = 0x323c1088, rem = 0x1a53e2e0},
|
||||
{hi = 0x49c3d579, lo = 0xb57e3052, div = 0x8fe8c087, quo = 0x833871ec, rem = 0x1b691cde},
|
||||
{hi = 0x055e153e, lo = 0x876ba83b, div = 0xd0a7b0e1, quo = 0x0695deae, rem = 0x1119514d},
|
||||
{hi = 0x1ab22cf1, lo = 0xc9c28af3, div = 0x626e63e5, quo = 0x456e54c0, rem = 0x18ca7b33},
|
||||
{hi = 0x5ce6ba97, lo = 0x46dbc829, div = 0xbf4a582f, quo = 0x7c53ef3f, rem = 0x6fff3398},
|
||||
{hi = 0x280dd6e5, lo = 0x13c19c79, div = 0xe67fd7e2, quo = 0x2c7c3e0b, rem = 0xcc8299c3},
|
||||
{hi = 0x1c7c2a51, lo = 0x8aecb540, div = 0x3decec9d, quo = 0x75c1d104, rem = 0x02afd5cc},
|
||||
{hi = 0x3a6e806b, lo = 0x142a6ad0, div = 0x56b24a8d, quo = 0xac89eeee, rem = 0x17a505ba},
|
||||
{hi = 0x23a1b1d0, lo = 0xda933d16, div = 0x85938fe1, quo = 0x4449c850, rem = 0x08e57ec6},
|
||||
{hi = 0x1f177f2e, lo = 0x107c53c1, div = 0xdef2389a, quo = 0x23b390c4, rem = 0x7d845dd9},
|
||||
{hi = 0x735cb354, lo = 0xbcf96584, div = 0xacc0d360, quo = 0xaaf3fec8, rem = 0x107b0284},
|
||||
{hi = 0x5ecb810e, lo = 0x51b4a6d1, div = 0x84db55d8, quo = 0xb6a8bd00, rem = 0x7d942ed1},
|
||||
{hi = 0x4765b107, lo = 0xded18aa4, div = 0x540b7c9f, quo = 0xd979b39b, rem = 0x4592e95f},
|
||||
{hi = 0xddb19fc7, lo = 0xe30727aa, div = 0xfaf579d9, quo = 0xe225a80a, rem = 0xcf1cfd30},
|
||||
{hi = 0x85f9707c, lo = 0x5511a037, div = 0x8e318efd, quo = 0xf133d2a5, rem = 0x5e6ded26},
|
||||
{hi = 0x0c2c41f1, lo = 0xbf357e4a, div = 0x62d254f1, quo = 0x1f88bf7d, rem = 0x421a359d},
|
||||
{hi = 0x335d8188, lo = 0x00fd4b21, div = 0xfcf1e085, quo = 0x33fc54b7, rem = 0x507e280e},
|
||||
{hi = 0x4eef80e4, lo = 0xfcd9e9de, div = 0xf2d2e5c0, quo = 0x53380265, rem = 0x07d9c51e},
|
||||
{hi = 0x431aeca5, lo = 0x07963290, div = 0xe6ca948b, quo = 0x4a6f5427, rem = 0xcfb6f563},
|
||||
{hi = 0x13638612, lo = 0x71f2880c, div = 0x25f44434, quo = 0x82c6db4c, rem = 0x0eddcc9c},
|
||||
{hi = 0x24dd96bb, lo = 0xd6b8ffca, div = 0xb3697b2b, quo = 0x349a55fc, rem = 0x61207a76},
|
||||
{hi = 0x3201b855, lo = 0x0e6b7026, div = 0x65a232ae, quo = 0x7df5a4a0, rem = 0x2a0e4b66},
|
||||
{hi = 0x1e2536d5, lo = 0xfbef9964, div = 0x97c9027e, quo = 0x32d7cea9, rem = 0x54699036},
|
||||
{hi = 0x03486ba3, lo = 0x4ae30d34, div = 0x5f768217, quo = 0x08cdbad7, rem = 0x1f6c15e3},
|
||||
{hi = 0x7000b42d, lo = 0xd9357d65, div = 0xc0b7f01f, quo = 0x94c7bd20, rem = 0x61d79685},
|
||||
{hi = 0x2f088bd1, lo = 0x098fe330, div = 0x3a2fc060, quo = 0xceee1d21, rem = 0x075d36d0},
|
||||
{hi = 0x30ede94b, lo = 0x1200278e, div = 0x42fc5880, quo = 0xbafe65ba, rem = 0x08bd5a8e},
|
||||
{hi = 0x5ed1fc0f, lo = 0x0537fbbf, div = 0x6ae246f5, quo = 0xe31b295f, rem = 0x630b69d4},
|
||||
{hi = 0x1d2496a2, lo = 0xecca6436, div = 0xaa60d4ea, quo = 0x2bc9d3a0, rem = 0x270e73f6},
|
||||
{hi = 0x97ae9a4e, lo = 0xba69862d, div = 0xea9984e9, quo = 0xa584c095, rem = 0x563c6a90},
|
||||
{hi = 0x12cf1435, lo = 0x99a99414, div = 0x2644910d, quo = 0x7dd36379, rem = 0x1871fdef},
|
||||
{hi = 0x7fc1828d, lo = 0x70c995ca, div = 0xdebea8f1, quo = 0x92d45c4d, rem = 0x9326294d},
|
||||
{hi = 0x32a003d1, lo = 0x6c09aff4, div = 0xd460becc, quo = 0x3d05fb48, rem = 0x7fc60294},
|
||||
{hi = 0x3add17a2, lo = 0xb4e2c499, div = 0x45b4eb3a, quo = 0xd82db19b, rem = 0x20833e7b},
|
||||
{hi = 0xc4a6d715, lo = 0xb1576cc0, div = 0xcf15af86, quo = 0xf31a46cc, rem = 0xb874e9f8},
|
||||
{hi = 0x2da93388, lo = 0x980b3f98, div = 0xf8e18784, quo = 0x2ef78f93, rem = 0x3b7bb2cc},
|
||||
{hi = 0x5d77f50a, lo = 0xc8f5c09b, div = 0xaa3cc6c4, quo = 0x8c8e703a, rem = 0x2f82f833},
|
||||
{hi = 0x4898d91b, lo = 0xe7956338, div = 0x4e4a2805, quo = 0xed62bc94, rem = 0x3c689454},
|
||||
{hi = 0xb9620ae8, lo = 0x0e9ed51d, div = 0xc281fe4d, quo = 0xf3fd8e35, rem = 0x458d792c},
|
||||
{hi = 0xc342d71a, lo = 0xecafbf43, div = 0xfbfa840c, quo = 0xc6609971, rem = 0x2db049f7},
|
||||
{hi = 0x4e2d4c4b, lo = 0x4609de2e, div = 0xc737fab5, quo = 0x64757da5, rem = 0x40d1e685},
|
||||
}
|
||||
Reference in New Issue
Block a user