Skip to content

moonbit-community/openblas.mbt

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

71 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

OpenBLAS.mbt

中文

This is an OpenBLAS binding library for the MoonBit Programming Language. OpenBLAS is a high-performance implementation of BLAS (Basic Linear Algebra Subprograms) and parts of LAPACK (Linear Algebra PACKage), widely used in scientific computing and machine learning.

⚠️ Development Warning

Important: The OpenBLAS bindings in this library are complete, but many APIs have not been thoroughly tested. Please test the relevant functions carefully before using them in a production environment. We welcome community contributions for test cases and bug reports.

System Requirements & Installation

macOS

Install OpenBLAS using Homebrew:

brew install openblas

Linux (Ubuntu/Debian)

sudo apt-get update
sudo apt-get install libopenblas-dev

Linux (CentOS/RHEL/Fedora)

# CentOS/RHEL
sudo yum install openblas-devel

# Fedora
sudo dnf install openblas-devel

Windows

Note: Windows is theoretically supported but has not been tested. You can try the following methods:

  1. Use vcpkg to install OpenBLAS.
  2. Download a pre-compiled version from the OpenBLAS official website.
  3. Adjust the environment configuration files accordingly.

Package Management & Installation

Update Package Index

moon update

Install Package

moon add Kaida-Amethyst/openblas

Project Configuration

1. Package Configuration

In the package where you intend to use OpenBLAS, configure moon.pkg.json:

{
  "import": [
    "Kaida-Amethyst/openblas/cblas",
    "Kaida-Amethyst/openblas/lapack"
  ],
  "link": {
    "native": {
      "cc": "$CC",
      "cc-flags": "$CC_FLAGS -w",
      "cc-link-flags": "$CC_LINK_FLAGS"
    }
  }
}

2. Environment Configuration

The $CC, $CC_FLAGS, and $CC_LINK_FLAGS are environment variables. It is recommended to configure them in an env.sh file.

# env.sh
OPENBLAS_PATH=$(brew --prefix openblas)  # macOS example

export CC=gcc
export CC_FLAGS="-I$OPENBLAS_PATH/include"
export CC_LINK_FLAGS="-L$OPENBLAS_PATH/lib -lopenblas"
export C_INCLUDE_PATH="$C_INCLUDE_PATH:/opt/homebrew/include:$OPENBLAS_PATH/include"

Linux users should adjust the paths accordingly:

# Linux example (paths may vary by distribution)
export CC=gcc
export CC_FLAGS="-I/usr/include/openblas"
export CC_LINK_FLAGS="-lopenblas"

Remember to load the environment variables before use:

source env.sh

Usage Examples

CBLAS Example - Vector Dot Product and Matrix Multiplication

Here is an example of using CBLAS for basic linear algebra operations:

