Jump to content

Connect Leeroopedia MCP: Equip your AI agents to search best practices, build plans, verify code, diagnose failures, and look up hyperparameter defaults.

Implementation:Haifengl Smile DenseMatrix Factory

From Leeroopedia


Overview

The DenseMatrix Factory provides static factory methods on the DenseMatrix abstract class for constructing dense matrices in the Smile tensor module. These methods create matrices from raw 2D arrays, generate special matrices (zeros, identity, diagonal, random), and handle off-heap memory allocation via java.lang.foreign.MemorySegment. The factory automatically selects the appropriate concrete implementation (DenseMatrix64 for Float64, DenseMatrix32 for Float32) based on the input type or the specified ScalarType.

Type

API Doc

Source Location

base/src/main/java/smile/tensor/DenseMatrix.java:L1339-1651

Import Statements

import smile.tensor.DenseMatrix;
import smile.tensor.ScalarType;
import smile.stat.distribution.Distribution;
import smile.stat.distribution.GaussianDistribution;

External Dependencies

Dependency Purpose Integration
BLAS (cblas_h) Scalar operations during initialization Via FFM (java.lang.foreign)
LAPACK (clapack_h) Used by downstream decomposition methods Via FFM (java.lang.foreign)
java.lang.foreign.MemorySegment Off-heap matrix storage Java Foreign Function & Memory API

API Signatures

public abstract class DenseMatrix implements Matrix, Serializable {

    // Construct from raw 2D arrays
    public static DenseMatrix of(double[][] A)
    public static DenseMatrix of(float[][] A)

    // Zero matrices
    public static DenseMatrix zeros(ScalarType scalarType, int m, int n)
    public DenseMatrix zeros(int m, int n)  // instance method, inherits ScalarType

    // Identity matrices
    public static DenseMatrix eye(ScalarType scalarType, int n)
    public static DenseMatrix eye(ScalarType scalarType, int m, int n)
    public DenseMatrix eye(int n)           // instance method, inherits ScalarType
    public DenseMatrix eye(int m, int n)    // instance method, inherits ScalarType

    // Diagonal matrices
    public static DenseMatrix diagflat(double[] diag)
    public static DenseMatrix diagflat(float[] diag)

    // Random matrices
    public static DenseMatrix rand(ScalarType scalarType, int m, int n)
    public static DenseMatrix rand(ScalarType scalarType, int m, int n, double lo, double hi)
    public static DenseMatrix rand(ScalarType scalarType, int m, int n, Distribution distribution)
    public static DenseMatrix randn(ScalarType scalarType, int m, int n)

    // Toeplitz matrices
    public static DenseMatrix toeplitz(double[] a)
    public static DenseMatrix toeplitz(float[] a)
    public static DenseMatrix toeplitz(double[] kl, double[] ku)
    public static DenseMatrix toeplitz(float[] kl, float[] ku)
}

Inputs and Outputs

Method Inputs Output Notes
of(double[][]) 2D double array DenseMatrix64 Copies data to off-heap; infers Float64
of(float[][]) 2D float array DenseMatrix32 Copies data to off-heap; infers Float32
zeros(ScalarType, m, n) Scalar type + dimensions DenseMatrix64 or DenseMatrix32 All elements initialized to zero
eye(ScalarType, n) Scalar type + size Square identity matrix In where aii=1
eye(ScalarType, m, n) Scalar type + dimensions Rectangular identity aii=1 for i<min(m,n)
diagflat(double[]) 1D diagonal values Square diagonal matrix Float64 scalar type
rand(ScalarType, m, n) Scalar type + dimensions Random uniform in [0,1) Uses MathEx.random()
randn(ScalarType, m, n) Scalar type + dimensions Random standard normal Delegates to GaussianDistribution
toeplitz(double[]) 1D array Symmetric Toeplitz matrix Sets UPLO=LOWER for symmetry

Implementation Details

Leading Dimension Optimization

The zeros() factory computes an optimized leading dimension before allocating:

static int ld(int n) {
    int elementSize = 4;
    if (n <= 256 / elementSize) return n;
    return (((n * elementSize + 511) / 512) * 512 + 64) / elementSize;
}

This ensures the leading dimension avoids powers of 2 that cause cache set conflicts on modern CPUs. For small matrices (n64), no padding is applied.

Scalar Type Dispatch

The zeros() method uses a switch expression to dispatch to the correct concrete type:

public static DenseMatrix zeros(ScalarType scalarType, int m, int n) {
    int ld = ld(m);
    return switch (scalarType) {
        case Float64 -> {
            double[] array = new double[ld * n];
            yield new DenseMatrix64(array, m, n, ld, null, null);
        }
        case Float32 -> {
            float[] array = new float[ld * n];
            yield new DenseMatrix32(array, m, n, ld, null, null);
        }
        default -> throw new UnsupportedOperationException("Unsupported ScalarType: " + scalarType);
    };
}

