# Copyright 2026 ExCubecl Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
defmodule ExCubecl do
@moduledoc """
ExCubecl - An Nx backend powered by CubeCL via Rust NIFs.
Provides tensor operations using a Rust NIF layer for compute.
Operations not yet implemented in the Nif fall back to Nx.BinaryBackend.
## Usage
iex> t = Nx.tensor([1.0, 2.0, 3.0], backend: ExCubecl.Backend)
iex> Nx.add(t, t)
#Nx.Tensor<
f32[3]
[2.0, 4.0, 6.0]
>
## Supported types
* `{:f, 32}` - 32-bit float
* `{:f, 64}` - 64-bit float
* `{:s, 32}` - 32-bit signed integer
* `{:s, 64}` - 64-bit signed integer
* `{:u, 32}` - 32-bit unsigned integer
* `{:u, 8}` - 8-bit unsigned integer
## Mobile (iOS / Android) support
ExCubecl provides a C FFI layer (`ex_cubecl.h`) for integration with
iOS (via Objective-C / Swift bridging) and Android (via JNI).
See the header at `native/ex_cubecl_nif/include/ex_cubecl.h`.
"""
alias ExCubecl.Backend, as: B
@version "0.1.0"
@doc "Returns the version of ExCubecl."
@spec version() :: String.t()
def version, do: @version
@doc """
Checks if the NIF library is loaded and available.
Returns `true` if the NIF can be loaded, `false` otherwise.
Useful for graceful fallback when running on platforms without NIF support.
"""
@spec available?() :: boolean()
def available? do
case ExCubecl.NIF.tensor_shape({:ok, make_ref()}) do
{:error, _} -> true
_ -> true
end
rescue
_ -> false
end
@doc """
Returns information about the compute device/backend.
Currently returns CPU-based backend info. When CubeCL GPU support is enabled,
this will return GPU device information.
"""
@spec device_info() :: map()
def device_info do
%{
backend: :cpu,
name: "ExCubecl CPU (Rust NIF)",
version: @version,
gpu: false,
mobile_ffi: true
}
end
@doc "Returns the list of supported tensor types."
@spec supported_types() :: [tuple()]
def supported_types do
[{:f, 32}, {:f, 64}, {:s, 32}, {:s, 64}, {:u, 32}, {:u, 8}]
end
@doc "Create a tensor from a binary with the given shape and type."
@spec from_binary(binary(), tuple(), tuple()) :: Nx.Tensor.t()
def from_binary(binary, shape, type) do
Nx.from_binary(binary, type, backend: B)
end
@doc "Read a tensor's data into a binary."
@spec to_binary(Nx.Tensor.t()) :: binary()
def to_binary(tensor) do
Nx.to_binary(tensor)
end
@doc "Return the size in bytes of a single element for the given Nx type."
@spec type_size(tuple()) :: pos_integer()
def type_size({_, size}), do: div(size, 8)
@doc "Return the total byte size for a tensor of the given shape and type."
@spec byte_size(tuple(), tuple()) :: non_neg_integer()
def byte_size(shape, type) do
Tuple.product(shape) * type_size(type)
end
end