npm package: @kkitahara/real-algebra
Description: ECMAScript modules for exactly manipulating real numbers of the form (p / q)sqrt(b).
Author: Koichi Kitahara
Latest version: 1.2.4

[![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)
[![license](https://img.shields.io/npm/l/@kkitahara/real-algebra.svg)](https://www.apache.org/licenses/LICENSE-2.0)
[![pipeline status](https://gitlab.com/kkitahara/real-algebra/badges/v1.2.4/pipeline.svg)](https://gitlab.com/kkitahara/real-algebra/commits/v1.2.4)
[![coverage report](https://gitlab.com/kkitahara/real-algebra/badges/v1.2.4/coverage.svg)](https://gitlab.com/kkitahara/real-algebra/commits/v1.2.4)
[![version](https://img.shields.io/npm/v/@kkitahara/real-algebra/latest.svg)](https://www.npmjs.com/package/@kkitahara/real-algebra)
[![bundle size](https://img.shields.io/bundlephobia/min/@kkitahara/real-algebra.svg)](https://www.npmjs.com/package/@kkitahara/real-algebra)
[![downloads per month](https://img.shields.io/npm/dm/@kkitahara/real-algebra.svg)](https://www.npmjs.com/package/@kkitahara/real-algebra)
[![downloads total](https://img.shields.io/npm/dt/@kkitahara/real-algebra.svg)](https://www.npmjs.com/package/@kkitahara/real-algebra)

# RealAlgebra

ECMAScript modules for exactly manipulating real 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.

## Installation
```
npm install @kkitahara/real-algebra
```

## Examples
```javascript
import { ExactRealAlgebra as RealAlgebra } from '@kkitahara/real-algebra'
let ralg = new RealAlgebra()
let a, b, c
```
Generate a new number
```javascript
a = ralg.num(1, 2, 5)
a.toString() // '(1 / 2)sqrt(5)'

a = ralg.num(1, 2)
a.toString() // '1 / 2'

a = ralg.num(3)
a.toString() // '3'
```
Generate a new number (short form, since v1.2.0)
```javascript
a = ralg.$(1, 2, 5)
a.toString() // '(1 / 2)sqrt(5)'

a = ralg.$(1, 2)
a.toString() // '1 / 2'

a = ralg.$(3)
a.toString() // '3'
```
:warning: `num` and `$` methods do not check if the 3rd parameter is
a square-free integer or not (must be square-free!).

Copy (create a new object)
```javascript
a = ralg.num(1, 2, 5)
b = ralg.copy(a)
b.toString() // '(1 / 2)sqrt(5)'
```
Equality
```javascript
a = ralg.num(1, 2, 5)
b = ralg.num(3, 2, 5)
ralg.eq(a, b) // false

b = ralg.num(1, 2, 5)
ralg.eq(a, b) // true
```
Inequality
```javascript
a = ralg.num(1, 2, 5)
b = ralg.num(3, 2, 5)
ralg.ne(a, b) // true

b = ralg.num(1, 2, 5)
ralg.ne(a, b) // false
```
isZero
```javascript
ralg.isZero(ralg.num(0)) // true
ralg.isZero(ralg.num(1, 2, 5)) // false
ralg.isZero(ralg.num(-1, 2, 5)) // false
```
isPositive
```javascript
ralg.isPositive(ralg.num(0)) // false
ralg.isPositive(ralg.num(1, 2, 5)) // true
ralg.isPositive(ralg.num(-1, 2, 5)) // false
```
isNegative
```javascript
ralg.isNegative(ralg.num(0)) // false
ralg.isNegative(ralg.num(1, 2, 5)) // false
ralg.isNegative(ralg.num(-1, 2, 5)) // true
```
isInteger (since v1.1.0)
```javascript
ralg.isInteger(ralg.num(0)) // true
ralg.isInteger(ralg.num(6, 3)) // true
ralg.isInteger(ralg.num(1, 2)) // false
ralg.isInteger(ralg.num(2, 1, 3)) // false
```
Addition
```javascript
a = ralg.num(1, 2, 5)
b = ralg.num(1, 2, 1)
// new object is generated
c = ralg.add(a, b)
c.toString() // '1 / 2 + (1 / 2)sqrt(5)'
```
In-place addition
```javascript
a = ralg.num(1, 2, 5)
b = ralg.num(1, 2, 1)
// new object is not generated
a = ralg.iadd(a, b)
a.toString() // '1 / 2 + (1 / 2)sqrt(5)'
```
Subtraction
```javascript
a = ralg.num(1, 2, 5)
b = ralg.num(1, 2, 1)
// new object is generated
c = ralg.sub(a, b)
c.toString() // '-1 / 2 + (1 / 2)sqrt(5)'
```
In-place subtraction
```javascript
a = ralg.num(1, 2, 5)
b = ralg.num(1, 2, 1)
// new object is not generated
a = ralg.isub(a, b)
a.toString() // '-1 / 2 + (1 / 2)sqrt(5)'
```
Multiplication
```javascript
a = ralg.iadd(ralg.num(1, 2), ralg.num(1, 2, 5))
b = ralg.iadd(ralg.num(-1, 2), ralg.num(1, 2, 5))
// new object is generated
c = ralg.mul(a, b)
c.toString() // '1'
```
In-place multiplication
```javascript
a = ralg.iadd(ralg.num(1, 2), ralg.num(1, 2, 5))
b = ralg.iadd(ralg.num(-1, 2), ralg.num(1, 2, 5))
// new object is not generated
a = ralg.imul(a, b)
a.toString() // '1'
```
Division
```javascript
a = ralg.iadd(ralg.num(1, 2), ralg.num(1, 2, 5))
b = ralg.iadd(ralg.num(-1, 2), ralg.num(1, 2, 5))
// new object is generated
c = ralg.div(a, b)
c.toString() // '3 / 2 + (1 / 2)sqrt(5)'
```
In-place division
```javascript
a = ralg.iadd(ralg.num(1, 2), ralg.num(1, 2, 5))
b = ralg.iadd(ralg.num(-1, 2), ralg.num(1, 2, 5))
// new object is not generated
a = ralg.idiv(a, b)
a.toString() // '3 / 2 + (1 / 2)sqrt(5)'
```
Multiplication by -1
```javascript
a = ralg.iadd(ralg.num(1, 2), ralg.num(1, 2, 5))
// new object is generated
b = ralg.neg(a)
b.toString() // '-1 / 2 - (1 / 2)sqrt(5)'
```
In-place multiplication by -1
```javascript
a = ralg.iadd(ralg.num(1, 2), ralg.num(1, 2, 5))
// new object is not generated
a = ralg.ineg(a)
a.toString() // '-1 / 2 - (1 / 2)sqrt(5)'
```
Absolute value
```javascript
a = ralg.iadd(ralg.num(1, 2), ralg.num(-1, 2, 5))
// new object is generated
b = ralg.abs(a)
b.toString() // '-1 / 2 + (1 / 2)sqrt(5)'
```
In-place evaluation of the absolute value
```javascript
a = ralg.iadd(ralg.num(1, 2), ralg.num(-1, 2, 5))
// new object is not generated
a = ralg.iabs(a)
a.toString() // '-1 / 2 + (1 / 2)sqrt(5)'
```
JSON (stringify and parse)
```javascript
a = ralg.iadd(ralg.num(1, 2), ralg.num(1, 2, 5))
let str = JSON.stringify(a)
b = JSON.parse(str, ralg.reviver)
ralg.eq(a, b) // true
```

### Numerical algebra
The above codes work with built-in numbers if you use
```javascript
import { RealAlgebra } from '@kkitahara/real-algebra'
let ralg = new RealAlgebra()
```
instead of ExactRealAlgebra.

In the numerical algebra, equality can be controlled
by the constructor argument `eps`:
```javascript
import { RealAlgebra } from '@kkitahara/real-algebra'
let ralg = new RealAlgebra()

let a = ralg.num(1, 2)
let b = ralg.num(1, 3)
ralg.eq(a, b) // false
ralg.isZero(ralg.num(1, 999999)) // false
```
```javascript
import { RealAlgebra } from '@kkitahara/real-algebra'
let eps = 0.5
let ralg = new RealAlgebra(eps)

let a = ralg.num(1, 2)
let b = ralg.num(1, 3)
ralg.eq(a, b) // true
ralg.isZero(ralg.num(1, 2)) // true
ralg.isZero(ralg.num(2, 3)) // false
```
Two numbers are considered to be equal
if the difference is smaller than or equal to `eps`.

### ESDoc documents
For more examples, see ESDoc documents:
```
cd node_modules/@kkitahara/real-algebra
npm install --only=dev
npm run doc
```
and open `doc/index.html` in your browser.

## LICENSE
&copy; 2019 Koichi Kitahara  
[Apache 2.0](LICENSE)