ceremonyclient/ec/bls48581/DBIG.go
2023-04-15 00:05:26 -04:00

299 lines
5.3 KiB
Go

/*
* Copyright (c) 2012-2020 MIRACL UK Ltd.
*
* This file is part of MIRACL Core
* (see https://github.com/miracl/core).
*
* 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.
*/
/* MiotCL double length DBIG number class */
package bls48581
import "strconv"
//import "fmt"
func NewDBIG() *DBIG {
b := new(DBIG)
for i := 0; i < DNLEN; i++ {
b.w[i] = 0
}
return b
}
func NewDBIGcopy(x *DBIG) *DBIG {
b := new(DBIG)
for i := 0; i < DNLEN; i++ {
b.w[i] = x.w[i]
}
return b
}
func NewDBIGscopy(x *BIG) *DBIG {
b := new(DBIG)
for i := 0; i < NLEN-1; i++ {
b.w[i] = x.w[i]
}
b.w[NLEN-1] = x.get(NLEN-1) & BMASK /* top word normalized */
b.w[NLEN] = x.get(NLEN-1) >> BASEBITS
for i := NLEN + 1; i < DNLEN; i++ {
b.w[i] = 0
}
return b
}
/* normalise this */
func (r *DBIG) norm() {
carry := Chunk(0)
for i := 0; i < DNLEN-1; i++ {
d := r.w[i] + carry
r.w[i] = d & BMASK
carry = d >> BASEBITS
}
r.w[DNLEN-1] = (r.w[DNLEN-1] + carry)
}
/* split DBIG at position n, return higher half, keep lower half */
func (r *DBIG) split(n uint) *BIG {
t := NewBIG()
m := n % BASEBITS
carry := r.w[DNLEN-1] << (BASEBITS - m)
for i := DNLEN - 2; i >= NLEN-1; i-- {
nw := (r.w[i] >> m) | carry
carry = (r.w[i] << (BASEBITS - m)) & BMASK
t.set(i-NLEN+1, nw)
}
r.w[NLEN-1] &= ((Chunk(1) << m) - 1)
return t
}
func (r *DBIG) cmove(g *DBIG, d int) Chunk {
var b = Chunk(-d)
s := Chunk(0)
v := r.w[0] ^ g.w[1]
va := v + v
va >>= 1
for i := 0; i < DNLEN; i++ {
t := (r.w[i] ^ g.w[i]) & b
t ^= v
e := r.w[i] ^ t
s ^= e
r.w[i] = e ^ va
}
return s
}
/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
func dcomp(a *DBIG, b *DBIG) int {
gt := Chunk(0)
eq := Chunk(1)
for i := DNLEN - 1; i >= 0; i-- {
gt |= ((b.w[i] - a.w[i]) >> BASEBITS) & eq
eq &= ((b.w[i] ^ a.w[i]) - 1) >> BASEBITS
}
return int(gt + gt + eq - 1)
}
/* Copy from another DBIG */
func (r *DBIG) copy(x *DBIG) {
for i := 0; i < DNLEN; i++ {
r.w[i] = x.w[i]
}
}
/* Copy from another BIG to upper half */
func (r *DBIG) ucopy(x *BIG) {
for i := 0; i < NLEN; i++ {
r.w[i] = 0
}
for i := NLEN; i < DNLEN; i++ {
r.w[i] = x.w[i-NLEN]
}
}
func (r *DBIG) add(x *DBIG) {
for i := 0; i < DNLEN; i++ {
r.w[i] = r.w[i] + x.w[i]
}
}
/* this-=x */
func (r *DBIG) sub(x *DBIG) {
for i := 0; i < DNLEN; i++ {
r.w[i] = r.w[i] - x.w[i]
}
}
/* this-=x */
func (r *DBIG) rsub(x *DBIG) {
for i := 0; i < DNLEN; i++ {
r.w[i] = x.w[i] - r.w[i]
}
}
/* general shift left */
func (r *DBIG) shl(k uint) {
n := k % BASEBITS
m := int(k / BASEBITS)
r.w[DNLEN-1] = (r.w[DNLEN-1-m] << n) | (r.w[DNLEN-m-2] >> (BASEBITS - n))
for i := DNLEN - 2; i > m; i-- {
r.w[i] = ((r.w[i-m] << n) & BMASK) | (r.w[i-m-1] >> (BASEBITS - n))
}
r.w[m] = (r.w[0] << n) & BMASK
for i := 0; i < m; i++ {
r.w[i] = 0
}
}
/* general shift right */
func (r *DBIG) shr(k uint) {
n := (k % BASEBITS)
m := int(k / BASEBITS)
for i := 0; i < DNLEN-m-1; i++ {
r.w[i] = (r.w[m+i] >> n) | ((r.w[m+i+1] << (BASEBITS - n)) & BMASK)
}
r.w[DNLEN-m-1] = r.w[DNLEN-1] >> n
for i := DNLEN - m; i < DNLEN; i++ {
r.w[i] = 0
}
}
func (r *DBIG) ctmod(m *BIG, bd uint) *BIG {
k := bd
r.norm()
c := NewDBIGscopy(m)
dr := NewDBIG()
c.shl(k)
for {
dr.copy(r)
dr.sub(c)
dr.norm()
r.cmove(dr, int(1-((dr.w[DNLEN-1]>>uint(CHUNK-1))&1)))
if k == 0 {
break
}
k -= 1
c.shr(1)
}
return NewBIGdcopy(r)
}
/* reduces this DBIG mod a BIG, and returns the BIG */
func (r *DBIG) Mod(m *BIG) *BIG {
k := r.nbits() - m.nbits()
if k < 0 {
k = 0
}
return r.ctmod(m, uint(k))
}
func (r *DBIG) ctdiv(m *BIG, bd uint) *BIG {
k := bd
c := NewDBIGscopy(m)
a := NewBIGint(0)
e := NewBIGint(1)
sr := NewBIG()
dr := NewDBIG()
r.norm()
c.shl(k)
e.shl(k)
for {
dr.copy(r)
dr.sub(c)
dr.norm()
d := int(1 - ((dr.w[DNLEN-1] >> uint(CHUNK-1)) & 1))
r.cmove(dr, d)
sr.copy(a)
sr.add(e)
sr.norm()
a.cmove(sr, d)
if k == 0 {
break
}
k -= 1
c.shr(1)
e.shr(1)
}
return a
}
/* return this/c */
func (r *DBIG) div(m *BIG) *BIG {
k := r.nbits() - m.nbits()
if k < 0 {
k = 0
}
return r.ctdiv(m, uint(k))
}
/* Convert to Hex String */
func (r *DBIG) toString() string {
s := ""
len := r.nbits()
if len%4 == 0 {
len /= 4
} else {
len /= 4
len++
}
for i := len - 1; i >= 0; i-- {
b := NewDBIGcopy(r)
b.shr(uint(i * 4))
s += strconv.FormatInt(int64(b.w[0]&15), 16)
}
return s
}
/* return number of bits */
func (r *DBIG) nbits() int {
k := DNLEN - 1
t := NewDBIGcopy(r)
t.norm()
for k >= 0 && t.w[k] == 0 {
k--
}
if k < 0 {
return 0
}
bts := int(BASEBITS) * k
c := t.w[k]
for c != 0 {
c /= 2
bts++
}
return bts
}
/* convert from byte array to BIG */
func DBIG_fromBytes(b []byte) *DBIG {
m := NewDBIG()
for i := 0; i < len(b); i++ {
m.shl(8)
m.w[0] += Chunk(int(b[i] & 0xff))
}
return m
}