derohe-miniblock-mod/cryptography/crypto/algebra_fieldvector.go
2021-12-04 16:42:11 +00:00

206 lines
5.3 KiB
Go

// Copyright 2017-2021 DERO Project. All rights reserved.
// Use of this source code in any form is governed by RESEARCH license.
// license can be found in the LICENSE file.
// GPG: 0F39 E425 8C65 3947 702A 8234 08B2 0360 A03A 9DE8
//
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package crypto
//import "fmt"
import "math/big"
//import "crypto/rand"
//import "encoding/hex"
import "github.com/deroproject/derohe/cryptography/bn256"
//import "golang.org/x/crypto/sha3"
type FieldVector struct {
vector []*big.Int
}
func NewFieldVector(input []*big.Int) *FieldVector {
return &FieldVector{vector: input}
}
func NewFieldVectorRandomFilled(capacity int) *FieldVector {
fv := &FieldVector{vector: make([]*big.Int, capacity, capacity)}
for i := range fv.vector {
fv.vector[i] = RandomScalarFixed()
}
return fv
}
func (fv *FieldVector) Length() int {
return len(fv.vector)
}
// slice and return
func (fv *FieldVector) Slice(start, end int) *FieldVector {
var result FieldVector
for i := start; i < end; i++ {
result.vector = append(result.vector, new(big.Int).Set(fv.vector[i]))
}
return &result
}
//copy and return
func (fv *FieldVector) Clone() *FieldVector {
return fv.Slice(0, len(fv.vector))
}
func (fv *FieldVector) Element(index int) *big.Int {
return fv.vector[index]
}
func (fv *FieldVector) SliceRaw(start, end int) []*big.Int {
var result FieldVector
for i := start; i < end; i++ {
result.vector = append(result.vector, new(big.Int).Set(fv.vector[i]))
}
return result.vector
}
func (fv *FieldVector) Flip() *FieldVector {
var result FieldVector
for i := range fv.vector {
result.vector = append(result.vector, new(big.Int).Set(fv.vector[(len(fv.vector)-i)%len(fv.vector)]))
}
return &result
}
func (fv *FieldVector) Sum() *big.Int {
var accumulator big.Int
for i := range fv.vector {
var accopy big.Int
accopy.Add(&accumulator, fv.vector[i])
accumulator.Mod(&accopy, bn256.Order)
}
return &accumulator
}
func (fv *FieldVector) Add(addendum *FieldVector) *FieldVector {
var result FieldVector
if len(fv.vector) != len(addendum.vector) {
panic("mismatched number of elements")
}
for i := range fv.vector {
var ri big.Int
ri.Mod(new(big.Int).Add(fv.vector[i], addendum.vector[i]), bn256.Order)
result.vector = append(result.vector, &ri)
}
return &result
}
func (gv *FieldVector) AddConstant(c *big.Int) *FieldVector {
var result FieldVector
for i := range gv.vector {
var ri big.Int
ri.Mod(new(big.Int).Add(gv.vector[i], c), bn256.Order)
result.vector = append(result.vector, &ri)
}
return &result
}
func (fv *FieldVector) Hadamard(exponent *FieldVector) *FieldVector {
var result FieldVector
if len(fv.vector) != len(exponent.vector) {
panic("mismatched number of elements")
}
for i := range fv.vector {
result.vector = append(result.vector, new(big.Int).Mod(new(big.Int).Mul(fv.vector[i], exponent.vector[i]), bn256.Order))
}
return &result
}
func (fv *FieldVector) InnerProduct(exponent *FieldVector) *big.Int {
if len(fv.vector) != len(exponent.vector) {
panic("mismatched number of elements")
}
accumulator := new(big.Int)
for i := range fv.vector {
tmp := new(big.Int).Mod(new(big.Int).Mul(fv.vector[i], exponent.vector[i]), bn256.Order)
accumulator.Add(accumulator, tmp)
accumulator.Mod(accumulator, bn256.Order)
}
return accumulator
}
func (fv *FieldVector) Negate() *FieldVector {
var result FieldVector
for i := range fv.vector {
result.vector = append(result.vector, new(big.Int).Mod(new(big.Int).Neg(fv.vector[i]), bn256.Order))
}
return &result
}
func (fv *FieldVector) Times(multiplier *big.Int) *FieldVector {
var result FieldVector
for i := range fv.vector {
res := new(big.Int).Mul(fv.vector[i], multiplier)
res.Mod(res, bn256.Order)
result.vector = append(result.vector, res)
}
return &result
}
func (fv *FieldVector) Invert() *FieldVector {
var result FieldVector
for i := range fv.vector {
result.vector = append(result.vector, new(big.Int).ModInverse(fv.vector[i], bn256.Order))
}
return &result
}
func (fv *FieldVector) Concat(addendum *FieldVector) *FieldVector {
var result FieldVector
for i := range fv.vector {
result.vector = append(result.vector, new(big.Int).Set(fv.vector[i]))
}
for i := range addendum.vector {
result.vector = append(result.vector, new(big.Int).Set(addendum.vector[i]))
}
return &result
}
func (fv *FieldVector) Extract(parity bool) *FieldVector {
var result FieldVector
remainder := 0
if parity {
remainder = 1
}
for i := range fv.vector {
if i%2 == remainder {
result.vector = append(result.vector, new(big.Int).Set(fv.vector[i]))
}
}
return &result
}