-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patharray.go
More file actions
125 lines (112 loc) · 4.26 KB
/
Copy patharray.go
File metadata and controls
125 lines (112 loc) · 4.26 KB
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
117
118
119
120
121
122
123
124
125
package npy
import "fmt"
// Array is the dynamically-typed result of reading a .npy file. The element
// type is discovered from the file and stored in Data as the matching Go
// slice type (for example []float64 or []int32).
type Array struct {
Shape []int // dimensions, as in NumPy
Fortran bool // true if the data is in Fortran (column-major) order
Dtype DType // the on-disk element type
Data any // the typed element slice, e.g. []float64
closer func() error
}
// Len returns the total number of elements (the product of Shape).
func (a *Array) Len() int { return numElements(a.Shape) }
// Close releases resources associated with the array. It is only meaningful
// for memory-mapped arrays; for in-memory arrays it is a no-op. After Close
// the Data slice of a memory-mapped array must not be used.
func (a *Array) Close() error {
if a.closer != nil {
err := a.closer()
a.closer = nil
return err
}
return nil
}
// Values returns the array's data as a typed slice. It returns an error if T
// does not match the array's on-disk dtype.
func Values[T Element](a *Array) ([]T, error) {
if s, ok := a.Data.([]T); ok {
return s, nil
}
var z T
return nil, fmt.Errorf("npy: array dtype is %s (%s), not %T", a.Dtype, a.Dtype.GoType(), z)
}
// The following convenience accessors return the data slice when the dtype
// matches and an error otherwise.
func (a *Array) Float64() ([]float64, error) { return Values[float64](a) }
func (a *Array) Float32() ([]float32, error) { return Values[float32](a) }
func (a *Array) Int64() ([]int64, error) { return Values[int64](a) }
func (a *Array) Int32() ([]int32, error) { return Values[int32](a) }
func (a *Array) Int16() ([]int16, error) { return Values[int16](a) }
func (a *Array) Int8() ([]int8, error) { return Values[int8](a) }
func (a *Array) Uint64() ([]uint64, error) { return Values[uint64](a) }
func (a *Array) Uint32() ([]uint32, error) { return Values[uint32](a) }
func (a *Array) Uint16() ([]uint16, error) { return Values[uint16](a) }
func (a *Array) Uint8() ([]uint8, error) { return Values[uint8](a) }
func (a *Array) Bool() ([]bool, error) { return Values[bool](a) }
func (a *Array) Complex64() ([]complex64, error) { return Values[complex64](a) }
func (a *Array) Complex128() ([]complex128, error) { return Values[complex128](a) }
// AsFloat64 returns a copy of the data converted to float64, regardless of the
// underlying numeric dtype. Boolean and complex arrays are not supported.
func (a *Array) AsFloat64() ([]float64, error) {
switch s := a.Data.(type) {
case []float64:
out := make([]float64, len(s))
copy(out, s)
return out, nil
case []float32:
return convertTo[float64](s), nil
case []int8:
return convertTo[float64](s), nil
case []int16:
return convertTo[float64](s), nil
case []int32:
return convertTo[float64](s), nil
case []int64:
return convertTo[float64](s), nil
case []uint8:
return convertTo[float64](s), nil
case []uint16:
return convertTo[float64](s), nil
case []uint32:
return convertTo[float64](s), nil
case []uint64:
return convertTo[float64](s), nil
default:
return nil, fmt.Errorf("npy: cannot convert dtype %s to float64", a.Dtype)
}
}
// realNumber is the set of element types convertible to a Go float64.
type realNumber interface {
~int8 | ~int16 | ~int32 | ~int64 |
~uint8 | ~uint16 | ~uint32 | ~uint64 |
~float32 | ~float64
}
func convertTo[D, S realNumber](in []S) []D {
out := make([]D, len(in))
for i, v := range in {
out[i] = D(v)
}
return out
}
// NDArray is the statically-typed result of reading a .npy file with a known
// element type. It is the fastest API: there are no runtime type assertions.
type NDArray[T Element] struct {
Values []T // the element data
Shape []int // dimensions
Fortran bool // true if the data is in Fortran (column-major) order
closer func() error
}
// Len returns the total number of elements.
func (n *NDArray[T]) Len() int { return len(n.Values) }
// Close releases resources for memory-mapped arrays; otherwise a no-op. After
// Close the Values slice of a memory-mapped array must not be used.
func (n *NDArray[T]) Close() error {
if n.closer != nil {
err := n.closer()
n.closer = nil
return err
}
return nil
}