fn cblas_example() -> Unit {
  // Example 1: Vector Dot Product
  println("=== CBLAS Vector Dot Product Example ===")
  let n = 4
  let x : FixedArray[Float] = [1.0, 2.0, 3.0, 4.0]
  let y : FixedArray[Float] = [2.0, 1.0, 4.0, 3.0]
  
  // Calculate x · y = 1*2 + 2*1 + 3*4 + 4*3 = 28
  let dot_result = @cblas.cblas_sdot(n, x, 1, y, 1)
  println("Vector dot product result: \{dot_result}")
  
  // Example 2: Vector Normalization
  println("\n=== Vector Normalization Example ===")
  let vec : FixedArray[Float] = [3.0, 4.0, 0.0]
  let norm = @cblas.cblas_snrm2(3, vec, 1)
  println("Euclidean norm of vector [3, 4, 0]: \{norm}")
  
  // Normalize the vector (divide by its norm)
  @cblas.cblas_sscal(3, 1.0 / norm, vec, 1)
  println("Normalized vector: [\{vec[0]}, \{vec[1]}, \{vec[2]}]")
  
  // Example 3: Matrix-Vector Multiplication (GEMV)
  println("\n=== Matrix-Vector Multiplication Example ===")
  let m = 3  // Matrix rows
  let n = 3  // Matrix columns
  let alpha : Float = 1.0
  let beta : Float = 0.0
  
  // 3x3 Matrix A (row-major order)
  let a : FixedArray[Float] = [
    1.0, 2.0, 3.0,  // Row 1
    4.0, 5.0, 6.0,  // Row 2
    7.0, 8.0, 9.0   // Row 3
  ]
  let input_vec : FixedArray[Float] = [1.0, 1.0, 1.0]
  let result_vec : FixedArray[Float] = [0.0, 0.0, 0.0]
  
  // Calculate result_vec = A * input_vec
  @cblas.cblas_sgemv(
    @cblas.CblasRowMajor, @cblas.CblasNoTrans,
    m, n, alpha, a, n, input_vec, 1, beta, result_vec, 1
  )
  
  println("Matrix A * vector [1,1,1] = [\{result_vec[0]}, \{result_vec[1]}, \{result_vec[2]}]")
  
  // Example 4: Vector Addition (AXPY: y = a*x + y)
  println("\n=== Vector Addition Example (AXPY) ===")
  let alpha2 : Float = 2.5
  let x2 : FixedArray[Float] = [1.0, 2.0, 3.0]
  let y2 : FixedArray[Float] = [4.0, 5.0, 6.0]
  
  println("Before: x = [\{x2[0]}, \{x2[1]}, \{x2[2]}], y = [\{y2[0]}, \{y2[1]}, \{y2[2]}]")
  
  // Calculate y = 2.5 * x + y
  @cblas.cblas_saxpy(3, alpha2, x2, 1, y2, 1)
  
  println("y = 2.5 * x + y = [\{y2[0]}, \{y2[1]}, \{y2[2]}]")
}

fn main {
  cblas_example()
}

LAPACK Example - Solving Linear Equations and Eigenvalue Decomposition

Here is an example of using LAPACK for advanced linear algebra operations:

fn lapack_example() -> Unit {
  // Example 1: Solve linear system Ax = b (using LU decomposition)
  println("=== LAPACK Linear System Solver Example ===")
  
  let n = 3      // Matrix dimension
  let nrhs = 1   // Number of right-hand side vectors
  
  // 3x3 coefficient matrix A (column-major order, as required by LAPACK)
  let a : FixedArray[Double] = [
    2.0, 1.0, 1.0,  // Column 1
    1.0, 3.0, 2.0,  // Column 2
    1.0, 2.0, 4.0   // Column 3
  ]
  
  // Right-hand side vector b
  let b : FixedArray[Double] = [8.0, 13.0, 18.0]
  
  // Row permutation array for LU decomposition
  let ipiv : FixedArray[Int] = [0, 0, 0]
  
  println("Solving system:")
  println("2x + y + z = 8")
  println("x + 3y + 2z = 13")  
  println("x + 2y + 4z = 18")
  
  // Call LAPACK's DGESV function to solve
  let info = @lapack.lapacke_dgesv(
    @lapack.LAPACK_COL_MAJOR, n, nrhs, a, n, ipiv, b, n
  )
  
  if info == 0 {
    println("Solution: x = \{b[0]}, y = \{b[1]}, z = \{b[2]}")
  } else {
    println("Failed to solve, error code: \{info}")
  }
  
  // Example 2: QR Decomposition of a matrix
  println("\n=== QR Decomposition Example ===")
  
  let m2 = 3
  let n2 = 3
  
  // Matrix to be decomposed (column-major)
  let a2 : FixedArray[Double] = [
    1.0, 1.0, 1.0,  // Column 1
    2.0, 1.0, 0.0,  // Column 2
    3.0, 2.0, 1.0   // Column 3
  ]
  
  // Array to store Householder reflector vectors
  let tau : FixedArray[Double] = [0.0, 0.0, 0.0]
  
  println("Performing QR decomposition on matrix:")
  println("A = [[1, 2, 3], [1, 1, 2], [1, 0, 1]]")
  
  // Call DGEQRF for QR decomposition
  let info2 = @lapack.lapacke_dgeqrf(
    @lapack.LAPACK_COL_MAJOR, m2, n2, a2, m2, tau
  )
  
  if info2 == 0 {
    println("QR decomposition completed successfully")
    println("Diagonal elements of R matrix: [\{a2[0]}, \{a2[4]}, \{a2[8]}]")
  } else {
    println("QR decomposition failed, error code: \{info2}")
  }
  
  // Example 3: Singular Value Decomposition (SVD)
  println("\n=== Singular Value Decomposition Example ===")
  
  let m3 = 2
  let n3 = 3
  
  // 2x3 matrix
  let a3 : FixedArray[Double] = [
    1.0, 3.0,     // Column 1
    2.0, 4.0,     // Column 2
    3.0, 5.0      // Column 3
  ]
  
  // Array for singular values
  let s : FixedArray[Double] = [0.0, 0.0]
  
  // U and VT matrices (simplified here, not extracted)
  let u : FixedArray[Double] = []
  let vt : FixedArray[Double] = []
  
  println("Calculating singular values of matrix [[1, 2, 3], [3, 4, 5]]")
  
  // Call DGESVD to compute singular values
  let info3 = @lapack.lapacke_dgesvd(
    @lapack.LAPACK_COL_MAJOR, 'N'.to_int().to_byte(), 'N'.to_int().to_byte(),
    m3, n3, a3, m3, s, u, m3, vt, n3
  )
  
  if info3 == 0 {
    println("Singular values: [\{s[0]}, \{s[1]}]")
  } else {
    println("SVD computation failed, error code: \{info3}")
  }
}

