2727template km (point: Tensor [float ], index: int , delta: float ): int =
2828 int (ceil (point[0 , index] / delta))
2929
30- iterator neighbours * [T](grid: RbfGrid [T], k: int ): int =
30+ iterator neighbours * [T](grid: RbfGrid [T], k: int , searchLevels: int = 1 ): int =
3131 # TODO : Create product iterator that doesn't need to allocate 3^gridDim seqs
32- for dir in product (@ [@ [- 1 , 0 , 1 ]].cycle (grid.gridDim)):
32+ let directions = @ [toSeq (- searchLevels .. searchLevels)].cycle (grid.gridDim)
33+ for dir in product (directions):
3334 block loopBody:
3435 var kNeigh = k
3536 for i, x in dir:
3637 let step = grid.gridSize ^ (grid.gridDim - i - 1 )
37- if (k div step) mod grid.gridSize == 0 and x == - 1 :
38+ for level in 1 .. searchLevels:
39+ if (k div step) mod grid.gridSize == level - 1 and x <= - level:
40+ break loopBody
41+ elif (k div step) mod grid.gridSize == grid.gridSize - level and x >= level:
42+ break loopBody
43+ #[ if ((k div step) mod grid.gridSize == 0 and x == -1) or ((k div step) mod grid.gridSize == 1 and x == -2):
3844 break loopBody
3945 elif (k div step) mod grid.gridSize == grid.gridSize - 1 and x == 1:
4046 break loopBody
41- else :
42- kNeigh += x * step
47+ else: ]#
48+ kNeigh += x * step
4349 if kNeigh >= 0 and kNeigh < grid.gridSize ^ grid.gridDim:
4450 yield kNeigh
4551
@@ -67,11 +73,23 @@ template dist2(p1, p2: Tensor[float]): float =
6773proc findAllWithin * [T](grid: RbfGrid [T], x: Tensor [float ], rho: float ): seq [int ] =
6874 assert x.shape.len == 2 and x.shape[0 ] == 1
6975 let index = grid.findIndex (x)
70- for k in grid.neighbours (index):
76+ let searchLevels = (rho / grid.gridDelta).ceil.int
77+ for k in grid.neighbours (index, searchLevels):
7178 for i in grid.indices[k]:
7279 if dist2 (x, grid.points[i, _]) <= rho* rho:
7380 result .add i
7481
82+ proc findAllBetween * [T](grid: RbfGrid [T], x: Tensor [float ], rho1, rho2: float ): seq [int ] =
83+ assert x.shape.len == 2 and x.shape[0 ] == 1
84+ assert rho2 > rho1
85+ let index = grid.findIndex (x)
86+ let searchLevels = (rho2 / grid.gridDelta).ceil.int
87+ for k in grid.neighbours (index, searchLevels):
88+ for i in grid.indices[k]:
89+ let d = dist2 (x, grid.points[i, _])
90+ if rho1* rho1 <= d and d <= rho2* rho2:
91+ result .add i
92+
7593proc newRbfGrid * [T](points: Tensor [float ], values: Tensor [T], gridSize: int = 0 ): RbfGrid [T] =
7694 let nPoints = points.shape[0 ]
7795 let nDims = points.shape[1 ]
@@ -108,7 +126,10 @@ template compactRbfFuncScalar*(r: float, epsilon: float): float =
108126
109127proc compactRbfFunc * (r: Tensor [float ], epsilon: float ): Tensor [float ] =
110128 result = map_inline (r):
111- (1 - x/ epsilon) ^ 4 * (4 * x/ epsilon + 1 ) * float (x < epsilon)
129+ let xeps = x / epsilon
130+ let temp = (1 - xeps)
131+ let temp2 = temp * temp
132+ temp2* temp2 * (4 * xeps + 1 ) * float (xeps < 1 )
112133
113134proc newRbf * [T](points: Tensor [float ], values: Tensor [T], rbfFunc: RbfFunc = compactRbfFunc, epsilon: float = 1 ): RbfType [T] =
114135 assert points.shape[0 ] == values.shape[0 ]
@@ -150,7 +171,8 @@ proc newRbfPu*[T](points: Tensor[float], values: Tensor[T], gridSize: int = 0, r
150171
151172proc eval * [T](rbf: RbfPUType [T], x: Tensor [float ]): Tensor [T] =
152173 assert x.shape.len == 2
153- assert (not ((x <= . rbf.limits.upper) and (x >= . rbf.limits.lower))).astype (int ).sum () == 0 , " Some of your points are outside the allowed limits"
174+ assert (not ((x <= . rbf.limits.upper) and (x >= . rbf.limits.lower))).astype (int ).sum () == 0 , " Some of your points are outside the allowed limits"
175+
154176 let nPoints = x.shape[0 ]
155177 let x = x.scalePoint (rbf.limits)
156178 result = newTensor [T](nPoints, rbf.nValues)
@@ -170,6 +192,32 @@ proc eval*[T](rbf: RbfPUType[T], x: Tensor[float]): Tensor[T] =
170192 else :
171193 result [row, _] = T (Nan ) # allow to pass default value to newRbfPU?
172194
195+ proc evalAlt * [T](rbf: RbfPUType [T], x: Tensor [float ]): Tensor [T] =
196+ assert x.shape.len == 2
197+ assert (not ((x <= . rbf.limits.upper) and (x >= . rbf.limits.lower))).astype (int ).sum () == 0 , " Some of your points are outside the allowed limits"
198+
199+ let nPoints = x.shape[0 ]
200+ let x = x.scalePoint (rbf.limits)
201+ result = newTensor [T](nPoints, rbf.nValues)
202+ var c = newTensor [float ](nPoints, 1 )
203+ var isSet = newTensor [bool ](nPoints, 1 )
204+ let nPatches = rbf.grid.points.shape[0 ]
205+ let pointGrid = newRbfGrid (x, x, rbf.grid.gridSize)
206+ for row in 0 ..< nPatches:
207+ let center = rbf.grid.points[row, _]
208+ let indices = pointGrid.findAllWithin (center, rbf.grid.gridDelta)
209+ if indices.len > 0 :
210+ let vals = rbf.grid.values[row, 0 ].eval (x[indices, _])
211+ for i, index in indices:
212+ let r = sqrt (dist2 (center, x[index, _]))
213+ let ci = compactRbfFuncScalar (r, rbf.grid.gridDelta)
214+ result [index, _] = result [index, _] + ci * vals[i, _]
215+ c[index] += ci
216+ isSet[index, 0 ] = true
217+
218+ result /.= c
219+ result [not isSet, _] = T (NaN )
220+
173221when isMainModule :
174222 let x1 = @ [@ [0.01 , 0.01 , 0.01 ], @ [1.0 , 1.0 , 0.0 ], @ [1.0 , 2.0 , 4.0 ]].toTensor
175223 let x2 = @ [@ [0.0 , 0.0 , 1.0 ], @ [1.0 , 1.0 , 2.0 ], @ [1.0 , 2.0 , 3.0 ]].toTensor
@@ -179,18 +227,32 @@ when isMainModule:
179227
180228 import benchy
181229
182- # let pos = randomTensor(5000, 3, 1.0)
183- # let vals = randomTensor(5000, 1, 1.0)
184- # timeIt "Rbf":
185- # keep newRbf(pos, vals)
230+ var pos = randomTensor (100000 , 3 , 1.0 )
231+ pos[0 , _] = [[1.0 , 1.0 , 1.0 ]]
232+ pos[1 , _] = [[0.0 , 0.0 , 0.0 ]]
233+ let vals = randomTensor (100000 , 1 , 1.0 )
234+ let evalPos = randomTensor (100000 , 3 , 0.9 )
235+ # let rb = newRbf(pos, vals)
236+ # let rbPU = newRbfPu(pos, vals)
237+ # timeIt "RbfPU eval":
238+ # keep rbPU.eval(evalPos)
239+ # timeIt "Rbf eval":
240+ # keep rb.eval(evalPos)
241+
186242 # let rbfPu = newRbfPu(x1, values, 3)
187243 # echo rbfPu.grid.values[1, 0]
188244 # echo rbfPu.eval(x1[[2, 1, 0], _])
189245
190246 # echo rbfPu.eval(sqrt x1)
191247 echo " ----------------"
192- #[ let xGrid = [[0.1, 0.1], [0.2, 0.3], [0.9, 0.9], [0.4, 0.4]].toTensor
248+ for y in countdown (4 , 0 ):
249+ var row = " "
250+ for x in 0 .. 4 :
251+ row &= $ (x* 5 + y) & " \t "
252+ echo row
253+
254+ let xGrid = [[0.1 , 0.1 ], [0.2 , 0.3 ], [0.9 , 0.9 ], [0.4 , 0.4 ]].toTensor
193255 let valuesGrid = @ [0 , 1 , 9 , 5 ].toTensor.reshape (4 , 1 )
194- let grid = newRbfGrid(xGrid, valuesGrid, 2 )
195- echo grid
196- echo grid.neighbours(3 ).toSeq ]#
256+ let grid = newRbfGrid (xGrid, valuesGrid, 5 )
257+ # echo grid
258+ echo grid.neighbours (7 , 1 ).toSeq
0 commit comments