Memory Layout

Matrices are stored in column-major order with element aij at offset jld+i. The underlying storage is a MemorySegment backed by a Java array, which the FFM API can pass directly to native BLAS/LAPACK functions.

Usage Examples

Creating a Matrix from Data

import smile.tensor.DenseMatrix;
import smile.tensor.ScalarType;

// From a 2D double array (yields Float64 DenseMatrix)
double[][] data = {
    {1.0, 2.0, 3.0},
    {4.0, 5.0, 6.0},
    {7.0, 8.0, 9.0}
};
DenseMatrix A = DenseMatrix.of(data);
System.out.println(A.nrow() + " x " + A.ncol()); // 3 x 3
System.out.println(A.scalarType());               // Float64

// From a 2D float array (yields Float32 DenseMatrix)
float[][] floatData = {
    {1.0f, 2.0f},
    {3.0f, 4.0f}
};
DenseMatrix B = DenseMatrix.of(floatData);
System.out.println(B.scalarType()); // Float32

Generating Special Matrices

import smile.tensor.DenseMatrix;
import smile.tensor.ScalarType;

// 4x4 zero matrix in double precision
DenseMatrix Z = DenseMatrix.zeros(ScalarType.Float64, 4, 4);

// 3x3 identity matrix in single precision
DenseMatrix I = DenseMatrix.eye(ScalarType.Float32, 3);
System.out.println(I.get(0, 0)); // 1.0
System.out.println(I.get(0, 1)); // 0.0

// 5x5 identity matrix (rectangular variant)
DenseMatrix I_rect = DenseMatrix.eye(ScalarType.Float64, 5, 3);

Random Matrix Generation

import smile.tensor.DenseMatrix;
import smile.tensor.ScalarType;

// 100x50 random matrix with uniform distribution in [0, 1)
DenseMatrix R = DenseMatrix.rand(ScalarType.Float64, 100, 50);

// 100x50 random matrix with standard normal distribution
DenseMatrix G = DenseMatrix.randn(ScalarType.Float64, 100, 50);

// Uniform random in a specific range [-1, 1)
DenseMatrix U = DenseMatrix.rand(ScalarType.Float64, 100, 50, -1.0, 1.0);

Diagonal and Toeplitz Matrices

import smile.tensor.DenseMatrix;

// Diagonal matrix from eigenvalues
double[] eigenvalues = {5.0, 3.0, 1.0};
DenseMatrix D = DenseMatrix.diagflat(eigenvalues);
// D = diag(5, 3, 1)

// Symmetric Toeplitz matrix (constant diagonals)
double[] toepCoeffs = {4.0, 1.0, 0.5};
DenseMatrix T = DenseMatrix.toeplitz(toepCoeffs);
// T is symmetric with UPLO = LOWER
System.out.println(T.isSymmetric()); // true

Setting Matrix Properties

import smile.tensor.DenseMatrix;
import smile.tensor.ScalarType;
import smile.linalg.UPLO;

// Create a symmetric matrix and mark it
DenseMatrix S = DenseMatrix.zeros(ScalarType.Float64, 3, 3);
S.set(0, 0, 4.0); S.set(0, 1, 2.0); S.set(0, 2, 1.0);
S.set(1, 0, 2.0); S.set(1, 1, 5.0); S.set(1, 2, 3.0);
S.set(2, 0, 1.0); S.set(2, 1, 3.0); S.set(2, 2, 6.0);
S.withUplo(UPLO.LOWER);  // Mark as symmetric (lower triangular storage)
System.out.println(S.isSymmetric()); // true

// Now Cholesky decomposition and symmetric BLAS routines are available

Error Handling

Condition Exception Message
m0 or n0 IllegalArgumentException "Invalid matrix size: m x n"
ld < m for COL_MAJOR IllegalArgumentException "Invalid leading dimension for COL_MAJOR: ld < m"
Unsupported ScalarType UnsupportedOperationException "Unsupported ScalarType: ..."
withUplo() on non-square matrix IllegalArgumentException "The matrix is not square: m x n"

Performance Considerations

  • The optimized leading dimension avoids cache line conflicts, which can improve GEMM performance by 10--30% on large matrices.
  • Off-heap memory via MemorySegment avoids the 2GB limit of Java arrays and enables zero-copy transfer to native routines.
  • For small matrices (n <= 64), no leading dimension padding is applied to avoid wasting memory.

Related

Environment

Categories

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment