Wave API¶
The Wave 0.2.1 binding targets 64-bit systems where C size_t matches Wave
u64. Import bindings/wave/hmath.wave beside your source as shown in the
Wave integration guide. All numerical values are f64.
Function index¶
| API | Purpose |
|---|---|
| initialize | Initialize the shared runtime after checking the ABI. |
| error_message | Borrow the current thread’s native error message. |
| scalar_add | Add two finite real scalars. |
| tensor_empty | Construct an empty wrapper without allocating a native tensor. |
| tensor_copy | Copy row-major values into an owned tensor. |
| vector_copy | Copy values into an owned rank-one tensor. |
| matrix_copy | Copy row-major values into an owned rank-two tensor. |
| tensor_clone | Acquire a separate owner for the same native tensor. |
| tensor_close | Release one owned wrapper and clear its handle. |
| tensor_count | Query the logical element count. |
| tensor_values | Copy logical values into caller-owned storage. |
| tensor_sum | Sum all logical tensor elements. |
| tensor_dot | Reduce corresponding products to one scalar. |
| tensor_add | Add identically shaped tensors element by element. |
| tensor_matmul | Multiply two dense rank-two matrices. |
Shared rules¶
Tensor { handle: ptr<u8> } owns one native reference. Treat owners linearly:
plain struct assignment does not retain a second reference. Use
tensor_clone, and close every owner, including those created before a later
failure. Keep all input handles live throughout a call.
Status-returning wrappers return i32: zero means success. The C
status table defines the other values. Read
error_message() immediately after a failed native checked call. Wrapper-only
validation (such as an occupied output slot or ABI mismatch) returns its code
without replacing the native diagnostic, so the message may describe an earlier
call. Do not use that stale message as the reason for wrapper validation failure.
Every tensor output must be a non-NULL pointer to a wrapper initialized with
tensor_empty(). Success transfers one owned reference; failure leaves that
empty wrapper unchanged. Scalar outputs are valid only on success. Inputs
must obey the C ABI's rank 8, 1,048,576-element, finite-data, and storage bounds.
Initialization and diagnostics¶
initialize() -> i32¶
Initialize the shared runtime after checking the ABI.
Parameters¶
None.
Returns¶
0 on success, 10 for unsupported ABI, 5 after irreversible shutdown.
Repeated initialization is allowed. Constructors and scalar_add call this
automatically. It does not create a tensor or an ownership obligation.
See also¶
tensor_copy, tensor_clone, tensor_close.
error_message() -> ptr<i8>¶
Borrow the current thread’s native error message.
Parameters¶
None.
Returns¶
a borrowed, NUL-terminated thread-local native error string. It remains valid until the next checked C call on this thread. Copy it before that call if it must survive; never free it. Wrapper-only validation does not set a fresh message; see the shared rules.
See also¶
tensor_copy, tensor_clone, tensor_close.
scalar_add(a: f64, b: f64, output: ptr<f64>) -> i32¶
Add two finite real scalars.
Parameters¶
| Name | Type / default | Description |
|---|---|---|
a |
f64 |
First finite scalar. |
b |
f64 |
Second finite scalar. |
output |
ptr<f64> |
Aligned writable scalar slot; valid only on success. |
Returns¶
status 0 and their sum in output after automatic initialization.
Errors¶
invalid/non-finite input or result, initialization or native runtime
failure. Example: scalar_add(2.0, 3.0, &value) writes 5.0 on success.
See also¶
tensor_copy, tensor_clone, tensor_close.
Construction and ownership¶
tensor_empty() -> Tensor¶
Construct an empty wrapper without allocating a native tensor.
Parameters¶
None.
Returns¶
Tensor { handle: null }, with no native
reference to release. Use this to initialize every result slot before passing
its address to a constructor, clone, add, or matrix multiplication.
See also¶
tensor_copy, tensor_clone, tensor_close.
tensor_copy(data: ptr<f64>, count: u64, shape: ptr<u64>, rank: u64, output: ptr<Tensor>) -> i32¶
Copy row-major values into an owned tensor.
Parameters¶
| Name | Type / default | Description |
|---|---|---|
data |
ptr<f64> |
Readable finite f64 values; NULL only for zero count. |
count |
u64 |
Number of values, equal to the shape product. |
shape |
ptr<u64> |
Array of rank dimensions; may be NULL for rank zero. |
rank |
u64 |
Dimension count, at most eight. |
output |
ptr<Tensor> |
Non-NULL pointer to a wrapper initialized with tensor_empty(). |
Returns¶
status 0 and a new owned row-major copy; input ownership is unchanged.
Errors¶
occupied/NULL output, invalid storage/dimensions, count mismatch, size bound, initialization, or allocation failure.
Notes¶
count readable finite doubles, rank dimensions, and empty
output wrapper. Count must equal the dimension product. Rank zero contains one
value; zero dimensions allow an empty tensor. Data must remain readable during
this synchronous call.
See also¶
tensor_clone, tensor_close, error_message.
vector_copy(data: ptr<f64>, count: u64, output: ptr<Tensor>) -> i32¶
Copy values into an owned rank-one tensor.
Parameters¶
| Name | Type / default | Description |
|---|---|---|
data |
ptr<f64> |
Readable finite f64 values; NULL only for zero count. |
count |
u64 |
Vector length, at most 1,048,576. |
output |
ptr<Tensor> |
Non-NULL pointer to an empty result wrapper. |
Returns¶
status 0 and a new owned rank-one tensor of length count.
Errors¶
the same construction errors as tensor_copy.
The values are copied, so the source can be reused once the call returns.
See also¶
tensor_copy, tensor_clone, tensor_close.
matrix_copy(data: ptr<f64>, count: u64, rows: u64, columns: u64, output: ptr<Tensor>) -> i32¶
Copy row-major values into an owned rank-two tensor.
Parameters¶
| Name | Type / default | Description |
|---|---|---|
data |
ptr<f64> |
Readable finite row-major values. |
count |
u64 |
Number of values, equal to rows * columns. |
rows |
u64 |
Nonnegative bounded row count. |
columns |
u64 |
Nonnegative bounded column count. |
output |
ptr<Tensor> |
Non-NULL pointer to an empty result wrapper. |
Returns¶
status 0 and a new owned rank-two matrix.
Errors¶
construction errors, including count != rows * columns.
For {1,2,3,4}, dimensions 2 by 2 create rows [1,2] and [3,4].
See also¶
tensor_copy, tensor_clone, tensor_close.
tensor_clone(source: Tensor, output: ptr<Tensor>) -> i32¶
Acquire a separate owner for the same native tensor.
Parameters¶
| Name | Type / default | Description |
|---|---|---|
source |
Tensor |
Live source wrapper; remains owned by the caller. |
output |
ptr<Tensor> |
Non-NULL pointer to an empty result wrapper. |
Returns¶
0 and a second owned reference to the same immutable native tensor. No values are copied. Both owners must be closed independently.
Errors¶
1 for an empty source, NULL output, or occupied output slot.
See also¶
tensor_copy, tensor_close, error_message.
tensor_close(tensor: ptr<Tensor>)¶
Release one owned wrapper and clear its handle.
Parameters¶
| Name | Type / default | Description |
|---|---|---|
tensor |
ptr<Tensor> |
Pointer to an owned or empty wrapper; NULL is a no-op. |
Returns¶
nothing. Release its native reference and set the handle to NULL. Repeated close is safe. Do not close the last owner concurrently with use. Cloned owners remain valid. Call this on all success and error cleanup paths.
See also¶
tensor_copy, tensor_clone, error_message.
Inspection¶
tensor_count(tensor: Tensor) -> u64¶
Query the logical element count.
Parameters¶
| Name | Type / default | Description |
|---|---|---|
tensor |
Tensor |
Live or empty wrapper; an empty wrapper returns zero. |
Returns¶
logical element count; empty/closed wrapper returns zero. A rank-zero scalar counts as one. This is a query, not a status result; a zero count cannot distinguish an empty tensor from an empty wrapper.
See also¶
tensor_copy, tensor_clone, tensor_close.
tensor_values(tensor: Tensor, output: ptr<f64>, count: u64) -> i32¶
Copy logical values into caller-owned storage.
Parameters¶
| Name | Type / default | Description |
|---|---|---|
tensor |
Tensor |
Live source wrapper. |
output |
ptr<f64> |
Aligned writable non-overlapping buffer; NULL for zero elements. |
count |
u64 |
Output capacity in f64 elements, at least tensor_count(tensor). |
Returns¶
0 after copying flat logical row-major values.
Errors¶
invalid handle/buffer, overlap, or insufficient capacity (8). It neither consumes the tensor nor transfers storage ownership.
Notes¶
live wrapper and aligned caller-owned output buffer; count
is capacity in doubles, at least tensor_count(tensor). It must not overlap
native input storage. A NULL buffer is allowed for zero elements.
See also¶
tensor_copy, tensor_clone, tensor_close.
Calculations¶
These wrappers use the existing runtime and disable cancellation (NULL C
context). Construct an input or call initialize() first. Common native failures
include unavailable runtime, allocation, and non-finite arithmetic.
tensor_sum(tensor: Tensor, output: ptr<f64>) -> i32¶
Sum all logical tensor elements.
Parameters¶
| Name | Type / default | Description |
|---|---|---|
tensor |
Tensor |
Live input wrapper. |
output |
ptr<f64> |
Aligned writable scalar slot; valid only on success. |
Returns¶
0 with the sum of every logical element, or zero for an empty tensor.
Errors¶
invalid pointers/handle or common native failures. The input owner remains unchanged.
See also¶
tensor_copy, tensor_clone, tensor_close.
tensor_dot(a: Tensor, b: Tensor, output: ptr<f64>) -> i32¶
Reduce corresponding products to one scalar.
Parameters¶
| Name | Type / default | Description |
|---|---|---|
a |
Tensor |
Live first wrapper. |
b |
Tensor |
Live second wrapper with identical shape. |
output |
ptr<f64> |
Aligned writable scalar slot; valid only on success. |
Returns¶
0 with the sum of elementwise products; matching empty tensors give zero.
Errors¶
shape mismatch, invalid pointers/handles, or common native failures. This is a scalar reduction, not matrix multiplication.
See also¶
tensor_copy, tensor_clone, tensor_close.
tensor_add(a: Tensor, b: Tensor, output: ptr<Tensor>) -> i32¶
Add identically shaped tensors element by element.
Parameters¶
| Name | Type / default | Description |
|---|---|---|
a |
Tensor |
Live first wrapper. |
b |
Tensor |
Live second wrapper with identical shape; no broadcasting. |
output |
ptr<Tensor> |
Non-NULL pointer to an empty result wrapper. |
Returns¶
0 with a new owned elementwise sum. Inputs remain unchanged; there is no broadcasting.
Errors¶
occupied/NULL output, shape mismatch, invalid handles, or common native failures. Close the result independently of its inputs.
See also¶
tensor_copy, tensor_clone, tensor_close.
tensor_matmul(a: Tensor, b: Tensor, output: ptr<Tensor>) -> i32¶
Multiply two dense rank-two matrices.
Parameters¶
| Name | Type / default | Description |
|---|---|---|
a |
Tensor |
Live left matrix of shape (m, k). |
b |
Tensor |
Live right matrix of shape (k, n). |
output |
ptr<Tensor> |
Non-NULL pointer to an empty wrapper; result shape is (m, n). |
Returns¶
0 with a new owned (m,n) dense product.
Errors¶
invalid/occupied output, rank/inner-dimension mismatch, element/work bounds (at most 16,777,216 scalar multiply-add steps), or common native failures. Batched and broadcasted matrix products are not exposed by this wrapper.
See also¶
tensor_copy, tensor_clone, tensor_close.
Example with cleanup¶
Place this file beside the binding, then use the compiler/linker setup in the Wave guide.
import("./hmath")::{Tensor, tensor_empty, vector_copy, tensor_sum, tensor_close};
fun main() -> i32 {
var samples: array<f64, 3> = [1.0, 2.0, 3.0];
var tensor: Tensor = tensor_empty();
var total: f64 = 0.0;
var status: i32 = vector_copy(&samples[0], 3, &tensor);
if (status == 0) {
status = tensor_sum(tensor, &total);
}
tensor_close(&tensor);
if (status != 0 || total != 6.0) {
return 1;
}
return 0;
}
The lower-level extern(c, ...) declarations support these wrappers. Their
contracts are the corresponding C ABI functions. The process owner,
rather than each Wave tensor, controls final runtime shutdown.