ECMAScript modules for exactly manipulating vectors and matrices of which elements are real or complex numbers of the form (p / q)sqrt(b).










ECMAScript modules for exactly manipulating vectors and matrices
of which elements are real or complex numbers of the form
(p / q)sqrt(b),
where p is an integer, q is a positive (non-zero) integer,
and b is a positive, square-free integer.
npm install @kkitahara/linear-algebra @kkitahara/complex-algebra @kkitahara/real-algebra
`Examples
$3
`javascript
import { ExactRealAlgebra as RealAlgebra } from '@kkitahara/real-algebra'
import { ComplexAlgebra } from '@kkitahara/complex-algebra'
import { LinearAlgebra } from '@kkitahara/linear-algebra'
let r = new RealAlgebra()
let c = new ComplexAlgebra(r)
let l = new LinearAlgebra(c)
let m1, m2, m3
`
Generate a new matrix (since v2.0.0)
`javascript
m1 = l.$(1, 0, 0, 1)
m1.toString() // '(1, 0, 0, 1)'m1 = l.$(r.$(1, 2, 5), c.$(0, 1), c.$(0, -1), 1)
m1.toString() // '((1 / 2)sqrt(5), i(1), i(-1), 1)'
// Some Array methods can be used
m1 = l.$(r.$(1, 2, 5), c.$(0, 1), c.$(0, -1), 1)
m1.push(c.$(3))
m1.toString() // '((1 / 2)sqrt(5), i(1), i(-1), 1, 3)'
`
Set and get the dimension
`javascript
m1 = l.$(1, 0, 0, 1)// 2 x 2 matix
m1.setDim(2, 2)
// number of rows
m1.getDim()[0] // 2
// number of columns
m1.getDim()[1] // 2
// elements are stored in row-major order
m1.toString() // '(1, 0,\n 0, 1)'
// 1 x 4 matix
m1.setDim(1, 4)
m1.getDim()[0] // 1
m1.getDim()[1] // 4
m1.toString() // '(1, 0, 0, 1)'
// 4 x 1 matix
m1.setDim(4, 1)
m1.getDim()[0] // 4
m1.getDim()[1] // 1
m1.toString() // '(1,\n 0,\n 0,\n 1)'
// 3 x 1 matix (inconsistent dimension)
m1.setDim(3, 1)
// throws an Error when getDim is called
m1.getDim() // Error
// 2 x 0 (0 means auto)
m1.setDim(2, 0)
m1.getDim()[0] // 2
m1.getDim()[1] // 2
// 0 x 1 (0 means auto)
m1.setDim(0, 1)
m1.getDim()[0] // 4
m1.getDim()[1] // 1
// 0 x 0 (this is an adaptive matrix, since v2.0.0)
m1.setDim(0, 0)
m1.isAdaptive() // true
m1.getDim() // Error
// matrices are adaptive by default
m1 = l.$(1, 0, 0, 1)
m1.isAdaptive() // true
`
:warning: matrix elements are stored in row-major order.Copy (generate a new object)
`javascript
m1 = l.$(1, 0, 0, 1).setDim(2, 2)
m2 = l.copy(m1)
m2.toString() // '(1, 0,\n 0, 1)'
m2.getDim()[0] // 2
m2.getDim()[1] // 2
`
Equality
`javascript
m1 = l.$(1, 0, 0, 1).setDim(2, 2)
m2 = l.$(1, 0, 0, 1).setDim(2, 2)
m3 = l.$(1, 0, 0, -1).setDim(2, 2)
l.eq(m1, m2) // true
l.eq(m1, m3) // false// matrices of different dimension are considered to be not equal
m1 = l.$(1, 0, 0, 1).setDim(2, 2)
m2 = l.$(1, 0, 0, 1).setDim(1, 4)
l.eq(m1, m2) // false
// here,
m1 is adaptive
m1 = l.$(1, 0, 0, 1)
m2 = l.$(1, 0, 0, 1).setDim(1, 4)
m3 = l.$(1, 0, 0, 1).setDim(4, 1)
l.eq(m1, m2) // true
l.eq(m1, m3) // true
l.eq(m2, m3) // false
`
Inequality
`javascript
m1 = l.$(1, 0, 0, 1).setDim(2, 2)
m2 = l.$(1, 0, 0, 1).setDim(2, 2)
m3 = l.$(1, 0, 0, -1).setDim(2, 2)
l.ne(m1, m2) // false
l.ne(m1, m3) // true// matrices of different dimension are considered to be not equal
m1 = l.$(1, 0, 0, 1).setDim(2, 2)
m2 = l.$(1, 0, 0, 1).setDim(1, 4)
l.ne(m1, m2) // true
// here,
m1 is adaptive
m1 = l.$(1, 0, 0, 1)
m2 = l.$(1, 0, 0, 1).setDim(1, 4)
m3 = l.$(1, 0, 0, 1).setDim(4, 1)
l.ne(m1, m2) // false
l.ne(m1, m3) // false
l.ne(m2, m3) // true
`
isZero
`javascript
m1 = l.$(1, 0, 0, 1).setDim(2, 2)
m2 = l.$(0, 0, 0, 0).setDim(2, 2)
l.isZero(m1) // false
l.isZero(m2) // true
`
isInteger (since v1.1.0)
`javascript
m1 = l.$(1, r.$(4, 2), -3, 4).setDim(2, 2)
m2 = l.$(1, r.$(1, 2), -3, 4).setDim(2, 2)
l.isInteger(m1) // true
l.isInteger(m2) // false
`
Element-wise addition
`javascript
m1 = l.$(1, 2, 3, 4)
m2 = l.$(1, 3, 1, 3)
// new object is generated
m3 = l.add(m1, m2)
m3.toString() // '(2, 5, 4, 7)'
`
In-place element-wise addition
`javascript
m1 = l.$(1, 2, 3, 4)
m2 = l.$(1, 3, 1, 3)
// new object is not generated
m1 = l.iadd(m1, m2)
m1.toString() // '(2, 5, 4, 7)'
`
Element-wise subtraction
`javascript
m1 = l.$(1, 2, 3, 4)
m2 = l.$(1, 3, 1, 3)
// new object is generated
m3 = l.sub(m1, m2)
m3.toString() // '(0, -1, 2, 1)'
`
In-place element-wise subtraction
`javascript
m1 = l.$(1, 2, 3, 4)
m2 = l.$(1, 3, 1, 3)
// new object is not generated
m1 = l.isub(m1, m2)
m1.toString() // '(0, -1, 2, 1)'
`
Element-wise multiplication
`javascript
m1 = l.$(1, 2, 3, 4)
m2 = l.$(1, 3, 1, 3)
// new object is generated
m3 = l.mul(m1, m2)
m3.toString() // '(1, 6, 3, 12)'
`
In-place element-wise multiplication
`javascript
m1 = l.$(1, 2, 3, 4)
m2 = l.$(1, 3, 1, 3)
// new object is not generated
m1 = l.imul(m1, m2)
m1.toString() // '(1, 6, 3, 12)'
`
Element-wise division
`javascript
m1 = l.$(1, 2, 3, 4)
m2 = l.$(1, 3, 1, 3)
// new object is generated
m3 = l.div(m1, m2)
m3.toString() // '(1, 2 / 3, 3, 4 / 3)'
`
In-place element-wise division
`javascript
m1 = l.$(1, 2, 3, 4)
m2 = l.$(1, 3, 1, 3)
// new object is not generated
m1 = l.idiv(m1, m2)
m1.toString() // '(1, 2 / 3, 3, 4 / 3)'
`
Scalar multiplication
`javascript
m1 = l.$(1, 2, 3, 4)
// new object is generated
m2 = l.smul(m1, r.$(1, 2))
m2.toString() // '(1 / 2, 1, 3 / 2, 2)'
`
In-place scalar multiplication
`javascript
m1 = l.$(1, 2, 3, 4)
// new object is not generated
m1 = l.ismul(m1, r.$(1, 2))
m1.toString() // '(1 / 2, 1, 3 / 2, 2)'
`
Scalar multiplication by -1
`javascript
m1 = l.$(1, 2, 3, 4)
// new object is generated
m2 = l.neg(m1)
m2.toString() // '(-1, -2, -3, -4)'
`
In-place scalar multiplication by -1
`javascript
m1 = l.$(1, 2, 3, 4)
// new object is not generated
m1 = l.ineg(m1)
m1.toString() // '(-1, -2, -3, -4)'
`
Scalar division (since v2.0.0)
`javascript
m1 = l.$(1, 2, 3, 4)
// new object is generated
m2 = l.sdiv(m1, 2)
m2.toString() // '(1 / 2, 1, 3 / 2, 2)'
`
In-place scalar division (since v2.0.0)
`javascript
m1 = l.$(1, 2, 3, 4)
// new object is not generated
m1 = l.isdiv(m1, 2)
m1.toString() // '(1 / 2, 1, 3 / 2, 2)'
`
Complex conjugate
`javascript
m1 = l.$(1, c.$(0, 2), 3, c.$(0, 4))
// new object is generated
m2 = l.cjg(m1)
m2.toString() // '(1, i(-2), 3, i(-4))'
`
In-place evaluation of the complex conjugate
`javascript
m1 = l.$(1, c.$(0, 2), 3, c.$(0, 4))
// new object is not generated
m1 = l.icjg(m1)
m1.toString() // '(1, i(-2), 3, i(-4))'
`
Transpose
`javascript
m1 = l.$(1, 2, 3, 4).setDim(2, 2)
// new object is generated
m2 = l.transpose(m1)
m2.toString() // '(1, 3,\n 2, 4)'
`
In-place evaluation of the transpose
`javascript
m1 = l.$(1, 2, 3, 4).setDim(2, 2)
// new object is not generated
m1 = l.itranspose(m1)
m1.toString() // '(1, 3,\n 2, 4)'
`
Conjugate transpose (Hermitian transpose)
`javascript
m1 = l.$(1, c.$(0, 2), 3, c.$(0, 4)).setDim(2, 2)
// new object is generated
m2 = l.cjgTranspose(m1)
m2.toString() // '(1, 3,\n i(-2), i(-4))'
`
In-place evaluation of the conjugate transpose
`javascript
m1 = l.$(1, c.$(0, 2), 3, c.$(0, 4)).setDim(2, 2)
// new object is not generated
m1 = l.icjgTranspose(m1)
m1.toString() // '(1, 3,\n i(-2), i(-4))'
`
Dot product
`javascript
m1 = l.$(1, c.$(0, 2))
m2 = l.$(c.$(0, 3), 2)
l.dot(m1, m2).toString() // 'i(-1)'
`
Square of the absolute value (Frobenius norm)
`javascript
m1 = l.$(1, c.$(0, 2))
let a = l.abs2(m1)
a.toString() // '5'
// return value is not a complex number (but a real number)
a.re // undefined
a.im // undefined
`
Matrix multiplication
`javascript
m1 = l.$(1, 2, 3, 4).setDim(2, 2)
m2 = l.$(1, 3, 1, 3).setDim(2, 2)
m3 = l.mmul(m1, m2)
m3.toString() // '(3, 9,\n 7, 21)'
`
LU-factorisation
`javascript
m1 = l.$(1, 2, 3, 4).setDim(2, 2)
// new object is generated
m2 = l.lup(m1)
`
In-place LU-factorisation
`javascript
m1 = l.$(1, 2, 3, 4).setDim(2, 2)
// new object is not generated
m1 = l.ilup(m1)
`
Solving a linear equation
`javascript
m1 = l.$(1, 2, 3, 4).setDim(2, 2)
m2 = l.$(1, 2, 3, 4).setDim(2, 2)// m1 m3 = m2, new object is generated
m3 = l.solve(l.lup(m1), m2)
m3.toString() // '(1, 0,\n 0, 1)'
// m3 m1 = m2, new object is generated
m3 = l.solve(m2, l.lup(m1))
m3.toString() // '(1, 0,\n 0, 1)'
`
Solving a linear equation in-place
`javascript
m1 = l.$(1, 2, 3, 4).setDim(2, 2)
m2 = l.$(1, 2, 3, 4).setDim(2, 2)// m1 m3 = m2, new object is not generated
m2 = l.isolve(l.lup(m1), m2)
m2.toString() // '(1, 0,\n 0, 1)'
m2 = l.$(1, 2, 3, 4).setDim(2, 2)
// m3 m1 = m2, new object is not generated
m2 = l.isolve(m2, l.lup(m1))
m2.toString() // '(1, 0,\n 0, 1)'
`
Determinant
`javascript
m1 = l.$(1, 2, 3, 4).setDim(2, 2)
m2 = l.lup(m1)
// det method supports only LU-factorised matrices
let det = l.det(m2)
det.toString() // '-2'
`
JSON (stringify and parse)
`javascript
m1 = l.$(1, r.$(2, 3, 5), 3, c.$(0, r.$(4, 5, 3))).setDim(2, 2)
let str = JSON.stringify(m1)
m2 = JSON.parse(str, l.reviver)
l.eq(m1, m2) // true
`$3
If complex numbers are not necessary, you can use RealAlgebra
instead of ComplexAlgebra.
`javascript
import { ExactRealAlgebra as RealAlgebra } from '@kkitahara/real-algebra'
import { LinearAlgebra } from '@kkitahara/linear-algebra'
let r = new RealAlgebra()
let l = new LinearAlgebra(r)
`$3
You can work with built-in numbers if you use
`javascript
import { RealAlgebra } from '@kkitahara/real-algebra'
`
instead of ExactRealAlgebra.
See the documents of @kkitahara/real-algebra for more details.$3
For more examples, see ESDoc documents:
`
cd node_modules/@kkitahara/linear-algebra
npm install --only=dev
npm run doc
`
and open doc/index.html` in your browser.