1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
|
package storage // import "gorgonia.org/tensor/internal/storage"
import (
"reflect"
"unsafe"
)
// Header is runtime representation of a slice. It's a cleaner version of reflect.SliceHeader.
// With this, we wouldn't need to keep the uintptr.
// This usually means additional pressure for the GC though, especially when passing around Headers
type Header struct {
Raw []byte
}
// TypedLen returns the length of data as if it was a slice of type t
func (h *Header) TypedLen(t reflect.Type) int {
return len(h.Raw) / int(t.Size())
}
func Copy(t reflect.Type, dst, src *Header) int {
copied := copy(dst.Raw, src.Raw)
return copied / int(t.Size())
}
func CopySliced(t reflect.Type, dst *Header, dstart, dend int, src *Header, sstart, send int) int {
dstBA := dst.Raw
srcBA := src.Raw
size := int(t.Size())
ds := dstart * size
de := dend * size
ss := sstart * size
se := send * size
copied := copy(dstBA[ds:de], srcBA[ss:se])
return copied / size
}
func SwapCopy(a, b *Header) {
for i := range a.Raw {
a.Raw[i], b.Raw[i] = b.Raw[i], a.Raw[i]
}
}
func Fill(t reflect.Type, dst, src *Header) int {
dstBA := dst.Raw
srcBA := src.Raw
size := int(t.Size())
lenSrc := len(srcBA)
dstart := 0
for {
copied := copy(dstBA[dstart:], srcBA)
dstart += copied
if copied < lenSrc {
break
}
}
return dstart / size
}
func CopyIter(t reflect.Type, dst, src *Header, diter, siter Iterator) int {
dstBA := dst.Raw
srcBA := src.Raw
size := int(t.Size())
var idx, jdx, i, j, count int
var err error
for {
if idx, err = diter.Next(); err != nil {
if err = handleNoOp(err); err != nil {
panic(err)
}
break
}
if jdx, err = siter.Next(); err != nil {
if err = handleNoOp(err); err != nil {
panic(err)
}
break
}
i = idx * size
j = jdx * size
copy(dstBA[i:i+size], srcBA[j:j+size])
// dstBA[i : i+size] = srcBA[j : j+size]
count++
}
return count
}
// Element gets the pointer of ith element
func ElementAt(i int, base unsafe.Pointer, typeSize uintptr) unsafe.Pointer {
return unsafe.Pointer(uintptr(base) + uintptr(i)*typeSize)
}
// AsByteSlice takes a slice of anything and returns a casted-as-byte-slice view of it.
// This function panics if input is not a slice.
func AsByteSlice(x interface{}) []byte {
xV := reflect.ValueOf(x)
xT := reflect.TypeOf(x).Elem() // expects a []T
hdr := reflect.SliceHeader{
Data: xV.Pointer(),
Len: xV.Len() * int(xT.Size()),
Cap: xV.Cap() * int(xT.Size()),
}
return *(*[]byte)(unsafe.Pointer(&hdr))
}
func FromMemory(ptr uintptr, memsize uintptr) []byte {
hdr := reflect.SliceHeader{
Data: ptr,
Len: int(memsize),
Cap: int(memsize),
}
return *(*[]byte)(unsafe.Pointer(&hdr))
}
|