-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfunctions.go
More file actions
148 lines (122 loc) · 4.58 KB
/
Copy pathfunctions.go
File metadata and controls
148 lines (122 loc) · 4.58 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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package array
import "unicode/utf8"
import "strings"
import "strconv"
import "fmt"
var _ = fmt.Printf
/* -------------------------------------------------------------------------------- */
// -- Free functions
/* -------------------------------------------------------------------------------- */
// -- Functions like `Index` and `Indices` should not require the creation of a
// -- matrix. It is wasteful to allocate a matrix simply to access its attributes.
// -- Obviously, if a matrix has already been allocated, its attributes can be used
// -- as inputs to the functions below.
// Index returns the linear index (into an array) that corresponds to the multi-index
// `indices` passed as input. The conversion requires the multi-index conversion
// factors as additional input.
func Index(micf []int, indices ...int) int {
return DotProdInt(indices, micf)
}
/* -------------------------------------------------------------------------------- */
// Indices returns the multi-index (into an array) that corresponds to the linear
// index `index` passed as input. The conversion requires the dimensions of the
// array as additional input.
func Indices(dims []int, index int) []int {
// dbgprfx := "[func Indices]>>"
// multi-index result
lenDims := len(dims)
mindex := make([]int, lenDims, lenDims)
num := index
den := CummProdInt(dims[1:])
// fmt.Printf("---- %s num = %v\n", dbgprfx, num)
// fmt.Printf("---- %s den = %v\n", dbgprfx, den)
// fmt.Printf("-- %s dims = %v\n", dbgprfx, dims)
// fmt.Printf("---- %s index = %v\n", dbgprfx, index)
var k, q, r int
for k = 1; k < lenDims; k++ {
q = num / den
r = num % den
// fmt.Printf("---- %s q = %v\n", dbgprfx, q)
// fmt.Printf("---- %s r = %v\n", dbgprfx, r)
// -- TODO: Eventually remove this verification step.
if correctDivision := (q*den+r == num); !correctDivision {
panic("** The conversion from a single index to a multi-index is incorrect.\n")
}
mindex[k-1] = q
num = r
den = CummProdInt(dims[(k + 1):])
}
mindex[k-1] = r
// fmt.Printf("---- %s mindex = %v\n", dbgprfx, mindex)
return mindex
}
/* -------------------------------------------------------------------------------- */
// NumelsFromDims returns the total numbers of elements contained in an `Array` whose dimensions are described by `dims`.
func NumelsFromDims(dims []int) int {
var numels int = 1
for k := range dims {
numels *= dims[k]
}
return numels
}
/* -------------------------------------------------------------------------------- */
// MultiIndexConversionFactors returns a slice `micf` of integers such that the
// inner product <micf,(i_1, i_2,..., i_p)>, where (i_1, i_2,..., i_p) is a
// multi-index with p == len(A.dims), satisfies
// A[<micf,(i_1, i_2,..., i_p)>] == A[i_1, i_2,..., i_p].
// In other words, the result is used to convert multi-indices to linear indices
// for arrays.
func MultiIndexConversionFactors(dims []int, ndims int) (micf []int) {
for k := range dims {
if k == ndims-1 {
// -- The last conversion factor (the one corresponding to the dimension that changes the fastest) is 1.
micf = append(micf, 1)
} else {
// -- Otherwise, the k-th conversion factor is the cummulative product, starting at k+1, of A.dims.
micf = append(micf, CummProdInt(dims, k+1))
}
}
return
}
/* -------------------------------------------------------------------------------- */
// Indices2Str converts a slice of type []int to a customised string representation.
// Example input arguments:
// indices: []int{1, 2, 3}
// bracketType: "()" or "[]"
// separator: ","
func Indices2Str(indices []int, bracketType string, separator string) (result string) {
var bracketRune rune
// -- The opening bracket
if len(bracketType) > 0 {
bracketRune, _ := utf8.DecodeRuneInString(bracketType)
result = strings.TrimSpace(string(bracketRune))
}
for k := range indices {
result += strconv.Itoa(indices[k])
if k < len(indices)-1 {
result += separator
}
}
// fmt.Printf("-- [Indices2Str] result = %#v\n", result)
// -- Add the closing bracket.
if len(bracketType) > 1 {
bracketRune, _ = utf8.DecodeRuneInString(bracketType[1:])
result += strings.TrimSpace(string(bracketRune))
}
return result
}
/* -------------------------------------------------------------------------------- */
func lastRunes(s string, n int) (result string) {
N := len(s)
// -- If the string is empty or more runes than bytes are requested, return the string itself.
// -- Always holds: #runes <= #bytes
if (N == 0) || (n > N) {
return s
}
for i := 0; i < n && N > 0; i++ {
_, size := utf8.DecodeLastRuneInString(s[:N])
N -= size
}
result = s[N:]
return
}