fn main {
  lapack_example()
}

API Reference

CBLAS Module

This library provides the complete CBLAS Level 1, Level 2, and Level 3 functions, including:

  • Level 1: Vector operations (dot product, norm, rotation, etc.)
  • Level 2: Matrix-vector operations (GEMV, SYR, etc.)
  • Level 3: Matrix-matrix operations (GEMM, SYRK, etc.)

It supports single-precision (s prefix) and double-precision (d prefix) floating-point operations, as well as complex numbers (c prefix for single-precision complex, z for double-precision complex).

LAPACK Module

This library provides core LAPACK functionalities, including:

  • Linear System Solvers: GESV, POSV, SYSV, etc.
  • Matrix Decompositions: LU, QR, Cholesky, SVD, etc.
  • Eigenvalue Problems: SYEV, GEEV, etc.
  • Least Squares Problems: GELS, etc.

License

This project is licensed under the Apache-2.0 License. See the LICENSE file for details.

Related Links


中文

OpenBLAS.mbt

这是一个为 MoonBit 编程语言 提供的 OpenBLAS 绑定库。OpenBLAS 是一个高性能的 BLAS (Basic Linear Algebra Subprograms) 和部分 LAPACK (Linear Algebra PACKage) 实现,广泛用于科学计算和机器学习领域。

⚠️ 开发中警告

重要提示: 本库的 OpenBLAS 绑定已经完成,但许多 API 尚未经过充分测试。在生产环境中使用前,请仔细测试相关功能。我们欢迎社区贡献测试用例和 bug 报告。

系统要求与安装

macOS

使用 Homebrew 安装 OpenBLAS:

brew install openblas

Linux (Ubuntu/Debian)

sudo apt-get update
sudo apt-get install libopenblas-dev

Linux (CentOS/RHEL/Fedora)

# CentOS/RHEL
sudo yum install openblas-devel

# Fedora
sudo dnf install openblas-devel

Windows

注意: Windows 理论上可用,但尚未经过测试。你可以尝试以下方法:

  1. 使用 vcpkg 安装 OpenBLAS
  2. 或者从 OpenBLAS 官网 下载预编译版本
  3. 相应地调整环境配置文件

包管理与安装

更新包索引

moon update

安装包

moon add Kaida-Amethyst/openblas

项目配置

1. 包配置

在需要使用openblas的包内,配置 moon.pkg.json

{
  "import": [
    "Kaida-Amethyst/openblas/cblas",
    "Kaida-Amethyst/openblas/lapack"
  ],
  "link": {
    "native": {
      "cc": "$CC",
      "cc-flags": "$CC_FLAGS -w",
      "cc-link-flags": "$CC_LINK_FLAGS"
    }
  }
}

