OSDN Git Service

Hulk did something
[bytom/vapor.git] / mining / tensority / go_algorithm / matrix.go
1 package go_algorithm
2
3 import (
4         "reflect"
5         "runtime"
6         "sync"
7         "unsafe"
8
9         "gonum.org/v1/gonum/mat"
10
11         "github.com/vapor/crypto/sha3pool"
12         "github.com/vapor/protocol/bc"
13 )
14
15 const (
16         matSize = 1 << 8 // Size of matrix
17         matNum  = 1 << 8 // Number of matrix
18 )
19
20 func mulMatrix(headerhash []byte, cache []uint32) []uint8 {
21         ui32data := make([]uint32, matNum*matSize*matSize/4)
22         for i := 0; i < 128; i++ {
23                 start := i * 1024 * 32
24                 for j := 0; j < 512; j++ {
25                         copy(ui32data[start+j*32:start+j*32+32], cache[start+j*64:start+j*64+32])
26                         copy(ui32data[start+512*32+j*32:start+512*32+j*32+32], cache[start+j*64+32:start+j*64+64])
27                 }
28         }
29
30         // Convert our destination slice to a int8 buffer
31         header := *(*reflect.SliceHeader)(unsafe.Pointer(&ui32data))
32         header.Len *= 4
33         header.Cap *= 4
34         i8data := *(*[]int8)(unsafe.Pointer(&header))
35
36         f64data := make([]float64, matNum*matSize*matSize)
37         for i := 0; i < matNum*matSize*matSize; i++ {
38                 f64data[i] = float64(i8data[i])
39         }
40
41         dataIdentity := make([]float64, matSize*matSize)
42         for i := 0; i < 256; i++ {
43                 dataIdentity[i*257] = float64(1)
44         }
45
46         var tmp [matSize][matSize]float64
47         var maArr [4][matSize][matSize]float64
48
49         runtime.GOMAXPROCS(4)
50         var wg sync.WaitGroup
51         wg.Add(4)
52
53         for k := 0; k < 4; k++ {
54                 go func(i int) {
55                         defer wg.Done()
56
57                         ma := mat.NewDense(matSize, matSize, dataIdentity)
58                         mc := mat.NewDense(matSize, matSize, make([]float64, matSize*matSize))
59
60                         var sequence [32]byte
61                         sha3pool.Sum256(sequence[:], headerhash[i*8:(i+1)*8])
62
63                         for j := 0; j < 2; j++ {
64                                 for k := 0; k < 32; k++ {
65                                         index := int(sequence[k])
66                                         mb := mat.NewDense(matSize, matSize, f64data[index*matSize*matSize:(index+1)*matSize*matSize])
67                                         mc.Mul(ma, mb.T())
68
69                                         for row := 0; row < matSize; row++ {
70                                                 for col := 0; col < matSize; col++ {
71                                                         i32v := int32(mc.At(row, col))
72                                                         i8v := int8((i32v & 0xff) +
73                                                                 ((i32v >> 8) & 0xff))
74                                                         mc.Set(row, col, float64(i8v))
75                                                 }
76                                         }
77                                         ma = mc
78                                 }
79                         }
80
81                         for row := 0; row < matSize; row++ {
82                                 for col := 0; col < matSize; col++ {
83                                         maArr[i][row][col] = ma.At(row, col)
84                                 }
85                         }
86                 }(k)
87         }
88         wg.Wait()
89
90         for i := 0; i < 4; i++ {
91                 for row := 0; row < matSize; row++ {
92                         for col := 0; col < matSize; col++ {
93                                 i32vtmp := int32(tmp[row][col])
94                                 i32vma := int32(maArr[i][row][col])
95                                 i8v := int8(int32(i32vtmp+i32vma) & 0xff)
96                                 tmp[row][col] = float64(i8v)
97                         }
98                 }
99         }
100
101         result := make([]uint8, 0)
102         for i := 0; i < matSize; i++ {
103                 for j := 0; j < matSize; j++ {
104                         result = append(result, uint8(tmp[i][j]))
105                 }
106         }
107         return result
108 }
109
110 // hashMatrix hash result of mulMatrix
111 func hashMatrix(result []uint8) *bc.Hash {
112         var mat8 [matSize][matSize]uint8
113         for i := 0; i < matSize; i++ {
114                 for j := 0; j < matSize; j++ {
115                         mat8[i][j] = result[i*matSize+j]
116                 }
117         }
118
119         var mat32 [matSize][matSize / 4]uint32
120
121         for i := 0; i < matSize; i++ {
122                 for j := 0; j < matSize/4; j++ {
123                         mat32[i][j] = ((uint32(mat8[i][j+192])) << 24) |
124                                 ((uint32(mat8[i][j+128])) << 16) |
125                                 ((uint32(mat8[i][j+64])) << 8) |
126                                 ((uint32(mat8[i][j])) << 0)
127                 }
128         }
129
130         for k := matSize; k > 1; k = k / 2 {
131                 for j := 0; j < k/2; j++ {
132                         for i := 0; i < matSize/4; i++ {
133                                 mat32[j][i] = fnv(mat32[j][i], mat32[j+k/2][i])
134                         }
135                 }
136         }
137
138         ui32data := make([]uint32, 0)
139         for i := 0; i < matSize/4; i++ {
140                 ui32data = append(ui32data, mat32[0][i])
141         }
142
143         // Convert our destination slice to a byte buffer
144         header := *(*reflect.SliceHeader)(unsafe.Pointer(&ui32data))
145         header.Len *= 4
146         header.Cap *= 4
147         dataBytes := *(*[]byte)(unsafe.Pointer(&header))
148
149         var h [32]byte
150         sha3pool.Sum256(h[:], dataBytes)
151         bcHash := bc.NewHash(h)
152         return &bcHash
153 }
154
155 func fnv(a, b uint32) uint32 {
156         return a*0x01000193 ^ b
157 }