File: header.go

package info (click to toggle)
golang-github-gorgonia-tensor 0.9.24-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 3,696 kB
  • sloc: sh: 18; asm: 18; makefile: 8
file content (116 lines) | stat: -rw-r--r-- 2,709 bytes parent folder | download
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))
}