2. 环境配置

上面的$CC$CC_FLAGS$CC_LINK_FLAGS均为环境变量,建议配置env.sh

# env.sh
OPENBLAS_PATH=$(brew --prefix openblas)  # macOS 示例

export CC=gcc
export CC_FLAGS="-I$OPENBLAS_PATH/include"
export CC_LINK_FLAGS="-L$OPENBLAS_PATH/lib -lopenblas"
export C_INCLUDE_PATH="$C_INCLUDE_PATH:/opt/homebrew/include:$OPENBLAS_PATH/include"

Linux 用户请相应调整路径:

# Linux 示例 (路径可能因发行版而异)
export CC=gcc
export CC_FLAGS="-I/usr/include/openblas"
export CC_LINK_FLAGS="-lopenblas"

在使用前记得加载环境变量:

source env.sh

使用示例

CBLAS 示例 - 向量点积和矩阵乘法

以下是一个使用 CBLAS 进行基础线性代数运算的示例:

fn cblas_example() -> Unit {
  // 示例 1: 向量点积
  println("=== CBLAS 向量点积示例 ===")
  let n = 4
  let x : FixedArray[Float] = [1.0, 2.0, 3.0, 4.0]
  let y : FixedArray[Float] = [2.0, 1.0, 4.0, 3.0]
  
  // 计算 x · y = 1*2 + 2*1 + 3*4 + 4*3 = 28
  let dot_result = @cblas.cblas_sdot(n, x, 1, y, 1)
  println("向量点积结果: \{dot_result}")
  
  // 示例 2: 向量归一化
  println("\n=== 向量归一化示例 ===")
  let vec : FixedArray[Float] = [3.0, 4.0, 0.0]
  let norm = @cblas.cblas_snrm2(3, vec, 1)
  println("向量 [3, 4, 0] 的欧几里得范数: \{norm}")
  
  // 归一化向量 (除以范数)
  @cblas.cblas_sscal(3, 1.0 / norm, vec, 1)
  println("归一化后的向量: [\{vec[0]}, \{vec[1]}, \{vec[2]}]")
  
  // 示例 3: 矩阵向量乘法 (GEMV)
  println("\n=== 矩阵向量乘法示例 ===")
  let m = 3  // 矩阵行数
  let n = 3  // 矩阵列数
  let alpha : Float = 1.0
  let beta : Float = 0.0
  
  // 3x3 矩阵 A (行主序存储)
  let a : FixedArray[Float] = [
    1.0, 2.0, 3.0,  // 第一行
    4.0, 5.0, 6.0,  // 第二行
    7.0, 8.0, 9.0   // 第三行
  ]
  let input_vec : FixedArray[Float] = [1.0, 1.0, 1.0]
  let result_vec : FixedArray[Float] = [0.0, 0.0, 0.0]
  
  // 计算 result_vec = A * input_vec
  @cblas.cblas_sgemv(
    @cblas.CblasRowMajor, @cblas.CblasNoTrans,
    m, n, alpha, a, n, input_vec, 1, beta, result_vec, 1
  )
  
  println("矩阵 A * 向量 [1,1,1] = [\{result_vec[0]}, \{result_vec[1]}, \{result_vec[2]}]")
  
  // 示例 4: 向量加法 (AXPY: y = a*x + y)
  println("\n=== 向量加法示例 (AXPY) ===")
  let alpha2 : Float = 2.5
  let x2 : FixedArray[Float] = [1.0, 2.0, 3.0]
  let y2 : FixedArray[Float] = [4.0, 5.0, 6.0]
  
  println("操作前: x = [\{x2[0]}, \{x2[1]}, \{x2[2]}], y = [\{y2[0]}, \{y2[1]}, \{y2[2]}]")
  
  // 计算 y = 2.5 * x + y
  @cblas.cblas_saxpy(3, alpha2, x2, 1, y2, 1)
  
  println("y = 2.5 * x + y = [\{y2[0]}, \{y2[1]}, \{y2[2]}]")
}

