Repository navigation
JNum v0.2.0: The Pure Java Numerical & Tensor Computing Ecosystem
We are thrilled to announce the official release of JNum v0.2.0!
While v0.1 proved that modern Java can replace C++ math backends by combining Java 25, the Foreign Function & Memory (FFM) API, and Project Panama Vector API, v0.2.0 expands JNum from a fast tensor engine into a comprehensive, production-ready numerical computing ecosystem.
JNum v0.2.0 introduces a 4-tier BLIS-inspired SIMD matrix multiplication engine, a complete Linear Algebra suite (SVD, Eigen, QR, Cholesky, Solvers), HuggingFace Safetensors & NumPy I/O with zero-copy memory mapping, a fused JIT expression engine, a statistical computing library, a neural network module, and a dedicated Kotlin DSL with operator overloading.
All of this remains 100% pure Java — zero JNI, zero native .dll/.so binaries, and zero sun.misc.Unsafe.
🚀 Key Features & Architectural Upgrades
1. 4-Tier Hardware-Adaptive BLIS MatMul Engine
Matrix multiplication has been completely re-engineered from the ground up, replacing scalar/basic SIMD with a 4-tier hardware-adaptive BLIS-style execution hierarchy:
-
Tier 0 (Nano Micro-Kernels): Fully unrolled register-direct kernels for small matrices (
$\le 4\times 4$ ), eliminating loop and dispatch overhead. -
Tier 1 (Direct Register-Blocked SIMD): Direct SIMD kernels without packing overhead for matrices up to
$128\times 128$ that comfortably fit in L1/L2 CPU cache. -
Tier 2 (Single-Threaded BLIS Cache-Blocked): Full 5-loop cache-blocking with
$A$ -panel ($M_C \times K_C$ ) and$B$ -panel ($K_C \times N_R$ ) packing for medium matrices ($128 < \max \le 256$ ) and low-FLOP counts. -
Tier 3 (Multi-Threaded BLIS Parallel): Cache-oblivious macro-kernel with parallel work-stealing ForkJoin scheduling for large matrices (
$> 256\times 256$ ). -
Performance:
-
$1024 \times 1024$ : ~10ms (best) / 14ms (avg) (down from 51ms in preview and 23ms in v0.1) — 15–22× faster than EJML and matching native OpenBLAS! -
$8192 \times 8192$ : ~5,500ms (best) / 6,500–7,000ms (avg) — 20–25× faster than EJML (which takes >141 seconds).
-
2. Complete Linear Algebra Suite (jnum.linalg.Linalg)
A full-featured linear algebra module matching numpy.linalg:
-
Matrix Decompositions:
-
Linalg.svd(A)— Singular Value Decomposition ($U, \Sigma, V^T$ ). -
Linalg.eig(A)&Linalg.eigh(A)— Eigenvalue and eigenvector solvers for general and symmetric/Hermitian matrices. -
Linalg.qr(A)— Householder QR factorization ($Q, R$ ). -
Linalg.cholesky(A)— Fast Cholesky decomposition ($L L^T$ ).
-
-
Solvers & Matrix Inversion:
-
Linalg.solve(A, B)— Direct solver for linear matrix equations$AX = B$ . -
Linalg.inv(A)— Full matrix inversion. -
Linalg.pinv(A)— Moore-Penrose pseudo-inverse with singular-value tolerance thresholding.
-
-
Metrics, Determinants & Norms:
-
Linalg.det(A)&Linalg.slogdet(A)— Determinant and sign/log-determinant for numerical stability. -
Linalg.matrixRank(A)— SVD-based numerical rank determination. -
Linalg.cond(A)— Matrix condition number. -
Linalg.norm(A, ord)— Matrix and vector$p$ -norms (Frobenius, nuclear,$L_1, L_2, L_\infty$ ). -
Linalg.trace(A, offset)— Diagonal trace with arbitrary offsets. -
Linalg.cosineSimilarity(A, B)— High-speed vector cosine similarity.
-
3. High-Performance File I/O & Zero-Copy Memory Mapping (jnum.io.JNumIO)
First-class interoperability with modern AI/ML and Python formats:
- Hugging Face Safetensors:
- Direct reading and writing of
.safetensorsmodel weights without external dependencies. readSafetensorsMmap(path)/MmapTensors: Instantaneous, zero-copy memory mapping of multi-gigabyte neural network checkpoints via JDK 25MemorySegment.map(...).inspectSafetensors(path): Fast header inspection without loading tensor payload.
- Direct reading and writing of
- NumPy Formats (
.npy&.npz):- Full support for NumPy
.npy(v1.0 & v2.0) and multi-array compressed/uncompressed.npzarchives. readNpyMmap(path)/MmapArrayfor memory-mapped zero-copy.npyingestion.
- Full support for NumPy
- CSV / TSV / Delimited Files:
- Ultra-fast
readCsv()andwriteCsv()powered byFastNumberParser(bypassing slowDouble.parseDouble()).
- Ultra-fast
- Asynchronous Non-Blocking I/O:
- Non-blocking
CompletableFutureAPIs for all readers and writers (readNpyAsync,writeSafetensorsAsync,readCsvAsync, etc.).
- Non-blocking
4. Statistical Computing Module (jnum.stat.Stats)
NumPy-grade summary statistics with full axis reduction and keepDims options:
- Central Tendency & Dispersion:
mean(),average()(with arbitrary weighting tensors),var(),std(),sampleVar(),sampleStd()with custom degrees of freedom (ddof). - Quantiles & Percentiles:
median(),quantile(),percentile(),iqr()(interquartile range) implementing all 9 standard quantile estimation methods (QuantileMethod). - Multivariate & Discrete Analysis:
cov()(full covariance matrices withrowvarsupport),mode(),ptp()(peak-to-peak),cumsum(),cumprod(), anddiff()(n-th discrete differences).
5. Fused JIT Expression Engine (jnum.internal.eval.EvalEngine)
Compile and evaluate complex compound expressions with zero intermediate allocations:
// Evaluates (a + b) * c - d in a single fused SIMD pass without temporary arrays
NDArray result = JNum.evaluate("(a + b) * c - d", a, b, c, d);- AST-based parsing and compilation directly into vectorized SIMD loops.
ConcurrentHashMapexpression plan cache eliminates parser overhead in hot loops.- Over 3× faster than chained standard operations on large datasets.
6. Neural Network Foundation (jnum.nn)
Lightweight, composable neural network components:
Modulebase class andSequentialcontainer.Linearlayer with configurable weights and biases.- SIMD-accelerated activation functions:
ReLU,Sigmoid,Softmax, andTanh.
7. First-Class Kotlin Module (kotlin-core)
Seamless, idiomatic Kotlin support via io.github.ch-abhinav:jnum-kotlin:
- Operator Overloading:
a + b,a - b,a * b,a / b,-a, plus in-place operators (+=,-=, etc.). - Infix Linear Algebra:
val c = a matmul b,val d = x dot y. - Pythonic Multidimensional Slicing:
val slice = arr[0..3, all, 2..10 step 2] val row = arr[2, all]
- All operators are marked
inlineto guarantee zero JVM call-frame or boxing overhead.
8. Expanded Type System & Vectorized Logic
- Added full
DType.boolsupport. - SIMD logical reductions and operations:
all(),any(),and(),or(),not(),xor(). - SIMD elementwise comparisons:
maximum(),minimum(). - Hardware-aligned memory allocations (64-byte alignment) to completely prevent split-cache-line penalties.
📊 Benchmark Shootout (Java 25, AVX-512/AVX2)
Benchmarks run via JMH 1.37 on JDK 25 (-Xms8g -Xmx8g -XX:+AlwaysPreTouch -XX:+UseParallelGC --add-modules jdk.incubator.vector).
1. Matrix Multiplication (ms/op — lower is better)
| Matrix Dimension | JNum v0.1 | JNum v0.2.0 (avg) | JNum v0.2.0 (best) | EJML v0.43 | NumPy (OpenBLAS) |
|---|---|---|---|---|---|
| 64 × 64 | ~0.08 ms | 0.013 ms | 0.010 ms | 0.140 ms | 0.013 ms |
| 128 × 128 | ~0.45 ms | 0.107 ms | 0.095 ms | 1.028 ms | 0.254 ms |
| 512 × 512 | ~4.10 ms | 3.45 ms | 2.80 ms | 27.16 ms | 1.86 ms |
| 1024 × 1024 | ~23.0 ms | 14.0 ms | 10.0 ms | 216.56 ms | 8.98 ms |
| 2048 × 2048 | — | 143.5 ms | 130.0 ms | 2,049.86 ms | 62.99 ms |
| 4096 × 4096 | — | 1,102.2 ms | 980.0 ms | 17,419.52 ms | 487.92 ms |
| 8192 × 8192 | — | 6,500–7,000 ms | 5,500 ms | 141,500+ ms (DNF) | 5,967.30 ms |
⚡ JNum v0.2.0 is 15–22× faster than EJML at 1024×1024, and performs on par with native C/Fortran OpenBLAS.
2. Transcendental & Trigonometric Functions (100M Elements, ms/op)
| Operation | JNum v0.2.0 | EJML | NumPy (OpenBLAS) | Speedup vs. EJML | Speedup vs. NumPy |
|---|---|---|---|---|---|
| Sin | 151.6 ms | 1,334.8 ms | 154.9 ms | 8.8× faster | 1.02× faster |
| Cos | 170.9 ms | 1,077.3 ms | 151.3 ms | 6.3× faster | ≈ tie |
| Tan | 269.2 ms | 1,767.3 ms | 792.7 ms | 6.6× faster | 2.9× faster |
| Exp | 111.5 ms | 805.0 ms | 122.1 ms | 7.2× faster | 1.1× faster |
| Log | 121.5 ms | 844.1 ms | 164.2 ms | 6.9× faster | 1.35× faster |
| Sqrt | 51.3 ms | 55.0 ms | 48.6 ms | 1.07× faster | ≈ tie |
| Tanh | 301.4 ms | 1,493.3 ms | 197.4 ms | 5.0× faster | 0.65× |
| Sigmoid | 115.0 ms | 973.7 ms | 440.5 ms | 8.5× faster | 3.8× faster |
3. Linear Algebra Inversion & Decompositions (ms/op)
| Operation | JNum v0.2.0 | ND4J (CPU Native) | Speedup vs. ND4J |
|---|---|---|---|
| Inverse [32×32] | 0.025 ms | 2.68 ms | 107× faster |
| Inverse [128×128] | 0.798 ms | 152.56 ms | 191× faster |
| Inverse [256×256] | 7.271 ms | 1,224.65 ms | 168× faster |
| Determinant [128×128] | 0.260 ms | 43.95 ms | 169× faster |
| Cholesky [32×32] | 0.006 ms | 6.64 ms | 1,100× faster |
| Solve [128×128] | 0.277 ms | 9.83 ms | 35× faster |
| QR [128×128] | 3.302 ms | 134.53 ms | 41× faster |
📦 Getting Started
1. Maven Dependency
JNum is published under io.github.ch-abhinav:
<!-- Core Java Tensor & Math Library -->
<dependency>
<groupId>io.github.ch-abhinav</groupId>
<artifactId>jnum</artifactId>
<version>0.2.0</version>
</dependency>
<!-- Optional: Kotlin Idiomatic Operator Extensions -->
<dependency>
<groupId>io.github.ch-abhinav</groupId>
<artifactId>jnum-kotlin</artifactId>
<version>0.2.0</version>
</dependency>2. Gradle (Kotlin DSL)
implementation("io.github.ch-abhinav:jnum:0.2.0")
implementation("io.github.ch-abhinav:jnum-kotlin:0.2.0")3. JVM Launch Configuration
Because JNum uses the Project Panama Vector API, add the following flag when compiling and running on Java 21+:
--add-modules jdk.incubator.vector(Optional for cleanest execution: --enable-native-access=ALL-UNNAMED)
🛠️ Quick Example
Java
import jnum.JNum;
import jnum.NDArray;
import jnum.linalg.Linalg;
import jnum.io.JNumIO;
import java.nio.file.Path;
// 1. Create tensors
NDArray a = JNum.randn(1024, 1024);
NDArray b = JNum.eye(1024);
// 2. BLIS-accelerated MatMul
NDArray c = Linalg.matmul(a, b);
// 3. Vectorized Math
NDArray activated = JNum.sigmoid(c);
// 4. Zero-copy Safetensors / NumPy I/O
JNumIO.writeNpy(activated, Path.of("weights.npy"));Kotlin
import jnum.*
import java.nio.file.Path
val a = JNum.randn(512, 512)
val b = JNum.eye(512)
// Infix & operator overloads
val c = (a matmul b) + 2.5
val slice = c[0..10, all]
// Safetensors export
JNumIO.writeSafetensors(mapOf("tensor" to slice), Path.of("model.safetensors"))⚠️ Migration & Breaking Changes from v0.1
- Maven Coordinates: Group ID migrated from
com.github.ch-abhinavto official verified Maven Central namespace:io.github.ch-abhinav. - Modular Architecture: Project is now modularized into
jnum-parent,jnum(Java core), andjnum-kotlin. - Dedicated Namespaces:
- Linear algebra functions moved to
jnum.linalg.Linalg. - File format loaders moved to
jnum.io.JNumIO. - Statistics moved to
jnum.stat.Stats. - Neural network components reside in
jnum.nn.
- Linear algebra functions moved to