-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
Copy pathComplex.js
189 lines (172 loc) · 5.27 KB
/
Complex.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
import Complex from 'complex.js'
import { format } from '../../utils/number.js'
import { isNumber, isUnit } from '../../utils/is.js'
import { factory } from '../../utils/factory.js'
const name = 'Complex'
const dependencies = []
export const createComplexClass = /* #__PURE__ */ factory(name, dependencies, () => {
/**
* Attach type information
*/
Object.defineProperty(Complex, 'name', { value: 'Complex' })
Complex.prototype.constructor = Complex
Complex.prototype.type = 'Complex'
Complex.prototype.isComplex = true
/**
* Get a JSON representation of the complex number
* @returns {Object} Returns a JSON object structured as:
* `{"mathjs": "Complex", "re": 2, "im": 3}`
*/
Complex.prototype.toJSON = function () {
return {
mathjs: 'Complex',
re: this.re,
im: this.im
}
}
/*
* Return the value of the complex number in polar notation
* The angle phi will be set in the interval of [-pi, pi].
* @return {{r: number, phi: number}} Returns and object with properties r and phi.
*/
Complex.prototype.toPolar = function () {
return {
r: this.abs(),
phi: this.arg()
}
}
/**
* Get a string representation of the complex number,
* with optional formatting options.
* @param {Object | number | Function} [options] Formatting options. See
* lib/utils/number:format for a
* description of the available
* options.
* @return {string} str
*/
Complex.prototype.format = function (options) {
let str = ''
let im = this.im
let re = this.re
const strRe = format(this.re, options)
const strIm = format(this.im, options)
// round either re or im when smaller than the configured precision
const precision = isNumber(options) ? options : options ? options.precision : null
if (precision !== null) {
const epsilon = Math.pow(10, -precision)
if (Math.abs(re / im) < epsilon) {
re = 0
}
if (Math.abs(im / re) < epsilon) {
im = 0
}
}
if (im === 0) {
// real value
str = strRe
} else if (re === 0) {
// purely complex value
if (im === 1) {
str = 'i'
} else if (im === -1) {
str = '-i'
} else {
str = strIm + 'i'
}
} else {
// complex value
if (im < 0) {
if (im === -1) {
str = strRe + ' - i'
} else {
str = strRe + ' - ' + strIm.substring(1) + 'i'
}
} else {
if (im === 1) {
str = strRe + ' + i'
} else {
str = strRe + ' + ' + strIm + 'i'
}
}
}
return str
}
/**
* Create a complex number from polar coordinates
*
* Usage:
*
* Complex.fromPolar(r: number, phi: number) : Complex
* Complex.fromPolar({r: number, phi: number}) : Complex
*
* @param {*} args...
* @return {Complex}
*/
Complex.fromPolar = function (args) {
switch (arguments.length) {
case 1:
{
const arg = arguments[0]
if (typeof arg === 'object') {
return Complex(arg)
} else {
throw new TypeError('Input has to be an object with r and phi keys.')
}
}
case 2:
{
const r = arguments[0]
let phi = arguments[1]
if (isNumber(r)) {
if (isUnit(phi) && phi.hasBase('ANGLE')) {
// convert unit to a number in radians
phi = phi.toNumber('rad')
}
if (isNumber(phi)) {
return new Complex({ r, phi })
}
throw new TypeError('Phi is not a number nor an angle unit.')
} else {
throw new TypeError('Radius r is not a number.')
}
}
default:
throw new SyntaxError('Wrong number of arguments in function fromPolar')
}
}
Complex.prototype.valueOf = Complex.prototype.toString
/**
* Create a Complex number from a JSON object
* @param {Object} json A JSON Object structured as
* {"mathjs": "Complex", "re": 2, "im": 3}
* All properties are optional, default values
* for `re` and `im` are 0.
* @return {Complex} Returns a new Complex number
*/
Complex.fromJSON = function (json) {
return new Complex(json)
}
/**
* Compare two complex numbers, `a` and `b`:
*
* - Returns 1 when the real part of `a` is larger than the real part of `b`
* - Returns -1 when the real part of `a` is smaller than the real part of `b`
* - Returns 1 when the real parts are equal
* and the imaginary part of `a` is larger than the imaginary part of `b`
* - Returns -1 when the real parts are equal
* and the imaginary part of `a` is smaller than the imaginary part of `b`
* - Returns 0 when both real and imaginary parts are equal.
*
* @params {Complex} a
* @params {Complex} b
* @returns {number} Returns the comparison result: -1, 0, or 1
*/
Complex.compare = function (a, b) {
if (a.re > b.re) { return 1 }
if (a.re < b.re) { return -1 }
if (a.im > b.im) { return 1 }
if (a.im < b.im) { return -1 }
return 0
}
return Complex
}, { isClass: true })