{"id":13483836,"url":"https://github.com/konovod/linalg","last_synced_at":"2025-05-05T21:33:46.020Z","repository":{"id":22538717,"uuid":"94973964","full_name":"konovod/linalg","owner":"konovod","description":"Linear algebra library based on LAPACK","archived":false,"fork":false,"pushed_at":"2024-01-11T10:39:31.000Z","size":10028,"stargazers_count":52,"open_issues_count":4,"forks_count":4,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-30T23:51:10.562Z","etag":null,"topics":["crystal","lapack","linear-algebra","matrix"],"latest_commit_sha":null,"homepage":"","language":"Crystal","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/konovod.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-06-21T07:07:04.000Z","updated_at":"2025-03-15T17:25:59.000Z","dependencies_parsed_at":"2024-05-02T20:00:56.819Z","dependency_job_id":"dbcd20e3-ec3c-4f4a-8bb4-d16921cbb907","html_url":"https://github.com/konovod/linalg","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/konovod%2Flinalg","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/konovod%2Flinalg/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/konovod%2Flinalg/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/konovod%2Flinalg/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/konovod","download_url":"https://codeload.github.com/konovod/linalg/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252580002,"owners_count":21771249,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["crystal","lapack","linear-algebra","matrix"],"created_at":"2024-07-31T17:01:15.784Z","updated_at":"2025-05-05T21:33:46.001Z","avatar_url":"https://github.com/konovod.png","language":"Crystal","funding_links":[],"categories":["Science and Data analysis"],"sub_categories":[],"readme":"[![Linux CI](https://github.com/konovod/linalg/actions/workflows/linux.yml/badge.svg)](https://github.com/konovod/linalg/actions/workflows/linux.yml)\n[![MacOSX CI](https://github.com/konovod/linalg/actions/workflows/macos.yml/badge.svg)](https://github.com/konovod/linalg/actions/workflows/macos.yml)\n[![Windows CI](https://github.com/konovod/linalg/actions/workflows/windows.yml/badge.svg)](https://github.com/konovod/linalg/actions/workflows/windows.yml)\n[![API Documentation](https://img.shields.io/website?down_color=red\u0026down_message=Offline\u0026label=API%20Documentation\u0026up_message=Online\u0026url=https%3A%2F%2Fkonovod.github.io%2Flinalg%2F)](https://konovod.github.io/linalg)\n\n# linalg\nLinear algebra library in Crystal, uses LAPACK.\n- direct access to LAPACK methods\n- convenient Matrix(T) class, supports T=Float32, Float64 and Complex.\n- high-level interface similar to scipy.linalg or MATLAB.\n\nKilling SciPy, one module at a time.\n\n## Installation\n\n1. Install LAPACK and BLAS. `sudo apt install libopenblas-base liblapack3` for Ubuntu, `sudo pacman -S lapack` (for better performance use `openblas-lapack` package from AUR) for Arch. For Windows you need libopenblas.dll (and libopenblas.lib) from https://github.com/xianyi/OpenBLAS/releases\n\n2. (for Ubuntu 18) it seems package doesn't create symlink, so use\n- `sudo ln -s /usr/lib/lapack/liblapack.so.3 /usr/lib/liblapack.so`\n- `sudo ln -s /usr/lib/openblas-base/libblas.so.3 /usr/lib/libcblas.so`\n\n3. Add this to your application's `shard.yml`:\n\n```yaml\ndependencies:\n  linalg:\n    github: konovod/linalg\n```\n4. Run `shards install` \n## Usage\n\n```crystal\nrequire \"linalg\"\n```\nBasic type aliases are\n- Mat = Matrix(Float64)\n- Mat32 = Matrix(Float32)\n- MatComplex = Matrix(Complex)\n\nComplex consisting of two Float32 isn't supported for now (it is easy, but I'm not sure if it's useful).\n\nTypes with prefix G (GMat, GMat32, GMatComplex) are for actually allocated matrices,\nothers are automatically converted to them when needed.\n\n```crystal\n#suggested to don't prefix LA:: everywhere\ninclude LA\n\n# create matrix from array of arrays (or tuple... everything Indexable)\nm = GMat[\n  [1, 2, 3],\n  [4, 5, 6],\n  [7, 8, 9],\n  [10, 11, 12],\n]\n\n# or using block\nm = GMat32.new(3, 4) { |i, j| i*3 + j + 1 }\n# or using one of other ways, check \"spec\" directory\n\n# do basic arithmetics\na = Mat.eye(3)\npp 2 * a - Mat.diag([2, 2, 2]) == Mat.zeros(3, 3) # =\u003e true\n\n# basic algebra\na = Mat.rand(5, 5) + 2 * Mat.identity(5)\npp (a.inv * a - Mat.identity(5)).norm \u003c 1e-6\n\nb = Mat.rand(5, 1)\nx = LA.solve(a, b) # or a.solve(b)\npp (a*x - b).norm \u003c 1e-6\n\nm = GMat[[-2, 4, 1], [2, -4, 1], [1, 1, 1]]\npp m.eigvals # =\u003e [-6.0, -1.0, 2.0]\n\n# extract submatrices (memory isn't copied as they reference to basic matrix)\nm = GMat[\n  [1, 2, 3],\n  [4, 5, 6],\n  [7, 8, 9],\n]\npp m.columns[2] # LA::SubMatrix(Float64) (3x1, None):\n# [3.0]\n# [6.0]\n# [9.0]\n\nx = m[1..1, 1..2]\npp x        # =\u003e [5.0, 6.0]\nx[0, 0] = 0 # m[1,1] is now 0 (questionable feature? maybe should be ##[]! for modifiable submatrices and ##[] for CoW?)\ny = x.clone # now y is a separate matrix\ny[0, 0] = 1 # m[1,1] is still 0\npp m[1, 1]\n\n```\nother present features:\n\n- svd (`Mat#svd` or `Mat#svdvals` for just values)\n- lu decomposition (`Mat#lu`)\n```crystal\n# to just get P L U matrices\np, l, u = a.lu\n\n# to get them in compact form and use for solving linear equations:\na = GMat32[\n  [2, 4],\n  [2, 8]\n  ]\n\nlu = a.lu_factor # lu is LUMatrix(T) - immutable object that can return it's content and solve systems\nputs lu.solve(GMat32[[2], [4]])\n```\n- matrix rank determination (using SVD or QRP)\n- linear least squares problem (`LA.solvels` to just get decision or `LA.lstsq` to also get rank and singular values (TODO - and residues))\n- cholesky decomposition (`#cholesky`, `#cholesky!`, `#cho_solve`)\n- `hessenberg` form\n- `qr`, `rq`, `lq`, `ql` decompositions\n- `schur` and `qz` (generalized schur) decomposition\n- generalized eigenproblem (`eigs(a, b, ...)`)\n- creating special matrices like `pascal` or `toeplitz` (check scipy.md for a full list)\n- matrix exponent and trigonomertic functions\n- matrix exponentiation (to integer powers only atm (TODO - fractional))\n\n\nThere is also concept of `Mat#flags` that represent properties of matrix (symmetric, positive definite etc), they are used to automatically select faster algorithms from LAPACK. Flags are partially enforced by runtime checks, with the possibility of user override. For example, if we say that `a.assume!(MatrixFlags::Symmetric)` then `a.transpose` or `a + Mat.diag(*a.size)` will also have this flag, so the LAPACK routines for symmetrical matrices will be used. In fact, `a.transpose` will return matrix clone as for symmetric matrices A=A'.\n\nSupported flags:\n```crystal\nenum MatrixFlags\n  Symmetric\n  Hermitian\n  PositiveDefinite\n  Orthogonal\n  UpperTriangular\n  LowerTriangular\n  Triangular      = UpperTriangular | LowerTriangular\n```\nNOTE for complex matrices `Orthogonal` flag means `Unitary`.\n\nMain functions for flags are:\n```crystal\n  a.assume!(flag) # sets matrix flag without check, can lead to incorrect results if matrix do not have corresponding property.\n  a.detect?(flag) # checks if matrix has property, if yes sets the flag. Returns true if check positive\n  a.detect(flag) # same as `detect?`, but returns matrix a\n  a.detect # detect all possible flags\n  a.flags # returns matrix flags\n```\nMost operations - matrix addition, multiplication, inversion, transposition and decompositions correctly update flags, but any direct access like `a[i,j] = 0` or `a.map!{|v| v+1}` resets flags to `None`, so use `a.detect` after them if you need to preserve flags (or `a.assume!(f)` if detection is too slow).\n\n## Development\n\n### Roadmap:\n\n##### Important\n\n- [x] saving/loading from files\n- [x] ways to evade allocations during calculations\n- [x] Matrix exponent and trigonometric\n- [ ] other matrix functions (fractional power and logarithm)\n- [x] Banded matrices\n  - [ ] mostly done, but some LAPACK routines could be added\n- [x] Column-major storage (optional?)\n- [ ] Other missing features from LAPACK (selectable and orderable eigenvalues, generalized decompositions, new routines etc)\n- [x] Sparse matrices\n  - [x] COO Matrix\n  - [x] CSR Matrix\n  - [x] CSC Matrix\n    - [ ] non-sorted mode\n  - [ ] sparse-dense multiplication\n  - [ ] Separate shard for SparseSuite or other libs\n\n- [ ] Other missing features from scipy.linalg (lyapunov/ricatti/sylvester equations, other things i don't know algorithms for)\n- [x] Support multithreading\\reenterability\n- [x] Allow matrices of unsupported types (use `check_type` only when actually needed)\n  - [ ] type still has to support `T.new(value)`, maybe this requirement can be relaxed\n  - [ ] also `map` signature has to be changed?\n\n##### Not so important\n\n- [x] saving/loading to matlab-like string\n- [ ] better pretty-print, with alignment and various precision\n- [x] use blas for multiplication\n- [ ] more flags support (inversion of diagonal matrix and other trivial cases)\n\n## Contributing\n\n1. Fork it ( https://github.com/konovod/linalg/fork )\n2. Create your feature branch (git checkout -b my-new-feature)\n3. Commit your changes (git commit -am 'Add some feature')\n4. Push to the branch (git push origin my-new-feature)\n5. Create a new Pull Request\n\n## Contributors\n\n- [konovod](https://github.com/konovod) - creator and maintainer\n- [RainbowZephyr](https://github.com/RainbowZephyr) - pseudoinverse implementation\n- [jtanderson](https://github.com/jtanderson) - `arange`, open-ended ranges in submatrices\n- [MatthiasWinkelmann](https://github.com/MatthiasWinkelmann) - `GMat.max` fix\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkonovod%2Flinalg","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkonovod%2Flinalg","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkonovod%2Flinalg/lists"}