Repository navigation
NDArray: the go-ndarray playground's Ruby API, on go-ndarray v0.11.0 - #813
Merged
Merged
Conversation
The go-ndarray playground shows each pipeline as Go | Ruby | NumPy and runs the Ruby column in the browser through cmd/wasm. This implements the API its code generator emits (ruby-ndarray-contract.md): - creation: arange(stop | start, stop | start, stop, step), linspace, eye(n, m, k), zeros()/ones() (0-d with no shape, or a shape Array), full(value, *shape) - views: reshape (with -1), T, squeeze(*axes), expand_dims, dup/copy (copy of the data), and NumPy basic indexing through a[...]: Integer, true for ':', a Range (exclusive, inclusive, endless, beginless) or an Enumerator::ArithmeticSequence ((0..) % 2, (-1..) % -1, (5...1) % -2) - elementwise: square, ** (scalar, array with broadcasting, and 2 ** a through NDArray#coerce), clip, NDArray.maximum/minimum - reductions: sum/mean/max/min/prod/argmax/argmin with (axis, keepdims:), cumsum - products and joins: NDArray.outer, NDArray.concatenate/stack(axis:) - p/inspect/to_s print go-ndarray's NumPy-style Repr Every method now checks its arguments: a wrong count raises ArgumentError, a wrong type TypeError, an index or axis out of range IndexError, other go-ndarray errors ArgumentError with go-ndarray's message. NDArray.arange(5) and NDArray.full() used to raise "ArgumentError: arange: runtime error: index out of range [1] with length 1", a recovered Go panic. TestNativeFaultBecomesRubyError relied on that bug; it now plants its own faulting native. go-ndarray v0.3.0 -> v0.11.0 (and go-fft v0.1.14 -> v0.23.0 with it), outside the grouped Renovate PR #792. The README no longer says the browser target does not build (it has since #684), in three places; readme_wasm_lane_test.go now catches that wording across line breaks. web/smoke.mjs runs an NDArray program in the JS host. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
The go-ndarray playground shows each pipeline as Go | Ruby | NumPy and runs the Ruby column in the browser through
cmd/wasm. This PR implements the RubyNDArrayAPI its code generator emits (the playground contract), ininternal/vm/ndarray.go.arange(stop)/(start, stop)/(start, stop, step),linspace(start, stop, num = 50),eye(n, m = n, k = 0),zeros()/ones()(0-d with no shape; a shape Array is accepted too),full(value, *shape)reshape(with-1),T,squeeze(*axes),expand_dims(axis),dup/copy(a copy of the data)a[...], NumPy basic indexing: Integer,truefor:, a Range (1...3,1..,...3, inclusive1..2/1..-1) or anEnumerator::ArithmeticSequence((0..) % 2,(1...7) % 3,(-1..) % -1,(5...1) % -2,1.step(7, 3)). All-Integer, one per axis, returns the element as a Float.square,**(scalar; array with broadcasting;2 ** athroughNDArray#coerce),clip,NDArray.maximum/minimum(a number on either side broadcasts)sum/mean/max/min/prod/argmax/argmintake(axis, keepdims:); with no axis they return a Float, or an Integer flat index for argmax/argmin.cumsum/cumsum(axis)NDArray.outer,NDArray.concatenate([...], axis:),NDArray.stack([...], axis:)p a/inspect/to_sprint go-ndarray's NumPy-styleRepr(array([[0., 1., 2.],\n [3., 4., 5.]])) instead ofArray(shape=[2 3], data=[...])Bugs fixed
NDArray.arange(5)raisedArgumentError: arange: runtime error: index out of range [1] with length 1, which was a recovered Go panic.NDArray.full()failed the same way. Every method now checks its arguments. A wrong count raisesArgumentError(MRI'swrong number of arguments (given n, expected m)), and a wrong type raisesTypeError. A go-ndarray error is re-raised with go-ndarray's own message:IndexErrorfor an index or axis out of range,ArgumentErrorfor the rest.TestNativeFaultBecomesRubyErrorusedNDArray.arange(6)as its example of a faulting native. It now lives innative_fault_internal_test.goand plants its own faulting native, so the safety net no longer depends on a binding staying broken.GOOS=js GOARCH=wasm"does not build". It has built since internal/vm, ci: fix the js/wasm build, and make the guard that caught it reachable #684.readme_wasm_lane_test.gonow compares a flattened README, so the reworded claims are caught across line breaks and bold markers. Checked: the test fails on the old README.Dependency
github.com/go-ndarray/ndarraygoes from v0.3.0 to v0.11.0, andgithub.com/go-fft/fftfrom v0.1.14 to v0.23.0 with it. This is done here rather than through the grouped Renovate PR #792, which is still dirty and is not touched.How the expectations were derived
ndarray_test.gowas worked out by hand from NumPy's definition of the operation. None was taken from the binding's own output.TestNDArraySlicingwalks the contract's indexing table row by row, plus inclusive ranges, negative steps, clamping, empty slices and multi-axis indexing. Each row holds three things that must agree: the Ruby index, the hand-derived NumPy elements and shape, and the same slice taken through go-ndarray's Go API (Slice(A/All/R/Rng/From/To/Step)).TestNDArrayMatchesGoOraclecomparespoutput with go-ndarray'sReprof the same computation done in Go. go-ndarray's Go API is the oracle the playground's Go column uses.array ** arrayhas no go-ndarray counterpart. It is checked against elementwisemath.Powafter broadcasting.TestNDArrayArgumentCheckscalls every method with too few arguments, too many, and wrong types. It asserts the exception class and message, and that no message containsruntime error.ndarray.gois at 100% coverage. TheToSrow leaves bothBELOW100records.web/smoke.mjsnow runs an NDArray program in the JS host, which is the playground's use case.Known differences from NumPy (go-ndarray's, not the binding's)
Reprformats floats in their shortest form, solinspace(0, 1, 5)printsarray([ 0., 0.25, 0.5, 0.75, 1.]). NumPy printsarray([0. , 0.25, 0.5 , 0.75, 1. ]). Large arrays also get a, shape=(...)suffix.clip(lo, hi)withlo > hiraisesArgumentError(go-ndarray's error). NumPy returnshieverywhere.argmax(axis)returns an int64 array, as NumPy does.to_astill yields Floats, as the contract requires.🤖 Generated with Claude Code