algebra
Advanced tools
Comparing version 0.12.7 to 1.0.0
24
index.js
require('strict-mode')(() => { | ||
var Boole = require('./src/Boole') | ||
const Boole = require('./src/Boole.js') | ||
exports.Boole = Boole | ||
var CompositionAlgebra = require('./src/CompositionAlgebra') | ||
const CompositionAlgebra = require('./src/CompositionAlgebra.js') | ||
exports.CompositionAlgebra = CompositionAlgebra | ||
var Cyclic = require('./src/Cyclic') | ||
exports.Cyclic = Cyclic | ||
var Scalar = require('./src/Scalar') | ||
const Scalar = require('./src/Scalar.js') | ||
exports.Scalar = Scalar | ||
var realField = require('./src/realField') | ||
const realField = require('./src/realField.js') | ||
var Real = CompositionAlgebra(realField, 1) | ||
var Complex = CompositionAlgebra(realField, 2) | ||
var Quaternion = CompositionAlgebra(realField, 4) | ||
var Octonion = CompositionAlgebra(realField, 8) | ||
const Real = CompositionAlgebra(realField, 1) | ||
const Complex = CompositionAlgebra(realField, 2) | ||
const Quaternion = CompositionAlgebra(realField, 4) | ||
const Octonion = CompositionAlgebra(realField, 8) | ||
@@ -26,4 +23,4 @@ exports.Real = Real | ||
var VectorSpace = require('./src/VectorSpace') | ||
var MatrixSpace = require('./src/MatrixSpace') | ||
const VectorSpace = require('./src/VectorSpace.js') | ||
const MatrixSpace = require('./src/MatrixSpace.js') | ||
@@ -40,3 +37,2 @@ exports.C = Complex | ||
exports.MatrixSpace = MatrixSpace | ||
exports.TensorSpace = require('./src/TensorSpace') | ||
}) |
{ | ||
"name": "algebra", | ||
"description": "means completeness and balancing, from the Arabic word الجبر", | ||
"version": "0.12.7", | ||
"version": "1.0.0", | ||
"homepage": "http://g14n.info/algebra", | ||
@@ -14,7 +14,3 @@ "author": { | ||
"build": "npm test && npm run browserify && npm run minify && npm run docs; git status", | ||
"browserify": "npm run browserify:dist; npm run browserify:test", | ||
"browserify:dist": "browserify -r ./index.js:${npm_package_name} -o dist/${npm_package_name}.js", | ||
"browserify:test": "browserify test/*.js -o docs/test/bundle.js", | ||
"coverage": "npm run istanbul && npm run coveralls", | ||
"coveralls": "cat ./coverage/lcov.info | coveralls --verbose", | ||
"browserify": "browserify -r ./index.js:${npm_package_name} -o dist/${npm_package_name}.js", | ||
"docs:_data": "for x in package.json tags.json; do npm run docs:_data:$x; done", | ||
@@ -29,3 +25,3 @@ "docs:_data:package.json": "cp package.json docs/_data/", | ||
"lint_test": "cd test; standa --env mocha; cd -", | ||
"minify": "cd dist; uglifyjs ${npm_package_name}.js --source-map --output ${npm_package_name}.min.js --compress --mangle -b beautify=false,preamble='\"// http://g14n.info/algebra\"'; cd -", | ||
"minify": "cd dist; terser ${npm_package_name}.js --source-map --output ${npm_package_name}.min.js --compress --mangle -b beautify=false,preamble='\"// http://g14n.info/algebra\"'; cd -", | ||
"postversion": "git push origin v${npm_package_version}; npm publish", | ||
@@ -55,17 +51,12 @@ "postpublish": "npm run docs:_data; git commit -am ':arrow_up: updated version'; git push origin master", | ||
"devDependencies": { | ||
"browserify": "^16.1.1", | ||
"coveralls": "^3.0.0", | ||
"istanbul": "^0.4.1", | ||
"browserify": "^16.5.0", | ||
"mocha": "^5.2.0", | ||
"mocha-lcov-reporter": "1.3.0", | ||
"pre-commit": "^1.1.2", | ||
"should": "^13.2.3", | ||
"standa": "^12.0.0", | ||
"uglify-es": "^3.3.9" | ||
"standa": "^14.0.0", | ||
"terser": "^4.3.1" | ||
}, | ||
"dependencies": { | ||
"algebra-cyclic": "^0.2.4", | ||
"cayley-dickson": "^0.5.4", | ||
"indices-permutations": "^0.2.3", | ||
"inherits": "^2.0.1", | ||
"laplace-determinant": "^0.2.1", | ||
@@ -77,5 +68,4 @@ "matrix-multiplication": "^0.5.2", | ||
"strict-mode": "^1.1.3", | ||
"tensor-contraction": "^0.2.0", | ||
"tensor-product": "^0.2.1" | ||
"tensor-contraction": "^0.2.0" | ||
} | ||
} |
565
README.md
@@ -5,13 +5,6 @@ # algebra | ||
> **New**: checkout matrices and vectors made of strings, with [cyclic algebra](#cyclic). | ||
**NOTA BENE** Imagine all code examples below as written in some REPL where expected output is documented as a comment. | ||
[![NPM version](https://badge.fury.io/js/algebra.svg)](http://badge.fury.io/js/algebra) | ||
[![Badge size](https://badge-size.herokuapp.com/fibo/algebra/master/dist/algebra.js)](https://github.com/fibo/algebra/blob/master/dist/algebra.js) | ||
[![Build Status](https://travis-ci.org/fibo/algebra.svg?branch=master)](https://travis-ci.org/fibo/algebra?branch=master) | ||
[![Dependency Status](https://gemnasium.com/fibo/algebra.svg)](https://gemnasium.com/fibo/algebra) | ||
[![Coverage Status](https://coveralls.io/repos/fibo/algebra/badge.svg?branch=master)](https://coveralls.io/r/fibo/algebra?branch=master) | ||
[![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com) | ||
[![Test page](https://img.shields.io/badge/test-page-blue.svg)](http://g14n.info/algebra/test) | ||
[![Change log](https://img.shields.io/badge/change-log-blue.svg)](http://g14n.info/algebra/changelog) | ||
@@ -21,8 +14,7 @@ | ||
![Algebra](http://g14n.info/algebra/images/Cover-Algebra.png)! | ||
[OnQuaternionsAndOctonions](http://g14n.info/algebra/images/Cover-OnQuaternionsAndOctonions.png) | ||
![Algebra](http://g14n.info/algebra/images/Cover-Algebra.png) | ||
![OnQuaternionsAndOctonions](http://g14n.info/algebra/images/Cover-OnQuaternionsAndOctonions.png) | ||
## Table Of Contents | ||
* [Status](#status) | ||
* [Features](#features) | ||
@@ -36,3 +28,2 @@ * [Installation](#installation) | ||
- [About operators](#about-operators) | ||
- [Cyclic](#cyclic) | ||
- [Composition Algebra](#composition-algebra) | ||
@@ -47,24 +38,4 @@ - [Scalar](#scalar) | ||
- [Matrix](#matrix) | ||
- [Tensor](#tensor) | ||
* [License](#license) | ||
## Status | ||
*algebra* is under development, but API should not change until version **1.0**. | ||
I am currently adding more tests and examples to achieve a stable version. | ||
Many functionalities of previous versions are now in separated atomic packages: | ||
* [algebra-cyclic] | ||
* [algebra-group] | ||
* [algebra-ring] | ||
* [cayley-dickson] | ||
* [indices-permutations] | ||
* [laplace-determinant] | ||
* [matrix-multiplication] | ||
* [multidim-array-index] | ||
* [tensor-contraction] | ||
* [tensor-product] | ||
## Features | ||
@@ -75,3 +46,2 @@ | ||
* Expressive syntax. | ||
* Everything is a Tensor. | ||
* [Immutable objects](https://en.wikipedia.org/wiki/Immutable_object). | ||
@@ -90,3 +60,3 @@ | ||
```html | ||
<script src="https://cdn.rawgit.com/fibo/algebra/master/dist/algebra.js"></script> | ||
<script src="https://unpkg.com/algebra/dist/algebra.min.js"></script> | ||
``` | ||
@@ -98,2 +68,6 @@ | ||
**NOTA BENE** Imagine all code examples below as written in some REPL where expected output is documented as a comment. | ||
All code in the examples below should be contained into a single file, like [test/quickStart.js](https://github.com/fibo/algebra/blob/master/test/quickStart.js). | ||
First of all, import *algebra* package. | ||
@@ -105,12 +79,2 @@ | ||
### Try it out | ||
All code in the examples below should be contained into a single file, like [test/quickStart.js](https://github.com/fibo/algebra/blob/master/test/quickStart.js). | ||
<ul class="box"> | ||
<li class="tonicdev"><a href="https://tonicdev.com/fibo/algebra-quick-start" target="_blank">Test algebra <em>quick start</em> in your browser.</a></li> | ||
</ul> | ||
[![view on requirebin](http://requirebin.com/badge.png)](http://requirebin.com/?gist=345763d95f093b9d9350) | ||
### Scalars | ||
@@ -131,3 +95,3 @@ | ||
```javascript | ||
R.add(1, 2, 3) // 1 + 2 + 3 = 6 | ||
R.add(1, 2) // 3 | ||
``` | ||
@@ -138,3 +102,4 @@ | ||
```javascript | ||
const x = new R(2) | ||
// x will be overwritten, see below | ||
let x = new R(2) | ||
const y = new R(-2) | ||
@@ -178,3 +143,3 @@ ``` | ||
const z1 = new C([1, 2]) | ||
let z1 = new C([1, 2]) | ||
const z2 = new C([3, 4]) | ||
@@ -202,3 +167,3 @@ | ||
```javascript | ||
const v1 = new R2([0, 1]) | ||
let v1 = new R2([0, 1]) | ||
const v2 = new R2([1, -2]) | ||
@@ -228,4 +193,4 @@ | ||
const m1 = new R3x2([1, 1, | ||
0, 1, | ||
1, 0]) | ||
0, 1, | ||
1, 0]) | ||
``` | ||
@@ -257,7 +222,7 @@ | ||
const m2 = new R2x2([1, 0, | ||
0, 2]) | ||
let m2 = new R2x2([1, 0, | ||
0, 2]) | ||
const m3 = new R2x2([0, -1, | ||
1, 0]) | ||
1, 0]) | ||
@@ -279,5 +244,5 @@ m2 = m2.mul(m3) | ||
All operators are implemented as static methods and as object methods. | ||
All operators can be implemented as *static methods* and as *object methods*. | ||
In both cases, operands are coerced to raw data. | ||
As an example, consider addition of vectors in a plane. | ||
As an example, consider addition of vectors in a *Cartesian Plane*. | ||
@@ -308,6 +273,6 @@ ```javascript | ||
Operators can be chained and accept multiple arguments when it makes sense. | ||
Operators can be chained when it makes sense. | ||
```javascript | ||
vector1.addition(vector1, vector1).equality([3, 6]) // true | ||
vector1.addition(vector1).equality([2, 4]) // true | ||
``` | ||
@@ -321,67 +286,2 @@ | ||
### Cyclic | ||
#### `Cyclic(elements)` | ||
Create an algebra cyclic ring, by passing its elements. The elements are provided | ||
as a string or an array, which lenght must be a prime number. This is necessary, | ||
otherwise the result would be a wild land where you can find [zero divisor][zero_divisor] beasts. | ||
Let's create a cyclic ring containing lower case letters, numbers and the blank | ||
char. How many are they? They are 26 + 10 + 1 = 37, that is prime! We like it. | ||
```javascript | ||
const Cyclic = algebra.Cyclic | ||
// The elements String or Array length must be prime. | ||
const elements = ' abcdefghijklmnopqrstuvwyxz0123456789' | ||
const Alphanum = Cyclic(elements) | ||
``` | ||
Operators derive from modular arithmetic | ||
```javascript | ||
const a = new Alphanum('a') | ||
Alphanum.addition('a', 'b') // 'c' | ||
``` | ||
You can also create element instances, and do any kind of operations. | ||
```javascript | ||
const x = new Alphanum('a') | ||
const y = x.add('c', 'a', 't') | ||
.mul('i', 's') | ||
.add('o', 'n') | ||
.sub('t', 'h', 'e') | ||
.div('t', 'a', 'b', 'l', 'e') | ||
y.data // 's' | ||
``` | ||
Yes, they are [scalars](#scalar) so you can build vector or matrix spaces on top of them. | ||
```javascript | ||
const VectorStrings2 = algebra.VectorSpace(Alphanum)(2) | ||
const MatrixStrings2x2 = algebra.MatrixSpace(Alphanum)(2) | ||
const vectorOfStrings = new VectorStrings2(['o', 'k']) | ||
const matrixOfStrings = new MatrixStrings2x2(['c', 'o', | ||
'o', 'l']) | ||
matrixOfStrings.mul(vectorOfStrings).data // ['x', 'y'] | ||
``` | ||
Note that, in the particular example above, since the matrix is simmetric | ||
it commutes with the vector, hence changing the order of the operands | ||
the result is still the same. | ||
```javascript | ||
vectorOfStrings.mul(matrixOfStrings).data // ['x', 'y'] | ||
``` | ||
### CompositionAlgebra | ||
@@ -457,7 +357,2 @@ | ||
Keeping in mind that *Byte* space defined above is an algebra, i.e. it has | ||
composition laws well defined, you maybe already noticed that, for example | ||
*byte2* could be seen as corresponding to 4, but in this strange structure | ||
we created, 4 * 4 = 2. | ||
You can play around with this structure. | ||
@@ -474,293 +369,211 @@ | ||
**NOTA BENE** The color space example in this section is still a *WiP*. | ||
The [scalars](https://en.wikipedia.org/wiki/Scalar_(mathematics)) are the building blocks, they are the elements you can use to create vectors and matrices. | ||
They are the underneath set enriched with a [ring](https://en.wikipedia.org/wiki/Ring_(mathematics)) structure which | ||
consists of two binary operators that generalize the arithmetic operations of addition and multiplication. | ||
A ring that has the commutativity property is called *abelian* (in honour to [Abel](https://en.wikipedia.org/wiki/Niels_Henrik_Abel)) or also a **field**. | ||
The [scalars](https://en.wikipedia.org/wiki/Scalar_(mathematics)) are the building blocks, they are the elements you can use to create vectors, | ||
matrices, tensors. They are the underneath set enriched with a | ||
[ring](https://en.wikipedia.org/wiki/Ring_(mathematics)) structure which | ||
consists of two binary operators that generalize the arithmetic operations of addition and multiplication. A ring that has the commutativity property | ||
is called *abelian* (in honour to [Abel](https://en.wikipedia.org/wiki/Niels_Henrik_Abel)) or also a **field**. | ||
Ok, let's make a simple example. [Real numbers](#real), with common addition and multiplication are a *scalar field*. | ||
Ok, let's make a simple example. [Real numbers](#real), with common addition | ||
and multiplication are a scalar field: see documentation below. The good new | ||
is that you can create any scalar field as long as you provide a set with | ||
two internal operations and related neutral elements that satisfy the ring | ||
axioms. That is why it will be used something maybe you did not expect could | ||
be treated as an algebra: in the examples below during this section we will | ||
play with the color space, giving a ring structure. | ||
The good new is that you can create any *scalar field* as long as you provide a set with two internal operations and related neutral elements that satisfy the ring axioms. | ||
Let's consider the space of html colors in the form | ||
We are going to create a scalar field using `BigInt` elements to implement something similar to a [Rational Number](https://en.wikipedia.org/wiki/Rational_number). The idea is to use a couple of numbers, the first one is the *numerator* and the second one the *denominator*. | ||
> RGB: Red Green Blue | ||
Arguments we need are the same as [algebra-ring]. Let's start by unities; every element is a couple of numbers, the | ||
*numerator* and the *denominator*, hence unitites are: | ||
composed of three hexadecimal values from `00` to `ff`. Let's start | ||
defining a sum operator on hexadecimals. | ||
* zero: `[ BigInt(0), BigInt(1) ]` | ||
* one: `[ BigInt(1), BigInt(1) ]` | ||
Credits and thanks for dec to hex and viceversa conversions goes to [this gist](https://gist.github.com/faisalman/4213592) author. | ||
We need a function that computes the *Great Common Divisor*. | ||
```javascript | ||
const hexSum = (hex1, hex2) => { | ||
const dec1 = parseInt(hex1, 16) % 256 | ||
const dec2 = parseInt(hex2, 16) % 256 | ||
// Sum modulo 256 and convert to hexadecimal. | ||
const hexResult = parseInt((dec1 + dec2) % 256, 10).toString(16) | ||
// Return left padded result. | ||
return hexResult.padStart(2, '0') | ||
function greatCommonDivisor (a, b) { | ||
if (b === BigInt(0)) { | ||
return a | ||
} else { | ||
return greatCommonDivisor(b, a % b) | ||
} | ||
} | ||
``` | ||
Note that it is used modulo 256 cause we need that our set is *closed* | ||
on this operator, it means that the sum of two colors must be another color. | ||
So now we can normalize a rational number, by removing the common divisors of numerator and denominator. | ||
To define color sum we can split a color in an array of three hexadecimals, | ||
and sum componentwise. | ||
```javascript | ||
const splitColor = (color) => { | ||
const r = color.substring(0, 2) | ||
const g = color.substring(2, 4) | ||
const b = color.substring(4, 6) | ||
function normalizeRational ([numerator, denominator]) { | ||
const divisor = greatCommonDivisor(numerator, denominator) | ||
return [r, g, b] | ||
return [numerator / divisor, denominator / divisor] | ||
} | ||
``` | ||
For example, white color `ffffff` will be splitted in `['ff', 'ff', 'ff']`. | ||
```javascript | ||
const colorSum = (color1, color2) => { | ||
const [r1, g1, b1] = splitColor(color1) | ||
const [r2, g2, b2] = splitColor(color2) | ||
const Rational = algebra.Scalar({ | ||
zero: [BigInt(0), BigInt(1)], | ||
one: [BigInt(1), BigInt(1)], | ||
equality: ([n1, d1], [n2, d2]) => (n1 * d2 === n2 * d1), | ||
contains: ([n, d]) => (typeof n === 'bigint' && typeof d === 'bigint'), | ||
addition: ([n1, d1], [n2, d2]) => normalizeRational([n1 * d2 + n2 * d1, d1 * d2]), | ||
negation: ([n, d]) => ([-n, d]), | ||
multiplication: ([n1, d1], [n2, d2]) => normalizeRational([n1 * n2, d1 * d2]), | ||
inversion: ([n, d]) => ([d, n]) | ||
}) | ||
``` | ||
const r = hexSum(r1, r2) | ||
const g = hexSum(g1, g2) | ||
const b = hexSum(b1, b2) | ||
So far so good, algebra dependencies will do some checks under the hood and will complain if something looks wrong. | ||
return [r, g, b].join('') | ||
} | ||
``` | ||
Let's create few rational numbers. | ||
You can check that this sum is *well defined*, and for example, green plus | ||
blue equals cyan. | ||
```javascript | ||
colorSum('00ff00', '0000ff') // '00ffff' | ||
const half = new Rational([BigInt(1), BigInt(2)]) | ||
const two = new Rational([BigInt(2), BigInt(1)]) | ||
``` | ||
The neutral element respect to this operator is *black* (`000000`). | ||
#### `Scalar.one` | ||
To define a scalar field we need another operation to be used as multiplication. | ||
Let's define a multiplication on hexadecimals first. | ||
Is the *neutral element* for [multiplication](#scalar-multiplication) operator. | ||
```javascript | ||
const hexMul = (hex1, hex2) => { | ||
const dec1 = parseInt(hex1, 16) % 256 | ||
const dec2 = parseInt(hex2, 16) % 256 | ||
Rational.one // [1n, 1n] | ||
``` | ||
// Multiply, then divide by 255 and convert to hexadecimal. | ||
const hexResult = parseInt((dec1 * dec2) / 255, 10).toString(16) | ||
#### `Scalar.zero` | ||
// Return left padded result. | ||
return hex.padStart(2, '0') | ||
} | ||
``` | ||
Is the *neutral element* for [addition](#scalar-addition) operator. | ||
Then similarly to `colorSum` it is possible to define a `colorMul` that | ||
applies `hexMul` componentwise. | ||
```javascript | ||
const colorMul = (color1, color2) => { | ||
const [r1, g1, b1] = splitColor(color1) | ||
const [r2, g2, b2] = splitColor(color2) | ||
const r = hexMul(r1, r2) | ||
const g = hexMul(g1, g2) | ||
const b = hexMul(b1, b2) | ||
return [r, g, b].join('') | ||
} | ||
Rational.zero // [0n, 1n] | ||
``` | ||
The neutral element for this operator is *white* (`ffffff`). | ||
#### `scalar.data` | ||
We are ready to create our scalar field over RGB colors. | ||
Arguments are the same as [algebra-ring]. | ||
The *data* attribute holds the raw data underneath our scalar instance. | ||
```javascript | ||
const RGB = algebra.Scalar( | ||
[ '000000', 'ffffff' ], | ||
{ | ||
equality: (a, b) => a === b, | ||
contains: (color) => { | ||
const [r, g, b] = splitColor(color) | ||
half.data // [1n, 2n] | ||
``` | ||
return (parseInt(r, 16) < 256) && (parseInt(g, 16) < 256) && (parseInt(b, 16) < 256) | ||
}, | ||
addition: colorSum, | ||
negation: (color) => { | ||
const [r, g, b] = splitColor(color) | ||
#### `Scalar.contains(scalar)` | ||
const decR = parseInt(r, 16) | ||
const decG = parseInt(g, 16) | ||
const decB = parseInt(b, 16) | ||
Checks a given argument is contained in the scalar field that was defined. | ||
const minusR = decR === 0 ? 0 : 256 - decR | ||
const minusG = decG === 0 ? 0 : 256 - decG | ||
const minusB = decB === 0 ? 0 : 256 - decB | ||
```javascript | ||
Rational.contains(half) // true | ||
Rational.contains([1n, 2n]) // true | ||
``` | ||
const hexMinusR = parseInt(minusR, 10).toString(16) | ||
const hexMinusG = parseInt(minusG, 10).toString(16) | ||
const hexMinusB = parseInt(minusB, 10).toString(16) | ||
#### `scalar1.belongsTo(Scalar)` | ||
const paddedMinusR = hexMinusR.padStart(2, '0') | ||
const paddedMinusG = hexMinusG.padStart(2, '0') | ||
const paddedMinusB = hexMinusB.padStart(2, '0') | ||
This is a class method that checks a scalar instance is contained in the given scalar field. | ||
return `${paddedMinusR}${paddedMinusG}${paddedMinusB}` | ||
}, | ||
multiplication: colorMul, | ||
inversion: (color) => { | ||
const [r, g, b] = splitColor(color) | ||
```javascript | ||
half.belongsTo(Rational) // true | ||
``` | ||
const decR = parseInt(r, 16) | ||
const decG = parseInt(g, 16) | ||
const decB = parseInt(b, 16) | ||
#### `Scalar.equality(scalar1, scalar2)` | ||
const invR = parseInt(255 * 255 / decR, 10).toString(16) | ||
const invG = parseInt(255 * 255 / decG, 10).toString(16) | ||
const invB = parseInt(255 * 255 / decB, 10).toString(16) | ||
Is a static method | ||
const paddedInvR = invR.padStart(2, '0') | ||
const paddedInvG = invG.padStart(2, '0') | ||
const paddedInvB = invB.padStart(2, '0') | ||
return `${paddedInvR}${paddedInvG}${paddedInvB}` | ||
}, | ||
} | ||
) | ||
```javascript | ||
Rational.equality(half, [BigInt(5), BigInt(10)]) | ||
``` | ||
So far so good, algebra dependencies will do some checks under the hood | ||
and complain if something looks wrong. Now we can create color instances | ||
#### `scalar1.equals(scalar2)` | ||
```javascript | ||
const green = new RGB('00ff00') | ||
const blue = new RGB('0000ff') | ||
half.equals([BigInt(2), BigInt(4)]) | ||
``` | ||
And as you may expect, you can do operations with them | ||
#### `Scalar.disequality(scalar1, scalar2)` | ||
```javascript | ||
const cyan = green.add(blue) | ||
cyan.data // '00ffff' | ||
Rational.disequality(half, two) // true | ||
``` | ||
#### Scalar attributes | ||
#### `scalar1.disequality(scalar2)` | ||
##### `Scalar.one` | ||
```javascript | ||
half.disequality(two) // true | ||
``` | ||
Is the *neutral element* for [multiplication](#scalar-multiplication) operator. | ||
In our *RGB* example it corrensponds to *white* (`ffffff`). | ||
#### `Scalar.addition(scalar1, scalar2)` | ||
```javascript | ||
RGB.one // 'ffffff' | ||
Rational.addition(half, two) // [5n , 2n] | ||
``` | ||
##### `Scalar.zero` | ||
#### `scalar1.addition(scalar2)` | ||
Is the *neutral element* for [addition](#scalar-addition) operator. | ||
In our *RGB* example it corrensponds to *black* (`000000`) | ||
```javascript | ||
RGB.zero // '000000' | ||
half.addition(two) // Scalar { data: [5n, 2n] } | ||
``` | ||
#### Scalar order | ||
#### `Scalar.subtraction(scalar1, scalar2)` | ||
It is always 0 for scalars, see also [Tensor order](#tensor-order). | ||
```javascript | ||
Rational.subtraction(two, half) // [3n , 2n] | ||
``` | ||
##### `Scalar.order` | ||
#### `scalar1.subtraction(scalar2)` | ||
The *order* is a static attribute. | ||
```javascript | ||
RGB.order // 0 | ||
two.multiplication(half) // Scalar { data: [1n, 1n] } | ||
``` | ||
##### `scalar.order` | ||
#### `Scalar.multiplication(scalar1, scalar2)` | ||
The *order* is also available as attribute of a Scalar class instance. | ||
```javascript | ||
green.order // 0 | ||
Rational.multiplication(half, two) // [1n, 1n] | ||
``` | ||
##### `scalar.data` | ||
#### `scalar1.multiplication(scalar2)` | ||
#### Scalar operators | ||
```javascript | ||
half.multiplication(two) // Scalar { data: [1n, 1n] } | ||
``` | ||
#### Scalar set operators | ||
#### `Scalar.division(scalar1, scalar2)` | ||
##### `Scalar.contains(scalar1, scalar2[, scalar3, … ])` | ||
```javascript | ||
Rational.division(two, half) // [1n, 4n] | ||
``` | ||
##### `scalar1.belongsTo(Scalar)` | ||
#### `scalar1.division(scalar2)` | ||
#### Scalar equality | ||
```javascript | ||
half.division(two) // Scalar { data: [1n, 4n] } | ||
``` | ||
##### `Scalar.equality(scalar1, scalar2)` | ||
#### `Scalar.negation(scalar)` | ||
##### `scalar1.equality(scalar2)` | ||
```javascript | ||
Rational.negation(two) // [-2n, 1n] | ||
``` | ||
#### Scalar disequality | ||
#### `scalar.negation()` | ||
##### `Scalar.disequality(scalar1, scalar2)` | ||
```javascript | ||
two.negation() // Scalar { data: [-2n, 1n] } | ||
``` | ||
##### `scalar1.disequality(scalar2)` | ||
#### `Scalar.inversion(scalar)` | ||
#### Scalar addition | ||
```javascript | ||
Rational.inversion(two) // [1n, 2n] | ||
``` | ||
##### `Scalar.addition(scalar1, scalar2[, scalar3, … ])` | ||
#### `scalar.inversion()` | ||
##### `scalar1.addition(scalar2[, scalar3, … ])` | ||
```javascript | ||
two.inversion() // Scalar { data: [1n, 2n] } | ||
``` | ||
#### Scalar subtraction | ||
<!-- TODO | ||
#### `Scalar.conjugation(scalar)` | ||
##### `Scalar.subtraction(scalar1, scalar2[, … ])` | ||
#### `scalar.conjugation()` | ||
--> | ||
##### `scalar1.subtraction(scalar2[, scalar3, … ])` | ||
#### Scalar multiplication | ||
##### `Scalar.multiplication(scalar1, scalar2[, scalar3, … ])` | ||
##### `scalar1.multiplication(scalar2[, scalar3, … ])` | ||
#### Scalar division | ||
##### `Scalar.division(scalar1, scalar2[, scalar3, … ])` | ||
##### `scalar1.division(scalar2[, scalar3, … ])` | ||
#### Scalar negation | ||
##### `Scalar.negation(scalar)` | ||
##### `scalar.negation()` | ||
#### Scalar inversion | ||
##### `Scalar.inversion(scalar)` | ||
##### `scalar.inversion()` | ||
#### Scalar conjugation | ||
##### `Scalar.conjugation(scalar)` | ||
##### `scalar.conjugation()` | ||
### Real | ||
Inherits everything from [Scalar](#scalar). | ||
Inherits everything from [Scalar](#scalar). Implements algebra of real numbers. | ||
@@ -796,4 +609,3 @@ ```javascript | ||
![Mandelbrot Set](http://g14n.info/algebra/images/Mandelbrot.gif) | ||
[OnQuaternionsAndOctonions](http://g14n.info/algebra/images/Cover-OnQuaternionsAndOctonions.png) | ||
![Mandelbrot Set](http://g14n.info/algebra/images/Mandelbrot.gif){:.responsive} | ||
@@ -834,3 +646,3 @@ The first thing I noticed when I started to study the Complex numbers is | ||
The real plane. | ||
The *Cartesian Plane*. | ||
@@ -911,4 +723,2 @@ ```javascript | ||
A *Vector* class inherits everything from [Tensor](#tensor). | ||
#### `VectorSpace(Scalar)(dimension)` | ||
@@ -1013,4 +823,2 @@ | ||
A *Matrix* class inherits everything from [Tensor](#tensor). | ||
#### `MatrixSpace(Scalar)(numRows[, numCols])` | ||
@@ -1052,97 +860,2 @@ | ||
### Tensor | ||
#### `TensorSpace(Scalar)(indices)` | ||
#### `Tensor.one` | ||
#### `Tensor.zero` | ||
#### `tensor.data` | ||
#### Tensor indices | ||
##### `Tensor.indices` | ||
##### `tensor.indices` | ||
#### Tensor order | ||
It represents the number of varying indices. | ||
* A scalar has order 0. | ||
* A vector has order 1. | ||
* A matrix has order 2. | ||
##### `Tensor.order` | ||
##### `tensor.order` | ||
#### `Tensor.contains(tensor1, tensor2[, tensor3, … ])` | ||
#### Tensor equality | ||
```javascript | ||
const T2x2x2 = TensorSpace(Real)([2, 2, 2]) | ||
const tensor1 = new T2x2x2([1, 2, 3, 4, 5, 6, 7, 8]) | ||
const tensor2 = new T2x2x2([2, 3, 4, 5, 6, 7, 8, 9]) | ||
``` | ||
##### `Tensor.equality(tensor1, tensor2)` | ||
```javascript | ||
T2x2x2.equality(tensor1, tensor1) // true | ||
T2x2x2.equality(tensor1, tensor2) // false | ||
``` | ||
##### `tensor1.equality(tensor2)` | ||
```javascript | ||
tensor1.equality(tensor1) // true | ||
tensor1.equality(tensor2) // false | ||
``` | ||
#### Tensor disequality | ||
#### `Tensor.disequality(tensor1, tensor2)` | ||
##### `tensor1.disequality(tensor2)` | ||
#### Tensor addition | ||
##### `Tensor.addition(tensor1, tensor2[, tensor3, … ])` | ||
##### `tensor1.addition(tensor2[, tensor3, … ])` | ||
#### Tensor subtraction | ||
##### `Tensor.subtraction(tensor1, tensor2[, tensor3, … ])` | ||
##### `tensor1.subtraction(tensor2[, tensor3, … ])` | ||
#### Tensor product | ||
##### `Tensor.product(tensor1, tensor2)` | ||
##### `tensor1.product(tensor2)` | ||
#### Tensor contraction | ||
##### `Tensor.contraction()` | ||
##### `tensor.contraction()` | ||
#### Tensor negation | ||
##### `Tensor.negation(tensor1)` | ||
##### `tensor.negation()` | ||
#### Tensor scalar multiplication | ||
##### `Tensor.scalarMultiplication(tensor, scalar)` | ||
##### `tensor.scalarMultiplication(scalar)` | ||
## License | ||
@@ -1149,0 +862,0 @@ |
const CayleyDickson = require('cayley-dickson') | ||
const createScalar = require('./createScalar') | ||
const no = require('not-defined') | ||
const Ring = require('./Ring.js') | ||
/** | ||
@@ -11,3 +12,3 @@ * A composition algebra is one of ℝ, ℂ, ℍ, O: | ||
* | ||
* @param {Object} field | ||
* @param {Object} ringDefinition | ||
* @param {Number} [num] of CayleyDickson construction iterations. Can be 1, 2, 4 or 8. | ||
@@ -18,3 +19,3 @@ * | ||
function CompositionAlgebra (field, num) { | ||
function CompositionAlgebra (ringDefinition, num) { | ||
if (no(num)) num = 1 | ||
@@ -28,5 +29,5 @@ | ||
return createScalar(CayleyDickson(field, logBase2)) | ||
return Ring(CayleyDickson(ringDefinition, logBase2)) | ||
} | ||
module.exports = CompositionAlgebra |
const determinant = require('laplace-determinant') | ||
const inherits = require('inherits') | ||
const itemsPool = require('./itemsPool') | ||
const matrixMultiplication = require('matrix-multiplication') | ||
const multiplication = require('matrix-multiplication') | ||
const multiDimArrayIndex = require('multidim-array-index') | ||
const no = require('not-defined') | ||
const operators = require('./operators.json') | ||
const staticProps = require('static-props') | ||
const TensorSpace = require('./TensorSpace') | ||
const tensorContraction = require('tensor-contraction') | ||
const toData = require('./toData') | ||
const itemsPool = require('./itemsPool.js') | ||
const toData = require('./toData.js') | ||
/** | ||
@@ -28,37 +25,85 @@ * Space of m x n matrices | ||
function MatrixSpace (Scalar) { | ||
const contraction = tensorContraction.bind(null, Scalar.addition) | ||
const { | ||
addition, | ||
equality, | ||
subtraction | ||
} = Scalar | ||
const contraction = tensorContraction.bind(null, addition) | ||
const enumerable = true | ||
/** | ||
* @param {Number} numRows | ||
* @param {Number} [numCols] defaults to a square matrix. | ||
* @param {Number} [numCols] if not defined it defaults to a square matrix. | ||
* | ||
* @returns {Function} Matrix | ||
* @returns {class} Matrix | ||
*/ | ||
return function (numRows, numCols) { | ||
// numCols defaults to numRows | ||
if (no(numCols)) numCols = numRows | ||
if (typeof numCols === 'undefined') numCols = numRows | ||
const dimension = numRows * numCols | ||
const indices = [numRows, numCols] | ||
const isSquare = (numRows === numCols) | ||
const indices = [numRows, numCols] | ||
const AbstractMatrix = TensorSpace(Scalar)(indices) | ||
/** | ||
* Determinant computation is defined only if it is a square matrix. | ||
*/ | ||
function computeDeterminant (matrix) { | ||
const data = toData(matrix) | ||
return determinant(data, Scalar, numRows) | ||
} | ||
/** | ||
* Calculates the matrix trace. | ||
* | ||
* https://en.wikipedia.org/wiki/Trace_(linear_algebra) | ||
* | ||
* @param {Object|Array} matrix | ||
* | ||
* @returns {Object} scalar | ||
* Matrix addition is the scalar addition for every item. | ||
*/ | ||
function trace (matrix) { | ||
const matrixData = toData(matrix) | ||
function matrixAddition (matrix1, matrix2) { | ||
const matrixData1 = toData(matrix1) | ||
const matrixData2 = toData(matrix2) | ||
return contraction([0, 1], indices, matrixData) | ||
const result = [] | ||
for (let i = 0; i < dimension; i++) { | ||
result.push(addition(matrixData1[i], matrixData2[i])) | ||
} | ||
return result | ||
} | ||
/** | ||
* Matrix equality checks that all elements are equal. | ||
* It also tries to check if numCols and numRows correspond. | ||
*/ | ||
function matrixEquality (matrix1, matrix2) { | ||
if (matrix1 instanceof Matrix && matrix2 instanceof Matrix) { | ||
if (matrix1.numCols !== matrix2.numCols) { | ||
return false | ||
} | ||
if (matrix1.numRows !== matrix2.numRows) { | ||
return false | ||
} | ||
} | ||
const matrixData1 = toData(matrix1) | ||
const matrixData2 = toData(matrix2) | ||
if (matrixData1.length !== matrixData2.length) { | ||
return false | ||
} | ||
for (let i = 0; i < dimension; i++) { | ||
if (!equality(matrixData1[i], matrixData2[i])) { | ||
return false | ||
} | ||
} | ||
return true | ||
} | ||
/** | ||
* Multiplies row by column to the right. | ||
@@ -71,7 +116,7 @@ * | ||
function multiplication (leftMatrix, rightMatrix) { | ||
function matrixMultiplication (leftMatrix, rightMatrix) { | ||
const leftMatrixData = toData(leftMatrix) | ||
const rightMatrixData = toData(rightMatrix) | ||
const rowByColumnMultiplication = matrixMultiplication(Scalar)(numCols) | ||
const rowByColumnMultiplication = multiplication(Scalar)(numCols) | ||
@@ -82,2 +127,35 @@ return rowByColumnMultiplication(leftMatrixData, rightMatrixData) | ||
/** | ||
* Matrix subtraction is the scalar subtraction for every item. | ||
*/ | ||
function matrixSubtraction (matrix1, matrix2) { | ||
const matrixData1 = toData(matrix1) | ||
const matrixData2 = toData(matrix2) | ||
const result = [] | ||
for (let i = 0; i < dimension; i++) { | ||
result.push(subtraction(matrixData1[i], matrixData2[i])) | ||
} | ||
return result | ||
} | ||
/** | ||
* Calculates the matrix trace. | ||
* | ||
* @see {@link https://en.wikipedia.org/wiki/Trace_(linear_algebra)} | ||
* | ||
* @param {Object|Array} matrix | ||
* | ||
* @returns {Object} scalar | ||
*/ | ||
function computeTrace (matrix) { | ||
const matrixData = toData(matrix) | ||
return contraction([0, 1], indices, matrixData) | ||
} | ||
/** | ||
* Calculates the transpose of a matrix. | ||
@@ -110,92 +188,108 @@ * | ||
function Matrix (data) { | ||
AbstractMatrix.call(this, data) | ||
staticProps(this)({ | ||
numCols, | ||
numRows | ||
}) | ||
function computeDeterminant () { | ||
const det = determinant(data, Scalar, numRows) | ||
return new Scalar(det) | ||
} | ||
if (isSquare) { | ||
class Matrix { | ||
constructor (data) { | ||
staticProps(this)({ | ||
trace: trace(data) | ||
}) | ||
data, | ||
numCols, | ||
numRows | ||
}, enumerable) | ||
staticProps(this)({ | ||
determinant: computeDeterminant, | ||
det: computeDeterminant | ||
Scalar, | ||
tr: () => this.transposed | ||
}) | ||
} | ||
function transposed () { | ||
const result = transpose(data) | ||
const VectorSpace = itemsPool.get('VectorSpace') | ||
if (isSquare) { | ||
staticProps(this)({ | ||
determinant: () => { | ||
const result = computeDeterminant(this) | ||
if (numRows === 1) { | ||
const Vector = VectorSpace(Scalar)(numCols) | ||
return new Vector(result) | ||
} else { | ||
const Matrix = MatrixSpace(Scalar)(numCols, numRows) | ||
return new Matrix(result) | ||
return new Scalar(result) | ||
}, | ||
trace: () => { | ||
const result = computeTrace(this) | ||
return new Scalar(result) | ||
} | ||
}) | ||
} | ||
} | ||
staticProps(this)({ | ||
transposed, | ||
tr: transposed | ||
}) | ||
} | ||
equality (matrix) { | ||
return matrixEquality(this, matrix) | ||
} | ||
inherits(Matrix, AbstractMatrix) | ||
get transposed () { | ||
const transposedElements = transpose(this) | ||
if (isSquare) { | ||
Matrix.trace = trace | ||
} | ||
// Get a class matrix in the transposed matrix space. | ||
// Note that numCols and numRows order as arguments is inverted. | ||
const TransposedMatrix = MatrixSpace(Scalar)(numCols, numRows) | ||
Matrix.prototype.multiplication = function (rightMatrix) { | ||
const leftMatrixData = this.data | ||
const result = multiplication(leftMatrixData, rightMatrix) | ||
return new TransposedMatrix(transposedElements) | ||
} | ||
const rightNumRows = numCols | ||
const rightNumCols = result.length / rightNumRows | ||
addition (matrix) { | ||
const result = matrixAddition(this, matrix) | ||
const Matrix = MatrixSpace(Scalar)(rightNumRows, rightNumCols) | ||
return new Matrix(result) | ||
} | ||
return new Matrix(result) | ||
} | ||
multiplication (matrix) { | ||
const result = matrixMultiplication(this, matrix) | ||
// Static operators. | ||
return new Matrix(result) | ||
} | ||
Matrix.multiplication = multiplication | ||
Matrix.transpose = transpose | ||
subtraction (matrix) { | ||
const result = matrixSubtraction(this, matrix) | ||
// Aliases | ||
return new Matrix(result) | ||
} | ||
} | ||
Matrix.tr = Matrix.transpose | ||
Matrix.mul = Matrix.multiplication | ||
// Method aliases. | ||
Matrix.prototype.add = Matrix.prototype.addition | ||
Matrix.prototype.eq = Matrix.prototype.equality | ||
Matrix.prototype.equal = Matrix.prototype.equality | ||
Matrix.prototype.mul = Matrix.prototype.multiplication | ||
Matrix.prototype.sub = Matrix.prototype.subtraction | ||
operators.group.forEach((operator) => { | ||
operators.aliasesOf[operator].forEach((alias) => { | ||
Matrix[alias] = Matrix[operator] | ||
Matrix.prototype[alias] = Matrix.prototype[operator] | ||
}) | ||
staticProps(Matrix)({ | ||
numCols, | ||
numRows | ||
}) | ||
operators.group.forEach((operator) => { | ||
Matrix[operator] = AbstractMatrix[operator] | ||
// Matrix static operators. | ||
staticProps(Matrix)({ | ||
addition: () => matrixAddition, | ||
equality: () => matrixEquality, | ||
multiplication: () => matrixMultiplication, | ||
subtraction: () => matrixSubtraction, | ||
transpose: () => transpose | ||
}) | ||
staticProps(Matrix)({ | ||
numCols, | ||
numRows | ||
add: Matrix.addition, | ||
eq: Matrix.equality, | ||
mul: Matrix.multiplication, | ||
sub: Matrix.subtraction, | ||
tr: Matrix.transpose | ||
}) | ||
if (isSquare) { | ||
Matrix.prototype.det = Matrix.prototype.determinant | ||
staticProps(Matrix)({ | ||
determinant: () => computeDeterminant, | ||
trace: () => computeTrace | ||
}) | ||
staticProps(Matrix)({ | ||
det: Matrix.determinant | ||
}) | ||
} | ||
return Matrix | ||
@@ -202,0 +296,0 @@ } |
@@ -19,7 +19,5 @@ const realField = { | ||
// | ||
// Hence we need to aproximate equality with an epsilon. | ||
// Hence we need to approximate equality with an epsilon. | ||
const epsilon = 0.000000000001 | ||
return Math.abs(a - b) < epsilon | ||
return Math.abs(a - b) < Number.EPSILON | ||
}, | ||
@@ -26,0 +24,0 @@ addition: (a, b) => a + b, |
@@ -1,14 +0,7 @@ | ||
const algebraRing = require('algebra-ring') | ||
const createScalar = require('./createScalar') | ||
const CompositionAlgebra = require('./CompositionAlgebra.js') | ||
/** | ||
* Create a Scalar. | ||
*/ | ||
function Scalar (neutralElements, operators) { | ||
const ring = algebraRing(neutralElements, operators) | ||
return createScalar(ring) | ||
function Scalar (ringDefinition) { | ||
return CompositionAlgebra(ringDefinition) | ||
} | ||
module.exports = Scalar |
@@ -1,7 +0,4 @@ | ||
const inherits = require('inherits') | ||
const itemsPool = require('./itemsPool') | ||
const matrixMultiplication = require('matrix-multiplication') | ||
const operators = require('./operators.json') | ||
const staticProps = require('static-props') | ||
const TensorSpace = require('./TensorSpace') | ||
const toData = require('./toData') | ||
@@ -24,6 +21,11 @@ | ||
function VectorSpace (Scalar) { | ||
const addition = Scalar.addition | ||
const multiplication = Scalar.multiplication | ||
const subtraction = Scalar.subtraction | ||
const { | ||
addition, | ||
equality, | ||
multiplication, | ||
subtraction | ||
} = Scalar | ||
const enumerable = true | ||
/** | ||
@@ -36,6 +38,2 @@ * @param {Number} dimension | ||
return function (dimension) { | ||
const indices = [dimension] | ||
const AbstractVector = TensorSpace(Scalar)(indices) | ||
/** | ||
@@ -64,3 +62,3 @@ * Computes the cross product of two vectors. | ||
let vector = [] | ||
const vector = [] | ||
@@ -76,5 +74,6 @@ vector.push(subtraction(multiplication(uy, vz), multiplication(uz, vy))) | ||
* Multiply a column vector by matrix on right side | ||
* @param {Object|Array} vector | ||
* | ||
* @returns {Object} scalar | ||
* @param leftVector | ||
* @param rightMatrix | ||
*/ | ||
@@ -118,3 +117,3 @@ | ||
* | ||
* https://en.wikipedia.org/wiki/Dot_product | ||
* @see {@link https://en.wikipedia.org/wiki/Dot_product} | ||
* | ||
@@ -128,3 +127,2 @@ * @param {Object|Array} vector1 | ||
function scalarProduct (vector1, vector2) { | ||
// TODO use tensor product and then contraction (trace) | ||
const vectorData1 = toData(vector1) | ||
@@ -147,93 +145,173 @@ const vectorData2 = toData(vector2) | ||
/** | ||
* Vector element. | ||
* Vector addition is the scalar addition for every coordinate. | ||
*/ | ||
function Vector (data) { | ||
AbstractVector.call(this, data) | ||
function vectorAddition (vector1, vector2) { | ||
const vectorData1 = toData(vector1) | ||
const vectorData2 = toData(vector2) | ||
staticProps(this)({ | ||
norm: norm(data), | ||
dimension | ||
}) | ||
const result = [] | ||
for (let i = 0; i < dimension; i++) { | ||
result.push(addition(vectorData1[i], vectorData2[i])) | ||
} | ||
return result | ||
} | ||
inherits(Vector, AbstractVector) | ||
/** | ||
* Vector equality checks that all coordinates are equal. | ||
*/ | ||
staticProps(Vector)({ dimension }) | ||
function vectorEquality (vector1, vector2) { | ||
const vectorData1 = toData(vector1) | ||
const vectorData2 = toData(vector2) | ||
Vector.prototype.scalarProduct = function (vector) { | ||
const data = this.data | ||
if (vectorData1.length !== vectorData2.length) { | ||
return false | ||
} | ||
const result = scalarProduct(data, vector) | ||
for (let i = 0; i < dimension; i++) { | ||
if (!equality(vectorData1[i], vectorData2[i])) { | ||
return false | ||
} | ||
} | ||
return new Scalar(result) | ||
return true | ||
} | ||
// Cross product is defined only in dimension 3. | ||
function crossProductMethod (vector) { | ||
const data = this.data | ||
/** | ||
* Vector subtraction is the scalar subtraction for every coordinate. | ||
*/ | ||
const result = crossProduct(data, vector) | ||
function vectorSubtraction (vector1, vector2) { | ||
const vectorData1 = toData(vector1) | ||
const vectorData2 = toData(vector2) | ||
return new Vector(result) | ||
} | ||
const result = [] | ||
if (dimension === 3) { | ||
Vector.crossProduct = crossProduct | ||
for (let i = 0; i < dimension; i++) { | ||
result.push(subtraction(vectorData1[i], vectorData2[i])) | ||
} | ||
Vector.prototype.crossProduct = crossProductMethod | ||
Vector.prototype.cross = crossProductMethod | ||
return result | ||
} | ||
Vector.prototype.multiplication = function (rightMatrix) { | ||
const MatrixSpace = itemsPool.get('MatrixSpace') | ||
/** | ||
* Vector element. | ||
*/ | ||
const leftVectorData = this.data | ||
const result = multiplicationByMatrix(leftVectorData, rightMatrix) | ||
class Vector { | ||
constructor (data) { | ||
staticProps(this)({ data }, enumerable) | ||
// TODO rightNumRows equals dimension | ||
// but the vector should be transposed. | ||
// Add transpose operator for vectors, then use it implicitly. | ||
const rightNumRows = dimension | ||
const rightNumCols = result.length / rightNumRows | ||
staticProps(this)({ | ||
norm: norm(data), | ||
dimension, | ||
Scalar | ||
}) | ||
const Matrix = MatrixSpace(Scalar)(rightNumRows, rightNumCols) | ||
// Method aliases. | ||
return new Matrix(result) | ||
staticProps(this)({ | ||
add: () => this.addition, | ||
eq: () => this.equality, | ||
equals: () => this.equality, | ||
mul: () => this.multiplication, | ||
scalar: () => this.scalarProduct, | ||
sub: () => this.subtraction | ||
}) | ||
} | ||
addition (vector) { | ||
const result = vectorAddition(this, vector) | ||
return new Vector(result) | ||
} | ||
equality (vector) { | ||
return vectorEquality(this, vector) | ||
} | ||
/** | ||
* Multiplication of a vector by a right matrix. | ||
* | ||
* Actually the vector it is supposed to be transposed, so it | ||
* becomes a row-vector, while by convention all vectors are column-vectors, | ||
* and after it is transposed, it can be multiplied by a right matrix. | ||
* | ||
* The transposition happens here implicitly. | ||
* | ||
* If you do not know what it means, do not worry. It is part of | ||
* Geometry first course at the first year of University, and you can | ||
* ignore it, since it has no consequences but it is hard to spot. | ||
* | ||
* I would like to thank and remember here in this comment, my awesome | ||
* prof. of Geometry. Thank you, Monti Bragadin. | ||
*/ | ||
multiplication (rightMatrix) { | ||
const MatrixSpace = itemsPool.get('MatrixSpace') | ||
const leftVectorData = this.data | ||
const result = multiplicationByMatrix(leftVectorData, rightMatrix) | ||
const rightNumRows = dimension | ||
const rightNumCols = result.length / rightNumRows | ||
const Matrix = MatrixSpace(Scalar)(rightNumRows, rightNumCols) | ||
return new Matrix(result) | ||
} | ||
scalarProduct (vector) { | ||
const result = scalarProduct(this, vector) | ||
return new Scalar(result) | ||
} | ||
subtraction (vector) { | ||
const result = vectorSubtraction(this, vector) | ||
return new Vector(result) | ||
} | ||
} | ||
// Static operators. | ||
staticProps(Vector)({ | ||
dimension | ||
}, enumerable) | ||
Vector.multiplication = multiplicationByMatrix | ||
Vector.norm = norm | ||
Vector.scalarProduct = scalarProduct | ||
// Vector static operators. | ||
operators.comparison.forEach((operator) => { | ||
Vector[operator] = AbstractVector[operator] | ||
staticProps(Vector)({ | ||
addition: () => vectorAddition, | ||
equality: () => vectorEquality, | ||
norm: () => norm, | ||
scalarProduct: () => scalarProduct, | ||
subtraction: () => vectorSubtraction | ||
}) | ||
operators.set.forEach((operator) => { | ||
Vector[operator] = AbstractVector[operator] | ||
staticProps(Vector)({ | ||
add: () => Vector.addition, | ||
eq: () => Vector.equality, | ||
scalar: () => Vector.scalarProduct, | ||
sub: () => Vector.subtraction | ||
}) | ||
operators.group.forEach((operator) => { | ||
Vector[operator] = AbstractVector[operator] | ||
}) | ||
function crossProductMethod (vector) { | ||
const data = this.data | ||
// Aliases | ||
const result = crossProduct(data, vector) | ||
Vector.mul = multiplicationByMatrix | ||
Vector.prototype.mul = Vector.prototype.multiplication | ||
return new Vector(result) | ||
} | ||
const myOperators = ['scalarProduct'].concat(operators.group) | ||
if (dimension === 3) { | ||
Vector.prototype.cross = crossProductMethod | ||
Vector.prototype.crossProduct = crossProductMethod | ||
myOperators.forEach((operator) => { | ||
operators.aliasesOf[operator].forEach((alias) => { | ||
Vector[alias] = Vector[operator] | ||
Vector.prototype[alias] = Vector.prototype[operator] | ||
staticProps(Vector)({ | ||
crossProduct: () => crossProduct, | ||
cross: () => crossProduct | ||
}) | ||
}) | ||
if (dimension === 3) { | ||
Vector.cross = crossProduct | ||
} | ||
@@ -240,0 +318,0 @@ |
379
test/api.js
/* eslint-disable indent */ | ||
/* eslint-env mocha */ | ||
/* global BigInt */ | ||
describe('API', () => { | ||
const algebra = require('algebra') | ||
const C = algebra.C | ||
const C2x2 = algebra.C2x2 | ||
const Complex = algebra.Complex | ||
const H = algebra.H | ||
const Quaternion = algebra.Quaternion | ||
const R = algebra.R | ||
const R2 = algebra.R2 | ||
const R3 = algebra.R3 | ||
const R2x2 = algebra.R2x2 | ||
const Real = algebra.Real | ||
const CompositionAlgebra = algebra.CompositionAlgebra | ||
const MatrixSpace = algebra.MatrixSpace | ||
const TensorSpace = algebra.TensorSpace | ||
const VectorSpace = algebra.VectorSpace | ||
@@ -36,3 +28,3 @@ const Boole = algebra.Boole | ||
vector1.addition(vector1, vector1).equality([3, 6]).should.be.ok() | ||
vector1.addition(vector1).equality([2, 4]).should.be.ok() | ||
@@ -88,124 +80,35 @@ vector1.data.should.deepEqual([1, 2]) | ||
describe('Scalar', () => { | ||
const hexSum = (hex1, hex2) => { | ||
const dec1 = parseInt(hex1, 16) % 256 | ||
const dec2 = parseInt(hex2, 16) % 256 | ||
const hexResult = parseInt((dec1 + dec2) % 256, 10).toString(16) | ||
return hexResult.padStart(2, '0') | ||
function greatCommonDivisor (a, b) { | ||
if (b === BigInt(0)) { | ||
return a | ||
} else { | ||
return greatCommonDivisor(b, a % b) | ||
} | ||
} | ||
const splitColor = (color) => { | ||
const r = color.substring(0, 2) | ||
const g = color.substring(2, 4) | ||
const b = color.substring(4, 6) | ||
function normalizeRational ([numerator, denominator]) { | ||
const divisor = greatCommonDivisor(numerator, denominator) | ||
return [r, g, b] | ||
return [numerator / divisor, denominator / divisor] | ||
} | ||
const colorSum = (color1, color2) => { | ||
const [r1, g1, b1] = splitColor(color1) | ||
const [r2, g2, b2] = splitColor(color2) | ||
const r = hexSum(r1, r2) | ||
const g = hexSum(g1, g2) | ||
const b = hexSum(b1, b2) | ||
return [r, g, b].join('') | ||
} | ||
const hexMul = (hex1, hex2) => { | ||
const dec1 = parseInt(hex1, 16) % 256 | ||
const dec2 = parseInt(hex2, 16) % 256 | ||
const hexResult = parseInt((dec1 * dec2) / 255, 10).toString(16) | ||
return hexResult.padStart(2, '0') | ||
} | ||
const colorMul = (color1, color2) => { | ||
const [r1, g1, b1] = splitColor(color1) | ||
const [r2, g2, b2] = splitColor(color2) | ||
const r = hexMul(r1, r2) | ||
const g = hexMul(g1, g2) | ||
const b = hexMul(b1, b2) | ||
return [r, g, b].join('') | ||
} | ||
describe('Color space example', () => { | ||
describe('colorSum()', () => { | ||
it('is well defined', () => { | ||
colorSum('00ff00', '0000ff').should.equal('00ffff') | ||
}) | ||
}) | ||
const Rational = algebra.Scalar({ | ||
zero: [BigInt(0), BigInt(1)], | ||
one: [BigInt(1), BigInt(1)], | ||
equality: ([n1, d1], [n2, d2]) => (n1 * d2 === n2 * d1), | ||
// eslint-disable-next-line | ||
contains: ([n, d]) => (typeof n === 'bigint' && typeof d === 'bigint'), | ||
addition: ([n1, d1], [n2, d2]) => normalizeRational([n1 * d2 + n2 * d1, d1 * d2]), | ||
negation: ([n, d]) => ([-n, d]), | ||
multiplication: ([n1, d1], [n2, d2]) => normalizeRational([n1 * n2, d1 * d2]), | ||
inversion: ([n, d]) => ([d, n]) | ||
}) | ||
const RGB = algebra.Scalar( | ||
[ '000000', 'ffffff' ], | ||
{ | ||
equality: (a, b) => a === b, | ||
contains: (color) => { | ||
const [r, g, b] = splitColor(color) | ||
const half = new Rational([BigInt(1), BigInt(2)]) | ||
const two = new Rational([BigInt(2), BigInt(1)]) | ||
return (parseInt(r, 16) < 256) && (parseInt(g, 16) < 256) && (parseInt(b, 16) < 256) | ||
}, | ||
addition: colorSum, | ||
negation: (color) => { | ||
const [r, g, b] = splitColor(color) | ||
const decR = parseInt(r, 16) | ||
const decG = parseInt(g, 16) | ||
const decB = parseInt(b, 16) | ||
const minusR = decR === 0 ? 0 : 255 - decR | ||
const minusG = decG === 0 ? 0 : 255 - decG | ||
const minusB = decB === 0 ? 0 : 255 - decB | ||
const hexMinusR = parseInt(minusR, 10).toString(16) | ||
const hexMinusG = parseInt(minusG, 10).toString(16) | ||
const hexMinusB = parseInt(minusB, 10).toString(16) | ||
const paddedMinusR = hexMinusR.padStart(2, '0') | ||
const paddedMinusG = hexMinusG.padStart(2, '0') | ||
const paddedMinusB = hexMinusB.padStart(2, '0') | ||
return `${paddedMinusR}${paddedMinusG}${paddedMinusB}` | ||
}, | ||
multiplication: colorMul, | ||
inversion: (color) => { | ||
const [r, g, b] = splitColor(color) | ||
const decR = parseInt(r, 16) | ||
const decG = parseInt(g, 16) | ||
const decB = parseInt(b, 16) | ||
const invR = parseInt(255 * 255 / decR, 10).toString(16) | ||
const invG = parseInt(255 * 255 / decG, 10).toString(16) | ||
const invB = parseInt(255 * 255 / decB, 10).toString(16) | ||
const paddedInvR = invR.padStart(2, '0') | ||
const paddedInvG = invG.padStart(2, '0') | ||
const paddedInvB = invB.padStart(2, '0') | ||
return `${paddedInvR}${paddedInvG}${paddedInvB}` | ||
} | ||
} | ||
) | ||
const green = new RGB('00ff00') | ||
const blue = new RGB('0000ff') | ||
const cyan = green.add(blue) | ||
describe('Color instances example', () => { | ||
it('works', () => { | ||
cyan.data.should.be.equal('00ffff') | ||
}) | ||
}) | ||
describe('Scalar.one', () => { | ||
it('is a static attribute', () => { | ||
RGB.one.should.be.equal('ffffff') | ||
Rational.one[0].should.be.deepEqual(BigInt(1)) | ||
Rational.one[1].should.be.deepEqual(BigInt(1)) | ||
}) | ||
@@ -216,98 +119,157 @@ }) | ||
it('is a static attribute', () => { | ||
RGB.zero.should.be.equal('000000') | ||
Rational.zero[0].should.be.equal(BigInt(0)) | ||
Rational.zero[1].should.be.equal(BigInt(1)) | ||
}) | ||
}) | ||
describe('Scalar.order', () => { | ||
it('is a static attribute', () => { | ||
RGB.order.should.be.equal(0) | ||
describe('scalar.data', () => { | ||
it('works', () => { | ||
half.data[0].should.be.eql(BigInt(1)) | ||
half.data[1].should.be.eql(BigInt(2)) | ||
}) | ||
}) | ||
describe('scalar.order', () => { | ||
it('is an attribute', () => { | ||
green.order.should.eql(0) | ||
describe('Scalar.contains', () => { | ||
it('works', () => { | ||
Rational.contains(half).should.be.ok() | ||
Rational.contains([BigInt(1), BigInt(2)]).should.be.ok() | ||
}) | ||
}) | ||
describe('data', () => { | ||
it('works') | ||
describe('scalar.belongsTo', () => { | ||
it('works', () => { | ||
half.belongsTo(Rational).should.be.ok() | ||
}) | ||
}) | ||
describe('contains', () => { | ||
it('works') | ||
describe('Scalar.equality', () => { | ||
it('works', () => { | ||
Rational.equality(half, [BigInt(5), BigInt(10)]) | ||
}) | ||
}) | ||
describe('belongsTo', () => { | ||
it('works') | ||
describe('scalar.equality', () => { | ||
it('works', () => { | ||
half.equality([BigInt(2), BigInt(4)]) | ||
}) | ||
}) | ||
describe('equality', () => { | ||
it('works') | ||
describe('Scalar.disequality', () => { | ||
it('works', () => { | ||
Rational.disequality(half, two).should.be.ok() | ||
}) | ||
}) | ||
describe('disequality', () => { | ||
it('works') | ||
describe('scalar.disequality', () => { | ||
it('works', () => { | ||
half.disequality(two).should.be.ok() | ||
}) | ||
}) | ||
describe('addition', () => { | ||
it('works') | ||
describe('Scalar.addition', () => { | ||
it('works', () => { | ||
const result = Rational.addition(half, two) | ||
result[0].should.eql(BigInt(5)) | ||
result[1].should.eql(BigInt(2)) | ||
}) | ||
}) | ||
describe('subtraction', () => { | ||
it('works') | ||
describe('scalar.addition', () => { | ||
it('works', () => { | ||
const result = half.addition(two) | ||
result.data[0].should.eql(BigInt(5)) | ||
result.data[1].should.eql(BigInt(2)) | ||
}) | ||
}) | ||
describe('multiplication', () => { | ||
it('works') | ||
describe('Scalar.subtraction', () => { | ||
it('works', () => { | ||
const result = Rational.subtraction(two, half) | ||
result[0].should.eql(BigInt(3)) | ||
result[1].should.eql(BigInt(2)) | ||
}) | ||
}) | ||
describe('division', () => { | ||
it('works') | ||
describe('scalar.subtraction', () => { | ||
it('works', () => { | ||
const result = two.subtraction(half) | ||
result.data[0].should.eql(BigInt(3)) | ||
result.data[1].should.eql(BigInt(2)) | ||
}) | ||
}) | ||
describe('negation', () => { | ||
it('works') | ||
describe('Scalar.multiplication', () => { | ||
it('works', () => { | ||
const result = Rational.multiplication(half, two) | ||
result[0].should.eql(BigInt(1)) | ||
result[1].should.eql(BigInt(1)) | ||
}) | ||
}) | ||
describe('inversion', () => { | ||
it('works') | ||
describe('scalar.multiplication', () => { | ||
it('works', () => { | ||
const result = half.multiplication(two) | ||
result.data[0].should.eql(BigInt(1)) | ||
result.data[1].should.eql(BigInt(1)) | ||
}) | ||
}) | ||
describe('conjugation', () => { | ||
it('works') | ||
describe('Scalar.division', () => { | ||
it('works', () => { | ||
const result = Rational.division(half, two) | ||
result[0].should.eql(BigInt(1)) | ||
result[1].should.eql(BigInt(4)) | ||
}) | ||
}) | ||
}) | ||
describe('Cyclic', () => { | ||
it('works', () => { | ||
const Cyclic = algebra.Cyclic | ||
describe('scalar.division', () => { | ||
it('works', () => { | ||
const result = half.division(two) | ||
const elements = ' abcdefghijklmnopqrstuvwyxz0123456789' | ||
result.data[0].should.eql(BigInt(1)) | ||
result.data[1].should.eql(BigInt(4)) | ||
}) | ||
}) | ||
const Alphanum = Cyclic(elements) | ||
describe('Scalar.negation', () => { | ||
it('works', () => { | ||
const result = Rational.negation(two) | ||
Alphanum.addition('a', 'b').should.eql('c') | ||
result[0].should.eql(BigInt(-2)) | ||
result[1].should.eql(BigInt(1)) | ||
}) | ||
}) | ||
const x = new Alphanum('a') | ||
describe('scalar.negation', () => { | ||
it('works', () => { | ||
const result = two.negation() | ||
const y = x.add('c', 'a', 't') | ||
.mul('i', 's') | ||
.add('o', 'n') | ||
.sub('t', 'h', 'e') | ||
.div('t', 'a', 'b', 'l', 'e') | ||
result.data[0].should.eql(BigInt(-2)) | ||
result.data[1].should.eql(BigInt(1)) | ||
}) | ||
}) | ||
y.data.should.eql('s') | ||
describe('Scalar.inversion', () => { | ||
it('works', () => { | ||
const result = Rational.inversion(two) | ||
const VectorStrings2 = algebra.VectorSpace(Alphanum)(2) | ||
const MatrixStrings2x2 = algebra.MatrixSpace(Alphanum)(2) | ||
result[0].should.eql(BigInt(1)) | ||
result[1].should.eql(BigInt(2)) | ||
}) | ||
}) | ||
const vectorOfStrings = new VectorStrings2(['o', 'k']) | ||
const matrixOfStrings = new MatrixStrings2x2(['c', 'o', | ||
'o', 'l']) | ||
matrixOfStrings.mul(vectorOfStrings) | ||
.data.should.deepEqual(['x', 'y']) | ||
describe('scalar.inversion', () => { | ||
it('works', () => { | ||
const result = two.inversion() | ||
vectorOfStrings.mul(matrixOfStrings) | ||
.data.should.deepEqual(['x', 'y']) | ||
result.data[0].should.eql(BigInt(1)) | ||
result.data[1].should.eql(BigInt(2)) | ||
}) | ||
}) | ||
@@ -346,46 +308,2 @@ }) | ||
describe('Common spaces', () => { | ||
describe('R', () => { | ||
it('is an alias of Real', () => { | ||
R.should.be.eql(Real) | ||
}) | ||
}) | ||
describe('R2', () => { | ||
it('is an alias of VectorSpace(Real)(2)', () => { | ||
R2.should.be.eql(VectorSpace(Real)(2)) | ||
}) | ||
}) | ||
describe('R3', () => { | ||
it('is an alias of VectorSpace(Real)(3)', () => { | ||
R3.should.be.eql(VectorSpace(Real)(3)) | ||
}) | ||
}) | ||
describe('R2x2', () => { | ||
it('is an alias of MatrixSpace(Real)(2)', () => { | ||
R2x2.should.be.eql(MatrixSpace(Real)(2)) | ||
}) | ||
}) | ||
describe('C', () => { | ||
it('is an alias of Complex', () => { | ||
C.should.be.eql(Complex) | ||
}) | ||
}) | ||
describe('C2x2', () => { | ||
it('is an alias of MatrixSpace(Complex)(2)', () => { | ||
C2x2.should.be.eql(MatrixSpace(Complex)(2)) | ||
}) | ||
}) | ||
describe('H', () => { | ||
it('is an alias of Quaternion', () => { | ||
H.should.be.eql(Quaternion) | ||
}) | ||
}) | ||
}) | ||
describe('Vector', () => { | ||
@@ -447,19 +365,2 @@ describe('Vector.dimension', () => { | ||
}) | ||
describe('Tensor', () => { | ||
describe('equality', () => { | ||
it('works', () => { | ||
const T2x2x2 = TensorSpace(Real)([2, 2, 2]) | ||
const tensor1 = new T2x2x2([1, 2, 3, 4, 5, 6, 7, 8]) | ||
const tensor2 = new T2x2x2([2, 3, 4, 5, 6, 7, 8, 9]) | ||
T2x2x2.equality(tensor1, tensor1).should.be.ok() | ||
T2x2x2.equality(tensor1, tensor2).should.not.be.ok() | ||
tensor1.equality(tensor1).should.be.ok() | ||
tensor1.equality(tensor2).should.not.be.ok() | ||
}) | ||
}) | ||
}) | ||
}) |
@@ -1,13 +0,13 @@ | ||
var algebra = require('algebra') | ||
/* eslint-env mocha */ | ||
var C = algebra.Complex | ||
const algebra = require('algebra') | ||
var methodBinaryOperator = require('./features/methodBinaryOperator') | ||
var methodUnaryOperator = require('./features/methodUnaryOperator') | ||
var staticBinaryOperator = require('./features/staticBinaryOperator') | ||
var staticUnaryOperator = require('./features/staticUnaryOperator') | ||
const C = algebra.Complex | ||
const methodBinaryOperator = require('./features/methodBinaryOperator') | ||
const methodUnaryOperator = require('./features/methodUnaryOperator') | ||
const staticBinaryOperator = require('./features/staticBinaryOperator') | ||
const staticUnaryOperator = require('./features/staticUnaryOperator') | ||
describe('Complex', () => { | ||
var operator | ||
describe('zero', () => { | ||
@@ -26,3 +26,3 @@ it('is static', () => { | ||
describe('addition', () => { | ||
operator = 'addition' | ||
const operator = 'addition' | ||
@@ -35,3 +35,3 @@ it('is a static method', staticBinaryOperator(C, operator, [2, 1], [2, 3], [4, 4])) | ||
describe('subtraction', () => { | ||
operator = 'subtraction' | ||
const operator = 'subtraction' | ||
@@ -44,3 +44,3 @@ it('is a static method', staticBinaryOperator(C, operator, [2, 1], [2, 3], [0, -2])) | ||
describe('multiplication', () => { | ||
operator = 'multiplication' | ||
const operator = 'multiplication' | ||
@@ -53,3 +53,3 @@ it('is a static method', staticBinaryOperator(C, operator, [2, 1], [2, -1], [5, 0])) | ||
describe('division', () => { | ||
operator = 'division' | ||
const operator = 'division' | ||
@@ -62,3 +62,3 @@ it('is a static method', staticBinaryOperator(C, operator, [2, 4], [2, 0], [1, 2])) | ||
describe('negation', () => { | ||
operator = 'negation' | ||
const operator = 'negation' | ||
@@ -71,3 +71,3 @@ it('is a static method', staticUnaryOperator(C, operator, [-2, 1], [2, -1])) | ||
describe('conjugation', () => { | ||
operator = 'conjugation' | ||
const operator = 'conjugation' | ||
@@ -74,0 +74,0 @@ it('is a static method', staticUnaryOperator(C, operator, [2, 1], [2, -1])) |
@@ -1,4 +0,6 @@ | ||
var CompositionAlgebra = require('../src/CompositionAlgebra') | ||
var realField = require('../src/realField') | ||
/* eslint-env mocha */ | ||
const CompositionAlgebra = require('../src/CompositionAlgebra') | ||
const realField = require('../src/realField') | ||
describe('CompositionAlgebra', () => { | ||
@@ -12,6 +14,6 @@ it('checks n is 1, 2, 4 or 8', () => { | ||
it('has signature (field, num)', () => { | ||
var R = CompositionAlgebra(realField, 1) | ||
var C = CompositionAlgebra(realField, 2) | ||
var H = CompositionAlgebra(realField, 4) | ||
var O = CompositionAlgebra(realField, 8) | ||
const R = CompositionAlgebra(realField, 1) | ||
const C = CompositionAlgebra(realField, 2) | ||
const H = CompositionAlgebra(realField, 4) | ||
const O = CompositionAlgebra(realField, 8) | ||
@@ -25,8 +27,8 @@ R.should.be.instanceOf(Function) | ||
it('returns a Scalar class', () => { | ||
var R = CompositionAlgebra(realField, 1) | ||
var C = CompositionAlgebra(realField, 2) | ||
const R = CompositionAlgebra(realField, 1) | ||
const C = CompositionAlgebra(realField, 2) | ||
R.addition(2, 3).should.be.eql(5) | ||
var x = new R(2) | ||
const x = new R(2) | ||
x.data.should.be.eql(2) | ||
@@ -38,3 +40,3 @@ | ||
var z = new C([1, 2]) | ||
const z = new C([1, 2]) | ||
z.data.should.be.eql([1, 2]) | ||
@@ -41,0 +43,0 @@ |
@@ -17,5 +17,5 @@ /** | ||
return function mutatorBinaryOperatorTest () { | ||
var scalar = new Scalar(operand1) | ||
const scalar = new Scalar(operand1) | ||
var result = scalar[operator](operand2) | ||
const result = scalar[operator](operand2) | ||
@@ -22,0 +22,0 @@ result.data.should.eql(resultData) |
@@ -16,5 +16,5 @@ /** | ||
return function mutatorUnaryOperatorTest () { | ||
var scalar = new Scalar(operand) | ||
const scalar = new Scalar(operand) | ||
var result = scalar[operator]() | ||
const result = scalar[operator]() | ||
@@ -21,0 +21,0 @@ result.data.should.eql(resultData) |
/* eslint-disable indent */ | ||
/* eslint-env mocha */ | ||
describe('MatrixSpace', () => { | ||
var algebra = require('algebra') | ||
const algebra = require('algebra') | ||
const notDefined = require('not-defined') | ||
var notDefined = require('not-defined') | ||
const MatrixSpace = algebra.MatrixSpace | ||
const Real = algebra.Real | ||
var MatrixSpace = algebra.MatrixSpace | ||
var Real = algebra.Real | ||
const methodBinaryOperator = require('./features/methodBinaryOperator') | ||
const staticBinaryOperator = require('./features/staticBinaryOperator') | ||
const staticUnaryOperator = require('./features/staticUnaryOperator') | ||
var methodBinaryOperator = require('./features/methodBinaryOperator') | ||
var staticBinaryOperator = require('./features/staticBinaryOperator') | ||
var staticUnaryOperator = require('./features/staticUnaryOperator') | ||
describe('MatrixSpace', () => { | ||
const R2x3 = MatrixSpace(Real)(2, 3) | ||
const R2x2 = MatrixSpace(Real)(2) | ||
const R3x2 = MatrixSpace(Real)(3, 2) | ||
var R1x4 = MatrixSpace(Real)(1, 4) | ||
var R2x3 = MatrixSpace(Real)(2, 3) | ||
var R2x2 = MatrixSpace(Real)(2) | ||
var R3x2 = MatrixSpace(Real)(3, 2) | ||
it('has signature (Scalar)(numRows, numCols)', () => { | ||
@@ -30,12 +29,12 @@ R2x3.numRows.should.be.eql(2) | ||
var matrix1 = new R2x2([ 2, 3, | ||
1, 1 ]) | ||
var matrix2 = new R2x2([ 0, 1, | ||
-1, 0 ]) | ||
var matrix3 = new R2x3([ 0, 1, 2, | ||
-2, 1, 0 ]) | ||
const matrix1 = new R2x2([2, 3, | ||
1, 1]) | ||
const matrix2 = new R2x2([0, 1, | ||
-1, 0]) | ||
const matrix3 = new R2x3([0, 1, 2, | ||
-2, 1, 0]) | ||
describe('data', () => { | ||
it('is enumerable', () => { | ||
matrix1.propertyIsEnumerable('data').should.be.ok() | ||
Object.prototype.propertyIsEnumerable.call(matrix1, 'data').should.be.ok() | ||
}) | ||
@@ -79,125 +78,71 @@ | ||
describe('addition()', () => { | ||
var operator = 'addition' | ||
const operator = 'addition' | ||
it('is a static method', staticBinaryOperator(R2x2, operator, | ||
[ 2, 3, | ||
1, 1 ], | ||
[ 0, 1, | ||
-1, 0 ], | ||
[ 2, 4, | ||
0, 1 ] | ||
)) | ||
[2, 3, | ||
1, 1], | ||
[0, 1, | ||
-1, 0], | ||
[2, 4, | ||
0, 1] | ||
)) | ||
it('is a class method', methodBinaryOperator(R2x2, operator, | ||
[ 2, 3, | ||
1, 1 ], | ||
[ 0, 1, | ||
-1, 0 ], | ||
[ 2, 4, | ||
0, 1 ] | ||
[2, 3, | ||
1, 1], | ||
[0, 1, | ||
-1, 0], | ||
[2, 4, | ||
0, 1] | ||
)) | ||
it('accepts multiple arguments', () => { | ||
R2x2.addition([ 2, 3, | ||
1, 1 ], | ||
[ 0, 1, | ||
-1, 0 ], | ||
[ -2, -4, | ||
0, -1 ]).should.deepEqual([0, 0, | ||
0, 0]) | ||
var matrix = new R2x2([ 2, 3, | ||
1, 1 ]) | ||
matrix.addition([ 0, 1, | ||
-1, 0 ], | ||
[ -2, -4, | ||
0, -1 ]).data.should.deepEqual([0, 0, | ||
0, 0]) | ||
}) | ||
}) | ||
describe('subtraction()', () => { | ||
var operator = 'subtraction' | ||
const operator = 'subtraction' | ||
it('is a static method', staticBinaryOperator(R2x2, operator, | ||
[2, 3, | ||
1, 1], | ||
[0, 1, | ||
-1, 0], | ||
[2, 2, | ||
2, 1] | ||
[2, 3, | ||
1, 1], | ||
[0, 1, | ||
-1, 0], | ||
[2, 2, | ||
2, 1] | ||
)) | ||
it('is a class method', methodBinaryOperator(R2x2, operator, | ||
[2, 3, | ||
1, 1], | ||
[0, 1, | ||
-1, 0], | ||
[2, 2, | ||
2, 1] | ||
[2, 3, | ||
1, 1], | ||
[0, 1, | ||
-1, 0], | ||
[2, 2, | ||
2, 1] | ||
)) | ||
it('accepts multiple arguments', () => { | ||
R2x2.subtraction([2, 3, | ||
1, 1], | ||
[0, 1, | ||
-1, 0], | ||
[2, 4, | ||
0, 1]).should.deepEqual([0, -2, | ||
2, 0]) | ||
var matrix = new R2x2([2, 3, | ||
1, 1]) | ||
matrix.subtraction([0, 1, | ||
-1, 0], | ||
[2, 4, | ||
0, 1]).data.should.deepEqual([0, -2, | ||
2, 0]) | ||
}) | ||
}) | ||
describe('multiplication()', () => { | ||
var operator = 'multiplication' | ||
const operator = 'multiplication' | ||
it('is a static method', staticBinaryOperator(R3x2, operator, | ||
[2, 3, | ||
1, 1, | ||
1, 1], | ||
[0, 1, 1, 1, | ||
-1, 0, 2, 3], | ||
[-3, 2, 8, 11, | ||
-1, 1, 3, 4, | ||
-1, 1, 3, 4] | ||
[2, 3, | ||
1, 1, | ||
1, 1], | ||
[0, 1, 1, 1, | ||
-1, 0, 2, 3], | ||
[-3, 2, 8, 11, | ||
-1, 1, 3, 4, | ||
-1, 1, 3, 4] | ||
)) | ||
it('is a class method', methodBinaryOperator(R2x2, operator, | ||
[2, 3, | ||
1, 1], | ||
[0, 1, | ||
-1, 0], | ||
[-3, 2, | ||
-1, 1] | ||
[2, 3, | ||
1, 1], | ||
[0, 1, | ||
-1, 0], | ||
[-3, 2, | ||
-1, 1] | ||
)) | ||
it('accepts multiple arguments', () => { | ||
R2x2.multiplication([1, 2, | ||
3, 4], | ||
[0, 1, | ||
-1, 0], | ||
[-1, 0, | ||
0, 1]).should.deepEqual([-2, 1, | ||
-4, 3]) | ||
var matrix = new R2x2([1, 2, | ||
3, 4]) | ||
matrix.multiplication([0, 1, | ||
-1, 0], | ||
[-1, 0, | ||
0, 1]).data.should.deepEqual([-2, 1, | ||
-4, 3]) | ||
}) | ||
}) | ||
describe('trace()', () => { | ||
var operator = 'trace' | ||
const operator = 'trace' | ||
@@ -209,3 +154,3 @@ it('is a static method', staticUnaryOperator(R2x2, operator, | ||
it('is not available for no square matrices', () => { | ||
it('is not available if it is not a square matrices', () => { | ||
notDefined(R3x2.trace).should.be.ok() | ||
@@ -217,12 +162,12 @@ }) | ||
it('is a static attribute', () => { | ||
var matrix2x2 = new R2x2([1, 2, | ||
5, 6]) | ||
const matrix2x2 = new R2x2([1, 2, | ||
5, 6]) | ||
matrix2x2.trace.should.be.eql(7) | ||
matrix2x2.trace.data.should.be.eql(7) | ||
}) | ||
it('is not available for no square matrices', () => { | ||
var matrix3x2 = new R3x2([1, 2, | ||
3, 4, | ||
5, 6]) | ||
const matrix3x2 = new R3x2([1, 2, | ||
3, 4, | ||
5, 6]) | ||
@@ -235,7 +180,7 @@ notDefined(matrix3x2.trace).should.be.ok() | ||
it('is a static operator', () => { | ||
var matrix3x2 = new R3x2([1, 2, | ||
3, 4, | ||
5, 6]) | ||
const matrix3x2 = new R3x2([1, 2, | ||
3, 4, | ||
5, 6]) | ||
var transposed = R3x2.transpose(matrix3x2) | ||
const transposed = R3x2.transpose(matrix3x2) | ||
@@ -249,7 +194,7 @@ transposed.should.deepEqual([1, 3, 5, | ||
it('is a class attribute', () => { | ||
var matrix3x2 = new R3x2([1, 2, | ||
3, 4, | ||
5, 6]) | ||
const matrix3x2 = new R3x2([1, 2, | ||
3, 4, | ||
5, 6]) | ||
var transposed = matrix3x2.transposed | ||
const transposed = matrix3x2.transposed | ||
@@ -261,4 +206,4 @@ transposed.data.should.deepEqual([1, 3, 5, | ||
it('holds a transposed matrix', () => { | ||
var matrix2x3 = new R2x3([1, 2, 3, | ||
4, 5, 6]) | ||
const matrix2x3 = new R2x3([1, 2, 3, | ||
4, 5, 6]) | ||
@@ -274,18 +219,9 @@ matrix2x3.transposed.data.should.deepEqual([1, 4, | ||
it('is an involution', () => { | ||
var matrix2x2a = new R2x2([1, 2, | ||
3, 4]) | ||
const matrix2x2a = new R2x2([1, 2, | ||
3, 4]) | ||
var matrix2x2b = matrix2x2a.transposed.transposed | ||
const matrix2x2b = matrix2x2a.transposed.transposed | ||
matrix2x2a.data.should.deepEqual(matrix2x2b.data) | ||
}) | ||
it('returns a vector if the Matrix has one row', () => { | ||
var matrix1x4 = new R1x4([1, 2, 3, 4]) | ||
var vector = matrix1x4.transposed | ||
matrix1x4.data.should.deepEqual(vector.data) | ||
vector.dimension.should.be.eql(matrix1x4.numCols) | ||
}) | ||
}) | ||
@@ -295,22 +231,18 @@ | ||
it('is an alias of multiplication()', () => { | ||
R2x2.mul.should.be.eql(R2x2.multiplication) | ||
const matrix2x2 = new R2x2([1, 2, | ||
3, 4]) | ||
var matrix2x2 = new R2x2([1, 2, | ||
3, 4]) | ||
const matrix3x2 = new R3x2([1, 2, | ||
3, 4, | ||
5, 6]) | ||
matrix2x2.multiplication.should.be.eql(matrix2x2.mul) | ||
matrix3x2.multiplication(matrix2x2).data.should.be.deepEqual(matrix3x2.mul(matrix2x2).data) | ||
}) | ||
}) | ||
describe('tr()', () => { | ||
it('is an alias of transpose()', () => { | ||
R2x2.tr.should.be.eql(R2x2.transpose) | ||
}) | ||
}) | ||
describe('tr', () => { | ||
it('is an alias of transposed', () => { | ||
var matrix = new R3x2([0, 1, | ||
1, 0, | ||
2, 2]) | ||
const matrix = new R3x2([0, 1, | ||
1, 0, | ||
2, 2]) | ||
@@ -317,0 +249,0 @@ matrix.tr.data.should.be.eql(matrix.transposed.data) |
/* eslint-disable indent */ | ||
/* eslint-env mocha */ | ||
describe('Quick start', () => { | ||
var algebra = require('algebra') | ||
const algebra = require('algebra') | ||
it('works', () => { | ||
var R = algebra.Real | ||
const R = algebra.Real | ||
R.add(1, 2, 3).should.eql(6) | ||
R.add(1, 2).should.eql(3) | ||
var x = new R(2) | ||
var y = new R(-2) | ||
let x = new R(2) | ||
const y = new R(-2) | ||
var r = x.mul(y) | ||
const r = x.mul(y) | ||
r.data.should.eql(-4) | ||
@@ -25,6 +26,6 @@ x.data.should.eql(2) | ||
var C = algebra.Complex | ||
const C = algebra.Complex | ||
var z1 = new C([1, 2]) | ||
var z2 = new C([3, 4]) | ||
let z1 = new C([1, 2]) | ||
const z2 = new C([3, 4]) | ||
@@ -39,6 +40,6 @@ z1 = z1.mul(z2) | ||
var R2 = algebra.VectorSpace(R)(2) | ||
const R2 = algebra.VectorSpace(R)(2) | ||
var v1 = new R2([0, 1]) | ||
var v2 = new R2([1, -2]) | ||
let v1 = new R2([0, 1]) | ||
const v2 = new R2([1, -2]) | ||
@@ -49,22 +50,23 @@ v1 = v1.add(v2) | ||
var R3x2 = algebra.MatrixSpace(R)(3, 2) | ||
const R3x2 = algebra.MatrixSpace(R)(3, 2) | ||
var m1 = new R3x2([1, 1, | ||
0, 1, | ||
1, 0]) | ||
const m1 = new R3x2([1, 1, | ||
0, 1, | ||
1, 0]) | ||
var v3 = m1.mul(v1) | ||
const v3 = m1.mul(v1) | ||
v3.data.should.deepEqual([0, -1, 1]) | ||
var R2x2 = algebra.MatrixSpace(R)(2) | ||
const R2x2 = algebra.MatrixSpace(R)(2) | ||
var m2 = new R2x2([1, 0, | ||
let m2 = new R2x2([1, 0, | ||
0, 2]) | ||
var m3 = new R2x2([0, -1, | ||
1, 0]) | ||
const m3 = new R2x2([0, -1, | ||
1, 0]) | ||
m2 = m2.mul(m3) | ||
m2.data.should.deepEqual([0, -1, 2, 0]) | ||
m2.data.should.deepEqual([0, -1, | ||
2, 0]) | ||
@@ -71,0 +73,0 @@ m2.determinant.data.should.be.eql(2) |
@@ -1,10 +0,15 @@ | ||
var algebra = require('algebra') | ||
/* eslint-env mocha */ | ||
var R = algebra.Real | ||
const algebra = require('algebra') | ||
const assert = require('assert') | ||
var methodBinaryOperator = require('./features/methodBinaryOperator') | ||
var methodUnaryOperator = require('./features/methodUnaryOperator') | ||
var staticBinaryOperator = require('./features/staticBinaryOperator') | ||
var staticUnaryOperator = require('./features/staticUnaryOperator') | ||
const realField = require('../src/realField') | ||
const R = algebra.Real | ||
const methodBinaryOperator = require('./features/methodBinaryOperator') | ||
const methodUnaryOperator = require('./features/methodUnaryOperator') | ||
const staticBinaryOperator = require('./features/staticBinaryOperator') | ||
const staticUnaryOperator = require('./features/staticUnaryOperator') | ||
describe('Real', () => { | ||
@@ -24,3 +29,3 @@ describe('zero', () => { | ||
describe('addition', () => { | ||
var operator = 'addition' | ||
const operator = 'addition' | ||
@@ -30,11 +35,6 @@ it('is a static method', staticBinaryOperator(R, operator, 2, 3, 5)) | ||
it('is a class method', methodBinaryOperator(R, operator, 1, 2, 3)) | ||
it('accepts many arguments', () => { | ||
var x = new R(1) | ||
x.addition(2, 3, 4).data.should.eql(10) | ||
}) | ||
}) | ||
describe('subtraction', () => { | ||
var operator = 'subtraction' | ||
const operator = 'subtraction' | ||
@@ -44,11 +44,6 @@ it('is a static method', staticBinaryOperator(R, operator, 2, 3, -1)) | ||
it('is a class method', methodBinaryOperator(R, operator, -1, -4, 3)) | ||
it('accepts many arguments', () => { | ||
var x = new R(10) | ||
x.subtraction(1, 2, 3).data.should.eql(4) | ||
}) | ||
}) | ||
describe('multiplication', () => { | ||
var operator = 'multiplication' | ||
const operator = 'multiplication' | ||
@@ -58,11 +53,6 @@ it('is a static method', staticBinaryOperator(R, operator, 8, -2, -16)) | ||
it('is a class method', methodBinaryOperator(R, operator, 2, 2, 4)) | ||
it('accepts many arguments', () => { | ||
var x = new R(2) | ||
x.multiplication(3, 4, 5).data.should.eql(120) | ||
}) | ||
}) | ||
describe('division', () => { | ||
var operator = 'division' | ||
const operator = 'division' | ||
@@ -72,11 +62,6 @@ it('is a static method', staticBinaryOperator(R, operator, 8, 2, 4)) | ||
it('is a class method', methodBinaryOperator(R, operator, -2, 4, -0.5)) | ||
it('accepts many arguments', () => { | ||
var x = new R(120) | ||
x.division(3, 4, 5).data.should.eql(2) | ||
}) | ||
}) | ||
describe('equality', () => { | ||
var operator = 'equality' | ||
const operator = 'equality' | ||
@@ -86,3 +71,3 @@ it('is a static method', staticBinaryOperator(R, operator, 10, 10, true)) | ||
it('is a class method', () => { | ||
var x = new R(10) | ||
const x = new R(10) | ||
x.equality(10).should.be.ok() | ||
@@ -93,3 +78,3 @@ }) | ||
describe('disequality', () => { | ||
var operator = 'disequality' | ||
const operator = 'disequality' | ||
@@ -99,3 +84,3 @@ it('is a static method', staticBinaryOperator(R, operator, 10, 20, true)) | ||
it('is a class method', () => { | ||
var x = new R(10) | ||
const x = new R(10) | ||
x.disequality(20).should.be.ok() | ||
@@ -106,3 +91,3 @@ }) | ||
describe('negation', () => { | ||
var operator = 'negation' | ||
const operator = 'negation' | ||
@@ -114,3 +99,3 @@ it('is a static method', staticUnaryOperator(R, operator, -2, 2)) | ||
it('is an involution', () => { | ||
var x = new R(10) | ||
const x = new R(10) | ||
x.negation().negation().data.should.be.eql(10) | ||
@@ -121,3 +106,3 @@ }) | ||
describe('inversion', () => { | ||
var operator = 'inversion' | ||
const operator = 'inversion' | ||
@@ -129,6 +114,12 @@ it('is a static method', staticUnaryOperator(R, operator, 2, 0.5)) | ||
it('is an involution', () => { | ||
var x = new R(10) | ||
const x = new R(10) | ||
x.inversion().inversion().data.should.be.eql(10) | ||
}) | ||
}) | ||
describe('realField', () => { | ||
it('epsilon', () => { | ||
assert(realField.equality(0.2 + 0.1, 0.3)) | ||
}) | ||
}) | ||
}) |
@@ -1,12 +0,14 @@ | ||
var CompositionAlgebra = require('algebra').CompositionAlgebra | ||
var realField = require('../src/realField') | ||
/* eslint-env mocha */ | ||
var R = CompositionAlgebra(realField) | ||
const CompositionAlgebra = require('algebra').CompositionAlgebra | ||
const realField = require('../src/realField') | ||
const R = CompositionAlgebra(realField) | ||
describe('CompositionAlgebra', () => { | ||
describe('data', () => { | ||
var pi = new R(Math.PI) | ||
const pi = new R(Math.PI) | ||
it('is enumerable', () => { | ||
pi.propertyIsEnumerable('data').should.be.ok() | ||
Object.prototype.propertyIsEnumerable.call(pi, 'data').should.be.ok() | ||
}) | ||
@@ -13,0 +15,0 @@ |
@@ -1,20 +0,22 @@ | ||
var algebra = require('algebra') | ||
var notDefined = require('not-defined') | ||
/* eslint-env mocha */ | ||
var Real = algebra.Real | ||
var VectorSpace = algebra.VectorSpace | ||
const algebra = require('algebra') | ||
const notDefined = require('not-defined') | ||
var methodBinaryOperator = require('./features/methodBinaryOperator') | ||
var staticBinaryOperator = require('./features/staticBinaryOperator') | ||
var staticUnaryOperator = require('./features/staticUnaryOperator') | ||
const Real = algebra.Real | ||
const VectorSpace = algebra.VectorSpace | ||
var R2 = VectorSpace(Real)(2) | ||
var R3 = VectorSpace(Real)(3) | ||
const methodBinaryOperator = require('./features/methodBinaryOperator') | ||
const staticBinaryOperator = require('./features/staticBinaryOperator') | ||
const staticUnaryOperator = require('./features/staticUnaryOperator') | ||
const R2 = VectorSpace(Real)(2) | ||
const R3 = VectorSpace(Real)(3) | ||
describe('VectorSpace', () => { | ||
describe('data', () => { | ||
var v = new R2([0, 1]) | ||
const vector = new R2([0, 1]) | ||
it('is enumerable', () => { | ||
v.propertyIsEnumerable('data').should.be.ok() | ||
Object.prototype.propertyIsEnumerable.call(vector, 'data').should.be.ok() | ||
}) | ||
@@ -25,3 +27,3 @@ | ||
'use strict' | ||
v.data = [2, 1] | ||
vector.data = [2, 1] | ||
}).should.throwError() | ||
@@ -32,3 +34,3 @@ }) | ||
describe('addition()', () => { | ||
var operator = 'addition' | ||
const operator = 'addition' | ||
@@ -38,13 +40,6 @@ it('is a static method', staticBinaryOperator(R2, operator, [0, 2], [-1, 3], [-1, 5])) | ||
it('is a class method', methodBinaryOperator(R2, operator, [0, 1], [1, 1], [1, 2])) | ||
it('accepts multiple arguments', () => { | ||
R2.addition([1, -1], [2, -2], [3, -3]).should.deepEqual([6, -6]) | ||
var vector = new R2([1, -1]) | ||
vector.addition([2, -2], [3, -3]).data.should.eql([6, -6]) | ||
}) | ||
}) | ||
describe('subtraction()', () => { | ||
var operator = 'subtraction' | ||
const operator = 'subtraction' | ||
@@ -54,9 +49,2 @@ it('is a static method', staticBinaryOperator(R2, operator, [0, 2], [-1, 3], [1, -1])) | ||
it('is a class method', methodBinaryOperator(R2, operator, [0, 1], [1, 1], [-1, 0])) | ||
it('accepts multiple arguments', () => { | ||
R2.subtraction([6, -6], [2, -2], [3, -3]).should.deepEqual([1, -1]) | ||
var vector = new R2([6, -6]) | ||
vector.subtraction([2, -2], [3, -3]).data.should.eql([1, -1]) | ||
}) | ||
}) | ||
@@ -66,3 +54,3 @@ | ||
it('is a static operator', () => { | ||
var data = R2.scalarProduct([0, 1], [1, 1]) | ||
const data = R2.scalarProduct([0, 1], [1, 1]) | ||
@@ -73,6 +61,6 @@ data.should.eql(1) | ||
it('is a class method', () => { | ||
var vector1 = new R2([0, 1]) | ||
var vector2 = new R2([1, 1]) | ||
const vector1 = new R2([0, 1]) | ||
const vector2 = new R2([1, 1]) | ||
var scalar = vector1.scalarProduct(vector2) | ||
const scalar = vector1.scalarProduct(vector2) | ||
@@ -83,6 +71,6 @@ scalar.data.should.be.eql(1) | ||
it('is returns a scalar', () => { | ||
var vector1 = new R2([0, 1]) | ||
var vector2 = new R2([1, 1]) | ||
const vector1 = new R2([0, 1]) | ||
const vector2 = new R2([1, 1]) | ||
var scalar = vector1.scalarProduct(vector2) | ||
const scalar = vector1.scalarProduct(vector2) | ||
@@ -93,24 +81,6 @@ scalar.data.should.be.eql(1) | ||
describe('dotProduct()', () => { | ||
it('is an alias of scalarProduct()', () => { | ||
R2.scalarProduct.should.be.eql(R2.dotProduct) | ||
var vector = new R2([0, 1]) | ||
vector.scalarProduct.should.be.eql(vector.dotProduct) | ||
}) | ||
}) | ||
describe('dot()', () => { | ||
it('is an alias of scalarProduct()', () => { | ||
R2.scalarProduct.should.be.eql(R2.dot) | ||
var vector = new R2([0, 1]) | ||
vector.scalarProduct.should.be.eql(vector.dot) | ||
}) | ||
}) | ||
describe('dimension', () => { | ||
it('is a static attribute', () => { | ||
var vector1 = new R2([0, 1]) | ||
var vector2 = new R3([1, 1, 2]) | ||
const vector1 = new R2([0, 1]) | ||
const vector2 = new R3([1, 1, 2]) | ||
@@ -127,4 +97,4 @@ vector1.dimension.should.be.eql(2) | ||
it('is an attribute holding a scalar', () => { | ||
var vector1 = new R2([0, 1]) | ||
var vector2 = new R3([1, 1, 2]) | ||
const vector1 = new R2([0, 1]) | ||
const vector2 = new R3([1, 1, 2]) | ||
@@ -137,3 +107,3 @@ vector1.norm.data.should.be.eql(1) | ||
describe('norm()', () => { | ||
var operator = 'norm' | ||
const operator = 'norm' | ||
@@ -147,3 +117,3 @@ it('is a static method', () => { | ||
describe('crossProduct()', () => { | ||
var operator = 'crossProduct' | ||
const operator = 'crossProduct' | ||
@@ -159,6 +129,6 @@ it('is a static method', () => { | ||
it('is defined only in dimension 3', () => { | ||
notDefined(R2.cross).should.be.ok() | ||
notDefined(R2.crossProduct).should.be.ok() | ||
var vector = new R2([1, 0]) | ||
notDefined(vector.cross).should.be.ok() | ||
const vector = new R2([1, 0]) | ||
notDefined(vector.crossProduct).should.be.ok() | ||
}) | ||
@@ -171,3 +141,3 @@ }) | ||
var vector = new R3([1, 0, 1]) | ||
const vector = new R3([1, 0, 1]) | ||
vector.crossProduct.should.be.eql(vector.cross) | ||
@@ -174,0 +144,0 @@ }) |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
402112
9
6
51
4330
857
4
1
- Removedalgebra-cyclic@^0.2.4
- Removedinherits@^2.0.1
- Removedtensor-product@^0.2.1
- Removedalgebra-cyclic@0.2.5(transitive)
- Removedinherits@2.0.4(transitive)
- Removedtensor-product@0.2.2(transitive)