fn main {
  cblas_example()
}

LAPACK 示例 - 线性方程组求解和特征值分解

以下是一个使用 LAPACK 进行高级线性代数运算的示例:

fn lapack_example() -> Unit {
  // 示例 1: 求解线性方程组 Ax = b (使用LU分解)
  println("=== LAPACK 线性方程组求解示例 ===")
  
  let n = 3  // 矩阵维数
  let nrhs = 1  // 右端向量个数
  
  // 3x3 系数矩阵 A (列主序存储,LAPACK 要求)
  let a : FixedArray[Double] = [
    2.0, 1.0, 1.0,  // 第一列
    1.0, 3.0, 2.0,  // 第二列  
    1.0, 2.0, 4.0   // 第三列
  ]
  
  // 右端向量 b
  let b : FixedArray[Double] = [8.0, 13.0, 18.0]
  
  // LU 分解的行置换数组
  let ipiv : FixedArray[Int] = [0, 0, 0]
  
  println("求解方程组:")
  println("2x + y + z = 8")
  println("x + 3y + 2z = 13")  
  println("x + 2y + 4z = 18")
  
  // 调用 LAPACK 的 DGESV 函数求解
  let info = @lapack.lapacke_dgesv(
    @lapack.LAPACK_COL_MAJOR, n, nrhs, a, n, ipiv, b, n
  )
  
  if info == 0 {
    println("解为: x = \{b[0]}, y = \{b[1]}, z = \{b[2]}")
  } else {
    println("求解失败, 错误代码: \{info}")
  }
  
  // 示例 2: 矩阵的QR分解
  println("\n=== QR 分解示例 ===")
  
  let m2 = 3
  let n2 = 3
  
  // 待分解的矩阵 (列主序)
  let a2 : FixedArray[Double] = [
    1.0, 1.0, 1.0,  // 第一列
    2.0, 1.0, 0.0,  // 第二列
    3.0, 2.0, 1.0   // 第三列
  ]
  
  // 存储 Householder 反射向量的数组
  let tau : FixedArray[Double] = [0.0, 0.0, 0.0]
  
  println("对矩阵进行 QR 分解:")
  println("A = [[1, 2, 3], [1, 1, 2], [1, 0, 1]]")
  
  // 调用 DGEQRF 进行 QR 分解
  let info2 = @lapack.lapacke_dgeqrf(
    @lapack.LAPACK_COL_MAJOR, m2, n2, a2, m2, tau
  )
  
  if info2 == 0 {
    println("QR 分解成功完成")
    println("R 矩阵的对角元素: [\{a2[0]}, \{a2[4]}, \{a2[8]}]")
  } else {
    println("QR 分解失败, 错误代码: \{info2}")
  }
  
  // 示例 3: 计算矩阵的奇异值分解 (SVD)
  println("\n=== 奇异值分解示例 ===")
  
  let m3 = 2
  let n3 = 3
  
  // 2x3 矩阵
  let a3 : FixedArray[Double] = [
    1.0, 3.0,     // 第一列
    2.0, 4.0,     // 第二列  
    3.0, 5.0      // 第三列
  ]
  
  // 奇异值数组
  let s : FixedArray[Double] = [0.0, 0.0]
  
  // U 和 VT 矩阵 (这里简化处理,不提取)
  let u : FixedArray[Double] = []
  let vt : FixedArray[Double] = []
  
  println("计算矩阵 [[1, 2, 3], [3, 4, 5]] 的奇异值")
  
  // 调用 DGESVD 计算奇异值
  let info3 = @lapack.lapacke_dgesvd(
    @lapack.LAPACK_COL_MAJOR, 'N'.to_int().to_byte(), 'N'.to_int().to_byte(),
    m3, n3, a3, m3, s, u, m3, vt, n3
  )
  
  if info3 == 0 {
    println("奇异值: [\{s[0]}, \{s[1]}]")
  } else {
    println("SVD 计算失败, 错误代码: \{info3}")
  }
}

fn main {
  lapack_example()
}

About

OpenBLAS binding in MoonBit

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •