{"id":37021944,"url":"https://github.com/dragonfly-ai/slash","last_synced_at":"2026-06-05T04:00:50.001Z","repository":{"id":41432255,"uuid":"78354441","full_name":"dragonfly-ai/slash","owner":"dragonfly-ai","description":"Linear Algebra and Statistics library for Scala.js, JVM, and Native.","archived":false,"fork":false,"pushed_at":"2026-06-03T01:36:14.000Z","size":8687,"stargazers_count":40,"open_issues_count":4,"forks_count":5,"subscribers_count":3,"default_branch":"main","last_synced_at":"2026-06-03T03:13:29.352Z","etag":null,"topics":["linear-algebra","machine-learning","matrix","matrix-decomposition","principal-component-analysis","scala-native","scala3","scalajs","statistics","vector"],"latest_commit_sha":null,"homepage":"https://dragonfly-ai.github.io/slash/","language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dragonfly-ai.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"dragonfly-ai"}},"created_at":"2017-01-08T16:11:15.000Z","updated_at":"2026-06-03T01:21:37.000Z","dependencies_parsed_at":"2025-12-30T08:02:59.350Z","dependency_job_id":null,"html_url":"https://github.com/dragonfly-ai/slash","commit_stats":null,"previous_names":["dragonfly-ai/slash"],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/dragonfly-ai/slash","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dragonfly-ai%2Fslash","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dragonfly-ai%2Fslash/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dragonfly-ai%2Fslash/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dragonfly-ai%2Fslash/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dragonfly-ai","download_url":"https://codeload.github.com/dragonfly-ai/slash/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dragonfly-ai%2Fslash/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33928631,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-05T02:00:06.157Z","response_time":120,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["linear-algebra","machine-learning","matrix","matrix-decomposition","principal-component-analysis","scala-native","scala3","scalajs","statistics","vector"],"created_at":"2026-01-14T02:36:46.182Z","updated_at":"2026-06-05T04:00:49.963Z","avatar_url":"https://github.com/dragonfly-ai.png","language":"Scala","funding_links":["https://github.com/sponsors/dragonfly-ai"],"categories":[],"sub_categories":[],"readme":"# S.L.A.S.H\nScala Linear Algebra \u0026 Statistics Hacks\n\n[![javadoc](https://javadoc.io/badge2/ai.dragonfly/slash_3/javadoc.svg)](https://javadoc.io/doc/ai.dragonfly/slash_3)\n\n\u003ch3\u003eDesign goals:\u003c/h3\u003e\n\n\u003col\u003e\n\u003cli\u003eCross compile to JVM, Native, and JavaScript platforms\u003c/li\u003e\n\u003cli\u003eMaximize performance\u003c/li\u003e\n\u003cli\u003eMinimize memory footprint\u003c/li\u003e\n\u003cli\u003eProvide convenient syntax\u003c/li\u003e\n\u003cli\u003eSeamlessly interoperate with other math libraries\u003c/li\u003e\n\u003cli\u003eSeamlessly interoperate with native languages like JavaScript, C/C++, and Java\u003c/li\u003e\n\u003cli\u003eSerialize efficiently and compactly by default\u003c/li\u003e\n\u003c/ol\u003e\n\n\u003ch3\u003esbt\u003c/h3\u003e\n\n```scala\nlibraryDependencies += \"ai.dragonfly\" %%% \"slash\" % \"\u003cLATEST_VERSION\u003e\"\n```\n\n\u003ch3\u003eFeatures:\u003c/h3\u003e\n\n- High performance Vector data types with convenient vector math syntax.\n- Probability Distributions, Parametric and Estimated (Online/Streaming): Gaussian/Normal, Poisson, LogNormal, Binomial (parametric only), Beta, and PERT; each with support for sampling and probability density functions, PDFs.\n- Sampleable trait for making types into generative models.\n- Math functions: Beta, Factorial, and Gamma functions: B(α, β), x! and Γ(x).  Convenience macros, methods, and case classes for computing logarithms of arbitrary base. \n- Geometry: Sample points uniformly from volumes defined by 3D tetrahedrons.\n- Bresenham Line Drawing Algorithm that invokes a lambda for each discrete point on a line.\n- Kernels: Gaussian, Epanechnikov, Uniform, and Discrete.\n- Flexible Histogram data structures with Console friendly Text Based Visualizations inspired by \u003ca href=\"https://github.com/JuliaPlots/UnicodePlots.jl\"\u003eJulia Plots\u003c/a\u003e.\n- Bijection[A, B]: an abstraction for bijective implicit conversions.\n- BigRandom: scala.util.Random extension methods to generate random BigInt and BigDecimal values.\n- Interval and Domain types and objects with support for random sampling.\n- Unicode text formatting utility for writing numeric value types in superscript or subscript positions.\n- Matrix math:\n  + multiplication for Matrix * Matrix, Matrix * Vector, and Scalar * Matrix\n  + element wise operations: add, subtract, multiply, and divide\n  + sub-matrix, column, row, and element operations: get, set\n  + determinant\n  + transpose\n  + inverse\n  + norm operations: one, two, infinity, and Frobenius\n  + decompositions: Cholesky, Eigen, LU, QR, and Singular Value\n- In memory data sets: unsupervised and supervised\n- Linear Regression based on both QR Decomposition and Singular Value Decomposition.\n- Principal Components Analysis\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;Instead of case classes, traits, or wrappers, this library represents all runtime vector data as native arrays of double precision floating point values.  However, it also uses Scala 3 features like opaque types, dependent types, and extension methods to decorate the array primitives with convenient syntax, e.g. overloaded operators like `+ - * / += -= *= /=`, and also, by expressing vector dimensionality as a type parameter, can prevent runtime errors resulting from trying to perform vector operations on vectors of mismatched dimensions at compile time.  For example:   \n\n```scala\nopaque type Vec[N \u003c: Int] = NArray[Double]\n\nval v2:Vec[2] = Vec[2](1.0, 2.0)\nval v3:Vec[3] = Vec[3](1.0, 2.0, 3.0)\n\nprintln((v2 + v3).show) // compiler error!\n\n// Even though, at runtime, v2 and v3 have the same type,\n// the compiler treats them as though they have different, distinct types.\n// This eliminates runtime exceptions related to mismatched vector dimensions.\n```\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;Why `NArray[Double]` and not `Array[Double]`?  Because Vec relies on \u003ca href=\"https://github.com/dragonfly-ai/narr\"\u003eNArr\u003c/a\u003e, JavaScript environments store vector data as: `Float64Array` while JVM and Native environments rely on: `Array[Double]`.  This ensures that whichever compilation target you choose, Vector will always reduce to the native array type with the highest available performance.\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;For a more detailed explanation of the design decisions that have shaped this library, see the \u003ca href=\"https://dragonfly-ai.github.io/vector/\"\u003edesign notes.\u003c/a\u003e\n\n\u003ch3 id=\"vectormath\"\u003eMore Vector Math Syntax:\u003c/h3\u003e\n\n```scala\nimport slash.vector.*\n\n// create a 3 dimensional vector\nval v1:Vec[3] = Vec[3](1.0, 0.5, 0.0)\n\n// print it to the console with expressive unicode text\nprintln(v1.show)  // -\u003e 《³↗〉1.0ᵢ 0.0ⱼ 0.0ₖ〉\n\n// perform various vector math operations\nval v2:Vec[3] = Vec[3](0.75, 1.0, 0.5)\n\nval v3:Vec[3] = v1 + v2\n\nprintln( v3.norm )\n\nv3 -= v1\n\nprintln( v3.euclideanDistanceTo(v2) )\n\n// perform Vector3 specific operations\nimport slash.vector.Vector3.*\n\nprintln(v1.x) // .x .y and .z provided by an extension method in Vector3\n\n// compute 3D Vector Cross product\nprintln( (v1 cross v2 ).show )\nprintln( (v1 ⨯ v2 ).show ) // or with a unicode ⨯ operator\n\nimport slash.Random.*\nval r:Random = defaultRandom\n\n// higher dimensional vectors\nval v42a:Vec[42] = r.nextVec[42]()\nval v42b:Vec[42] = r.nextVec[42]()\n\nprintln( v42a dot v42b )\nprintln( (v42a - v42b).render() ) // fully customisable render method.\nprintln( (v42a + v42b).csv() ) // output vector sum as comma separated values\nprintln( (v42a + v42b).tsv() ) // output vector sum tab separated values\n```\n\n\u003ch3\u003eMatrix math\u003c/h3\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;This matrix library differs most significantly from others like \u003ca href=\"https://math.nist.gov/javanumerics/jama/\"\u003eJAMA\u003c/a\u003e and \u003ca href=\"https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/org/apache/commons/math3/linear/\"\u003eApache Commons Math\u003c/a\u003e, by providing compile time dimensionality checks.  Instead of encoding matrix row and column dimensions with method parameters or `Array[Double].length` values, this library relies on dependent types.  For example:\n\n```scala\n// create an 3 x 2 matrix of zeros.\nval m:Mat[3, 2] = Mat.zeros[3, 2]\n\n// create a 3 x 3 matrix with convenient matrix literal syntax:\nval m0:Mat[3, 3] = Mat[3,3](\n  1, 2, 3,\n  4, 5, 6,\n  7, 8, 9\n)\n```\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;By encoding the matrix's row and column dimensions into its type, the compiler can prevent a whole category of runtime errors that arise from mismatched matrix dimensions:\n\n```scala\n// create an 3 x 2 matrix of zeros:\nval m0:Mat[3, 2] = Mat.zeros[3, 2]\n// create an 2 x 3 matrix of zeros:\nval m1:Mat[2, 3] = Mat.zeros[2, 3]\n\nval m:Mat[3, 3] = m0 * m1\nval m = m * m1 // compiler error!\n```\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;Relatedly, many matrix operations like `determinant`, Cholesky decomposition, etc, only pertain to square matrices.  This library relies on type conditioned extension methods so that users simply cannot attempt to invoke these operations on rectangular matrices.  More specifically:\n\n```scala\nextension [MN \u003c: Int] (m: Mat[MN, MN])(using ValueOf[MN]) {\n  def determinant: Double = LU[MN, MN](m).determinant\n}\n```\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;Instead of including a `determinant` method directly in the `Matrix` class, this extension method makes a `determinant` method available only for square matrices.  Trying to invoke the `determinant` method on a rectangular matrix, for which M != N, will yield a compiler error.\n\n\n\n\u003ch3\u003eJavaScript Optimization\u003c/h3\u003e\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;Because matrix relies on \u003ca href=\"https://github.com/dragonfly-ai/narr\"\u003eNArr\u003c/a\u003e, JavaScript environments store matrix data as:\n```scala\nvar matrixArray:NArray[Double]\n```\n\u0026nbsp;\u0026nbsp;\u0026nbsp;which is equivalent to:\n```scala\nvar matrixArray:Float64Array\n```\n\u0026nbsp;\u0026nbsp;\u0026nbsp;In JVM and Native environments, matrix data occupies normal scala `Array[Double]`.\n\n\u003ch3\u003eHistory\u003c/h3\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;Although it began as a 1:1 port of \u003ca href=\"https://math.nist.gov/javanumerics/jama/\"\u003eJAMA\u003c/a\u003e for Scala 3 and Scala.js projects, it has expanded to include features that make matrix operations more comfortable in idiomatic Scala. Past versions of this library JAMA from the \u003ca href=\"https://mvnrepository.com/artifact/gov.nist.math/jama/1.0.3\"\u003emaven repository\u003c/a\u003e on the JVM side, and provided facades for a JavaScript version of JAMA ported through \u003ca href=\"http://www.jsweet.org\"\u003eJsweet\u003c/a\u003e and included through the \u003ca href=\"https://scalacenter.github.io/scalajs-bundler/\"\u003escalajs-bundler\u003c/a\u003e sbt plugin.  As scalajs-bundler has slipped into an unmaintained status, this library evolved into a pure scala port of JAMA and has begun to take its own shape.\n\n\u003ch3\u003eExclusions\u003c/h3\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;This implementation of JAMA excludes test and I/O functionality as well as some constructors that comments in the original JAMA library describe as dangerous and unnecessary.\n\n\u003ch3\u003eVerification\u003c/h3\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;See the verification subproject of this repository to evaluate the fidelity of this port from Java to Scala.  Given the original JaMa implementation of hypot, these two matrix libraries produce identical output, however, modern Java includes a more advanced implementation of the hypot function and using it produces tiny discrepancies between Jama and this scala implementation.\n\n\u003ch3\u003eParametric Probability Distributions\u003c/h3\u003e\n\n```scala\nimport slash.stats.probability.distributions.*\n\n// create a gaussian distribution parametrically\nval g:Gaussian = Gaussian(10.0, 42.0)\ng.p(7.0)   // evaluate the Probability Density Function at 7.0, in other words: PDF(7.0)\ng.random() // randomly sample a value from this gaussian model\n```\n\n\n\u003ch3\u003eEstimated, also called Online or Streaming, Probability Distributions\u003c/h3\u003e\n\n```scala\nimport slash.stats.probability.distributions.*\n\n// create a gaussian distribution parametrically\nval eg:stream.Gaussian = stream.Gaussian()\n// observe some trials\neg.observe(7.0)\neg.observe(7.5)\neg.observe(9.1)\neg.observe(6.3)\neg.observe(8.4)\n\n// estimate a parametric Gaussian distribution from the observations\nval pg:Gaussian = eg.estimate\npg.p(8.0)   // estimate the Probability Density Function at 8.0, in other words: PDF'(8.0)\npg.random() // randomly sample a value from the estimated gaussian model\n```\n\n\n\u003ch3\u003eCompile time Logarithms\u003c/h3\u003e\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;To compute `logₓ(y)`, where `x` is any value of type: `Double`, we compute: `log₁₀(y) / log₁₀(x)`.  Which can introduce a lot of computational overhead, especially when done in loops which repeatedly compute the same value for `log₁₀(x)`.  To improve performance and legibility, this library provides a `log[BASE \u003c: Double | Int]` macro that computes the `log₁₀(x)` denominator at compile time; it also clarifies the operation by allowing users to write the base of the log into the type parameter and the operand as a method parameter.  As such, instead of: `log(2 /*base*/, 42 /*operand*/)` we can write: `log[2](42)`.\n\n```scala\nimport slash.*\n\n// Compile time optimized Logarithms of known base:\nlog[2](42.0)  // Computes log₂(42) at compile time\nlog[0.5](11.0)  // Computes log₀.₅(11) at compile time\n\nvar i: Int = 1; while (i \u003e 0) {\n  println( log[2](i) )  // computes half of this operation at compile time\n  i = i \u003c\u003c 1\n}\n```\n\n\u003ch3\u003eRuntime Logarithms\u003c/h3\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;The runtime `Log` class can yield comparable performance in cases when the base of the logarithm can't be known at compile time, or can't be expressed as a constant.\n\n```scala\nimport slash.*\n// Use the runtime Log class for:\n// a base determined by a value:\nimport slash.Constant.π\nval logBasePi: Log = Log(π)\nlogBasePi(13)\n// or any base unknown at compile time,\nval logBaseRandom:Log = Log(Math.random())\nlogBaseRandom(42)\n```\n\nUnicode Histogram Plot:\n\n```\nHistogram: { \n\t[-17.00,-11.00 ) 🌑 ︙    ∝ 3.0E-4\n\t[-11.00, -5.00 ) 🌑 ▕█   ∝ 0.0094\n\t[ -5.00,  1.00 ) 🌑 ▕████████    ∝ 0.0732\n\t[  1.00,  7.00 ) 🌒 ▕███████████████████████████    ∝ 0.2447\n\t[  7.00, 13.00 ) 🌓 ▕███████████████████████████████████████   ∝ 0.3516\n\t[ 13.00, 19.00 ) 🌔 ▕██████████████████████████▋   ∝ 0.2411`\n\t[ 19.00, 25.00 ) 🌔 ▕███████▌   ∝ 0.069\n\t[ 25.00, 31.00 ) 🌔 ▕█   ∝ 0.0101\n\t[ 31.00, 37.00 ) 🌔 ︙    ∝ 5.0E-4\n\t[ 37.00, 43.00 ] 🌕 ︰    ∝ 1.0E-4\n}\n```\nThese plots label the bins with standardised math notation for open and closed intervals, but also use the unicode glyphs for the phases of the moon to represent the cumulative distribution.\n\n\u003ch3\u003eAdd the SBT dependency:\u003c/h3\u003e\n\n```scala\nlibraryDependencies += \"ai.dragonfly\" %%% \"vector\" % \"\u003cLATEST_VERSION\u003e\"\n```\n\n\u003ch2\u003eFAQ:\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\n\n`NArray[Double]` is useful, but why exclude `NArray[Float]`?\n\nIn Scala.js, the runtime type of `Float` doesn't fully exist, while Scala.js, Scala JVM, and Scala Native all share the same implementation of `Double`.\n\u003c/li\u003e\n\u003cli\u003eWhat if a vector's dimension depends on a variable?  Can this library support vectors with dimensionality defined at runtime?\n\nYes, but with some limitations.  Please consider the following examples:\n\n```scala\n// Vectors with lengths defined at runtime.\n\n// method 1:\nval l0:Int = r.nextInt (100)\ntype N0 = l0.type\nval rtv0: Vec[N0] = r.nextVec[N0]()\nprintln(rtv0.render())\n\n// method 2:\nval l1: Int = r.nextInt(100)\nval rtv1: Vec[l1.type] = r.nextVec[l1.type]()\nprintln(rtv1.render())\n\n// For better or worse, this throws a compiler error even though l1 == l2 is true:\nval l1: Int = r.nextInt(100)\nval l2: Int = 0 + l1\nval rtv1: Vec[l1.type] = r.nextVec[l1.type]()\nval rtv2: Vec[l2.type] = r.nextVec[l2.type]()\nprintln((rtv1 + rtv2).render())\n  \n//    [error] 57 |    println((rtv1 + rtv2).render())\n//    [error]    |                    ^^^^\n//    [error]    |             Found:    (rtv2 : slash.vector.Vec[(l2 : Int)])\n//    [error]    |             Required: slash.vector.Vec[(l1 : Int)]\n\n\n// However, you can do this:\nval l1: Int = r.nextInt(100)\nval l2: Int = 0 + l1\nval rtv1: Vec[l1.type] = r.nextVec[l1.type]()\nval rtv2: Vec[l2.type] = r.nextVec[l2.type]()\nprintln((rtv1 + rtv2.asInstanceOf[Vec[l1.type]]).render())\n```\n\nTo coordinate runtime vector dimensions across a system, SLASH provides the `VectorSpace` and `MatrixSpace` classes:\n\n```scala\nval l1: Int = r.nextInt(100)\nval vs = VectorSpace(l1)\nval rtv1: Vec[vs.N] = r.nextVec[vs.N]()\nval rtv2: Vec[vs.N] = r.nextVec[vs.N]()\nprintln((rtv1 + rtv2.asInstanceOf[Vec[vs.N]]).render())\n```\nUnfortunately, this means having to think about a concept that no other math library has had, but it can also head off all kinds of run time errors caused by mismatched dimension exceptions.\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cbr /\u003e\n\nProjects that rely on this Library:\n\nhttps://github.com/dragonfly-ai/uriel\n\nhttps://github.com/dragonfly-ai/spatial\n\nhttps://github.com/dragonfly-ai/mesh\n\nhttps://github.com/dragonfly-ai/img\n\nAcknowledgements: \u003cbr /\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;This library has evolved over years, but owes a lot of its virtues to feedback from the Scala Discord community.  In no particular order:\n\nhttps://github.com/ekrich - Performance tips and encouragement.\n\nhttps://github.com/armanbilge - Continuous Integration tools and support.\n\nhttps://github.com/s5bug - Design insights.\n\nhttps://github.com/BalmungSan - Design insights.\n\nhttps://github.com/Quafadas - Contributor!\n\nhttps://github.com/philwalk - Design insights, and contributor!\n\nhttps://github.com/JD557 - Design insights, named this library, and contributor!\n\nhttps://github.com/J-mie6 - Git advice.\n\nThanks, scala fam!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdragonfly-ai%2Fslash","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdragonfly-ai%2Fslash","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdragonfly-ai%2Fslash/lists"}