mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 02:42:27 +00:00
1371 lines
36 KiB
Go
1371 lines
36 KiB
Go
// +build !amd64 generic
|
|
|
|
// Copyright 2020 ConsenSys Software Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
// Code generated by goff (v0.3.5) DO NOT EDIT
|
|
|
|
// /!\ WARNING /!\
|
|
// this code has not been audited and is provided as-is. In particular,
|
|
// there is no security guarantees such as constant time implementation
|
|
// or side-channel attack resistance
|
|
// /!\ WARNING /!\
|
|
|
|
package bls12381
|
|
|
|
import "math/bits"
|
|
|
|
func add(z, x, y *fe) {
|
|
var carry uint64
|
|
|
|
z[0], carry = bits.Add64(x[0], y[0], 0)
|
|
z[1], carry = bits.Add64(x[1], y[1], carry)
|
|
z[2], carry = bits.Add64(x[2], y[2], carry)
|
|
z[3], carry = bits.Add64(x[3], y[3], carry)
|
|
z[4], carry = bits.Add64(x[4], y[4], carry)
|
|
z[5], _ = bits.Add64(x[5], y[5], carry)
|
|
|
|
// if z > q --> z -= q
|
|
// note: this is NOT constant time
|
|
if !(z[5] < 1873798617647539866 || (z[5] == 1873798617647539866 && (z[4] < 5412103778470702295 || (z[4] == 5412103778470702295 && (z[3] < 7239337960414712511 || (z[3] == 7239337960414712511 && (z[2] < 7435674573564081700 || (z[2] == 7435674573564081700 && (z[1] < 2210141511517208575 || (z[1] == 2210141511517208575 && (z[0] < 13402431016077863595))))))))))) {
|
|
var b uint64
|
|
z[0], b = bits.Sub64(z[0], 13402431016077863595, 0)
|
|
z[1], b = bits.Sub64(z[1], 2210141511517208575, b)
|
|
z[2], b = bits.Sub64(z[2], 7435674573564081700, b)
|
|
z[3], b = bits.Sub64(z[3], 7239337960414712511, b)
|
|
z[4], b = bits.Sub64(z[4], 5412103778470702295, b)
|
|
z[5], _ = bits.Sub64(z[5], 1873798617647539866, b)
|
|
}
|
|
}
|
|
|
|
func addAssign(z, y *fe) {
|
|
var carry uint64
|
|
|
|
z[0], carry = bits.Add64(z[0], y[0], 0)
|
|
z[1], carry = bits.Add64(z[1], y[1], carry)
|
|
z[2], carry = bits.Add64(z[2], y[2], carry)
|
|
z[3], carry = bits.Add64(z[3], y[3], carry)
|
|
z[4], carry = bits.Add64(z[4], y[4], carry)
|
|
z[5], _ = bits.Add64(z[5], y[5], carry)
|
|
|
|
// if z > q --> z -= q
|
|
// note: this is NOT constant time
|
|
if !(z[5] < 1873798617647539866 || (z[5] == 1873798617647539866 && (z[4] < 5412103778470702295 || (z[4] == 5412103778470702295 && (z[3] < 7239337960414712511 || (z[3] == 7239337960414712511 && (z[2] < 7435674573564081700 || (z[2] == 7435674573564081700 && (z[1] < 2210141511517208575 || (z[1] == 2210141511517208575 && (z[0] < 13402431016077863595))))))))))) {
|
|
var b uint64
|
|
z[0], b = bits.Sub64(z[0], 13402431016077863595, 0)
|
|
z[1], b = bits.Sub64(z[1], 2210141511517208575, b)
|
|
z[2], b = bits.Sub64(z[2], 7435674573564081700, b)
|
|
z[3], b = bits.Sub64(z[3], 7239337960414712511, b)
|
|
z[4], b = bits.Sub64(z[4], 5412103778470702295, b)
|
|
z[5], _ = bits.Sub64(z[5], 1873798617647539866, b)
|
|
}
|
|
}
|
|
|
|
func ladd(z, x, y *fe) {
|
|
var carry uint64
|
|
|
|
z[0], carry = bits.Add64(x[0], y[0], 0)
|
|
z[1], carry = bits.Add64(x[1], y[1], carry)
|
|
z[2], carry = bits.Add64(x[2], y[2], carry)
|
|
z[3], carry = bits.Add64(x[3], y[3], carry)
|
|
z[4], carry = bits.Add64(x[4], y[4], carry)
|
|
z[5], _ = bits.Add64(x[5], y[5], carry)
|
|
}
|
|
|
|
func laddAssign(z, y *fe) {
|
|
var carry uint64
|
|
|
|
z[0], carry = bits.Add64(z[0], y[0], 0)
|
|
z[1], carry = bits.Add64(z[1], y[1], carry)
|
|
z[2], carry = bits.Add64(z[2], y[2], carry)
|
|
z[3], carry = bits.Add64(z[3], y[3], carry)
|
|
z[4], carry = bits.Add64(z[4], y[4], carry)
|
|
z[5], _ = bits.Add64(z[5], y[5], carry)
|
|
}
|
|
|
|
func double(z, x *fe) {
|
|
var carry uint64
|
|
|
|
z[0], carry = bits.Add64(x[0], x[0], 0)
|
|
z[1], carry = bits.Add64(x[1], x[1], carry)
|
|
z[2], carry = bits.Add64(x[2], x[2], carry)
|
|
z[3], carry = bits.Add64(x[3], x[3], carry)
|
|
z[4], carry = bits.Add64(x[4], x[4], carry)
|
|
z[5], _ = bits.Add64(x[5], x[5], carry)
|
|
|
|
// if z > q --> z -= q
|
|
// note: this is NOT constant time
|
|
if !(z[5] < 1873798617647539866 || (z[5] == 1873798617647539866 && (z[4] < 5412103778470702295 || (z[4] == 5412103778470702295 && (z[3] < 7239337960414712511 || (z[3] == 7239337960414712511 && (z[2] < 7435674573564081700 || (z[2] == 7435674573564081700 && (z[1] < 2210141511517208575 || (z[1] == 2210141511517208575 && (z[0] < 13402431016077863595))))))))))) {
|
|
var b uint64
|
|
z[0], b = bits.Sub64(z[0], 13402431016077863595, 0)
|
|
z[1], b = bits.Sub64(z[1], 2210141511517208575, b)
|
|
z[2], b = bits.Sub64(z[2], 7435674573564081700, b)
|
|
z[3], b = bits.Sub64(z[3], 7239337960414712511, b)
|
|
z[4], b = bits.Sub64(z[4], 5412103778470702295, b)
|
|
z[5], _ = bits.Sub64(z[5], 1873798617647539866, b)
|
|
}
|
|
}
|
|
|
|
func doubleAssign(z *fe) {
|
|
var carry uint64
|
|
|
|
z[0], carry = bits.Add64(z[0], z[0], 0)
|
|
z[1], carry = bits.Add64(z[1], z[1], carry)
|
|
z[2], carry = bits.Add64(z[2], z[2], carry)
|
|
z[3], carry = bits.Add64(z[3], z[3], carry)
|
|
z[4], carry = bits.Add64(z[4], z[4], carry)
|
|
z[5], _ = bits.Add64(z[5], z[5], carry)
|
|
|
|
// if z > q --> z -= q
|
|
// note: this is NOT constant time
|
|
if !(z[5] < 1873798617647539866 || (z[5] == 1873798617647539866 && (z[4] < 5412103778470702295 || (z[4] == 5412103778470702295 && (z[3] < 7239337960414712511 || (z[3] == 7239337960414712511 && (z[2] < 7435674573564081700 || (z[2] == 7435674573564081700 && (z[1] < 2210141511517208575 || (z[1] == 2210141511517208575 && (z[0] < 13402431016077863595))))))))))) {
|
|
var b uint64
|
|
z[0], b = bits.Sub64(z[0], 13402431016077863595, 0)
|
|
z[1], b = bits.Sub64(z[1], 2210141511517208575, b)
|
|
z[2], b = bits.Sub64(z[2], 7435674573564081700, b)
|
|
z[3], b = bits.Sub64(z[3], 7239337960414712511, b)
|
|
z[4], b = bits.Sub64(z[4], 5412103778470702295, b)
|
|
z[5], _ = bits.Sub64(z[5], 1873798617647539866, b)
|
|
}
|
|
}
|
|
|
|
func ldouble(z, x *fe) {
|
|
var carry uint64
|
|
|
|
z[0], carry = bits.Add64(x[0], x[0], 0)
|
|
z[1], carry = bits.Add64(x[1], x[1], carry)
|
|
z[2], carry = bits.Add64(x[2], x[2], carry)
|
|
z[3], carry = bits.Add64(x[3], x[3], carry)
|
|
z[4], carry = bits.Add64(x[4], x[4], carry)
|
|
z[5], _ = bits.Add64(x[5], x[5], carry)
|
|
}
|
|
|
|
func sub(z, x, y *fe) {
|
|
var b uint64
|
|
z[0], b = bits.Sub64(x[0], y[0], 0)
|
|
z[1], b = bits.Sub64(x[1], y[1], b)
|
|
z[2], b = bits.Sub64(x[2], y[2], b)
|
|
z[3], b = bits.Sub64(x[3], y[3], b)
|
|
z[4], b = bits.Sub64(x[4], y[4], b)
|
|
z[5], b = bits.Sub64(x[5], y[5], b)
|
|
if b != 0 {
|
|
var c uint64
|
|
z[0], c = bits.Add64(z[0], 13402431016077863595, 0)
|
|
z[1], c = bits.Add64(z[1], 2210141511517208575, c)
|
|
z[2], c = bits.Add64(z[2], 7435674573564081700, c)
|
|
z[3], c = bits.Add64(z[3], 7239337960414712511, c)
|
|
z[4], c = bits.Add64(z[4], 5412103778470702295, c)
|
|
z[5], _ = bits.Add64(z[5], 1873798617647539866, c)
|
|
}
|
|
}
|
|
|
|
func subAssign(z, y *fe) {
|
|
var b uint64
|
|
z[0], b = bits.Sub64(z[0], y[0], 0)
|
|
z[1], b = bits.Sub64(z[1], y[1], b)
|
|
z[2], b = bits.Sub64(z[2], y[2], b)
|
|
z[3], b = bits.Sub64(z[3], y[3], b)
|
|
z[4], b = bits.Sub64(z[4], y[4], b)
|
|
z[5], b = bits.Sub64(z[5], y[5], b)
|
|
if b != 0 {
|
|
var c uint64
|
|
z[0], c = bits.Add64(z[0], 13402431016077863595, 0)
|
|
z[1], c = bits.Add64(z[1], 2210141511517208575, c)
|
|
z[2], c = bits.Add64(z[2], 7435674573564081700, c)
|
|
z[3], c = bits.Add64(z[3], 7239337960414712511, c)
|
|
z[4], c = bits.Add64(z[4], 5412103778470702295, c)
|
|
z[5], _ = bits.Add64(z[5], 1873798617647539866, c)
|
|
}
|
|
}
|
|
|
|
func lsubAssign(z, y *fe) {
|
|
var b uint64
|
|
z[0], b = bits.Sub64(z[0], y[0], 0)
|
|
z[1], b = bits.Sub64(z[1], y[1], b)
|
|
z[2], b = bits.Sub64(z[2], y[2], b)
|
|
z[3], b = bits.Sub64(z[3], y[3], b)
|
|
z[4], b = bits.Sub64(z[4], y[4], b)
|
|
z[5], b = bits.Sub64(z[5], y[5], b)
|
|
}
|
|
|
|
func neg(z, x *fe) {
|
|
if x.isZero() {
|
|
z.zero()
|
|
return
|
|
}
|
|
var borrow uint64
|
|
z[0], borrow = bits.Sub64(13402431016077863595, x[0], 0)
|
|
z[1], borrow = bits.Sub64(2210141511517208575, x[1], borrow)
|
|
z[2], borrow = bits.Sub64(7435674573564081700, x[2], borrow)
|
|
z[3], borrow = bits.Sub64(7239337960414712511, x[3], borrow)
|
|
z[4], borrow = bits.Sub64(5412103778470702295, x[4], borrow)
|
|
z[5], _ = bits.Sub64(1873798617647539866, x[5], borrow)
|
|
}
|
|
|
|
func mul(z, x, y *fe) {
|
|
|
|
var t [6]uint64
|
|
var c [3]uint64
|
|
{
|
|
// round 0
|
|
v := x[0]
|
|
c[1], c[0] = bits.Mul64(v, y[0])
|
|
m := c[0] * 9940570264628428797
|
|
c[2] = madd0(m, 13402431016077863595, c[0])
|
|
c[1], c[0] = madd1(v, y[1], c[1])
|
|
c[2], t[0] = madd2(m, 2210141511517208575, c[2], c[0])
|
|
c[1], c[0] = madd1(v, y[2], c[1])
|
|
c[2], t[1] = madd2(m, 7435674573564081700, c[2], c[0])
|
|
c[1], c[0] = madd1(v, y[3], c[1])
|
|
c[2], t[2] = madd2(m, 7239337960414712511, c[2], c[0])
|
|
c[1], c[0] = madd1(v, y[4], c[1])
|
|
c[2], t[3] = madd2(m, 5412103778470702295, c[2], c[0])
|
|
c[1], c[0] = madd1(v, y[5], c[1])
|
|
t[5], t[4] = madd3(m, 1873798617647539866, c[0], c[2], c[1])
|
|
}
|
|
{
|
|
// round 1
|
|
v := x[1]
|
|
c[1], c[0] = madd1(v, y[0], t[0])
|
|
m := c[0] * 9940570264628428797
|
|
c[2] = madd0(m, 13402431016077863595, c[0])
|
|
c[1], c[0] = madd2(v, y[1], c[1], t[1])
|
|
c[2], t[0] = madd2(m, 2210141511517208575, c[2], c[0])
|
|
c[1], c[0] = madd2(v, y[2], c[1], t[2])
|
|
c[2], t[1] = madd2(m, 7435674573564081700, c[2], c[0])
|
|
c[1], c[0] = madd2(v, y[3], c[1], t[3])
|
|
c[2], t[2] = madd2(m, 7239337960414712511, c[2], c[0])
|
|
c[1], c[0] = madd2(v, y[4], c[1], t[4])
|
|
c[2], t[3] = madd2(m, 5412103778470702295, c[2], c[0])
|
|
c[1], c[0] = madd2(v, y[5], c[1], t[5])
|
|
t[5], t[4] = madd3(m, 1873798617647539866, c[0], c[2], c[1])
|
|
}
|
|
{
|
|
// round 2
|
|
v := x[2]
|
|
c[1], c[0] = madd1(v, y[0], t[0])
|
|
m := c[0] * 9940570264628428797
|
|
c[2] = madd0(m, 13402431016077863595, c[0])
|
|
c[1], c[0] = madd2(v, y[1], c[1], t[1])
|
|
c[2], t[0] = madd2(m, 2210141511517208575, c[2], c[0])
|
|
c[1], c[0] = madd2(v, y[2], c[1], t[2])
|
|
c[2], t[1] = madd2(m, 7435674573564081700, c[2], c[0])
|
|
c[1], c[0] = madd2(v, y[3], c[1], t[3])
|
|
c[2], t[2] = madd2(m, 7239337960414712511, c[2], c[0])
|
|
c[1], c[0] = madd2(v, y[4], c[1], t[4])
|
|
c[2], t[3] = madd2(m, 5412103778470702295, c[2], c[0])
|
|
c[1], c[0] = madd2(v, y[5], c[1], t[5])
|
|
t[5], t[4] = madd3(m, 1873798617647539866, c[0], c[2], c[1])
|
|
}
|
|
{
|
|
// round 3
|
|
v := x[3]
|
|
c[1], c[0] = madd1(v, y[0], t[0])
|
|
m := c[0] * 9940570264628428797
|
|
c[2] = madd0(m, 13402431016077863595, c[0])
|
|
c[1], c[0] = madd2(v, y[1], c[1], t[1])
|
|
c[2], t[0] = madd2(m, 2210141511517208575, c[2], c[0])
|
|
c[1], c[0] = madd2(v, y[2], c[1], t[2])
|
|
c[2], t[1] = madd2(m, 7435674573564081700, c[2], c[0])
|
|
c[1], c[0] = madd2(v, y[3], c[1], t[3])
|
|
c[2], t[2] = madd2(m, 7239337960414712511, c[2], c[0])
|
|
c[1], c[0] = madd2(v, y[4], c[1], t[4])
|
|
c[2], t[3] = madd2(m, 5412103778470702295, c[2], c[0])
|
|
c[1], c[0] = madd2(v, y[5], c[1], t[5])
|
|
t[5], t[4] = madd3(m, 1873798617647539866, c[0], c[2], c[1])
|
|
}
|
|
{
|
|
// round 4
|
|
v := x[4]
|
|
c[1], c[0] = madd1(v, y[0], t[0])
|
|
m := c[0] * 9940570264628428797
|
|
c[2] = madd0(m, 13402431016077863595, c[0])
|
|
c[1], c[0] = madd2(v, y[1], c[1], t[1])
|
|
c[2], t[0] = madd2(m, 2210141511517208575, c[2], c[0])
|
|
c[1], c[0] = madd2(v, y[2], c[1], t[2])
|
|
c[2], t[1] = madd2(m, 7435674573564081700, c[2], c[0])
|
|
c[1], c[0] = madd2(v, y[3], c[1], t[3])
|
|
c[2], t[2] = madd2(m, 7239337960414712511, c[2], c[0])
|
|
c[1], c[0] = madd2(v, y[4], c[1], t[4])
|
|
c[2], t[3] = madd2(m, 5412103778470702295, c[2], c[0])
|
|
c[1], c[0] = madd2(v, y[5], c[1], t[5])
|
|
t[5], t[4] = madd3(m, 1873798617647539866, c[0], c[2], c[1])
|
|
}
|
|
{
|
|
// round 5
|
|
v := x[5]
|
|
c[1], c[0] = madd1(v, y[0], t[0])
|
|
m := c[0] * 9940570264628428797
|
|
c[2] = madd0(m, 13402431016077863595, c[0])
|
|
c[1], c[0] = madd2(v, y[1], c[1], t[1])
|
|
c[2], z[0] = madd2(m, 2210141511517208575, c[2], c[0])
|
|
c[1], c[0] = madd2(v, y[2], c[1], t[2])
|
|
c[2], z[1] = madd2(m, 7435674573564081700, c[2], c[0])
|
|
c[1], c[0] = madd2(v, y[3], c[1], t[3])
|
|
c[2], z[2] = madd2(m, 7239337960414712511, c[2], c[0])
|
|
c[1], c[0] = madd2(v, y[4], c[1], t[4])
|
|
c[2], z[3] = madd2(m, 5412103778470702295, c[2], c[0])
|
|
c[1], c[0] = madd2(v, y[5], c[1], t[5])
|
|
z[5], z[4] = madd3(m, 1873798617647539866, c[0], c[2], c[1])
|
|
}
|
|
|
|
// if z > q --> z -= q
|
|
// note: this is NOT constant time
|
|
if !(z[5] < 1873798617647539866 || (z[5] == 1873798617647539866 && (z[4] < 5412103778470702295 || (z[4] == 5412103778470702295 && (z[3] < 7239337960414712511 || (z[3] == 7239337960414712511 && (z[2] < 7435674573564081700 || (z[2] == 7435674573564081700 && (z[1] < 2210141511517208575 || (z[1] == 2210141511517208575 && (z[0] < 13402431016077863595))))))))))) {
|
|
var b uint64
|
|
z[0], b = bits.Sub64(z[0], 13402431016077863595, 0)
|
|
z[1], b = bits.Sub64(z[1], 2210141511517208575, b)
|
|
z[2], b = bits.Sub64(z[2], 7435674573564081700, b)
|
|
z[3], b = bits.Sub64(z[3], 7239337960414712511, b)
|
|
z[4], b = bits.Sub64(z[4], 5412103778470702295, b)
|
|
z[5], _ = bits.Sub64(z[5], 1873798617647539866, b)
|
|
}
|
|
}
|
|
|
|
func square(z, x *fe) {
|
|
|
|
var t [6]uint64
|
|
var c [3]uint64
|
|
{
|
|
// round 0
|
|
v := x[0]
|
|
c[1], c[0] = bits.Mul64(v, x[0])
|
|
m := c[0] * 9940570264628428797
|
|
c[2] = madd0(m, 13402431016077863595, c[0])
|
|
c[1], c[0] = madd1(v, x[1], c[1])
|
|
c[2], t[0] = madd2(m, 2210141511517208575, c[2], c[0])
|
|
c[1], c[0] = madd1(v, x[2], c[1])
|
|
c[2], t[1] = madd2(m, 7435674573564081700, c[2], c[0])
|
|
c[1], c[0] = madd1(v, x[3], c[1])
|
|
c[2], t[2] = madd2(m, 7239337960414712511, c[2], c[0])
|
|
c[1], c[0] = madd1(v, x[4], c[1])
|
|
c[2], t[3] = madd2(m, 5412103778470702295, c[2], c[0])
|
|
c[1], c[0] = madd1(v, x[5], c[1])
|
|
t[5], t[4] = madd3(m, 1873798617647539866, c[0], c[2], c[1])
|
|
}
|
|
{
|
|
// round 1
|
|
v := x[1]
|
|
c[1], c[0] = madd1(v, x[0], t[0])
|
|
m := c[0] * 9940570264628428797
|
|
c[2] = madd0(m, 13402431016077863595, c[0])
|
|
c[1], c[0] = madd2(v, x[1], c[1], t[1])
|
|
c[2], t[0] = madd2(m, 2210141511517208575, c[2], c[0])
|
|
c[1], c[0] = madd2(v, x[2], c[1], t[2])
|
|
c[2], t[1] = madd2(m, 7435674573564081700, c[2], c[0])
|
|
c[1], c[0] = madd2(v, x[3], c[1], t[3])
|
|
c[2], t[2] = madd2(m, 7239337960414712511, c[2], c[0])
|
|
c[1], c[0] = madd2(v, x[4], c[1], t[4])
|
|
c[2], t[3] = madd2(m, 5412103778470702295, c[2], c[0])
|
|
c[1], c[0] = madd2(v, x[5], c[1], t[5])
|
|
t[5], t[4] = madd3(m, 1873798617647539866, c[0], c[2], c[1])
|
|
}
|
|
{
|
|
// round 2
|
|
v := x[2]
|
|
c[1], c[0] = madd1(v, x[0], t[0])
|
|
m := c[0] * 9940570264628428797
|
|
c[2] = madd0(m, 13402431016077863595, c[0])
|
|
c[1], c[0] = madd2(v, x[1], c[1], t[1])
|
|
c[2], t[0] = madd2(m, 2210141511517208575, c[2], c[0])
|
|
c[1], c[0] = madd2(v, x[2], c[1], t[2])
|
|
c[2], t[1] = madd2(m, 7435674573564081700, c[2], c[0])
|
|
c[1], c[0] = madd2(v, x[3], c[1], t[3])
|
|
c[2], t[2] = madd2(m, 7239337960414712511, c[2], c[0])
|
|
c[1], c[0] = madd2(v, x[4], c[1], t[4])
|
|
c[2], t[3] = madd2(m, 5412103778470702295, c[2], c[0])
|
|
c[1], c[0] = madd2(v, x[5], c[1], t[5])
|
|
t[5], t[4] = madd3(m, 1873798617647539866, c[0], c[2], c[1])
|
|
}
|
|
{
|
|
// round 3
|
|
v := x[3]
|
|
c[1], c[0] = madd1(v, x[0], t[0])
|
|
m := c[0] * 9940570264628428797
|
|
c[2] = madd0(m, 13402431016077863595, c[0])
|
|
c[1], c[0] = madd2(v, x[1], c[1], t[1])
|
|
c[2], t[0] = madd2(m, 2210141511517208575, c[2], c[0])
|
|
c[1], c[0] = madd2(v, x[2], c[1], t[2])
|
|
c[2], t[1] = madd2(m, 7435674573564081700, c[2], c[0])
|
|
c[1], c[0] = madd2(v, x[3], c[1], t[3])
|
|
c[2], t[2] = madd2(m, 7239337960414712511, c[2], c[0])
|
|
c[1], c[0] = madd2(v, x[4], c[1], t[4])
|
|
c[2], t[3] = madd2(m, 5412103778470702295, c[2], c[0])
|
|
c[1], c[0] = madd2(v, x[5], c[1], t[5])
|
|
t[5], t[4] = madd3(m, 1873798617647539866, c[0], c[2], c[1])
|
|
}
|
|
{
|
|
// round 4
|
|
v := x[4]
|
|
c[1], c[0] = madd1(v, x[0], t[0])
|
|
m := c[0] * 9940570264628428797
|
|
c[2] = madd0(m, 13402431016077863595, c[0])
|
|
c[1], c[0] = madd2(v, x[1], c[1], t[1])
|
|
c[2], t[0] = madd2(m, 2210141511517208575, c[2], c[0])
|
|
c[1], c[0] = madd2(v, x[2], c[1], t[2])
|
|
c[2], t[1] = madd2(m, 7435674573564081700, c[2], c[0])
|
|
c[1], c[0] = madd2(v, x[3], c[1], t[3])
|
|
c[2], t[2] = madd2(m, 7239337960414712511, c[2], c[0])
|
|
c[1], c[0] = madd2(v, x[4], c[1], t[4])
|
|
c[2], t[3] = madd2(m, 5412103778470702295, c[2], c[0])
|
|
c[1], c[0] = madd2(v, x[5], c[1], t[5])
|
|
t[5], t[4] = madd3(m, 1873798617647539866, c[0], c[2], c[1])
|
|
}
|
|
{
|
|
// round 5
|
|
v := x[5]
|
|
c[1], c[0] = madd1(v, x[0], t[0])
|
|
m := c[0] * 9940570264628428797
|
|
c[2] = madd0(m, 13402431016077863595, c[0])
|
|
c[1], c[0] = madd2(v, x[1], c[1], t[1])
|
|
c[2], z[0] = madd2(m, 2210141511517208575, c[2], c[0])
|
|
c[1], c[0] = madd2(v, x[2], c[1], t[2])
|
|
c[2], z[1] = madd2(m, 7435674573564081700, c[2], c[0])
|
|
c[1], c[0] = madd2(v, x[3], c[1], t[3])
|
|
c[2], z[2] = madd2(m, 7239337960414712511, c[2], c[0])
|
|
c[1], c[0] = madd2(v, x[4], c[1], t[4])
|
|
c[2], z[3] = madd2(m, 5412103778470702295, c[2], c[0])
|
|
c[1], c[0] = madd2(v, x[5], c[1], t[5])
|
|
z[5], z[4] = madd3(m, 1873798617647539866, c[0], c[2], c[1])
|
|
}
|
|
|
|
// if z > q --> z -= q
|
|
// note: this is NOT constant time
|
|
if !(z[5] < 1873798617647539866 || (z[5] == 1873798617647539866 && (z[4] < 5412103778470702295 || (z[4] == 5412103778470702295 && (z[3] < 7239337960414712511 || (z[3] == 7239337960414712511 && (z[2] < 7435674573564081700 || (z[2] == 7435674573564081700 && (z[1] < 2210141511517208575 || (z[1] == 2210141511517208575 && (z[0] < 13402431016077863595))))))))))) {
|
|
var b uint64
|
|
z[0], b = bits.Sub64(z[0], 13402431016077863595, 0)
|
|
z[1], b = bits.Sub64(z[1], 2210141511517208575, b)
|
|
z[2], b = bits.Sub64(z[2], 7435674573564081700, b)
|
|
z[3], b = bits.Sub64(z[3], 7239337960414712511, b)
|
|
z[4], b = bits.Sub64(z[4], 5412103778470702295, b)
|
|
z[5], _ = bits.Sub64(z[5], 1873798617647539866, b)
|
|
}
|
|
}
|
|
|
|
func wadd(z, x, y *wfe) {
|
|
var carry uint64
|
|
|
|
z[0], carry = bits.Add64(x[0], y[0], 0)
|
|
z[1], carry = bits.Add64(x[1], y[1], carry)
|
|
z[2], carry = bits.Add64(x[2], y[2], carry)
|
|
z[3], carry = bits.Add64(x[3], y[3], carry)
|
|
z[4], carry = bits.Add64(x[4], y[4], carry)
|
|
z[5], carry = bits.Add64(x[5], y[5], carry)
|
|
z[6], carry = bits.Add64(x[6], y[6], carry)
|
|
z[7], carry = bits.Add64(x[7], y[7], carry)
|
|
z[8], carry = bits.Add64(x[8], y[8], carry)
|
|
z[9], carry = bits.Add64(x[9], y[9], carry)
|
|
z[10], carry = bits.Add64(x[10], y[10], carry)
|
|
z[11], _ = bits.Add64(x[11], y[11], carry)
|
|
|
|
if !(z[11] < 1873798617647539866 || (z[11] == 1873798617647539866 && (z[10] < 5412103778470702295 || (z[10] == 5412103778470702295 && (z[9] < 7239337960414712511 || (z[9] == 7239337960414712511 && (z[8] < 7435674573564081700 || (z[8] == 7435674573564081700 && (z[7] < 2210141511517208575 || (z[7] == 2210141511517208575 && (z[6] < 13402431016077863595))))))))))) {
|
|
var b uint64
|
|
z[6], b = bits.Sub64(z[6], 13402431016077863595, 0)
|
|
z[7], b = bits.Sub64(z[7], 2210141511517208575, b)
|
|
z[8], b = bits.Sub64(z[8], 7435674573564081700, b)
|
|
z[9], b = bits.Sub64(z[9], 7239337960414712511, b)
|
|
z[10], b = bits.Sub64(z[10], 5412103778470702295, b)
|
|
z[11], _ = bits.Sub64(z[11], 1873798617647539866, b)
|
|
}
|
|
}
|
|
|
|
func waddAssign(x, y *wfe) {
|
|
wadd(x, x, y)
|
|
}
|
|
|
|
func lwadd(z, x, y *wfe) {
|
|
var carry uint64
|
|
|
|
z[0], carry = bits.Add64(x[0], y[0], 0)
|
|
z[1], carry = bits.Add64(x[1], y[1], carry)
|
|
z[2], carry = bits.Add64(x[2], y[2], carry)
|
|
z[3], carry = bits.Add64(x[3], y[3], carry)
|
|
z[4], carry = bits.Add64(x[4], y[4], carry)
|
|
z[5], carry = bits.Add64(x[5], y[5], carry)
|
|
z[6], carry = bits.Add64(x[6], y[6], carry)
|
|
z[7], carry = bits.Add64(x[7], y[7], carry)
|
|
z[8], carry = bits.Add64(x[8], y[8], carry)
|
|
z[9], carry = bits.Add64(x[9], y[9], carry)
|
|
z[10], carry = bits.Add64(x[10], y[10], carry)
|
|
z[11], _ = bits.Add64(x[11], y[11], carry)
|
|
}
|
|
|
|
func lwaddAssign(x, y *wfe) {
|
|
lwadd(x, x, y)
|
|
}
|
|
|
|
func wsub(z, x, y *wfe) {
|
|
var b uint64
|
|
z[0], b = bits.Sub64(x[0], y[0], 0)
|
|
z[1], b = bits.Sub64(x[1], y[1], b)
|
|
z[2], b = bits.Sub64(x[2], y[2], b)
|
|
z[3], b = bits.Sub64(x[3], y[3], b)
|
|
z[4], b = bits.Sub64(x[4], y[4], b)
|
|
z[5], b = bits.Sub64(x[5], y[5], b)
|
|
z[6], b = bits.Sub64(x[6], y[6], b)
|
|
z[7], b = bits.Sub64(x[7], y[7], b)
|
|
z[8], b = bits.Sub64(x[8], y[8], b)
|
|
z[9], b = bits.Sub64(x[9], y[9], b)
|
|
z[10], b = bits.Sub64(x[10], y[10], b)
|
|
z[11], b = bits.Sub64(x[11], y[11], b)
|
|
if b != 0 {
|
|
var c uint64
|
|
z[6], c = bits.Add64(z[6], 13402431016077863595, 0)
|
|
z[7], c = bits.Add64(z[7], 2210141511517208575, c)
|
|
z[8], c = bits.Add64(z[8], 7435674573564081700, c)
|
|
z[9], c = bits.Add64(z[9], 7239337960414712511, c)
|
|
z[10], c = bits.Add64(z[10], 5412103778470702295, c)
|
|
z[11], _ = bits.Add64(z[11], 1873798617647539866, c)
|
|
}
|
|
}
|
|
|
|
func wsubAssign(x, y *wfe) {
|
|
wsub(x, x, y)
|
|
}
|
|
|
|
func lwsub(z, x, y *wfe) {
|
|
var b uint64
|
|
z[0], b = bits.Sub64(x[0], y[0], 0)
|
|
z[1], b = bits.Sub64(x[1], y[1], b)
|
|
z[2], b = bits.Sub64(x[2], y[2], b)
|
|
z[3], b = bits.Sub64(x[3], y[3], b)
|
|
z[4], b = bits.Sub64(x[4], y[4], b)
|
|
z[5], b = bits.Sub64(x[5], y[5], b)
|
|
z[6], b = bits.Sub64(x[6], y[6], b)
|
|
z[7], b = bits.Sub64(x[7], y[7], b)
|
|
z[8], b = bits.Sub64(x[8], y[8], b)
|
|
z[9], b = bits.Sub64(x[9], y[9], b)
|
|
z[10], b = bits.Sub64(x[10], y[10], b)
|
|
z[11], b = bits.Sub64(x[11], y[11], b)
|
|
}
|
|
|
|
func lwsubAssign(x, y *wfe) {
|
|
lwsub(x, x, y)
|
|
}
|
|
|
|
func wdouble(z, x *wfe) {
|
|
var carry uint64
|
|
|
|
z[0], carry = bits.Add64(x[0], x[0], 0)
|
|
z[1], carry = bits.Add64(x[1], x[1], carry)
|
|
z[2], carry = bits.Add64(x[2], x[2], carry)
|
|
z[3], carry = bits.Add64(x[3], x[3], carry)
|
|
z[4], carry = bits.Add64(x[4], x[4], carry)
|
|
z[5], carry = bits.Add64(x[5], x[5], carry)
|
|
z[6], carry = bits.Add64(x[6], x[6], carry)
|
|
z[7], carry = bits.Add64(x[7], x[7], carry)
|
|
z[8], carry = bits.Add64(x[8], x[8], carry)
|
|
z[9], carry = bits.Add64(x[9], x[9], carry)
|
|
z[10], carry = bits.Add64(x[10], x[10], carry)
|
|
z[11], _ = bits.Add64(x[11], x[11], carry)
|
|
|
|
if !(z[11] < 1873798617647539866 || (z[11] == 1873798617647539866 && (z[10] < 5412103778470702295 || (z[10] == 5412103778470702295 && (z[9] < 7239337960414712511 || (z[9] == 7239337960414712511 && (z[8] < 7435674573564081700 || (z[8] == 7435674573564081700 && (z[7] < 2210141511517208575 || (z[7] == 2210141511517208575 && (z[6] < 13402431016077863595))))))))))) {
|
|
var b uint64
|
|
z[6], b = bits.Sub64(z[6], 13402431016077863595, 0)
|
|
z[7], b = bits.Sub64(z[7], 2210141511517208575, b)
|
|
z[8], b = bits.Sub64(z[8], 7435674573564081700, b)
|
|
z[9], b = bits.Sub64(z[9], 7239337960414712511, b)
|
|
z[10], b = bits.Sub64(z[10], 5412103778470702295, b)
|
|
z[11], _ = bits.Sub64(z[11], 1873798617647539866, b)
|
|
}
|
|
}
|
|
|
|
func wdoubleAssign(x *wfe) {
|
|
wdouble(x, x)
|
|
}
|
|
|
|
func lwdouble(z, x *wfe) {
|
|
var carry uint64
|
|
|
|
z[0], carry = bits.Add64(x[0], x[0], 0)
|
|
z[1], carry = bits.Add64(x[1], x[1], carry)
|
|
z[2], carry = bits.Add64(x[2], x[2], carry)
|
|
z[3], carry = bits.Add64(x[3], x[3], carry)
|
|
z[4], carry = bits.Add64(x[4], x[4], carry)
|
|
z[5], carry = bits.Add64(x[5], x[5], carry)
|
|
z[6], carry = bits.Add64(x[6], x[6], carry)
|
|
z[7], carry = bits.Add64(x[7], x[7], carry)
|
|
z[8], carry = bits.Add64(x[8], x[8], carry)
|
|
z[9], carry = bits.Add64(x[9], x[9], carry)
|
|
z[10], carry = bits.Add64(x[10], x[10], carry)
|
|
z[11], _ = bits.Add64(x[11], x[11], carry)
|
|
}
|
|
|
|
func fromWide(c *fe, w *wfe) {
|
|
montRed(c, w)
|
|
}
|
|
|
|
func wmul(w *wfe, a, b *fe) {
|
|
|
|
var w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11 uint64
|
|
var a0 = a[0]
|
|
var a1 = a[1]
|
|
var a2 = a[2]
|
|
var a3 = a[3]
|
|
var a4 = a[4]
|
|
var a5 = a[5]
|
|
var b0 = b[0]
|
|
var b1 = b[1]
|
|
var b2 = b[2]
|
|
var b3 = b[3]
|
|
var b4 = b[4]
|
|
var b5 = b[5]
|
|
var u, v, c, t uint64
|
|
|
|
{
|
|
// i = 0, j = 0
|
|
c, w0 = bits.Mul64(a0, b0)
|
|
|
|
// i = 0, j = 1
|
|
u, v = bits.Mul64(a1, b0)
|
|
w1 = v + c
|
|
c = u + (v&c|(v|c)&^w1)>>63
|
|
|
|
// i = 0, j = 2
|
|
u, v = bits.Mul64(a2, b0)
|
|
w2 = v + c
|
|
c = u + (v&c|(v|c)&^w2)>>63
|
|
|
|
// i = 0, j = 3
|
|
u, v = bits.Mul64(a3, b0)
|
|
w3 = v + c
|
|
c = u + (v&c|(v|c)&^w3)>>63
|
|
|
|
// i = 0, j = 4
|
|
u, v = bits.Mul64(a4, b0)
|
|
w4 = v + c
|
|
c = u + (v&c|(v|c)&^w4)>>63
|
|
|
|
// i = 0, j = 5
|
|
u, v = bits.Mul64(a5, b0)
|
|
w5 = v + c
|
|
w6 = u + (v&c|(v|c)&^w5)>>63
|
|
}
|
|
|
|
{
|
|
|
|
// i = 1, j = 0
|
|
c, v = bits.Mul64(a0, b1)
|
|
t = v + w1
|
|
c += (v&w1 | (v|w1)&^t) >> 63
|
|
w1 = t
|
|
|
|
// i = 1, j = 1
|
|
u, v = bits.Mul64(a1, b1)
|
|
t = v + w2
|
|
u += (v&w2 | (v|w2)&^t) >> 63
|
|
w2 = t + c
|
|
c = u + (t&c|(t|c)&^w2)>>63
|
|
|
|
// i = 1, j = 2
|
|
u, v = bits.Mul64(a2, b1)
|
|
t = v + w3
|
|
u += (v&w3 | (v|w3)&^t) >> 63
|
|
w3 = t + c
|
|
c = u + (t&c|(t|c)&^w3)>>63
|
|
|
|
// i = 1, j = 3
|
|
u, v = bits.Mul64(a3, b1)
|
|
t = v + w4
|
|
u += (v&w4 | (v|w4)&^t) >> 63
|
|
w4 = t + c
|
|
c = u + (t&c|(t|c)&^w4)>>63
|
|
|
|
// i = 1, j = 4
|
|
u, v = bits.Mul64(a4, b1)
|
|
t = v + w5
|
|
u += (v&w5 | (v|w5)&^t) >> 63
|
|
w5 = t + c
|
|
c = u + (t&c|(t|c)&^w5)>>63
|
|
|
|
// i = 1, j = 5
|
|
u, v = bits.Mul64(a5, b1)
|
|
t = v + w6
|
|
u += (v&w6 | (v|w6)&^t) >> 63
|
|
w6 = t + c
|
|
w7 = u + (t&c|(t|c)&^w6)>>63
|
|
}
|
|
|
|
{
|
|
// i = 2, j = 0
|
|
c, v = bits.Mul64(a0, b2)
|
|
t = v + w2
|
|
c += (v&w2 | (v|w2)&^t) >> 63
|
|
w2 = t
|
|
|
|
// i = 2, j = 1
|
|
u, v = bits.Mul64(a1, b2)
|
|
t = v + w3
|
|
u += (v&w3 | (v|w3)&^t) >> 63
|
|
w3 = t + c
|
|
c = u + (t&c|(t|c)&^w3)>>63
|
|
|
|
// i = 2, j = 2
|
|
u, v = bits.Mul64(a2, b2)
|
|
t = v + w4
|
|
u += (v&w4 | (v|w4)&^t) >> 63
|
|
w4 = t + c
|
|
c = u + (t&c|(t|c)&^w4)>>63
|
|
|
|
// i = 2, j = 3
|
|
u, v = bits.Mul64(a3, b2)
|
|
t = v + w5
|
|
u += (v&w5 | (v|w5)&^t) >> 63
|
|
w5 = t + c
|
|
c = u + (t&c|(t|c)&^w5)>>63
|
|
|
|
// i = 2, j = 4
|
|
u, v = bits.Mul64(a4, b2)
|
|
t = v + w6
|
|
u += (v&w6 | (v|w6)&^t) >> 63
|
|
w6 = t + c
|
|
c = u + (t&c|(t|c)&^w6)>>63
|
|
|
|
// i = 2, j = 5
|
|
u, v = bits.Mul64(a5, b2)
|
|
t = v + w7
|
|
u += (v&w7 | (v|w7)&^t) >> 63
|
|
w7 = t + c
|
|
w8 = u + (t&c|(t|c)&^w7)>>63
|
|
}
|
|
|
|
{
|
|
// i = 3, j = 0
|
|
c, v = bits.Mul64(a0, b3)
|
|
t = v + w3
|
|
c += (v&w3 | (v|w3)&^t) >> 63
|
|
w3 = t
|
|
|
|
// i = 3, j = 1
|
|
u, v = bits.Mul64(a1, b3)
|
|
t = v + w4
|
|
u += (v&w4 | (v|w4)&^t) >> 63
|
|
w4 = t + c
|
|
c = u + (t&c|(t|c)&^w4)>>63
|
|
|
|
// i = 3, j = 2
|
|
u, v = bits.Mul64(a2, b3)
|
|
t = v + w5
|
|
u += (v&w5 | (v|w5)&^t) >> 63
|
|
w5 = t + c
|
|
c = u + (t&c|(t|c)&^w5)>>63
|
|
|
|
// i = 3, j = 3
|
|
u, v = bits.Mul64(a3, b3)
|
|
t = v + w6
|
|
u += (v&w6 | (v|w6)&^t) >> 63
|
|
w6 = t + c
|
|
c = u + (t&c|(t|c)&^w6)>>63
|
|
|
|
// i = 3, j = 4
|
|
u, v = bits.Mul64(a4, b3)
|
|
t = v + w7
|
|
u += (v&w7 | (v|w7)&^t) >> 63
|
|
w7 = t + c
|
|
c = u + (t&c|(t|c)&^w7)>>63
|
|
|
|
// i = 3, j = 5
|
|
u, v = bits.Mul64(a5, b3)
|
|
t = v + w8
|
|
u += (v&w8 | (v|w8)&^t) >> 63
|
|
w8 = t + c
|
|
w9 = u + (t&c|(t|c)&^w8)>>63
|
|
}
|
|
|
|
{
|
|
// i = 4, j = 0
|
|
c, v = bits.Mul64(a0, b4)
|
|
t = v + w4
|
|
c += (v&w4 | (v|w4)&^t) >> 63
|
|
w4 = t
|
|
|
|
// i = 4, j = 1
|
|
u, v = bits.Mul64(a1, b4)
|
|
t = v + w5
|
|
u += (v&w5 | (v|w5)&^t) >> 63
|
|
w5 = t + c
|
|
c = u + (t&c|(t|c)&^w5)>>63
|
|
|
|
// i = 4, j = 2
|
|
u, v = bits.Mul64(a2, b4)
|
|
t = v + w6
|
|
u += (v&w6 | (v|w6)&^t) >> 63
|
|
w6 = t + c
|
|
c = u + (t&c|(t|c)&^w6)>>63
|
|
|
|
// i = 4, j = 3
|
|
u, v = bits.Mul64(a3, b4)
|
|
t = v + w7
|
|
u += (v&w7 | (v|w7)&^t) >> 63
|
|
w7 = t + c
|
|
c = u + (t&c|(t|c)&^w7)>>63
|
|
|
|
// i = 4, j = 4
|
|
u, v = bits.Mul64(a4, b4)
|
|
t = v + w8
|
|
u += (v&w8 | (v|w8)&^t) >> 63
|
|
w8 = t + c
|
|
c = u + (t&c|(t|c)&^w8)>>63
|
|
|
|
// i = 4, j = 5
|
|
u, v = bits.Mul64(a5, b4)
|
|
t = v + w9
|
|
u += (v&w9 | (v|w9)&^t) >> 63
|
|
w9 = t + c
|
|
w10 = u + (t&c|(t|c)&^w9)>>63
|
|
}
|
|
|
|
{
|
|
// i = 5, j = 0
|
|
c, v = bits.Mul64(a0, b5)
|
|
t = v + w5
|
|
c += (v&w5 | (v|w5)&^t) >> 63
|
|
w5 = t
|
|
|
|
// i = 5, j = 1
|
|
u, v = bits.Mul64(a1, b5)
|
|
t = v + w6
|
|
u += (v&w6 | (v|w6)&^t) >> 63
|
|
w6 = t + c
|
|
c = u + (t&c|(t|c)&^w6)>>63
|
|
|
|
// i = 5, j = 2
|
|
u, v = bits.Mul64(a2, b5)
|
|
t = v + w7
|
|
u += (v&w7 | (v|w7)&^t) >> 63
|
|
w7 = t + c
|
|
c = u + (t&c|(t|c)&^w7)>>63
|
|
|
|
// i = 5, j = 3
|
|
u, v = bits.Mul64(a3, b5)
|
|
t = v + w8
|
|
u += (v&w8 | (v|w8)&^t) >> 63
|
|
w8 = t + c
|
|
c = u + (t&c|(t|c)&^w8)>>63
|
|
|
|
// i = 5, j = 4
|
|
u, v = bits.Mul64(a4, b5)
|
|
t = v + w9
|
|
u += (v&w9 | (v|w9)&^t) >> 63
|
|
w9 = t + c
|
|
c = u + (t&c|(t|c)&^w9)>>63
|
|
|
|
// i = 5, j = 5
|
|
u, v = bits.Mul64(a5, b5)
|
|
t = v + w10
|
|
u += (v&w10 | (v|w10)&^t) >> 63
|
|
w10 = t + c
|
|
w11 = u + (t&c|(t|c)&^w10)>>63
|
|
}
|
|
|
|
w[0] = w0
|
|
w[1] = w1
|
|
w[2] = w2
|
|
w[3] = w3
|
|
w[4] = w4
|
|
w[5] = w5
|
|
w[6] = w6
|
|
w[7] = w7
|
|
w[8] = w8
|
|
w[9] = w9
|
|
w[10] = w10
|
|
w[11] = w11
|
|
}
|
|
|
|
func montRed(c *fe, w *wfe) {
|
|
|
|
// Reduces T as T (R^-1) modp
|
|
// Handbook of Applied Cryptography
|
|
// Hankerson, Menezes, Vanstone
|
|
// Algorithm 14.32 Montgomery reduction
|
|
|
|
w0 := w[0]
|
|
w1 := w[1]
|
|
w2 := w[2]
|
|
w3 := w[3]
|
|
w4 := w[4]
|
|
w5 := w[5]
|
|
w6 := w[6]
|
|
w7 := w[7]
|
|
w8 := w[8]
|
|
w9 := w[9]
|
|
w10 := w[10]
|
|
w11 := w[11]
|
|
p0 := modulus[0]
|
|
p1 := modulus[1]
|
|
p2 := modulus[2]
|
|
p3 := modulus[3]
|
|
p4 := modulus[4]
|
|
p5 := modulus[5]
|
|
|
|
var e1, e2, el, res uint64
|
|
var t1, t2, u uint64
|
|
|
|
{
|
|
|
|
// i = 0
|
|
u = w0 * inp
|
|
//
|
|
e1, res = bits.Mul64(u, p0)
|
|
t1 = res + w0
|
|
e1 += (res&w0 | (res|w0)&^t1) >> 63
|
|
//
|
|
e2, res = bits.Mul64(u, p1)
|
|
t1 = res + e1
|
|
e2 += (res&e1 | (res|e1)&^t1) >> 63
|
|
t2 = t1 + w1
|
|
e2 += (t1&w1 | (t1|w1)&^t2) >> 63
|
|
w1 = t2
|
|
//
|
|
e1, res = bits.Mul64(u, p2)
|
|
t1 = res + e2
|
|
e1 += (res&e2 | (res|e2)&^t1) >> 63
|
|
t2 = t1 + w2
|
|
e1 += (t1&w2 | (t1|w2)&^t2) >> 63
|
|
w2 = t2
|
|
//
|
|
e2, res = bits.Mul64(u, p3)
|
|
t1 = res + e1
|
|
e2 += (res&e1 | (res|e1)&^t1) >> 63
|
|
t2 = t1 + w3
|
|
e2 += (t1&w3 | (t1|w3)&^t2) >> 63
|
|
w3 = t2
|
|
//
|
|
e1, res = bits.Mul64(u, p4)
|
|
t1 = res + e2
|
|
e1 += (res&e2 | (res|e2)&^t1) >> 63
|
|
t2 = t1 + w4
|
|
e1 += (t1&w4 | (t1|w4)&^t2) >> 63
|
|
w4 = t2
|
|
//
|
|
e2, res = bits.Mul64(u, p5)
|
|
t1 = res + e1
|
|
e2 += (res&e1 | (res|e1)&^t1) >> 63
|
|
t2 = t1 + w5
|
|
e2 += (t1&w5 | (t1|w5)&^t2) >> 63
|
|
w5 = t2
|
|
//
|
|
t1 = w6 + el
|
|
e1 = (w6&el | (w6|el)&^t1) >> 63
|
|
t2 = t1 + e2
|
|
e1 += (t1&e2 | (t1|e2)&^t2) >> 63
|
|
w6 = t2
|
|
el = e1
|
|
}
|
|
|
|
{
|
|
// i = 1
|
|
u = w1 * inp
|
|
//
|
|
e1, res = bits.Mul64(u, p0)
|
|
t1 = res + w1
|
|
e1 += (res&w1 | (res|w1)&^t1) >> 63
|
|
//
|
|
e2, res = bits.Mul64(u, p1)
|
|
t1 = res + e1
|
|
e2 += (res&e1 | (res|e1)&^t1) >> 63
|
|
t2 = t1 + w2
|
|
e2 += (t1&w2 | (t1|w2)&^t2) >> 63
|
|
w2 = t2
|
|
//
|
|
e1, res = bits.Mul64(u, p2)
|
|
t1 = res + e2
|
|
e1 += (res&e2 | (res|e2)&^t1) >> 63
|
|
t2 = t1 + w3
|
|
e1 += (t1&w3 | (t1|w3)&^t2) >> 63
|
|
w3 = t2
|
|
//
|
|
e2, res = bits.Mul64(u, p3)
|
|
t1 = res + e1
|
|
e2 += (res&e1 | (res|e1)&^t1) >> 63
|
|
t2 = t1 + w4
|
|
e2 += (t1&w4 | (t1|w4)&^t2) >> 63
|
|
w4 = t2
|
|
//
|
|
e1, res = bits.Mul64(u, p4)
|
|
t1 = res + e2
|
|
e1 += (res&e2 | (res|e2)&^t1) >> 63
|
|
t2 = t1 + w5
|
|
e1 += (t1&w5 | (t1|w5)&^t2) >> 63
|
|
w5 = t2
|
|
//
|
|
e2, res = bits.Mul64(u, p5)
|
|
t1 = res + e1
|
|
e2 += (res&e1 | (res|e1)&^t1) >> 63
|
|
t2 = t1 + w6
|
|
e2 += (t1&w6 | (t1|w6)&^t2) >> 63
|
|
w6 = t2
|
|
//
|
|
t1 = w7 + el
|
|
e1 = (w7&el | (w7|el)&^t1) >> 63
|
|
t2 = t1 + e2
|
|
e1 += (t1&e2 | (t1|e2)&^t2) >> 63
|
|
w7 = t2
|
|
el = e1
|
|
}
|
|
|
|
{
|
|
// i = 2
|
|
u = w2 * inp
|
|
//
|
|
e1, res = bits.Mul64(u, p0)
|
|
t1 = res + w2
|
|
e1 += (res&w2 | (res|w2)&^t1) >> 63
|
|
//
|
|
e2, res = bits.Mul64(u, p1)
|
|
t1 = res + e1
|
|
e2 += (res&e1 | (res|e1)&^t1) >> 63
|
|
t2 = t1 + w3
|
|
e2 += (t1&w3 | (t1|w3)&^t2) >> 63
|
|
w3 = t2
|
|
//
|
|
e1, res = bits.Mul64(u, p2)
|
|
t1 = res + e2
|
|
e1 += (res&e2 | (res|e2)&^t1) >> 63
|
|
t2 = t1 + w4
|
|
e1 += (t1&w4 | (t1|w4)&^t2) >> 63
|
|
w4 = t2
|
|
//
|
|
e2, res = bits.Mul64(u, p3)
|
|
t1 = res + e1
|
|
e2 += (res&e1 | (res|e1)&^t1) >> 63
|
|
t2 = t1 + w5
|
|
e2 += (t1&w5 | (t1|w5)&^t2) >> 63
|
|
w5 = t2
|
|
//
|
|
e1, res = bits.Mul64(u, p4)
|
|
t1 = res + e2
|
|
e1 += (res&e2 | (res|e2)&^t1) >> 63
|
|
t2 = t1 + w6
|
|
e1 += (t1&w6 | (t1|w6)&^t2) >> 63
|
|
w6 = t2
|
|
//
|
|
e2, res = bits.Mul64(u, p5)
|
|
t1 = res + e1
|
|
e2 += (res&e1 | (res|e1)&^t1) >> 63
|
|
t2 = t1 + w7
|
|
e2 += (t1&w7 | (t1|w7)&^t2) >> 63
|
|
w7 = t2
|
|
//
|
|
t1 = w8 + el
|
|
e1 = (w8&el | (w8|el)&^t1) >> 63
|
|
t2 = t1 + e2
|
|
e1 += (t1&e2 | (t1|e2)&^t2) >> 63
|
|
w8 = t2
|
|
el = e1
|
|
}
|
|
|
|
{
|
|
// i = 3
|
|
u = w3 * inp
|
|
//
|
|
e1, res = bits.Mul64(u, p0)
|
|
t1 = res + w3
|
|
e1 += (res&w3 | (res|w3)&^t1) >> 63
|
|
//
|
|
e2, res = bits.Mul64(u, p1)
|
|
t1 = res + e1
|
|
e2 += (res&e1 | (res|e1)&^t1) >> 63
|
|
t2 = t1 + w4
|
|
e2 += (t1&w4 | (t1|w4)&^t2) >> 63
|
|
w4 = t2
|
|
//
|
|
e1, res = bits.Mul64(u, p2)
|
|
t1 = res + e2
|
|
e1 += (res&e2 | (res|e2)&^t1) >> 63
|
|
t2 = t1 + w5
|
|
e1 += (t1&w5 | (t1|w5)&^t2) >> 63
|
|
w5 = t2
|
|
//
|
|
e2, res = bits.Mul64(u, p3)
|
|
t1 = res + e1
|
|
e2 += (res&e1 | (res|e1)&^t1) >> 63
|
|
t2 = t1 + w6
|
|
e2 += (t1&w6 | (t1|w6)&^t2) >> 63
|
|
w6 = t2
|
|
//
|
|
e1, res = bits.Mul64(u, p4)
|
|
t1 = res + e2
|
|
e1 += (res&e2 | (res|e2)&^t1) >> 63
|
|
t2 = t1 + w7
|
|
e1 += (t1&w7 | (t1|w7)&^t2) >> 63
|
|
w7 = t2
|
|
//
|
|
e2, res = bits.Mul64(u, p5)
|
|
t1 = res + e1
|
|
e2 += (res&e1 | (res|e1)&^t1) >> 63
|
|
t2 = t1 + w8
|
|
e2 += (t1&w8 | (t1|w8)&^t2) >> 63
|
|
w8 = t2
|
|
//
|
|
t1 = w9 + el
|
|
e1 = (w9&el | (w9|el)&^t1) >> 63
|
|
t2 = t1 + e2
|
|
e1 += (t1&e2 | (t1|e2)&^t2) >> 63
|
|
w9 = t2
|
|
el = e1
|
|
}
|
|
|
|
{
|
|
// i = 4
|
|
u = w4 * inp
|
|
//
|
|
e1, res = bits.Mul64(u, p0)
|
|
t1 = res + w4
|
|
e1 += (res&w4 | (res|w4)&^t1) >> 63
|
|
//
|
|
e2, res = bits.Mul64(u, p1)
|
|
t1 = res + e1
|
|
e2 += (res&e1 | (res|e1)&^t1) >> 63
|
|
t2 = t1 + w5
|
|
e2 += (t1&w5 | (t1|w5)&^t2) >> 63
|
|
w5 = t2
|
|
//
|
|
e1, res = bits.Mul64(u, p2)
|
|
t1 = res + e2
|
|
e1 += (res&e2 | (res|e2)&^t1) >> 63
|
|
t2 = t1 + w6
|
|
e1 += (t1&w6 | (t1|w6)&^t2) >> 63
|
|
w6 = t2
|
|
//
|
|
e2, res = bits.Mul64(u, p3)
|
|
t1 = res + e1
|
|
e2 += (res&e1 | (res|e1)&^t1) >> 63
|
|
t2 = t1 + w7
|
|
e2 += (t1&w7 | (t1|w7)&^t2) >> 63
|
|
w7 = t2
|
|
//
|
|
e1, res = bits.Mul64(u, p4)
|
|
t1 = res + e2
|
|
e1 += (res&e2 | (res|e2)&^t1) >> 63
|
|
t2 = t1 + w8
|
|
e1 += (t1&w8 | (t1|w8)&^t2) >> 63
|
|
w8 = t2
|
|
//
|
|
e2, res = bits.Mul64(u, p5)
|
|
t1 = res + e1
|
|
e2 += (res&e1 | (res|e1)&^t1) >> 63
|
|
t2 = t1 + w9
|
|
e2 += (t1&w9 | (t1|w9)&^t2) >> 63
|
|
w9 = t2
|
|
//
|
|
t1 = w10 + el
|
|
e1 = (w10&el | (w10|el)&^t1) >> 63
|
|
t2 = t1 + e2
|
|
e1 += (t1&e2 | (t1|e2)&^t2) >> 63
|
|
w10 = t2
|
|
el = e1
|
|
}
|
|
|
|
{
|
|
// i = 5
|
|
u = w5 * inp
|
|
//
|
|
e1, res = bits.Mul64(u, p0)
|
|
t1 = res + w5
|
|
e1 += (res&w5 | (res|w5)&^t1) >> 63
|
|
//
|
|
e2, res = bits.Mul64(u, p1)
|
|
t1 = res + e1
|
|
e2 += (res&e1 | (res|e1)&^t1) >> 63
|
|
t2 = t1 + w6
|
|
e2 += (t1&w6 | (t1|w6)&^t2) >> 63
|
|
w6 = t2
|
|
//
|
|
e1, res = bits.Mul64(u, p2)
|
|
t1 = res + e2
|
|
e1 += (res&e2 | (res|e2)&^t1) >> 63
|
|
t2 = t1 + w7
|
|
e1 += (t1&w7 | (t1|w7)&^t2) >> 63
|
|
w7 = t2
|
|
//
|
|
e2, res = bits.Mul64(u, p3)
|
|
t1 = res + e1
|
|
e2 += (res&e1 | (res|e1)&^t1) >> 63
|
|
t2 = t1 + w8
|
|
e2 += (t1&w8 | (t1|w8)&^t2) >> 63
|
|
w8 = t2
|
|
//
|
|
e1, res = bits.Mul64(u, p4)
|
|
t1 = res + e2
|
|
e1 += (res&e2 | (res|e2)&^t1) >> 63
|
|
t2 = t1 + w9
|
|
e1 += (t1&w9 | (t1|w9)&^t2) >> 63
|
|
w9 = t2
|
|
//
|
|
e2, res = bits.Mul64(u, p5)
|
|
t1 = res + e1
|
|
e2 += (res&e1 | (res|e1)&^t1) >> 63
|
|
t2 = t1 + w10
|
|
e2 += (t1&w10 | (t1|w10)&^t2) >> 63
|
|
w10 = t2
|
|
//
|
|
t1 = w11 + el
|
|
e1 = (w11&el | (w11|el)&^t1) >> 63
|
|
t2 = t1 + e2
|
|
e1 += (t1&e2 | (t1|e2)&^t2) >> 63
|
|
w11 = t2
|
|
}
|
|
|
|
e1--
|
|
c[0] = w6 - ((p0) & ^e1)
|
|
e2 = (^w6&p0 | (^w6|p0)&c[0]) >> 63
|
|
c[1] = w7 - ((p1 + e2) & ^e1)
|
|
e2 = (^w7&p1 | (^w7|p1)&c[1]) >> 63
|
|
c[2] = w8 - ((p2 + e2) & ^e1)
|
|
e2 = (^w8&p2 | (^w8|p2)&c[2]) >> 63
|
|
c[3] = w9 - ((p3 + e2) & ^e1)
|
|
e2 = (^w9&p3 | (^w9|p3)&c[3]) >> 63
|
|
c[4] = w10 - ((p4 + e2) & ^e1)
|
|
e2 = (^w10&p4 | (^w10|p4)&c[4]) >> 63
|
|
c[5] = w11 - ((p5 + e2) & ^e1)
|
|
|
|
sub(c, c, &modulus)
|
|
}
|
|
|
|
func fp2Add(c, a, b *fe2) {
|
|
add(&c[0], &a[0], &b[0])
|
|
add(&c[1], &a[1], &b[1])
|
|
}
|
|
|
|
func fp2AddAssign(a, b *fe2) {
|
|
addAssign(&a[0], &b[0])
|
|
addAssign(&a[1], &b[1])
|
|
}
|
|
|
|
func fp2Ladd(c, a, b *fe2) {
|
|
ladd(&c[0], &a[0], &b[0])
|
|
ladd(&c[1], &a[1], &b[1])
|
|
}
|
|
|
|
func fp2LaddAssign(a, b *fe2) {
|
|
laddAssign(&a[0], &b[0])
|
|
laddAssign(&a[1], &b[1])
|
|
}
|
|
|
|
func fp2Double(c, a *fe2) {
|
|
double(&c[0], &a[0])
|
|
double(&c[1], &a[1])
|
|
}
|
|
|
|
func fp2DoubleAssign(a *fe2) {
|
|
doubleAssign(&a[0])
|
|
doubleAssign(&a[1])
|
|
}
|
|
|
|
func fp2Ldouble(c, a *fe2) {
|
|
ldouble(&c[0], &a[0])
|
|
ldouble(&c[1], &a[1])
|
|
}
|
|
|
|
func fp2Sub(c, a, b *fe2) {
|
|
sub(&c[0], &a[0], &b[0])
|
|
sub(&c[1], &a[1], &b[1])
|
|
}
|
|
|
|
func fp2SubAssign(c, a *fe2) {
|
|
subAssign(&c[0], &a[0])
|
|
subAssign(&c[1], &a[1])
|
|
}
|
|
|
|
func mulByNonResidue(c, a *fe2) {
|
|
t := new(fe)
|
|
sub(t, &a[0], &a[1])
|
|
add(&c[1], &a[0], &a[1])
|
|
c[0].set(t)
|
|
}
|
|
|
|
func mulByNonResidueAssign(a *fe2) {
|
|
t := new(fe)
|
|
sub(t, &a[0], &a[1])
|
|
add(&a[1], &a[0], &a[1])
|
|
a[0].set(t)
|
|
}
|
|
|
|
func wfp2Add(c, a, b *wfe2) {
|
|
wadd(&c[0], &a[0], &b[0])
|
|
wadd(&c[1], &a[1], &b[1])
|
|
}
|
|
|
|
func wfp2AddAssign(c, a *wfe2) {
|
|
waddAssign(&c[0], &a[0])
|
|
waddAssign(&c[1], &a[1])
|
|
}
|
|
|
|
func wfp2Ladd(c, a, b *wfe2) {
|
|
lwadd(&c[0], &a[0], &b[0])
|
|
lwadd(&c[1], &a[1], &b[1])
|
|
}
|
|
|
|
func wfp2LaddAssign(a, b *wfe2) {
|
|
lwaddAssign(&a[0], &b[0])
|
|
lwaddAssign(&a[1], &b[1])
|
|
}
|
|
|
|
func wfp2AddMixed(c, a, b *wfe2) {
|
|
wadd(&c[0], &a[0], &b[0])
|
|
lwadd(&c[1], &a[1], &b[1])
|
|
}
|
|
|
|
func wfp2AddMixedAssign(a, b *wfe2) {
|
|
waddAssign(&a[0], &b[0])
|
|
lwaddAssign(&a[1], &b[1])
|
|
}
|
|
|
|
func wfp2Sub(c, a, b *wfe2) {
|
|
wsub(&c[0], &a[0], &b[0])
|
|
wsub(&c[1], &a[1], &b[1])
|
|
}
|
|
|
|
func wfp2SubAssign(a, b *wfe2) {
|
|
wsub(&a[0], &a[0], &b[0])
|
|
wsub(&a[1], &a[1], &b[1])
|
|
}
|
|
|
|
func wfp2SubMixed(c, a, b *wfe2) {
|
|
wsub(&c[0], &a[0], &b[0])
|
|
lwsub(&c[1], &a[1], &b[1])
|
|
}
|
|
|
|
func wfp2SubMixedAssign(a, b *wfe2) {
|
|
wsubAssign(&a[0], &b[0])
|
|
lwsubAssign(&a[1], &b[1])
|
|
}
|
|
|
|
func wfp2Double(c, a *wfe2) {
|
|
wdouble(&c[0], &a[0])
|
|
wdouble(&c[1], &a[1])
|
|
}
|
|
|
|
func wfp2DoubleAssign(a *wfe2) {
|
|
wdoubleAssign(&a[0])
|
|
wdoubleAssign(&a[1])
|
|
}
|
|
|
|
func wfp2MulByNonResidue(c, a *wfe2) {
|
|
wt0 := &wfe{}
|
|
wadd(wt0, &a[0], &a[1])
|
|
wsub(&c[0], &a[0], &a[1])
|
|
c[1].set(wt0)
|
|
}
|
|
|
|
func wfp2MulByNonResidueAssign(a *wfe2) {
|
|
wt0 := &wfe{}
|
|
wadd(wt0, &a[0], &a[1])
|
|
wsub(&a[0], &a[0], &a[1])
|
|
a[1].set(wt0)
|
|
}
|
|
|
|
var wfp2Mul func(c *wfe2, a, b *fe2) = wfp2MulGeneric
|
|
var wfp2Square func(c *wfe2, a *fe2) = wfp2SquareGeneric
|