Implement matrix multiplication with pure Go
Set suitable backend for GF127 arithmetic for Concat(), Sum() etc.
This commit is contained in:
parent
06362477ed
commit
f613ab2c25
3 changed files with 37 additions and 9 deletions
|
@ -160,23 +160,24 @@ func Add(a, b, c *GF127) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mul sets c to a*b.
|
// Mul sets c to a*b.
|
||||||
|
// TODO make it work in-place without allocations
|
||||||
// TODO optimization: no need to perform shift by i every time, cache results
|
// TODO optimization: no need to perform shift by i every time, cache results
|
||||||
func Mul(a, b, c *GF127) {
|
func Mul(a, b, c *GF127) {
|
||||||
c[0] = 0
|
r := new(GF127)
|
||||||
c[1] = 0
|
|
||||||
d := new(GF127)
|
d := new(GF127)
|
||||||
for i := uint(0); i < 64; i++ {
|
for i := uint(0); i < 64; i++ {
|
||||||
if b[0]&(1<<i) != 0 {
|
if b[0]&(1<<i) != 0 {
|
||||||
shl(i, a, d)
|
shl(i, a, d)
|
||||||
Add(c, d, c)
|
Add(r, d, r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := uint(0); i < 63; i++ {
|
for i := uint(0); i < 63; i++ {
|
||||||
if b[1]&(1<<i) != 0 {
|
if b[1]&(1<<i) != 0 {
|
||||||
shl(i+64, a, d)
|
shl(i+64, a, d)
|
||||||
Add(c, d, c)
|
Add(r, d, r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*c = *r
|
||||||
}
|
}
|
||||||
|
|
||||||
// shl performs left shift by consecutive multiplications by 2.
|
// shl performs left shift by consecutive multiplications by 2.
|
||||||
|
|
|
@ -36,7 +36,7 @@ const (
|
||||||
bitAVX2 = 1 << 5
|
bitAVX2 = 1 << 5
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func setFeatures() {
|
||||||
maxID, _, _, _ := cpuid(0, 0)
|
maxID, _, _, _ := cpuid(0, 0)
|
||||||
if maxID < 1 {
|
if maxID < 1 {
|
||||||
return
|
return
|
||||||
|
|
35
tz/sl2.go
35
tz/sl2.go
|
@ -4,6 +4,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"github.com/nspcc-dev/tzhash/gf127"
|
"github.com/nspcc-dev/tzhash/gf127"
|
||||||
|
"github.com/nspcc-dev/tzhash/gogf127"
|
||||||
)
|
)
|
||||||
|
|
||||||
type sl2 [2][2]gf127.GF127
|
type sl2 [2][2]gf127.GF127
|
||||||
|
@ -13,6 +14,18 @@ var id = sl2{
|
||||||
{gf127.GF127{0, 0}, gf127.GF127{1, 0}},
|
{gf127.GF127{0, 0}, gf127.GF127{1, 0}},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var mul func(a, b, c *sl2, x *[4]gf127.GF127)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
setFeatures()
|
||||||
|
|
||||||
|
if hasAVX {
|
||||||
|
mul = mulSL2AVX
|
||||||
|
} else {
|
||||||
|
mul = mulSL2Pure
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *sl2) MarshalBinary() (data []byte, err error) {
|
func (c *sl2) MarshalBinary() (data []byte, err error) {
|
||||||
s := c.ByteArray()
|
s := c.ByteArray()
|
||||||
return s[:], nil
|
return s[:], nil
|
||||||
|
@ -79,8 +92,7 @@ func (c *sl2) mulStrassen(a, b *sl2, x *[8]gf127.GF127) *sl2 {
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *sl2) mul(a, b *sl2, x *[4]gf127.GF127) *sl2 {
|
func mulSL2AVX(a, b, c *sl2, x *[4]gf127.GF127) {
|
||||||
// naive implementation
|
|
||||||
gf127.Mul(&a[0][0], &b[0][0], &x[0])
|
gf127.Mul(&a[0][0], &b[0][0], &x[0])
|
||||||
gf127.Mul(&a[0][0], &b[0][1], &x[1])
|
gf127.Mul(&a[0][0], &b[0][1], &x[1])
|
||||||
gf127.Mul(&a[1][0], &b[0][0], &x[2])
|
gf127.Mul(&a[1][0], &b[0][0], &x[2])
|
||||||
|
@ -94,8 +106,22 @@ func (c *sl2) mul(a, b *sl2, x *[4]gf127.GF127) *sl2 {
|
||||||
gf127.Add(&c[1][0], &x[2], &c[1][0])
|
gf127.Add(&c[1][0], &x[2], &c[1][0])
|
||||||
gf127.Mul(&a[1][1], &b[1][1], &c[1][1])
|
gf127.Mul(&a[1][1], &b[1][1], &c[1][1])
|
||||||
gf127.Add(&c[1][1], &x[3], &c[1][1])
|
gf127.Add(&c[1][1], &x[3], &c[1][1])
|
||||||
|
}
|
||||||
|
|
||||||
return c
|
func mulSL2Pure(a, b, c *sl2, x *[4]gf127.GF127) {
|
||||||
|
gogf127.Mul((*gogf127.GF127)(&a[0][0]), (*gogf127.GF127)(&b[0][0]), (*gogf127.GF127)(&x[0]))
|
||||||
|
gogf127.Mul((*gogf127.GF127)(&a[0][0]), (*gogf127.GF127)(&b[0][1]), (*gogf127.GF127)(&x[1]))
|
||||||
|
gogf127.Mul((*gogf127.GF127)(&a[1][0]), (*gogf127.GF127)(&b[0][0]), (*gogf127.GF127)(&x[2]))
|
||||||
|
gogf127.Mul((*gogf127.GF127)(&a[1][0]), (*gogf127.GF127)(&b[0][1]), (*gogf127.GF127)(&x[3]))
|
||||||
|
|
||||||
|
gogf127.Mul((*gogf127.GF127)(&a[0][1]), (*gogf127.GF127)(&b[1][0]), (*gogf127.GF127)(&c[0][0]))
|
||||||
|
gogf127.Add((*gogf127.GF127)(&c[0][0]), (*gogf127.GF127)(&x[0]), (*gogf127.GF127)(&c[0][0]))
|
||||||
|
gogf127.Mul((*gogf127.GF127)(&a[0][1]), (*gogf127.GF127)(&b[1][1]), (*gogf127.GF127)(&c[0][1]))
|
||||||
|
gogf127.Add((*gogf127.GF127)(&c[0][1]), (*gogf127.GF127)(&x[1]), (*gogf127.GF127)(&c[0][1]))
|
||||||
|
gogf127.Mul((*gogf127.GF127)(&a[1][1]), (*gogf127.GF127)(&b[1][0]), (*gogf127.GF127)(&c[1][0]))
|
||||||
|
gogf127.Add((*gogf127.GF127)(&c[1][0]), (*gogf127.GF127)(&x[2]), (*gogf127.GF127)(&c[1][0]))
|
||||||
|
gogf127.Mul((*gogf127.GF127)(&a[1][1]), (*gogf127.GF127)(&b[1][1]), (*gogf127.GF127)(&c[1][1]))
|
||||||
|
gogf127.Add((*gogf127.GF127)(&c[1][1]), (*gogf127.GF127)(&x[3]), (*gogf127.GF127)(&c[1][1]))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *sl2) MulA() *sl2 {
|
func (c *sl2) MulA() *sl2 {
|
||||||
|
@ -129,7 +155,8 @@ func (c *sl2) MulB() *sl2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *sl2) Mul(a, b *sl2) *sl2 {
|
func (c *sl2) Mul(a, b *sl2) *sl2 {
|
||||||
return c.mul(a, b, new([4]gf127.GF127))
|
mul(a, b, c, new([4]gf127.GF127))
|
||||||
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inv returns inverse of a in GL_2(GF(2^127))
|
// Inv returns inverse of a in GL_2(GF(2^127))
|
||||||
|
|
Loading…
Reference in a new issue