-
Notifications
You must be signed in to change notification settings - Fork 35
/
cartesian.py
100 lines (74 loc) · 2.51 KB
/
cartesian.py
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
"""
Filename: cartesian.py
Authors: Pablo Winant
Implements cartesian products and regular cartesian grids.
"""
import numpy
from numba import njit
def cartesian(nodes, order="C"):
"""Cartesian product of a list of arrays
Parameters:
-----------
nodes: (list of 1d-arrays)
order: ('C' or 'F') order in which the product is enumerated
Returns:
--------
out: (2d-array) each line corresponds to one point of the product space
"""
nodes = [numpy.array(e) for e in nodes]
shapes = [e.shape[0] for e in nodes]
n = len(nodes)
l = numpy.prod(shapes)
out = numpy.zeros((l, n))
if order == "C":
repetitions = numpy.cumprod([1] + shapes[:-1])
else:
shapes.reverse()
sh = [1] + shapes[:-1]
repetitions = numpy.cumprod(sh)
repetitions = repetitions.tolist()
repetitions.reverse()
for i in range(n):
_repeat_1d(nodes[i], repetitions[i], out[:, i])
return out
def mlinspace(a, b, nums, order="C"):
"""Constructs a regular cartesian grid
Parameters:
-----------
a: (1d-array) lower bounds in each dimension
b: (1d-array) upper bounds in each dimension
nums: (1d-array) number of nodes along each dimension
order: ('C' or 'F') order in which the product is enumerated
Returns:
--------
out: (2d-array) each line corresponds to one point of the product space
"""
a = numpy.array(a, dtype="float64")
b = numpy.array(b, dtype="float64")
nums = numpy.array(nums, dtype="int64")
nodes = [numpy.linspace(a[i], b[i], nums[i]) for i in range(len(nums))]
return cartesian(nodes, order=order)
@njit(cache=True)
def _repeat_1d(x, K, out):
"""Repeats each element of a vector many times and repeats the whole result many times
Parameters
----------
x: (1d array) vector to be repeated
K: (int) number of times each element of x is repeated (inner iterations)
out: (1d array) placeholder for the result
Returns
-------
None
"""
N = x.shape[0]
L = out.shape[0] // (K * N) # number of outer iterations
# K # number of inner iterations
# the result out should enumerate in C-order the elements
# of a 3-dimensional array T of dimensions (K,N,L)
# such that for all k,n,l, we have T[k,n,l] == x[n]
for n in range(N):
val = x[n]
for k in range(K):
for l in range(L):
ind = k * N * L + n * L + l
out[ind] = val