carray-jit 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +917 -3
  3. data/README.md +14 -12
  4. data/carray-jit.gemspec +1 -3
  5. data/docs/00_Introduction.md +5 -3
  6. data/docs/01_GettingStarted.md +1 -1
  7. data/docs/02_KernelShapes.md +94 -15
  8. data/docs/03_SupportedFeatures.md +665 -32
  9. data/docs/04_Compiling.md +34 -7
  10. data/docs/05_DesignNotes.md +3 -3
  11. data/docs/06_Cheatsheet.md +200 -7
  12. data/docs/07_StepByStep.ja.md +533 -0
  13. data/docs/07_StepByStep.md +534 -0
  14. data/docs/08_LanguageReference.md +427 -0
  15. data/examples/README.md +12 -0
  16. data/examples/applications/alarm.rb +121 -0
  17. data/examples/applications/collatz.rb +105 -0
  18. data/examples/applications/cubic_spline.rb +331 -0
  19. data/examples/applications/dithering.rb +144 -0
  20. data/examples/applications/group_stats.rb +115 -0
  21. data/examples/applications/lookup.rb +126 -0
  22. data/examples/applications/median_filter.rb +153 -0
  23. data/examples/applications/parcel_ascent.rb +220 -0
  24. data/examples/applications/point_in_polygon.rb +111 -0
  25. data/examples/applications/random_walk.rb +98 -0
  26. data/examples/applications/van_der_pol.rb +186 -0
  27. data/examples/applications/wet_bulb.rb +140 -0
  28. data/examples/features/10_complex.rb +14 -4
  29. data/examples/features/15_loops.rb +7 -1
  30. data/lib/carray/jit/access.rb +14 -0
  31. data/lib/carray/jit/analyzer.rb +2218 -140
  32. data/lib/carray/jit/block_reader.rb +37 -6
  33. data/lib/carray/jit/c_function.rb +961 -86
  34. data/lib/carray/jit/c_generator.rb +1970 -191
  35. data/lib/carray/jit/call.rb +68 -0
  36. data/lib/carray/jit/compiler.rb +102 -14
  37. data/lib/carray/jit/expression.rb +271 -33
  38. data/lib/carray/jit/kernel.rb +382 -32
  39. data/lib/carray/jit/node.rb +374 -9
  40. data/lib/carray/jit/sorting_networks.rb +182 -0
  41. data/lib/carray/jit/type_assignment.rb +424 -35
  42. data/lib/carray/jit/version.rb +1 -1
  43. data/lib/carray/jit.rb +547 -77
  44. metadata +23 -8
  45. data/ext/carray_jit_access/carray_jit_access.c +0 -460
  46. data/ext/carray_jit_access/extconf.rb +0 -8
data/CHANGELOG.md CHANGED
@@ -37,6 +37,922 @@ version you have and a newer one.
37
37
  a release needs is said in the gemspec, and an entry says so only
38
38
  when the answer changes. -->
39
39
 
40
+ ## 0.1.4
41
+
42
+ - New: a lazy `then_else` (a lazy condition or branch) is compiled with
43
+ the expression around it, masked cells included. With 0.1.3, a masked
44
+ one made this gem raise, and CArray stopped asking it for the rest of
45
+ the process.
46
+
47
+ - New: `CArray.fuse` expressions holding comparisons or `shift` -- a
48
+ stencil, or a rule like the Game of Life's -- are compiled whole.
49
+
50
+ - New: `stand_in:` on `CArray::JIT.watching` and `CFunction#watching` is the
51
+ number a failed body answers its C caller with, for a caller that reads
52
+ the return value as a status rather than as a value -- GSL's callbacks
53
+ return `int`, where 0 is `GSL_SUCCESS`, so a failed body handed the
54
+ default is read as a step that went well. It is cast to whatever the body
55
+ returns, reaches the call that failed and every call turned away after it,
56
+ and is put back when the window closes. The default is 0, which is what a
57
+ failed call has always answered.
58
+
59
+ - New: `CArray::JIT.watching(*functions, on_error: [hook, data]) { ... }`
60
+ opens one window over several compiled bodies -- an objective and its
61
+ gradient, a function and its jacobian. Every flag goes down before the
62
+ block and every one is read after it, and the failure raised is the first
63
+ in the argument list. `on_error:` sets that pair on each of them for the
64
+ window's length and puts back whatever hook was there before.
65
+
66
+ - New: `CFunction#on_error(hook, data)` names a C function,
67
+ `void (*)(void *)`, that a compiled body calls with `data` when it fails,
68
+ once, from the call that failed -- so a library holding the address can
69
+ be told to stop, as `nlopt_force_stop` tells NLopt. `#call` from Ruby
70
+ does not call it, and `on_error(nil)` takes it away. A body that cannot
71
+ fail accepts one and never calls it.
72
+
73
+ - New: a `jit_function` body may ask whether a pointer parameter was handed
74
+ an address -- `if grad`, `grad.nil?`, `grad == nil`, `grad != nil` -- and
75
+ `f.call` passes `nil` there as `NULL`. This is what a callback needs where
76
+ the caller leaves a pointer out per call, as NLopt does with the gradient
77
+ under a derivative-free method. A bare pointer name outside a condition is
78
+ still refused, and a `void *` may be asked but not reached through.
79
+
80
+ - Change: needs CArray 3.0.3 or later in the 3.0 series. Lazy `then_else`,
81
+ integer powers, and comparisons and `shift` in `CArray.fuse` are compiled
82
+ from that version; install it alongside this release.
83
+
84
+ - Change: in a block, an integer literal above `2**63 - 1` is refused where
85
+ it would be computed as an int64 (it wrapped to a negative number).
86
+ Meeting a uint64 or a Float, or stored into a uint64 or float array, it
87
+ keeps its value as before.
88
+
89
+ - Change: a negative Integer meeting a uint64 in a block is refused, as
90
+ CArray refuses the same operand: a literal when the block is compiled, a
91
+ captured value with `RangeError` when it is called. `w[i] > -1` used to
92
+ be false for every cell.
93
+
94
+ - Change: in `jit_for`, an inner loop whose range is read from a local or
95
+ a cell (`(0...bound[i]).each`) runs, where it was refused. A subscript
96
+ that loop's index walks is checked at each access, as `a[b[i]]` is, and
97
+ raises `IndexError` past the end; a range written in literals and
98
+ captured integers is still checked before the kernel runs.
99
+
100
+ - Change: in a block, `round`, `ceil`, `truncate` and `to_i` stored into
101
+ a float cell give `0.0` for a value that rounds to zero, never `-0.0`,
102
+ as Ruby's Integer has no sign of zero.
103
+
104
+ - Change: in a block, a zero float remainder keeps the dividend's sign, as
105
+ Ruby's `Float#%` does: `-4.0 % 2.0` is `-0.0`. CArray's own `%` still
106
+ answers `0.0`.
107
+
108
+ - Change: in a block, a shift means what it means to `Integer#<<` and
109
+ `#>>`: a negative count shifts the other way, and a count of 64 or more
110
+ shifts every bit out. It was C's shift, with no defined answer there.
111
+
112
+ - Change: a body lent out answers its C caller the same way whichever way it
113
+ failed. A `raise` answered 0, while a division that had no divisor ran on
114
+ to the end and answered whatever the body made of the zero the helper
115
+ handed back -- `100 + a / 0` answered 100. Both now answer the window's
116
+ `stand_in:`, which is 0 where none was given. A caller reading the flag
117
+ rather than the return value sees no change.
118
+
119
+ - Fix: a plan holding a mask rule this gem does not know is declined and
120
+ walked by CArray, rather than raising.
121
+
122
+ - Fix: a lazy expression or `CArray.fuse` over an operand that is not
123
+ laid out end to end -- a slice, a stepped slice, a transpose, a gather,
124
+ or an operand broadcast against the others (`col.lazy * y.lazy` with
125
+ `col` of shape (n, 1)) -- is compiled; it was declined and walked by
126
+ CArray. Storing one into such a view is compiled too. A destination
127
+ that writes one cell more than once is still left to CArray.
128
+
129
+ - Fix: an integer power in a lazy expression -- `x.lazy ** 2` over a
130
+ Float array, or any power of an integer array -- is compiled; it was
131
+ declined and left to CArray every time, since the C it calls was not in
132
+ the generated source.
133
+
134
+ - Fix: in a block, a negative real raised to a power that is not an
135
+ integer, stored into a complex cell or joined with a Complex
136
+ (`z[i] = x ** y`, `x ** y + 1i`), is now the Complex Ruby gives,
137
+ to the last bit, where it was `NaN`. Read as a real -- a float cell,
138
+ or a local assigned the power -- it stays `NaN`.
139
+
140
+ - Fix: a block loop whose range ends at the top of int64 runs as Ruby's
141
+ does: `(MAX-2..MAX).each` ran no passes.
142
+
143
+ - Fix: a literal past a double, `1e400`, is an infinity as in Ruby, and an
144
+ Integer literal past uint64 is refused; both were a C compiler error.
145
+
146
+ - Fix: signed overflow wraps consistently within a kernel. Compiled
147
+ without `-fwrapv`, a kernel could contradict itself: `y = -a; y > 0 ?
148
+ y : 0` stored a negative value for `a = INT64_MIN`. `INT64_MIN / -1` in
149
+ a block is `INT64_MIN` rather than a trap on x86.
150
+
151
+ - Fix: the `carray-jit` command runs when the carray gem is not installed.
152
+ `status`, `list`, `show` and `clear` used to stop with
153
+ `Gem::MissingSpecError`; they now work on the cache directory named
154
+ `carraynone`. Nothing changes where carray is installed as a gem.
155
+
156
+ - Fix: a compiled `jit_function` exports its own declared symbol and nothing
157
+ under a fixed name, so several of them can be linked into one library.
158
+ Two bodies that could fail -- either raising, or dividing an integer by
159
+ something that might be zero -- used to define `carray_jit_error` and its
160
+ three neighbours twice and the link failed with duplicate symbols, which
161
+ is what carray-jit-aot hit when a library held two such functions. Those
162
+ four are static now, and the one function that answers where they stand
163
+ carries the body's digest.
164
+
165
+ - Fix: the flag a lent body reports through, and the hook `CFunction#on_error`
166
+ sets, belong to the thread rather than to the compiled object, so two
167
+ threads lending one body no longer read each other's failures -- which
168
+ two separately written blocks with the same text do without meaning to.
169
+ `#watching`, `#on_error`, `#clear_error` and `#report_error` are unchanged;
170
+ what moves is where a hook is set, which is now the thread that will lend
171
+ the address. A library that calls the body from threads of its own is
172
+ outside the window.
173
+
174
+ - Fix: a `jit_function` body that calls a function borrowed with
175
+ `jit_extern` from a library other than libm now links on macOS, where it
176
+ failed with "Undefined symbols". Nothing changes elsewhere: Linux linked
177
+ it already.
178
+
179
+ - Fix: a prototype given to `jit_function` or `jit_extern` reads C's integer
180
+ types in any word order and without `int`, as C does -- `unsigned n`,
181
+ `long unsigned int`, `short unsigned` -- so a header's declaration can be
182
+ copied as it stands. `int unsigned`, which was taken as a signed `int`,
183
+ is now unsigned. A combination C does not have, such as `short long`, is
184
+ refused.
185
+
186
+ ## 0.1.3
187
+
188
+ - New: `CArray::JIT.call_provider` is asked at a `jit_call` site before
189
+ anything is compiled, and answering `nil` means "not mine, compile it". It
190
+ is handed the prototype, the block -- whose binding says which method and
191
+ which module the site is in -- and the names the declaration gave, and
192
+ answers anything that responds to `call`. The one client is carray-aot,
193
+ which builds these same sites into a shared object ahead of the program so
194
+ that a machine running that gem reaches no compiler; it is the position
195
+ `jit_extern` puts a function from a library in, said about a call rather
196
+ than about a name.
197
+
198
+ - New: `CArray.jit_call(prototype) { ... }` compiles the block as a C
199
+ function and calls it where it stands, with the locals around it. The
200
+ declaration's parameter names are the join and do the work twice: they are
201
+ the body's parameters, so the block declares none, and they name the locals
202
+ the call reads -- `CArray.jit_call("void (*)(double *out, const double
203
+ *values, size_t n, size_t window)")` inside a method holding `out`,
204
+ `values`, `n` and `window`. In C a parameter's name in a prototype is
205
+ decoration; here it is the whole binding, and a declared name with no local
206
+ behind it is refused at the call rather than read as nil inside it. What it
207
+ saves over `jit_function` and a `call` is the argument list, which restates
208
+ the declaration in an order nothing checks; what it costs is reading those
209
+ locals through the block's binding, about 0.3 microseconds against a call
210
+ that costs several. Compiled once per call site, and `clear_registry`
211
+ reaches those as it reaches the rest.
212
+
213
+ - New: `CArray::JIT::CFunction#c_source_as(symbol)` hands the compiled C over
214
+ under a symbol the caller picked, for a caller writing it into a file of
215
+ its own rather than letting this compile it -- the symbol this compiler
216
+ writes carries a digest of the body, which is right for an object in a
217
+ cache and wrong for one committed to a repository. A name C cannot spell
218
+ and a name in this compiler's own `carray_jit_` namespace are refused; a
219
+ name the C library already has is the caller's to avoid, since the prefix
220
+ that closes that hazard is what is being replaced. A function bound with
221
+ `jit_extern` has no C of its own and says so.
222
+
223
+ - New: a parallel assignment is in the subset -- `a, b = b, a`, and the
224
+ `a, b = b, a + b` a recurrence advances by. Every value on the right is
225
+ settled before anything on the left is written, as in Ruby, so the
226
+ temporary that spelling saves no longer has to be written by hand. A cell
227
+ is a target as much as a name is (`a[i], a[j] = a[j], a[i]`), each value
228
+ keeps its own type and carries its mask. The readings that take a single
229
+ value apart are refused by name: `a, b = f(x)`, `a, b = [1, 2]`,
230
+ `a, *rest = ...`, `a, (b, c) = ...`, and a count that does not match.
231
+
232
+ - New: a local array may be larger than a stack frame should hold, and its
233
+ shape may be written over an integer the block captured --
234
+ `CArray.double(n)`, which was refused. Either way the kernel allocates the
235
+ array once at its entry and frees it at its exit, so a constructor written
236
+ inside the cell loop is still one allocation; 4 KiB for one array and
237
+ 16 KiB for one kernel's arrays together now say where an array lives rather
238
+ than whether it is allowed, and nothing is refused for its size. A kernel
239
+ whose arrays all fit in the frame emits the C it emitted before. Where the
240
+ length is one the kernel works out, every subscript on that axis is checked
241
+ where the cell is reached rather than as the block is read, and a C
242
+ function takes the array only through a pointer that declares no length
243
+ (`const double *v`, not `const double v[3]`). The same block at two lengths
244
+ is one compiled kernel: the length travels as an argument and is not in the
245
+ C. A shape that comes to zero or less raises `ArgumentError` when the
246
+ kernel runs, and an allocation the system refuses raises `NoMemoryError`,
247
+ both naming the array and what its shape came to. A `jit_function` body
248
+ allocates nothing -- it is called once per cell -- and refuses such an
249
+ array, naming the pointer parameter to take it through instead.
250
+
251
+ - New: a kernel that carries masks takes a local array, which it refused
252
+ before. Every local array of such a kernel is declared with a shadow of one
253
+ byte a cell beside its cells, and a cell carries a mask the way a plain
254
+ local does: what the expression written into it carried. So a window copied
255
+ into a workspace keeps its holes. `w[k] = UNDEF` marks a cell and
256
+ `w[k] == UNDEF` asks about one; the zeroed spellings clear the shadow with
257
+ the cells, so a cell starts every pass present, while `CArray.empty` leaves
258
+ both unspecified. The shadow counts against the 4 KiB an array is held to
259
+ and the 16 KiB a kernel is, so an array that fits by its cells alone may
260
+ not fit once it carries masks. Two things still refuse such an array:
261
+ `sum`, `min`, `max` and `sort`, because what they should do with a missing
262
+ cell is not decided, and a C function, because a mask travels in no C
263
+ declaration -- both say so where they used to be refused for having no mask
264
+ at all. A kernel that carries no masks emits what it emitted before, and a
265
+ compiled function's body carries none at all.
266
+
267
+ - New: an inner loop's range may be written over another index --
268
+ `3.times { |p| (p+1...3).each { |r| ... } }`, the shape a triangular loop
269
+ takes -- where that index is one of the loops around it. Forward
270
+ elimination and Neville's interpolation are the two this was wanted for,
271
+ and both now read as they do on paper rather than as a full loop with an
272
+ `if` inside it. The C was always emitted; what stood in the way was the
273
+ call, where each index's range is worked out so that a subscript can be
274
+ held to its array. A range over another index has no single pair of
275
+ numbers to be, so it is read as an interval, at its widest: every pass the
276
+ loop could take and sometimes more. Where that refuses a reach the loop
277
+ never makes, the message says which index the range was written over and
278
+ that it was read at its widest. A range over a local variable, a sibling
279
+ loop's index or a deeper one is still refused.
280
+
281
+ - New: a local array may have more than one axis --
282
+ `CArray.double(3, 4)`, `CArray.new(:float64, [2, 3, 4])` -- in any of the
283
+ five places one can be made. The shape is written out as it always was, so
284
+ the strides are constants: `m[r, c]` is `m[(r) * 4 + (c)]`, one subscript
285
+ per axis, and each axis is checked against its own extent. That is what
286
+ flattening by hand gives up -- `m[r * 4 + c]` with a column of 4 reads a
287
+ cell of the next row and says nothing, where `m[r, c]` is refused by name
288
+ and a computed column raises. The stack limits count cells rather than
289
+ axes, so `CArray.double(32, 32)` is 8 KiB and past the 4 KiB an array is
290
+ held to. Handed to a C function the array goes as the flat run of cells it
291
+ is, row after row, so a `double[3][4]` reaches `const double a[12]` and the
292
+ length is matched over every cell. The four intrinsics still take one axis.
293
+
294
+ - New: a `CArray.jit_function` body may make a local array and use
295
+ `sum`/`min`/`max`/`sort` over one, which completes the four entry points.
296
+ A body closes over nothing, so this is the only place scratch space could
297
+ come from other than an extra parameter -- and a signature settled
298
+ elsewhere, a callback's, has no room for one. The array is declared at the
299
+ head of the function, a recursive body gets one per call, and a body hands
300
+ one to another compiled function under the same rules a kernel does. The
301
+ helpers an intrinsic needs travel with the body: carried in its own file
302
+ when it is compiled alone, and merged into the kernel's preamble when it is
303
+ pasted, one helper per element type and length however many bodies want it.
304
+ The stack limits stay per function -- 4 KiB an array, 16 KiB a body -- and a
305
+ chain of pasted functions is not counted, so a deep chain stands as many
306
+ frames as it has; that is the bargain a deep recursion already takes. Still
307
+ excluded: more than one axis, and a contraction.
308
+
309
+ - New: a local array may be handed to a C function -- one from
310
+ `CArray.jit_function` or `CArray.jit_extern` -- wherever the declaration
311
+ takes a pointer, from any of the four entry points that make one. What the
312
+ declaration says is matched as the block is read rather than at the call,
313
+ both the element type and the length being written in the block: an exact
314
+ element type, and at least as many cells as a sized declarator asks for.
315
+ A parameter that is not `const` may be written through, and the line after
316
+ the call reads what the callee left; the zeroed constructors still clear at
317
+ the line, so nothing carries into the next cell. Passing one array to two
318
+ parameters is fine, the declarations carrying no `restrict`. Note that a
319
+ borrowed function which keeps the pointer past the call is left pointing at
320
+ a stack frame that has gone, and that a declaration carrying no length --
321
+ `const double *x` -- gives nothing to check against. Still excluded when this landed: a `jit_function` body,
322
+ more than one axis, and a contraction; the first two arrived later in this
323
+ release, and a contraction is still refused.
324
+
325
+ - New: a local array, and the four intrinsics over one, may be written in a
326
+ `CArray.jit_each`, `CArray.jit_map` or `CArray.jit_stencil` block as well as
327
+ in `CArray.jit_for`. These are the spellings that wanted one: a block with
328
+ no index cannot pick a row of a captured array, so a `jit_stencil` median
329
+ filter had nowhere to put its window -- it is now nine doubles on the cell's
330
+ stack and `sort(w)`. `border: :mask` takes one, the frame being marked
331
+ before the loop runs rather than carried through it. A name the block makes
332
+ an array under is refused where the block also closes over an array of that
333
+ name, since in these spellings an assignment writes that array's cell;
334
+ rename one of the two. A `jit_map` block may not end by making an array, its
335
+ value having to fit in a cell. Still excluded when this landed: a `jit_function` body, a
336
+ contraction, more than one axis, passing one to a C function, and a kernel
337
+ that carries masks; all but the contraction arrived later in this release.
338
+
339
+ - New: `sum(w)`, `min(w)`, `max(w)` and `sort(w)` inside a `CArray.jit_for`
340
+ block, over a local array of one axis. They are bare calls, the compiler's
341
+ own names, rather than methods on the array -- `w.sum` is refused, and
342
+ `sum = 0.0` beside `sum(w)` is still a local. `sum` accumulates in the
343
+ element's computation type in index order; `min` and `max` skip a NaN
344
+ wherever it stands, and answer `NaN` for an array of nothing but NaN,
345
+ which is what `CArray#min` and `#max` answer (they answered the type's
346
+ limit until a later change in this release). `sort`
347
+ is a statement and orders the cells ascending with every NaN after every
348
+ number, as `CArray#sort` does; the relative order of `-0.0` and `0.0` is
349
+ not promised. Up to 16 cells it emits a comparator network with no branch
350
+ in it, above that an insertion sort. Excluded for now: a captured array
351
+ (a whole-array reduction is `CArray#sum`), more than one axis, two
352
+ arguments, boolean for all four, Complex for `min` / `max` / `sort`, and
353
+ the other entry points.
354
+
355
+ - New: a `CArray` made inside a `CArray.jit_for` block is a C array on the
356
+ block's stack -- `w = CArray.double(9)`, `CArray.new(:int64, [256])` or
357
+ `CArray.empty(:float64, [9])`, read and written at a subscript. One axis,
358
+ with the length written out as an integer or integers joined by `+`, `-` and
359
+ `*`; the zeroed spellings are cleared each time the line runs, as Ruby makes
360
+ a fresh array there. A subscript is checked as the block is read where the
361
+ loop's range says it can be, and at the access otherwise, raising
362
+ `IndexError`. One array is held to 4 KiB of stack and one kernel's to 16 KiB.
363
+ Excluded for now: more than one axis, passing one to a C function, the other
364
+ entry points (`jit_each`, `jit_map`, `jit_stencil`, `jit_function`), a kernel
365
+ that carries masks, and CArray's Numo/NumPy spellings (`CArray.zeros`,
366
+ `CArray::Int64.empty`), which are refused with the carray spelling named.
367
+ Note `CArray.float` is float32 and `CArray.complex` is cmplx64.
368
+
369
+ - New: `CArray#jit_init` fills an array from a formula over its indices, with
370
+ the block compiled: `CArray.int32(1000, 1000).jit_init { |i, j| (i + j) % 2 }`
371
+ is what the constructor block `CArray.int32(n, n) { |i, j| ... }` says,
372
+ without the Ruby call per cell. One parameter per axis, the block's value is
373
+ the cell, and the receiver comes back. It is the only entry point here that
374
+ is an instance method, because the array being written is the receiver: the
375
+ extents are its shape, so neither the index space nor the target is said
376
+ twice, where `CArray.jit_for(n, n) { |i, j| z[i, j] = ... }` says both. A
377
+ block outside the compilable subset raises rather than running the slow
378
+ loop, as every other entry point here does. Reach for it where the formula
379
+ will not go through whole-array arithmetic -- where it will, that needs no
380
+ compiler and is faster still.
381
+
382
+ - New: a kernel can draw random numbers, from a `CArray::Rng`. `rand =
383
+ CArray::Rng.new(seed: 4)` and then `rand.random` in a `jit_for`, `jit_each`
384
+ or `jit_map` block draws one double in `[0.0, 1.0)` per cell, at about
385
+ 0.8 ns; `random(rng: rand)` is the same draw spelled as
386
+ `CArray#random!(rng:)` spells it; `rand.randomn` is a standard normal, at
387
+ about 10 ns, and `randomn(rng: rand)` the same; and `rand.bits` is the raw
388
+ word a draw came from. All of them read one generator, so mixing them in a
389
+ kernel walks one sequence. The generator is CArray's and there is no entry point here: a
390
+ block closing over one is what a kernel needs. Each has its own state, so
391
+ two in one kernel are two sequences, and the state survives the call --
392
+ a second kernel carries on rather than starting again. `seed:` is data
393
+ rather than code, so every seed shares one compiled kernel. A sequence can
394
+ begin with `a.random!(rng: rand)` and continue in a kernel: those are the
395
+ same numbers one `random!` over both arrays would have laid down, because
396
+ CArray hands out the generator's C and this gem pastes it. Needs CArray
397
+ 3.0.2 or newer, which is where `CArray::Rng` arrived; an older one is
398
+ refused where the block closes over the generator, and leaves every kernel
399
+ that draws nothing alone. A draw is refused inside `jit_function`, which
400
+ has nowhere to keep a state; take `int64_t state[4]` as a parameter there
401
+ and pass `rand.state`. Which draw lands in which cell is still the loop's
402
+ order, so where that has to be settled, fill an array with
403
+ `CArray#random!` before the call.
404
+
405
+ - New: `CFunction#watching`, and `#clear_error` / `#report_error` beside it,
406
+ for the window in which a compiled function's address is lent to a C
407
+ library. `#call` answers for one call; a library given `#pointer` calls as
408
+ often as it likes, and `f.watching { ... }` is what puts the flag down
409
+ before that and raises what the body reported after it. A failure inside
410
+ the block outranks the library's own complaint about the stand-in it was
411
+ handed. Windows nest, and a `#call` made inside one leaves it armed.
412
+
413
+ - New: `Math.gamma`, which is not `tgamma` and is not lowered to one: Ruby's
414
+ answer is tgamma with a table of exact values in front of it for a whole
415
+ number up to 23, and a `Math::DomainError` where tgamma answers a negative
416
+ whole number or negative infinity with a NaN. Both are reproduced -- the
417
+ table is written into the generated C, filled from the Ruby that compiled
418
+ it, as `Math::PI` is emitted as the double Ruby would have used, and the
419
+ error carries Ruby's class and Ruby's words. A cell with no value in it
420
+ does not raise. Measured over the whole numbers to 26, the halves, the
421
+ infinities and the overflow, a kernel and the Ruby loop agree in every bit.
422
+
423
+ - New: `Math.erf` and `Math.erfc`, which are 1:1 with math.h's `erf` and
424
+ `erfc` -- Ruby calls those very functions, so a kernel and the Ruby loop
425
+ agree to the bit, infinities included. A float32 cell is worked on narrow
426
+ and so gets `erff`, as it gets `sinf`. There is no postfix `x.erf`:
427
+ `CArray::CoreExtensions` does not provide one, and this compiles the
428
+ refinement's names rather than inventing them.
429
+
430
+ - New: `x.clamp(low, high)`, which answers the value or whichever bound it
431
+ ran past. The value and both bounds have to be one class: Ruby hands back
432
+ the receiver in one branch and a bound in the other, so `1.clamp(0.0, 3.0)`
433
+ is an Integer and `5.clamp(0.0, 3.0)` a Float, and no type settled before
434
+ the loop runs is both -- the refusal says which way round it is and what to
435
+ write. Two widths of one class are not that case, so a float32 cell keeps
436
+ its width. What Ruby raises `ArgumentError` for is raised here too: bounds
437
+ the wrong way round, and a NaN that cannot be ordered. The class is Ruby's
438
+ and so are the words for the first; for the NaN the message names the
439
+ reason rather than the value, since what comes back from a kernel is a code
440
+ and not a number. A cell with no value in it does not raise. The range
441
+ form, `x.clamp(0.0..1.0)`, is not in the subset -- two bounds are two
442
+ bounds.
443
+
444
+ - New: a compiled function may take and return a C99 complex --
445
+ `CArray.jit_function("double _Complex step(double _Complex z)") { |z| z * z
446
+ + Complex(0.0, 1.0) }`. `double _Complex`, `float _Complex` and
447
+ `<complex.h>`'s `double complex` all read, by value or as a pointer, where
448
+ `double _Complex v[]` takes a `cmplx128` array as `double v[]` takes a
449
+ `float64` one. A kernel calls such a function as C calls it. A call from
450
+ Ruby goes through a second entry point compiled beside the body, since
451
+ Fiddle has no type to carry a complex by value in; it calls the body rather
452
+ than repeating it, so `f.call` and `f.block.call` stay the same body run
453
+ two ways. A function bound with `jit_extern` and declared with a complex is
454
+ callable from a kernel but not from Ruby -- there is no source here to
455
+ compile an entry point beside -- and says so.
456
+
457
+ - New: a `jit_function` body may take an unsigned 64-bit value by parameter --
458
+ `CArray.jit_function("size_t stride(size_t n, size_t width)") { |n, w| n * w }`
459
+ -- where before only a pointer to one could be taken. The value arrives
460
+ whole above 2^63 and the arithmetic on it is unsigned, wrapping at the width
461
+ as CArray's own `uint64` operators wrap. A kernel's captured scalars are
462
+ unchanged: those travel in the kernel's own buffers, which carry doubles,
463
+ int64s and complexes.
464
+
465
+ - New: `x.nan?` and `x.finite?`, which compile to C's `isnan` and `isfinite`
466
+ and answer what Ruby answers. `nan?` is a Float's question: an Integer and
467
+ a Complex have no method by that name and raise `NoMethodError` in Ruby, so
468
+ a kernel refuses both rather than answering false. `finite?` answers for an
469
+ Integer (true, whatever it holds) and for a Complex (both parts finite, as
470
+ Ruby asks it) as well as for a Float. `infinite?` is refused: Ruby answers
471
+ it with nil, 1 or -1 rather than true or false, and a kernel has no nil to
472
+ answer with -- the message names `x.abs == Float::INFINITY`, or
473
+ `x == Float::INFINITY` where the sign is the question.
474
+
475
+ - New: the operator assignments -- `+= -= *= /= %= **= &= |= ^= <<= >>=` --
476
+ on a local, on a cell (`out[i] += e`, `work[i, k] += e`, a scatter such as
477
+ `counts[bin[i]] += 1`), on a CScalar and through a `jit_function`'s pointer
478
+ parameter. Each is read as the assignment it stands for, `x = x + e`, so
479
+ the type rules, the mask propagation and the fold that splits an
480
+ accumulator into partial sums are the ones already there: a reduction
481
+ written `total += values[j]` is still split. `||=` and `&&=` are refused,
482
+ being about whether a value is nil or false rather than about arithmetic.
483
+
484
+ - New: an inner loop counts by a stride, written the way an extent writes
485
+ one: `(n-1).step(0, -1) { |k| ... }` is a downward sweep and
486
+ `(0...n).step(2) { |k| ... }` a stride of two. `step` includes the index it
487
+ is given, as Ruby's does, where a `...` range excludes it, and the stride
488
+ is a literal because it is what says which way the loop runs. This is the
489
+ other half of a row of workspace -- filling one and walking back down it no
490
+ longer needs `k = width - 1 - t`, which made the position a value the
491
+ kernel worked out and so put a bounds test on every cell of the sweep: 0.41
492
+ ns/cell against 0.24 for the same sweep written with `step`. An accumulator
493
+ is split into partial sums only for a loop counting by one; a stride keeps
494
+ the serial chain, and so keeps Ruby's order. `downto`, `upto` and
495
+ `reverse_each` are refused by name, naming `step` as what to write.
496
+
497
+ - New: an inner loop's index may address a write, so a cell can be given a
498
+ row of workspace -- `(0...width).each { |k| work[i, k] = ... }` fills it,
499
+ and `work[i, k]` reads it back inside the same cell. That is what an
500
+ algorithm needing a few numbers per cell is written with: a small dense
501
+ solve, a tableau, a sweep and the pass back down it, in one kernel rather
502
+ than in several that each pay a call. The cell is bounds-checked before the
503
+ kernel runs, as one addressed by `i` is. Inside the row the body may do as
504
+ it likes -- sort it, walk it backwards, write at a position it works out --
505
+ which is what a median filter needs and what no extra axis can say. Reading
506
+ an array the kernel writes through an inner index is still refused where
507
+ the read leaves the cell the outer indices picked: a read carrying an inner
508
+ index addresses every axis some write walks with an outer index with that
509
+ same index, at whatever offset, or it reaches cells another outer iteration
510
+ owns. Where the sweep can be said as an extra axis instead --
511
+ `jit_for(rows, 1...width)` -- that remains the faster form once the rows
512
+ are long.
513
+
514
+ - New: a function compiled with `CArray.jit_function` may call another one
515
+ compiled with `CArray.jit_function`, by the name the block reaches it by --
516
+ `hypot = CArray.jit_function("double (*)(double, double)") { |a, b|
517
+ root.call(a * a + b * b) }`. The called body is pasted into the caller's C
518
+ and reached by symbol, so what comes back is still one self-contained
519
+ object with one address, and a chain of any depth arrives together with the
520
+ messages its bodies raise. Everything else a body closes over is refused as
521
+ before -- a number, an array, and a function bound with `jit_extern`, which
522
+ is only an address and has nowhere in a compiled object to live. The name
523
+ may be a constant as well as a local, which is what lets a method reach
524
+ one: `def` closes over nothing.
525
+
526
+ - New: `CArray::JIT.contraction_of` returns the number that multiplies the
527
+ product as `:scale`, which is 1 where there is none, so
528
+ `a[i,k] * b[k,j] * 2.0` comes back as its two terms and 2.0 rather than as
529
+ nil. A number is not a term -- it has no indices and no cell -- but it is
530
+ not a reason to give up on the terms either, and a caller that takes them
531
+ apart puts it back. Written out or closed over is the same number; anything
532
+ a name holds that is not a Numeric is still nil. This shipped in 0.1.2,
533
+ whose entry describes the same two methods without mentioning it.
534
+
535
+ - Change: this gem no longer builds a C extension, so installing it needs no
536
+ compiler for itself -- one is still needed at run time to compile a kernel.
537
+ The addressing it used to carry is `CArray::AddressBasis`, in carray, which
538
+ is where the knowledge about carray's views belonged; `CArray::JIT::Access`
539
+ remains as an alias for this release. carray 3.0.2 or newer is required,
540
+ which the gemspec already asked for.
541
+
542
+ - Change: `CArray.jit_for`, `CArray.jit_each` and `CArray.jit_map` are this
543
+ gem's alone. From CArray 3.0.2 they are not defined until
544
+ `require "carray/jit"` has run, so a program that calls one without it gets
545
+ `NoMethodError` rather than CArray's `NotImplementedError`. With the gem
546
+ required nothing changes, against any CArray this gem accepts.
547
+
548
+ - Change: `CArray::JIT::CFunction#name` answers the name the declaration gave
549
+ -- `:square` for `CArray.jit_function("double square(double x)")` -- and
550
+ the new `#symbol` answers the name in the object, which for a compiled
551
+ function carries a digest of the body. It used to answer whichever of the
552
+ two its constructor was handed: the declared name for a function bound with
553
+ `jit_extern`, the symbol for one compiled from a block. Code reading
554
+ `#name` to reach or paste a function wants `#symbol`; code putting it in a
555
+ message wants `#name`, which is `nil` where the declaration named no
556
+ function. `#to_s` now prints the declaration rather than the symbol.
557
+
558
+ - Change: a compiled function whose body has failed does no more work until
559
+ its flag is put down again -- it returns 0 without running, and one
560
+ declared `void` leaves its out-parameters alone. Before, it reported the
561
+ first failure and then answered normally, so a library that kept calling
562
+ could converge on values it was no longer entitled to. Nothing changes for
563
+ a caller using `#call`, which puts the flag down for each call; a caller
564
+ holding `#pointer` opens a window with `#watching` or `#clear_error`. A
565
+ kernel is unaffected: it is handed its own error slot and never reaches
566
+ this flag.
567
+
568
+ - Change: naming a contraction's axes now replaces the convention rather than
569
+ adding a clause to it. `CArray.jit_contract(:i, :j) { ... }` names all of
570
+ the result's axes, so every index left out of the list is summed at however
571
+ few positions it sits -- where before, one sitting at a single position was
572
+ refused as a free index with nowhere to go. So `jit_contract(:i) { |k|
573
+ a[i,k] }` is the row sums, and `contract_terms(terms, free: [])` over a
574
+ product is its total; both were refused. (`a.sum(axis: 1)` remains the
575
+ faster way to write a reduction, being one.) With nothing named the
576
+ convention is unchanged: a repetition is a sum and a single position is
577
+ free. What this makes exact is the correspondence with einsum's two modes,
578
+ the argument list being the arrow's right-hand side; `"ik->i"` and
579
+ `"ik,kj->"` can now be said.
580
+
581
+ Where the block assigns into an array of yours, an axis on the left-hand
582
+ side that the list leaves out is still refused -- it is the list falling
583
+ short of the result rather than an index to sum, and the left-hand side is
584
+ the one place that can be seen. The message says so in those terms now.
585
+
586
+ - Change: `min(w)` and `max(w)` over a floating local array answer `NaN` when
587
+ every cell is `NaN`, where they answered `Infinity` and `-Infinity`. This
588
+ follows CArray 3.0.2, which made the same change to its own `min` and `max`;
589
+ the gemspec already asks for that version. An array holding at least one
590
+ number answers as before, a `NaN` still losing to any number, and an integer
591
+ local array is unchanged.
592
+
593
+ - Change: `CArray.jit_contract` refuses an index that stands inside a
594
+ subscript the kernel works out -- `a[i, idx[k]] * v[k]` -- saying that a
595
+ contraction counts positions and this one is a position of `idx`. It was
596
+ read as an index appearing once, so the sum the notation asks for did not
597
+ happen and the result came back a whole matrix. Write such a gather with
598
+ `CArray.jit_for`.
599
+
600
+ - Change: an indexed kernel (`CArray.jit_for` and the rest) refuses an
601
+ operand it cannot walk -- a gather, a lazy array -- that is a view of an
602
+ array the same kernel writes, naming `a[order[i]]` as the spelling that
603
+ means something. Such an operand is copied before the loop and put back
604
+ after it, so the loop read cells that had stopped being current and a
605
+ direct write to the same array was dropped at the end.
606
+
607
+ - Change: arithmetic between two booleans -- `flag[i] * flag[i]`, `+`, `-`,
608
+ `/`, `%` -- raises `CArray::JIT::Unsupported` where the operator stands,
609
+ as `true * true` raises in Ruby. Used as a condition it compiled and ran.
610
+ `&`, `|` and `^` on booleans are unchanged.
611
+
612
+ - Change: a captured Integer above 2**63-1 meeting an integer is refused,
613
+ where before it was absorbed into that integer's width and computed from a
614
+ wrapped value. CArray refuses the same expression whatever the array's own
615
+ type is -- `CArray.uint64(1) { 5 } + 2**63` raises `bignum too big to
616
+ convert into 'long long'` -- and this follows it: a bare Integer brings no
617
+ width, and the message names `CScalar.uint64() { big }`, which a kernel reads
618
+ as the one-cell array it is. A Float or a Complex on the other side is
619
+ unaffected, and so is a capture that fits an int64. A loop that adds such a
620
+ capture to an accumulator is refused for the same reason: state the width
621
+ once with a CScalar, for the seed and for the value.
622
+
623
+ - Change: a `CArray.jit_each` or `CArray.jit_map` block whose *only* array is
624
+ handed to a C function whole is now refused, naming the array and saying
625
+ that it does not settle how many cells there are to compute.
626
+ `CArray.jit_map { DOT4.call(w, w) }` used to answer an array as long as `w`
627
+ -- a length that came from an array nobody walks -- and the same block under
628
+ `jit_each` failed inside Fiddle with `unknown symbol "ca_call_cslab_0_r"`.
629
+ `CArray.jit_for` with a count takes these, as it always did.
630
+
631
+ - Change: a block parameter that names a loop index is refused when the
632
+ generated C already uses that name for a captured array (`p_a`, `m_a`,
633
+ `a_s0`, `a_ms0` or `a_n0` for an array `a`), or when it contains `__` or
634
+ starts with `carray_jit_`. Rename the index.
635
+
636
+ - Change: a `CArray.jit_function` body that subscripts a pointer parameter
637
+ with a literal outside the length its declaration gave -- `v[7]` or
638
+ `v[-1]` against `double v[2]` -- raises `CArray::JIT::Unsupported` as the
639
+ body is read. It compiled, and wrote or read past what the caller was
640
+ held to. A computed subscript, and any subscript on a pointer declared
641
+ without a length, are unchecked as before.
642
+
643
+ - Change: an extent that counts down as a `Range` -- `(n-2)..0` -- raises
644
+ `CArray::JIT::Unsupported` naming `(n-2).step(0, -1)`, the spelling Ruby
645
+ iterates backwards with. Ruby gives such a Range no elements, so the
646
+ kernel ran no passes and said nothing, which is what the guide says this
647
+ refusal exists to prevent. An empty range whose ends agree (`0...0`) is a
648
+ count of zero as before.
649
+
650
+ - Change: a body compiled with `CArray.jit_function` or `CArray.jit_call` may
651
+ call a function bound with `jit_extern`. It was refused -- a borrowed
652
+ function is only an address, and a compiled body has no `functions` buffer
653
+ to take one in -- but an address is not what a body needs from it. It needs
654
+ the name, which is what the declaration states and what a linker or a
655
+ loader resolves; `jit_extern` opened the library to find the function, so
656
+ the symbol is in the process by the time the body is compiled. The
657
+ generated file declares it (`double j0(double);`) and calls it by name. A
658
+ kernel is unchanged and still takes the address through its buffer, which
659
+ is what a kernel has and a body has not. A file built ahead of the program
660
+ links the library the usual way: one that is not linked by default is the
661
+ caller's to add.
662
+
663
+ - Change: `require "carray/jit/call"` defines `CArray.jit_call` without
664
+ loading the compiler, and the compiler is required at the first call site
665
+ no provider answers. A program whose sites were all built ahead of it --
666
+ by carray-jit-aot -- never loads the analyzer, the generator or the cache
667
+ at all, where before it loaded them and reached none of them.
668
+ `require "carray/jit"` loads everything as it did, and a program that
669
+ knows nothing about this sees no difference.
670
+
671
+ - Change: a subscript that walks with one index and adds another --
672
+ `a[i + r]`, `r` an inner loop's index -- is refused as the block is read,
673
+ with a message that says so and that the sum put in a local first
674
+ (`k = i + r`, then `a[k]`) is checked at each cell and runs. It was
675
+ refused at the call, for a reason about an inner loop's range. The
676
+ exception is `CArray::JIT::Unsupported`, as it was.
677
+
678
+ - Change: a kernel or `jit_function` body that reads a local after an inner
679
+ loop's block in which the local was first assigned, or after a `while` in
680
+ which it was first assigned, is refused with a message naming the local.
681
+ These did not compile before either, failing in the C compiler instead.
682
+ Give the local a value before the loop.
683
+
684
+ - Change: a local assigned before the summand of a `CArray.jit_contract`
685
+ block is refused saying so -- a contraction is one expression, which is
686
+ why it takes no local array either. It was refused as "`u` is read before
687
+ it is assigned", about a local assigned on the line above.
688
+
689
+ - Change: the refusal for a `CArray.jit_stencil` writing into a view of an
690
+ array it reads says that the two are views of one array and that the test
691
+ is the storage rather than the cells, so two slabs that share none are
692
+ refused too, and names the copy to read from. It said a stencil writes
693
+ into an array of its own, which of two slabs is not true.
694
+
695
+ - Change: the refusal for a block whose source cannot be read names
696
+ `RubyVM.keep_script_lines = true` and `CArray::JIT.compile`, which takes a
697
+ kernel as text. It named `source:`, which is a keyword no entry point
698
+ takes; the guide said the same.
699
+
700
+ - Change: `CArray#jit_init` given a block that takes a splat or an optional
701
+ parameter says so, where it said "the block names -1 indices".
702
+
703
+ - Change: a keyword in value position is named as it was written --
704
+ `unless` in `CArray.jit_map { unless a > 1.0 then ... end }` says
705
+ "`unless` -- write it as `if` with the condition negated", where it said
706
+ "unsupported expression Unless". Statement position already did.
707
+
708
+ - Change: a statement outside the subset is named as it was written --
709
+ ``got `unless` -- write it as `if` with the condition negated`` rather than
710
+ `got Unless`, which was this compiler's reading of it and not anything
711
+ anyone typed. The list of what a body may hold was written out in two
712
+ places and they had come apart; it is one place now.
713
+
714
+ - Change: the three names left in Ruby's `Math` say why they are not lowered
715
+ rather than saying that C has no counterpart, which was untrue of all of
716
+ them -- `lgamma`, `frexp` and `ldexp` all exist. `Math.lgamma` and
717
+ `Math.frexp` each answer with a pair, and a cell holds one number;
718
+ `Math.ldexp` takes an exponent where a math call here computes every
719
+ argument in the type of its result. A name Ruby's `Math` does not have says
720
+ that instead of guessing at a reason.
721
+
722
+ - Change: a compiler this process cannot find -- `CARRAY_JIT_CC` naming
723
+ something that is not there -- raises `CArray::JIT::CompilationError`
724
+ saying so and naming the variable, where it raised `Errno::ENOENT` from
725
+ the spawn with the program name and nothing else.
726
+
727
+ - Change: a cache directory owned by another user is refused, as one other
728
+ users can write to already was; everything in it is `dlopen`ed. A cache
729
+ root that is a symlink is followed as before, and the owner of the
730
+ directory it lands on is what is asked about. Set `CARRAY_JIT_CACHE` to a
731
+ directory of your own where this refuses.
732
+
733
+ - Change: the docs now say what a compare-exchange costs under a mask. A
734
+ swap writes two cells where an ordinary assignment writes one, and a sort
735
+ runs one over every cell repeatedly, so a single missing cell spreads
736
+ across the row -- the ordinary rule for a branch decided by a missing
737
+ cell, at an unusually high gain. A sort written by hand is not refused
738
+ the way `sort` on a local array is, so ask `a[i] == UNDEF` first and
739
+ decide it.
740
+
741
+ - Change: the docs now say what a branch not taken costs under a mask. A
742
+ branch decided by a missing cell masks what it writes; taking the other
743
+ path writes nothing, so a conclusion reached that way -- `found` left at
744
+ -1 for a row whose only candidate was masked -- is reported as an ordinary
745
+ value. Ask about the mask with `a[i] == UNDEF` where that matters.
746
+
747
+ - Change: the docs now say that a negative Float to a fractional power is
748
+ `NaN`, as `pow` and CArray answer, where Ruby answers a Complex. This was
749
+ already the behaviour; a whole-number exponent or a non-negative base is
750
+ Ruby's number.
751
+
752
+ - Change: the docs now say that an Integer compared with a Float is
753
+ compared as two doubles, as CArray compares them, so past 2^53 the answer
754
+ can differ from Ruby's exact comparison. This was already the behaviour;
755
+ below 2^53 nothing differs.
756
+
757
+ - Change: the docs now say that `Math.sqrt`, `log`, `log2`, `log10`, `asin`,
758
+ `acos`, `acosh` and `atanh` answer `NaN` outside their domain, as `math.h`
759
+ does, where Ruby raises `Math::DomainError`, and that `Math.sqrt(-0.0)` is
760
+ `-0.0`. This was already the behaviour. `Math.gamma` still raises as Ruby
761
+ does. Test the argument in the block where it may leave the domain.
762
+
763
+ - Fix: a loop whose bound is an unsigned parameter -- `size_t n` and its kin
764
+ -- runs the passes Ruby runs. The counter is an `int64_t` and the bound was
765
+ compared against it uncast, so C converted the *counter* to unsigned
766
+ instead: `(-3...n).each` over `n = 4` ran no passes where Ruby runs seven,
767
+ and answered without saying anything. A count that never goes below zero
768
+ was unaffected, which is every `n.times`. The cast is written down now, so
769
+ the generated C also compiles clean where it carried `-Wsign-compare`
770
+ before.
771
+
772
+ - Fix: a `CArray.jit_each` or `CArray.jit_map` pass that reads a view of an
773
+ array it also writes -- two blocks that share cells, a transpose written
774
+ over itself, a gather held in `g` and written back as `src = g + 1.0` --
775
+ reads the values the expression started with, as Ruby and CArray's own
776
+ operators do. Such an operand was read as the pass went, so it came back
777
+ holding the kernel's own output: `hi = lo * 2.0` over overlapping blocks
778
+ gave all zeros, and a gather over 20000 cells was wrong in 8192 of them.
779
+ It is copied once before the loop instead. `a = a + 1.0`, and views that
780
+ share a root without sharing a cell, are untouched.
781
+
782
+ - Fix: `CArray.jit_contract` takes a summand that calls a function made with
783
+ `CArray.jit_function` or `CArray.jit_extern`, which the docs say it does;
784
+ it was refused as an unsupported method. What the function hands back
785
+ types the result the contraction is collected into.
786
+
787
+ - Fix: a cell of a local array written under an `if` or a `while` whose
788
+ condition read a missing cell is masked, as a plain local and a cell of an
789
+ array now are. It was left present deliberately; the rule the docs give
790
+ for it is the one the other two keep.
791
+
792
+ - Fix: a local assigned under an `if` or a `while` whose condition read a
793
+ missing cell is masked, as a cell written there already was. It came back
794
+ a number like any other, so `found = -1; ...; if a[i, j] > x then found =
795
+ j end; out[i] = found` reported a position found under a mask. A condition
796
+ that asks about the mask itself (`a[i] == UNDEF`) still masks nothing.
797
+
798
+ - Fix: a build no longer fails with "could not load freshly compiled" when
799
+ another process evicts its object in the moment between the build and the
800
+ load. It opens the object before publishing it to the cache. Reachable
801
+ where `CARRAY_JIT_CACHE_LIMIT` is smaller than the number of processes
802
+ building at once: with five of them, a limit of 2 lost every one.
803
+
804
+ - Fix: a build whose compile fails leaves no `.c` behind in the cache. Such
805
+ a file was never looked up -- a cache hit is an object -- and eviction
806
+ passes over it, so one stayed for good, and one more for every kernel of
807
+ every run against a toolchain that cannot compile.
808
+
809
+ - Fix: two threads of one process compiling at the same time no longer
810
+ raise `Errno::ENOENT`; three threads in four did. A build now takes a lock
811
+ for the length of the compile, so the second thread finds the object the
812
+ first one left and reuses it rather than building its own. Compiling two
813
+ different kernels in two threads is that much less parallel -- four of
814
+ them took 970 ms here against 800.
815
+
816
+ - Fix: multiplying two Complex numbers, or a real number by a Complex
817
+ (`x * z`), gives Ruby's answer where an infinity meets a zero:
818
+ `0.0 * Complex(Float::INFINITY, 0.0)` is `0.0+0.0i`, where it was
819
+ `NaN+NaN*i`. Finite products are unchanged, `cmplx64` included, and
820
+ `z * x` still scales each part as it did.
821
+
822
+ - Fix: `%` by a float zero raises `ZeroDivisionError`, as Ruby's does --
823
+ `x % 0.0`, `x % -0.0`, an integer cell `% 0.0` -- in a kernel and in a
824
+ `CArray.jit_function` alike. It answered `NaN`, which is what CArray's `%`
825
+ answers and not what the docs promised. A float `/` by zero is still an
826
+ infinity, as it is in Ruby.
827
+
828
+ - Fix: `min(w)` and `max(w)` over a floating local array keep the first of
829
+ two cells that compare equal, as CArray's `min` and `max` do, so `0.0`
830
+ and `-0.0` come back in the order they stood; which zero came back was
831
+ left to the C library. NaN is still skipped, and an array of nothing but
832
+ NaN still answers `NaN`.
833
+
834
+ - Fix: `floor`, `ceil`, `round`, `truncate` and `to_i` on a Float raise
835
+ `FloatDomainError` for a NaN or an infinity, as Ruby does, and `RangeError`
836
+ for a result past int64; they gave a clamped or arbitrary number. Written
837
+ straight into a float cell, or returned from a `CArray.jit_function`
838
+ declared `double`, the result is Ruby's however large -- `1e20.floor` is
839
+ `1e20`. A loop doing little but rounding runs slower for the check.
840
+
841
+ - Fix: `.abs` on an integer compiles in `CArray.jit_for`, `CArray.jit_map`,
842
+ `CArray.jit_function` and the other entry points; it raised
843
+ `CArray::JIT::CompilationError` unless the kernel also allocated a local
844
+ array. `(-2**63).abs` in an int64 wraps to itself, as other int64
845
+ overflow does. Float and complex `.abs` are unchanged.
846
+
847
+ - Fix: an inner loop stepping by more than one over a start written over
848
+ another index -- `2.times { |p| (p...8).step(3) { |k| ... } }` -- is held
849
+ to the cells every pass reaches, not only the pass from the earliest
850
+ start. A subscript one pass took past the end of an array was let through
851
+ and written; it is now refused as the call is prepared. A step of one, and
852
+ a start that does not move, are read as before.
853
+
854
+ - Fix: a local array whose shape is written over captured integers --
855
+ `CArray.double(n, m)` -- raises `ArgumentError` when its lengths each fit
856
+ but their product does not count in bytes. Such a product wrapped to a
857
+ small number, the kernel allocated that, and subscripts in range on every
858
+ axis wrote past it. A shape of one axis, or of lengths whose product
859
+ fits, is unaffected.
860
+
861
+ - Fix: `CArray::JIT.clear_registry` now forgets the functions
862
+ `CArray.jit_function` compiled, as it already did kernels, so the next
863
+ call reads them back from the cache on disk.
864
+
865
+ - Fix: a block run through `eval` -- in a console, or from code that builds
866
+ its kernels as text -- no longer stays in memory for the life of the
867
+ process once nothing refers to it. On Ruby 3.2 it still does.
868
+
869
+ - Fix: a kernel over a masked array read and wrote the wrong cells of its
870
+ mask, and on a large enough array wrote past the end of it, when an
871
+ unmasked operand whose number of axes differs from the kernel's -- a row
872
+ added across a grid, or a contraction's operand -- sorted by name before
873
+ the masked one. Kernels whose operands all share the kernel's rank, and
874
+ kernels over no masked array, were not affected.
875
+
876
+ - Fix: a local array indexed by an inner loop whose range is not known until
877
+ the kernel runs -- a bound that is a captured integer, and now a range
878
+ written over another index -- is checked where the cell is reached. Such a
879
+ subscript was checked nowhere: the check that reads the loop's range could
880
+ not settle it, and the check at the access did not cover an index, so a
881
+ write past the end of the array went into the block's stack frame. It now
882
+ raises `IndexError` as every other unsettled subscript does.
883
+
884
+ - Fix: in a `CArray.jit_each`, `CArray.jit_map` or `CArray.jit_stencil`
885
+ block, an array handed to a C function whole -- and read in no other way --
886
+ is no longer lined up with the operands. One whose length differed from
887
+ theirs used to fail with `broadcast_to: cannot broadcast axis 0`, which
888
+ named an axis and said nothing about the call it was written for; a set of
889
+ weights four cells long may now stand beside a thousand cells of operand.
890
+ What decides which arrays those are is the declaration, not the spelling: a
891
+ parameter taking a number by value reads the cell, so that array is walked
892
+ and lines up as before, and an array both read by cell and handed over is
893
+ an operand too.
894
+
895
+ - Fix: a local in a kernel or `jit_function` body, or a captured variable
896
+ starting `carray_jit_`, may be given a name the generated C also uses -- a
897
+ kernel parameter such as `error`, a C keyword such as `int`, `a_n0` beside a
898
+ captured array `a`, or a name containing `__`. It failed to compile, raised
899
+ an `IndexError` for an index in range, or shared its value with another
900
+ name; it is now renamed in the generated C only.
901
+
902
+ - Fix: two inner loops in one kernel or `jit_function` body may assign a
903
+ local of the same name, at one type or two, and a local assigned inside a
904
+ `while` may be read after it when it was also assigned before it. The
905
+ first failed in the C compiler or was refused as changing type; the second
906
+ failed in the C compiler.
907
+
908
+ - Fix: a loop in a `jit_function` body, and a `while` or inner loop in a
909
+ kernel whose body held the kernel's first way to fail, kept running after
910
+ an integer division by zero, a computed index out of range, `clamp` or
911
+ `Math.gamma` had reported a failure -- so a `while` decided by the value
912
+ handed back could run forever. Such a loop now leaves at the head of its
913
+ next pass, and the call raises as it already did.
914
+
915
+ - Fix: `CArray.jit_each` and `CArray.jit_map` no longer refuse a block that
916
+ hands a one-cell array to a C function. Those entries line their operands up
917
+ with the expression's shape, and an array passed to a pointer parameter was
918
+ lined up with the rest -- so a one-cell array holding state came back
919
+ stretched and read-only, and the copy-back after the call raised `can not
920
+ modify read-only array`. An array handed over by address is passed whole
921
+ rather than walked, so it is left as it is now. `jit_for` was never
922
+ affected, and a `CScalar` was affected the same way an array was.
923
+
924
+ - Fix: a captured Integer above 2**63-1 reaches a kernel whole. It was packed
925
+ into the int64 slot the kernel reads its integers from, which took the value
926
+ modulo the width and said nothing: `big / 3`, `big > 100` and `big * 1.0`
927
+ answered from a negative number, while `+` and `*` came out right and hid it.
928
+ Such a capture is a uint64 now -- the width CArray has for those values --
929
+ and a value neither an int64 nor a uint64 holds is refused where the capture
930
+ is read, naming the value.
931
+
932
+ - Fix: a C declaration written with `ptrdiff_t` compiles. `size_t` and the
933
+ other `<stddef.h>` names have read since 0.1.0, but the C generated for a
934
+ body that took one declared no such type, so `CArray.jit_function("ptrdiff_t
935
+ (*)(ptrdiff_t)")` failed in the C compiler with `unknown type name`.
936
+ `size_t` was unaffected, by luck rather than by design.
937
+
938
+ - Fix: two inner loops in one body may both be written `{ |k| ... }`. They
939
+ are one name in the block and were one index here, so the second loop's
940
+ range replaced the first's and a reach was checked against the wrong one --
941
+ `a[k-1]` in a loop from 1 was refused for starting at 0 once a later loop
942
+ started there. Each loop now counts in an identifier of its own, and the
943
+ messages go on speaking the name the block wrote.
944
+
945
+ - Fix: a block holding a character outside ASCII no longer raises. The file a
946
+ block sits in was read with `File.read`, which uses
947
+ `Encoding.default_external` -- a setting that has nothing to do with a
948
+ source's encoding: on a machine with no locale set it is US-ASCII, and the
949
+ file came back as its own bytes under a tag that the first `rstrip` on a
950
+ line holding a comment in Japanese raised on. The file is now read as bytes
951
+ and given the encoding the parser gave it: UTF-8, or what a `coding` magic
952
+ comment names on the first line or on the second where a shebang takes the
953
+ first.
954
+
955
+
40
956
  ## 0.1.2
41
957
 
42
958
  - New: `CArray.jit_contract` takes the result's axes as symbols, which says
@@ -115,9 +1031,7 @@ version you have and a newer one.
115
1031
  `CArray.jit_function("void (*)(uint64_t *, int64_t)")` reached its cells as
116
1032
  an opaque slot rather than an array, and a `uint64_t` return type was
117
1033
  refused as "no value a compiled body can produce" -- from a table written
118
- before uint64 was a type a kernel computes in. A `uint64_t` parameter taken
119
- by value is still refused, and now says why: a value reaches a body as a
120
- double, an int64 or a complex, and a uint64 fits none of them whole.
1034
+ before uint64 was a type a kernel computes in.
121
1035
 
122
1036
  - Fix: `CArray.jit_map` collects a cmplx64 value into a cmplx64 array rather
123
1037
  than refusing to allocate one. Nothing else changes type: a block whose value