@fluixi/utils 1.0.0-alpha.100
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +68 -0
- package/dist/index.cjs +2858 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1 -0
- package/dist/index.mjs +2838 -0
- package/dist/lib/array/advanced.cjs +2227 -0
- package/dist/lib/array/advanced.d.ts +1116 -0
- package/dist/lib/array/advanced.d.ts.map +1 -0
- package/dist/lib/array/advanced.js +2429 -0
- package/dist/lib/array/advanced.mjs +2204 -0
- package/dist/lib/array/array.cjs +57 -0
- package/dist/lib/array/array.d.ts +6 -0
- package/dist/lib/array/array.d.ts.map +1 -0
- package/dist/lib/array/array.js +31 -0
- package/dist/lib/array/array.mjs +36 -0
- package/dist/lib/array/index.cjs +2344 -0
- package/dist/lib/array/index.d.ts +4 -0
- package/dist/lib/array/index.d.ts.map +1 -0
- package/dist/lib/array/index.js +3 -0
- package/dist/lib/array/index.mjs +2322 -0
- package/dist/lib/array/utils.cjs +103 -0
- package/dist/lib/array/utils.d.ts +100 -0
- package/dist/lib/array/utils.d.ts.map +1 -0
- package/dist/lib/array/utils.js +165 -0
- package/dist/lib/array/utils.mjs +82 -0
- package/dist/lib/color/color.cjs +2190 -0
- package/dist/lib/color/color.d.ts +366 -0
- package/dist/lib/color/color.d.ts.map +1 -0
- package/dist/lib/color/color.js +722 -0
- package/dist/lib/color/color.mjs +2167 -0
- package/dist/lib/color/constants.cjs +380 -0
- package/dist/lib/color/constants.d.ts +361 -0
- package/dist/lib/color/constants.d.ts.map +1 -0
- package/dist/lib/color/constants.js +358 -0
- package/dist/lib/color/constants.mjs +359 -0
- package/dist/lib/color/conversions.cjs +629 -0
- package/dist/lib/color/conversions.d.ts +166 -0
- package/dist/lib/color/conversions.d.ts.map +1 -0
- package/dist/lib/color/conversions.js +766 -0
- package/dist/lib/color/conversions.mjs +608 -0
- package/dist/lib/color/helpers.cjs +2534 -0
- package/dist/lib/color/helpers.d.ts +75 -0
- package/dist/lib/color/helpers.d.ts.map +1 -0
- package/dist/lib/color/helpers.js +419 -0
- package/dist/lib/color/helpers.mjs +2511 -0
- package/dist/lib/color/index.cjs +2641 -0
- package/dist/lib/color/index.d.ts +12 -0
- package/dist/lib/color/index.d.ts.map +1 -0
- package/dist/lib/color/index.js +15 -0
- package/dist/lib/color/index.mjs +2619 -0
- package/dist/lib/color/types.cjs +18 -0
- package/dist/lib/color/types.d.ts +179 -0
- package/dist/lib/color/types.d.ts.map +1 -0
- package/dist/lib/color/types.js +1 -0
- package/dist/lib/color/types.mjs +0 -0
- package/dist/lib/color/utils.cjs +962 -0
- package/dist/lib/color/utils.d.ts +199 -0
- package/dist/lib/color/utils.d.ts.map +1 -0
- package/dist/lib/color/utils.js +858 -0
- package/dist/lib/color/utils.mjs +939 -0
- package/dist/lib/compare/comparators.cjs +171 -0
- package/dist/lib/compare/comparators.d.ts +65 -0
- package/dist/lib/compare/comparators.d.ts.map +1 -0
- package/dist/lib/compare/comparators.js +210 -0
- package/dist/lib/compare/comparators.mjs +150 -0
- package/dist/lib/compare/index.cjs +172 -0
- package/dist/lib/compare/index.d.ts +2 -0
- package/dist/lib/compare/index.d.ts.map +1 -0
- package/dist/lib/compare/index.js +1 -0
- package/dist/lib/compare/index.mjs +152 -0
- package/dist/lib/cookie/codec.cjs +72 -0
- package/dist/lib/cookie/codec.d.ts +22 -0
- package/dist/lib/cookie/codec.d.ts.map +1 -0
- package/dist/lib/cookie/codec.js +67 -0
- package/dist/lib/cookie/codec.mjs +51 -0
- package/dist/lib/cookie/index.cjs +75 -0
- package/dist/lib/cookie/index.d.ts +2 -0
- package/dist/lib/cookie/index.d.ts.map +1 -0
- package/dist/lib/cookie/index.js +1 -0
- package/dist/lib/cookie/index.mjs +53 -0
- package/dist/lib/crypto/hash.cjs +83 -0
- package/dist/lib/crypto/hash.d.ts +6 -0
- package/dist/lib/crypto/hash.d.ts.map +1 -0
- package/dist/lib/crypto/hash.js +53 -0
- package/dist/lib/crypto/hash.mjs +62 -0
- package/dist/lib/crypto/index.cjs +85 -0
- package/dist/lib/crypto/index.d.ts +2 -0
- package/dist/lib/crypto/index.d.ts.map +1 -0
- package/dist/lib/crypto/index.js +1 -0
- package/dist/lib/crypto/index.mjs +62 -0
- package/dist/lib/dom/events.cjs +40 -0
- package/dist/lib/dom/events.d.ts +159 -0
- package/dist/lib/dom/events.d.ts.map +1 -0
- package/dist/lib/dom/events.js +50 -0
- package/dist/lib/dom/events.mjs +19 -0
- package/dist/lib/dom/index.cjs +78 -0
- package/dist/lib/dom/index.d.ts +3 -0
- package/dist/lib/dom/index.d.ts.map +1 -0
- package/dist/lib/dom/index.js +2 -0
- package/dist/lib/dom/index.mjs +56 -0
- package/dist/lib/dom/utils.cjs +57 -0
- package/dist/lib/dom/utils.d.ts +6 -0
- package/dist/lib/dom/utils.d.ts.map +1 -0
- package/dist/lib/dom/utils.js +37 -0
- package/dist/lib/dom/utils.mjs +36 -0
- package/dist/lib/functions/functions.cjs +366 -0
- package/dist/lib/functions/functions.d.ts +329 -0
- package/dist/lib/functions/functions.d.ts.map +1 -0
- package/dist/lib/functions/functions.js +585 -0
- package/dist/lib/functions/functions.mjs +345 -0
- package/dist/lib/functions/index.cjs +369 -0
- package/dist/lib/functions/index.d.ts +3 -0
- package/dist/lib/functions/index.d.ts.map +1 -0
- package/dist/lib/functions/index.js +1 -0
- package/dist/lib/functions/index.mjs +347 -0
- package/dist/lib/functions/types.cjs +18 -0
- package/dist/lib/functions/types.d.ts +2 -0
- package/dist/lib/functions/types.d.ts.map +1 -0
- package/dist/lib/functions/types.js +1 -0
- package/dist/lib/functions/types.mjs +0 -0
- package/dist/lib/helpers.cjs +78 -0
- package/dist/lib/helpers.d.ts +13 -0
- package/dist/lib/helpers.d.ts.map +1 -0
- package/dist/lib/helpers.js +66 -0
- package/dist/lib/helpers.mjs +59 -0
- package/dist/lib/index.cjs +2857 -0
- package/dist/lib/index.d.ts +6 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +8 -0
- package/dist/lib/index.mjs +2836 -0
- package/dist/lib/maths/constants.cjs +70 -0
- package/dist/lib/maths/constants.d.ts +84 -0
- package/dist/lib/maths/constants.d.ts.map +1 -0
- package/dist/lib/maths/constants.js +79 -0
- package/dist/lib/maths/constants.mjs +50 -0
- package/dist/lib/maths/fn/advanced.cjs +231 -0
- package/dist/lib/maths/fn/advanced.d.ts +149 -0
- package/dist/lib/maths/fn/advanced.d.ts.map +1 -0
- package/dist/lib/maths/fn/advanced.js +264 -0
- package/dist/lib/maths/fn/advanced.mjs +208 -0
- package/dist/lib/maths/fn/basic.cjs +212 -0
- package/dist/lib/maths/fn/basic.d.ts +182 -0
- package/dist/lib/maths/fn/basic.d.ts.map +1 -0
- package/dist/lib/maths/fn/basic.js +343 -0
- package/dist/lib/maths/fn/basic.mjs +191 -0
- package/dist/lib/maths/fn/complex.cjs +268 -0
- package/dist/lib/maths/fn/complex.d.ts +153 -0
- package/dist/lib/maths/fn/complex.d.ts.map +1 -0
- package/dist/lib/maths/fn/complex.js +383 -0
- package/dist/lib/maths/fn/complex.mjs +247 -0
- package/dist/lib/maths/fn/index.cjs +877 -0
- package/dist/lib/maths/fn/index.d.ts +10 -0
- package/dist/lib/maths/fn/index.d.ts.map +1 -0
- package/dist/lib/maths/fn/index.js +9 -0
- package/dist/lib/maths/fn/index.mjs +855 -0
- package/dist/lib/maths/fn/trigo.cjs +179 -0
- package/dist/lib/maths/fn/trigo.d.ts +147 -0
- package/dist/lib/maths/fn/trigo.d.ts.map +1 -0
- package/dist/lib/maths/fn/trigo.js +227 -0
- package/dist/lib/maths/fn/trigo.mjs +156 -0
- package/dist/lib/maths/fn/vector.cjs +728 -0
- package/dist/lib/maths/fn/vector.d.ts +512 -0
- package/dist/lib/maths/fn/vector.d.ts.map +1 -0
- package/dist/lib/maths/fn/vector.js +1136 -0
- package/dist/lib/maths/fn/vector.mjs +707 -0
- package/dist/lib/maths/formatter.cjs +61 -0
- package/dist/lib/maths/formatter.d.ts +35 -0
- package/dist/lib/maths/formatter.d.ts.map +1 -0
- package/dist/lib/maths/formatter.js +56 -0
- package/dist/lib/maths/formatter.mjs +40 -0
- package/dist/lib/maths/guards.cjs +164 -0
- package/dist/lib/maths/guards.d.ts +166 -0
- package/dist/lib/maths/guards.d.ts.map +1 -0
- package/dist/lib/maths/guards.js +315 -0
- package/dist/lib/maths/guards.mjs +144 -0
- package/dist/lib/maths/index.cjs +1152 -0
- package/dist/lib/maths/index.d.ts +24 -0
- package/dist/lib/maths/index.d.ts.map +1 -0
- package/dist/lib/maths/index.js +29 -0
- package/dist/lib/maths/index.mjs +1130 -0
- package/dist/lib/maths/parser.cjs +75 -0
- package/dist/lib/maths/parser.d.ts +20 -0
- package/dist/lib/maths/parser.d.ts.map +1 -0
- package/dist/lib/maths/parser.js +78 -0
- package/dist/lib/maths/parser.mjs +54 -0
- package/dist/lib/maths/random.cjs +49 -0
- package/dist/lib/maths/random.d.ts +27 -0
- package/dist/lib/maths/random.d.ts.map +1 -0
- package/dist/lib/maths/random.js +49 -0
- package/dist/lib/maths/random.mjs +28 -0
- package/dist/lib/maths/types/advanced.cjs +18 -0
- package/dist/lib/maths/types/advanced.d.ts +357 -0
- package/dist/lib/maths/types/advanced.d.ts.map +1 -0
- package/dist/lib/maths/types/advanced.js +5 -0
- package/dist/lib/maths/types/advanced.mjs +0 -0
- package/dist/lib/maths/types/basic.cjs +18 -0
- package/dist/lib/maths/types/basic.d.ts +95 -0
- package/dist/lib/maths/types/basic.d.ts.map +1 -0
- package/dist/lib/maths/types/basic.js +5 -0
- package/dist/lib/maths/types/basic.mjs +0 -0
- package/dist/lib/maths/types/index.cjs +19 -0
- package/dist/lib/maths/types/index.d.ts +4 -0
- package/dist/lib/maths/types/index.d.ts.map +1 -0
- package/dist/lib/maths/types/index.js +3 -0
- package/dist/lib/maths/types/index.mjs +1 -0
- package/dist/lib/maths/types/negative.cjs +18 -0
- package/dist/lib/maths/types/negative.d.ts +51 -0
- package/dist/lib/maths/types/negative.d.ts.map +1 -0
- package/dist/lib/maths/types/negative.js +5 -0
- package/dist/lib/maths/types/negative.mjs +0 -0
- package/dist/lib/maths/types/operations.cjs +18 -0
- package/dist/lib/maths/types/operations.d.ts +188 -0
- package/dist/lib/maths/types/operations.d.ts.map +1 -0
- package/dist/lib/maths/types/operations.js +6 -0
- package/dist/lib/maths/types/operations.mjs +0 -0
- package/dist/lib/object/clone.cjs +88 -0
- package/dist/lib/object/clone.d.ts +46 -0
- package/dist/lib/object/clone.d.ts.map +1 -0
- package/dist/lib/object/clone.js +104 -0
- package/dist/lib/object/clone.mjs +65 -0
- package/dist/lib/object/diff.cjs +573 -0
- package/dist/lib/object/diff.d.ts +203 -0
- package/dist/lib/object/diff.d.ts.map +1 -0
- package/dist/lib/object/diff.js +805 -0
- package/dist/lib/object/diff.mjs +550 -0
- package/dist/lib/object/getter-setter.cjs +2351 -0
- package/dist/lib/object/getter-setter.d.ts +361 -0
- package/dist/lib/object/getter-setter.d.ts.map +1 -0
- package/dist/lib/object/getter-setter.js +1771 -0
- package/dist/lib/object/getter-setter.mjs +2330 -0
- package/dist/lib/object/index.cjs +3956 -0
- package/dist/lib/object/index.d.ts +13 -0
- package/dist/lib/object/index.d.ts.map +1 -0
- package/dist/lib/object/index.js +12 -0
- package/dist/lib/object/index.mjs +3936 -0
- package/dist/lib/object/merge.cjs +1029 -0
- package/dist/lib/object/merge.d.ts +93 -0
- package/dist/lib/object/merge.d.ts.map +1 -0
- package/dist/lib/object/merge.js +474 -0
- package/dist/lib/object/merge.mjs +1006 -0
- package/dist/lib/object/object.cjs +280 -0
- package/dist/lib/object/object.d.ts +128 -0
- package/dist/lib/object/object.d.ts.map +1 -0
- package/dist/lib/object/object.js +432 -0
- package/dist/lib/object/object.mjs +257 -0
- package/dist/lib/object/omit.cjs +2022 -0
- package/dist/lib/object/omit.d.ts +351 -0
- package/dist/lib/object/omit.d.ts.map +1 -0
- package/dist/lib/object/omit.js +656 -0
- package/dist/lib/object/omit.mjs +1999 -0
- package/dist/lib/object/reconcile.cjs +126 -0
- package/dist/lib/object/reconcile.d.ts +7 -0
- package/dist/lib/object/reconcile.d.ts.map +1 -0
- package/dist/lib/object/reconcile.js +122 -0
- package/dist/lib/object/reconcile.mjs +105 -0
- package/dist/lib/object/selector.cjs +303 -0
- package/dist/lib/object/selector.d.ts +50 -0
- package/dist/lib/object/selector.d.ts.map +1 -0
- package/dist/lib/object/selector.js +371 -0
- package/dist/lib/object/selector.mjs +282 -0
- package/dist/lib/object/sort.cjs +209 -0
- package/dist/lib/object/sort.d.ts +149 -0
- package/dist/lib/object/sort.d.ts.map +1 -0
- package/dist/lib/object/sort.js +298 -0
- package/dist/lib/object/sort.mjs +186 -0
- package/dist/lib/object/transform.cjs +2211 -0
- package/dist/lib/object/transform.d.ts +620 -0
- package/dist/lib/object/transform.d.ts.map +1 -0
- package/dist/lib/object/transform.js +1058 -0
- package/dist/lib/object/transform.mjs +2190 -0
- package/dist/lib/object/types.cjs +18 -0
- package/dist/lib/object/types.d.ts +250 -0
- package/dist/lib/object/types.d.ts.map +1 -0
- package/dist/lib/object/types.js +1 -0
- package/dist/lib/object/types.mjs +0 -0
- package/dist/lib/object/utils.cjs +326 -0
- package/dist/lib/object/utils.d.ts +165 -0
- package/dist/lib/object/utils.d.ts.map +1 -0
- package/dist/lib/object/utils.js +444 -0
- package/dist/lib/object/utils.mjs +305 -0
- package/dist/lib/primitive/boolean/boolean.cjs +407 -0
- package/dist/lib/primitive/boolean/boolean.d.ts +276 -0
- package/dist/lib/primitive/boolean/boolean.d.ts.map +1 -0
- package/dist/lib/primitive/boolean/boolean.js +615 -0
- package/dist/lib/primitive/boolean/boolean.mjs +386 -0
- package/dist/lib/primitive/boolean/index.cjs +382 -0
- package/dist/lib/primitive/boolean/index.d.ts +3 -0
- package/dist/lib/primitive/boolean/index.d.ts.map +1 -0
- package/dist/lib/primitive/boolean/index.js +2 -0
- package/dist/lib/primitive/boolean/index.mjs +359 -0
- package/dist/lib/primitive/boolean/types.cjs +18 -0
- package/dist/lib/primitive/boolean/types.d.ts +14 -0
- package/dist/lib/primitive/boolean/types.d.ts.map +1 -0
- package/dist/lib/primitive/boolean/types.js +1 -0
- package/dist/lib/primitive/boolean/types.mjs +0 -0
- package/dist/lib/primitive/date/date.cjs +1126 -0
- package/dist/lib/primitive/date/date.d.ts +641 -0
- package/dist/lib/primitive/date/date.d.ts.map +1 -0
- package/dist/lib/primitive/date/date.js +1998 -0
- package/dist/lib/primitive/date/date.mjs +1105 -0
- package/dist/lib/primitive/date/index.cjs +1128 -0
- package/dist/lib/primitive/date/index.d.ts +3 -0
- package/dist/lib/primitive/date/index.d.ts.map +1 -0
- package/dist/lib/primitive/date/index.js +2 -0
- package/dist/lib/primitive/date/index.mjs +1105 -0
- package/dist/lib/primitive/date/types.cjs +18 -0
- package/dist/lib/primitive/date/types.d.ts +205 -0
- package/dist/lib/primitive/date/types.d.ts.map +1 -0
- package/dist/lib/primitive/date/types.js +7 -0
- package/dist/lib/primitive/date/types.mjs +0 -0
- package/dist/lib/primitive/index.cjs +2338 -0
- package/dist/lib/primitive/index.d.ts +5 -0
- package/dist/lib/primitive/index.d.ts.map +1 -0
- package/dist/lib/primitive/index.js +4 -0
- package/dist/lib/primitive/index.mjs +2316 -0
- package/dist/lib/primitive/string/index.cjs +875 -0
- package/dist/lib/primitive/string/index.d.ts +3 -0
- package/dist/lib/primitive/string/index.d.ts.map +1 -0
- package/dist/lib/primitive/string/index.js +2 -0
- package/dist/lib/primitive/string/index.mjs +852 -0
- package/dist/lib/primitive/string/parser-2.cjs +543 -0
- package/dist/lib/primitive/string/parser-2.d.ts +17 -0
- package/dist/lib/primitive/string/parser-2.d.ts.map +1 -0
- package/dist/lib/primitive/string/parser-2.js +656 -0
- package/dist/lib/primitive/string/parser-2.mjs +522 -0
- package/dist/lib/primitive/string/parser.cjs +236 -0
- package/dist/lib/primitive/string/parser.d.ts +9 -0
- package/dist/lib/primitive/string/parser.d.ts.map +1 -0
- package/dist/lib/primitive/string/parser.js +775 -0
- package/dist/lib/primitive/string/parser.mjs +215 -0
- package/dist/lib/primitive/string/string.cjs +926 -0
- package/dist/lib/primitive/string/string.d.ts +535 -0
- package/dist/lib/primitive/string/string.d.ts.map +1 -0
- package/dist/lib/primitive/string/string.js +1301 -0
- package/dist/lib/primitive/string/string.mjs +903 -0
- package/dist/lib/primitive/string/types.cjs +18 -0
- package/dist/lib/primitive/string/types.d.ts +318 -0
- package/dist/lib/primitive/string/types.d.ts.map +1 -0
- package/dist/lib/primitive/string/types.js +5 -0
- package/dist/lib/primitive/string/types.mjs +0 -0
- package/dist/lib/primitive/types.cjs +18 -0
- package/dist/lib/primitive/types.d.ts +27 -0
- package/dist/lib/primitive/types.d.ts.map +1 -0
- package/dist/lib/primitive/types.js +1 -0
- package/dist/lib/primitive/types.mjs +0 -0
- package/dist/lib/url/index.cjs +327 -0
- package/dist/lib/url/index.d.ts +3 -0
- package/dist/lib/url/index.d.ts.map +1 -0
- package/dist/lib/url/index.js +2 -0
- package/dist/lib/url/index.mjs +304 -0
- package/dist/lib/url/parser.cjs +325 -0
- package/dist/lib/url/parser.d.ts +216 -0
- package/dist/lib/url/parser.d.ts.map +1 -0
- package/dist/lib/url/parser.js +488 -0
- package/dist/lib/url/parser.mjs +304 -0
- package/dist/lib/url/types.cjs +18 -0
- package/dist/lib/url/types.d.ts +18 -0
- package/dist/lib/url/types.d.ts.map +1 -0
- package/dist/lib/url/types.js +1 -0
- package/dist/lib/url/types.mjs +0 -0
- package/dist/tsconfig.lib.tsbuildinfo +1 -0
- package/package.json +127 -0
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Complex number operations.
|
|
3
|
+
* @module ComplexFunctions
|
|
4
|
+
*/
|
|
5
|
+
// Constants
|
|
6
|
+
const EPSILON = 1e-10;
|
|
7
|
+
const TWO_PI = 2 * Math.PI;
|
|
8
|
+
/**
|
|
9
|
+
* Checks if a value is approximately zero within epsilon.
|
|
10
|
+
* @param value - The value to check
|
|
11
|
+
* @returns True if the value is effectively zero
|
|
12
|
+
*/
|
|
13
|
+
function isApproximatelyZero(value) {
|
|
14
|
+
return Math.abs(value) < EPSILON;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Safely compares two numbers with epsilon precision.
|
|
18
|
+
* @param a - First number
|
|
19
|
+
* @param b - Second number
|
|
20
|
+
* @returns True if numbers are approximately equal
|
|
21
|
+
*/
|
|
22
|
+
function approximatelyEqual(a, b) {
|
|
23
|
+
return Math.abs(a - b) < EPSILON;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Normalizes a complex number by handling near-zero values.
|
|
27
|
+
* @param c - The complex number to normalize
|
|
28
|
+
* @returns Normalized complex number
|
|
29
|
+
*/
|
|
30
|
+
function normalizeComplex(c) {
|
|
31
|
+
return {
|
|
32
|
+
real: isApproximatelyZero(c.real) ? 0 : c.real,
|
|
33
|
+
imag: isApproximatelyZero(c.imag) ? 0 : c.imag,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Validates that a value is a finite number.
|
|
38
|
+
* @param value - The value to validate
|
|
39
|
+
* @param name - Name of the value for error messages
|
|
40
|
+
* @throws {Error} If value is not a finite number
|
|
41
|
+
*/
|
|
42
|
+
function validateNumber(value, name) {
|
|
43
|
+
if (typeof value !== 'number' || !Number.isFinite(value)) {
|
|
44
|
+
throw new Error(`${name} must be a finite number, got ${value}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Validates a complex number.
|
|
49
|
+
* @param c - The complex number to validate
|
|
50
|
+
* @param name - Name of the complex number for error messages
|
|
51
|
+
* @throws {Error} If complex number is invalid
|
|
52
|
+
*/
|
|
53
|
+
function validateComplexNumber(c, name = 'Complex number') {
|
|
54
|
+
if (!c || typeof c !== 'object') {
|
|
55
|
+
throw new Error(`${name} must be an object`);
|
|
56
|
+
}
|
|
57
|
+
validateNumber(c.real, `${name}.real`);
|
|
58
|
+
validateNumber(c.imag, `${name}.imag`);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Creates a complex number with validation and normalization.
|
|
62
|
+
* @param real - Real part
|
|
63
|
+
* @param imag - Imaginary part
|
|
64
|
+
* @returns Validated and normalized complex number
|
|
65
|
+
*/
|
|
66
|
+
export function createComplex(real, imag = 0) {
|
|
67
|
+
validateNumber(real, 'real');
|
|
68
|
+
validateNumber(imag, 'imag');
|
|
69
|
+
return normalizeComplex({ real, imag });
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Checks if two complex numbers are approximately equal.
|
|
73
|
+
* @param a - First complex number
|
|
74
|
+
* @param b - Second complex number
|
|
75
|
+
* @returns True if numbers are approximately equal
|
|
76
|
+
*/
|
|
77
|
+
export function complexEquals(a, b) {
|
|
78
|
+
validateComplexNumber(a, 'First complex number');
|
|
79
|
+
validateComplexNumber(b, 'Second complex number');
|
|
80
|
+
return (approximatelyEqual(a.real, b.real) && approximatelyEqual(a.imag, b.imag));
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Adds two complex numbers.
|
|
84
|
+
* @param a - First complex number
|
|
85
|
+
* @param b - Second complex number
|
|
86
|
+
* @returns The sum as a complex number
|
|
87
|
+
*/
|
|
88
|
+
export function addComplex(a, b) {
|
|
89
|
+
validateComplexNumber(a, 'First complex number');
|
|
90
|
+
validateComplexNumber(b, 'Second complex number');
|
|
91
|
+
return normalizeComplex({
|
|
92
|
+
real: a.real + b.real,
|
|
93
|
+
imag: a.imag + b.imag,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Subtracts two complex numbers.
|
|
98
|
+
* @param a - First complex number
|
|
99
|
+
* @param b - Second complex number
|
|
100
|
+
* @returns The difference as a complex number (a - b)
|
|
101
|
+
*/
|
|
102
|
+
export function subtractComplex(a, b) {
|
|
103
|
+
validateComplexNumber(a, 'First complex number');
|
|
104
|
+
validateComplexNumber(b, 'Second complex number');
|
|
105
|
+
return normalizeComplex({
|
|
106
|
+
real: a.real - b.real,
|
|
107
|
+
imag: a.imag - b.imag,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Multiplies two complex numbers.
|
|
112
|
+
* @param a - First complex number
|
|
113
|
+
* @param b - Second complex number
|
|
114
|
+
* @returns The product as a complex number
|
|
115
|
+
*/
|
|
116
|
+
export function multiplyComplex(a, b) {
|
|
117
|
+
validateComplexNumber(a, 'First complex number');
|
|
118
|
+
validateComplexNumber(b, 'Second complex number');
|
|
119
|
+
return normalizeComplex({
|
|
120
|
+
real: a.real * b.real - a.imag * b.imag,
|
|
121
|
+
imag: a.real * b.imag + a.imag * b.real,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Divides two complex numbers.
|
|
126
|
+
* @param a - Numerator complex number
|
|
127
|
+
* @param b - Denominator complex number
|
|
128
|
+
* @returns The quotient as a complex number
|
|
129
|
+
* @throws {Error} If dividing by zero or near-zero complex number
|
|
130
|
+
*/
|
|
131
|
+
export function divideComplex(a, b) {
|
|
132
|
+
validateComplexNumber(a, 'Numerator complex number');
|
|
133
|
+
validateComplexNumber(b, 'Denominator complex number');
|
|
134
|
+
const denominator = b.real * b.real + b.imag * b.imag;
|
|
135
|
+
if (isApproximatelyZero(denominator)) {
|
|
136
|
+
throw new Error('Cannot divide by zero or near-zero complex number');
|
|
137
|
+
}
|
|
138
|
+
return normalizeComplex({
|
|
139
|
+
real: (a.real * b.real + a.imag * b.imag) / denominator,
|
|
140
|
+
imag: (a.imag * b.real - a.real * b.imag) / denominator,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Calculates the magnitude (absolute value) of a complex number.
|
|
145
|
+
* @param c - The complex number
|
|
146
|
+
* @returns The magnitude (non-negative)
|
|
147
|
+
*/
|
|
148
|
+
export function magnitudeComplex(c) {
|
|
149
|
+
validateComplexNumber(c);
|
|
150
|
+
const magnitude = Math.sqrt(c.real * c.real + c.imag * c.imag);
|
|
151
|
+
return isApproximatelyZero(magnitude) ? 0 : magnitude;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Calculates the conjugate of a complex number.
|
|
155
|
+
* @param c - The complex number
|
|
156
|
+
* @returns The complex conjugate
|
|
157
|
+
*/
|
|
158
|
+
export function conjugateComplex(c) {
|
|
159
|
+
validateComplexNumber(c);
|
|
160
|
+
return normalizeComplex({
|
|
161
|
+
real: c.real,
|
|
162
|
+
imag: -c.imag,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Calculates the argument (angle) of a complex number in radians.
|
|
167
|
+
* @param c - The complex number
|
|
168
|
+
* @returns The principal argument in radians (-π, π]
|
|
169
|
+
*/
|
|
170
|
+
export function argumentComplex(c) {
|
|
171
|
+
validateComplexNumber(c);
|
|
172
|
+
if (isApproximatelyZero(c.real) && isApproximatelyZero(c.imag)) {
|
|
173
|
+
return 0; // Argument of zero is conventionally 0
|
|
174
|
+
}
|
|
175
|
+
return Math.atan2(c.imag, c.real);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Converts a complex number to polar form.
|
|
179
|
+
* @param c - The complex number
|
|
180
|
+
* @returns Polar representation {magnitude, angle}
|
|
181
|
+
*/
|
|
182
|
+
export function toPolarComplex(c) {
|
|
183
|
+
validateComplexNumber(c);
|
|
184
|
+
return {
|
|
185
|
+
magnitude: magnitudeComplex(c),
|
|
186
|
+
angle: argumentComplex(c),
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Converts polar form to a complex number.
|
|
191
|
+
* @param magnitude - The magnitude (must be non-negative)
|
|
192
|
+
* @param angle - The angle in radians
|
|
193
|
+
* @returns The complex number
|
|
194
|
+
* @throws {Error} If magnitude is negative
|
|
195
|
+
*/
|
|
196
|
+
export function fromPolarComplex(magnitude, angle) {
|
|
197
|
+
validateNumber(magnitude, 'magnitude');
|
|
198
|
+
validateNumber(angle, 'angle');
|
|
199
|
+
if (magnitude < -EPSILON) {
|
|
200
|
+
throw new Error('Magnitude must be non-negative');
|
|
201
|
+
}
|
|
202
|
+
// Normalize angle to (-π, π]
|
|
203
|
+
let normalizedAngle = angle % TWO_PI;
|
|
204
|
+
if (normalizedAngle > Math.PI)
|
|
205
|
+
normalizedAngle -= TWO_PI;
|
|
206
|
+
if (normalizedAngle <= -Math.PI)
|
|
207
|
+
normalizedAngle += TWO_PI;
|
|
208
|
+
const mag = Math.max(0, magnitude); // Ensure non-negative
|
|
209
|
+
return normalizeComplex({
|
|
210
|
+
real: mag * Math.cos(normalizedAngle),
|
|
211
|
+
imag: mag * Math.sin(normalizedAngle),
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Calculates the square root of a complex number.
|
|
216
|
+
* @param c - The complex number
|
|
217
|
+
* @returns Array of two complex square roots (principal and secondary)
|
|
218
|
+
*/
|
|
219
|
+
export function sqrtComplex(c) {
|
|
220
|
+
validateComplexNumber(c);
|
|
221
|
+
// Special case for zero
|
|
222
|
+
if (isApproximatelyZero(c.real) && isApproximatelyZero(c.imag)) {
|
|
223
|
+
const zero = createComplex(0, 0);
|
|
224
|
+
return [zero, zero];
|
|
225
|
+
}
|
|
226
|
+
const magnitude = magnitudeComplex(c);
|
|
227
|
+
const angle = argumentComplex(c);
|
|
228
|
+
const rootMagnitude = Math.sqrt(magnitude);
|
|
229
|
+
const rootAngle1 = angle / 2;
|
|
230
|
+
const rootAngle2 = rootAngle1 + Math.PI;
|
|
231
|
+
return [
|
|
232
|
+
fromPolarComplex(rootMagnitude, rootAngle1),
|
|
233
|
+
fromPolarComplex(rootMagnitude, rootAngle2),
|
|
234
|
+
];
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Calculates the power of a complex number with a real exponent.
|
|
238
|
+
* @param c - The complex number
|
|
239
|
+
* @param exponent - The exponent (real number)
|
|
240
|
+
* @returns The complex number raised to the power
|
|
241
|
+
*/
|
|
242
|
+
export function powerComplex(c, exponent) {
|
|
243
|
+
validateComplexNumber(c);
|
|
244
|
+
validateNumber(exponent, 'exponent');
|
|
245
|
+
// Special cases for optimization
|
|
246
|
+
if (isApproximatelyZero(exponent)) {
|
|
247
|
+
return createComplex(1, 0); // c^0 = 1
|
|
248
|
+
}
|
|
249
|
+
if (approximatelyEqual(exponent, 1)) {
|
|
250
|
+
return createComplex(c.real, c.imag); // c^1 = c
|
|
251
|
+
}
|
|
252
|
+
if (approximatelyEqual(exponent, 2)) {
|
|
253
|
+
// Square directly for better performance
|
|
254
|
+
return multiplyComplex(c, c);
|
|
255
|
+
}
|
|
256
|
+
if (isApproximatelyZero(c.real) && isApproximatelyZero(c.imag)) {
|
|
257
|
+
if (exponent > 0) {
|
|
258
|
+
return createComplex(0, 0); // 0^n = 0 for n > 0
|
|
259
|
+
}
|
|
260
|
+
else if (exponent < 0) {
|
|
261
|
+
throw new Error('Cannot raise zero to a negative power');
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
const polar = toPolarComplex(c);
|
|
265
|
+
const magnitude = Math.pow(polar.magnitude, exponent);
|
|
266
|
+
// Handle negative magnitude due to floating point errors
|
|
267
|
+
const safeMagnitude = magnitude < -EPSILON ? Math.abs(magnitude) : Math.max(0, magnitude);
|
|
268
|
+
const angle = polar.angle * exponent;
|
|
269
|
+
return fromPolarComplex(safeMagnitude, angle);
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Calculates the natural logarithm of a complex number.
|
|
273
|
+
* @param c - The complex number
|
|
274
|
+
* @returns The principal value of natural logarithm as a complex number
|
|
275
|
+
* @throws {Error} If the complex number is zero or near-zero
|
|
276
|
+
*/
|
|
277
|
+
export function lnComplex(c) {
|
|
278
|
+
validateComplexNumber(c);
|
|
279
|
+
const magnitude = magnitudeComplex(c);
|
|
280
|
+
if (isApproximatelyZero(magnitude)) {
|
|
281
|
+
throw new Error('Cannot take logarithm of zero or near-zero complex number');
|
|
282
|
+
}
|
|
283
|
+
const angle = argumentComplex(c);
|
|
284
|
+
return normalizeComplex({
|
|
285
|
+
real: Math.log(magnitude),
|
|
286
|
+
imag: angle,
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Calculates the exponential of a complex number.
|
|
291
|
+
* @param c - The complex number
|
|
292
|
+
* @returns The exponential as a complex number
|
|
293
|
+
*/
|
|
294
|
+
export function expComplex(c) {
|
|
295
|
+
validateComplexNumber(c);
|
|
296
|
+
const expReal = Math.exp(c.real);
|
|
297
|
+
return normalizeComplex({
|
|
298
|
+
real: expReal * Math.cos(c.imag),
|
|
299
|
+
imag: expReal * Math.sin(c.imag),
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Calculates the sine of a complex number.
|
|
304
|
+
* @param c - The complex number
|
|
305
|
+
* @returns The sine as a complex number
|
|
306
|
+
*/
|
|
307
|
+
export function sinComplex(c) {
|
|
308
|
+
validateComplexNumber(c);
|
|
309
|
+
// sin(a + bi) = sin(a)cosh(b) + i cos(a)sinh(b)
|
|
310
|
+
return normalizeComplex({
|
|
311
|
+
real: Math.sin(c.real) * Math.cosh(c.imag),
|
|
312
|
+
imag: Math.cos(c.real) * Math.sinh(c.imag),
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Calculates the cosine of a complex number.
|
|
317
|
+
* @param c - The complex number
|
|
318
|
+
* @returns The cosine as a complex number
|
|
319
|
+
*/
|
|
320
|
+
export function cosComplex(c) {
|
|
321
|
+
validateComplexNumber(c);
|
|
322
|
+
// cos(a + bi) = cos(a)cosh(b) - i sin(a)sinh(b)
|
|
323
|
+
return normalizeComplex({
|
|
324
|
+
real: Math.cos(c.real) * Math.cosh(c.imag),
|
|
325
|
+
imag: -Math.sin(c.real) * Math.sinh(c.imag),
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Checks if a complex number is zero (or effectively zero).
|
|
330
|
+
* @param c - The complex number to check
|
|
331
|
+
* @returns True if the complex number is effectively zero
|
|
332
|
+
*/
|
|
333
|
+
export function isZeroComplex(c) {
|
|
334
|
+
validateComplexNumber(c);
|
|
335
|
+
return isApproximatelyZero(c.real) && isApproximatelyZero(c.imag);
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Returns the real part of a complex number.
|
|
339
|
+
* @param c - The complex number
|
|
340
|
+
* @returns The real part
|
|
341
|
+
*/
|
|
342
|
+
export function getReal(c) {
|
|
343
|
+
validateComplexNumber(c);
|
|
344
|
+
return c.real;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Returns the imaginary part of a complex number.
|
|
348
|
+
* @param c - The complex number
|
|
349
|
+
* @returns The imaginary part
|
|
350
|
+
*/
|
|
351
|
+
export function getImag(c) {
|
|
352
|
+
validateComplexNumber(c);
|
|
353
|
+
return c.imag;
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Negates a complex number.
|
|
357
|
+
* @param c - The complex number
|
|
358
|
+
* @returns The negated complex number
|
|
359
|
+
*/
|
|
360
|
+
export function negateComplex(c) {
|
|
361
|
+
validateComplexNumber(c);
|
|
362
|
+
return normalizeComplex({
|
|
363
|
+
real: -c.real,
|
|
364
|
+
imag: -c.imag,
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Calculates the reciprocal of a complex number.
|
|
369
|
+
* @param c - The complex number
|
|
370
|
+
* @returns The reciprocal (1/c)
|
|
371
|
+
* @throws {Error} If the complex number is zero or near-zero
|
|
372
|
+
*/
|
|
373
|
+
export function reciprocalComplex(c) {
|
|
374
|
+
validateComplexNumber(c);
|
|
375
|
+
const denominator = c.real * c.real + c.imag * c.imag;
|
|
376
|
+
if (isApproximatelyZero(denominator)) {
|
|
377
|
+
throw new Error('Cannot calculate reciprocal of zero or near-zero complex number');
|
|
378
|
+
}
|
|
379
|
+
return normalizeComplex({
|
|
380
|
+
real: c.real / denominator,
|
|
381
|
+
imag: -c.imag / denominator,
|
|
382
|
+
});
|
|
383
|
+
}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
// src/lib/maths/fn/complex.ts
|
|
2
|
+
var EPSILON = 1e-10;
|
|
3
|
+
var TWO_PI = 2 * Math.PI;
|
|
4
|
+
function isApproximatelyZero(value) {
|
|
5
|
+
return Math.abs(value) < EPSILON;
|
|
6
|
+
}
|
|
7
|
+
function approximatelyEqual(a, b) {
|
|
8
|
+
return Math.abs(a - b) < EPSILON;
|
|
9
|
+
}
|
|
10
|
+
function normalizeComplex(c) {
|
|
11
|
+
return {
|
|
12
|
+
real: isApproximatelyZero(c.real) ? 0 : c.real,
|
|
13
|
+
imag: isApproximatelyZero(c.imag) ? 0 : c.imag
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function validateNumber(value, name) {
|
|
17
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
18
|
+
throw new Error(`${name} must be a finite number, got ${value}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function validateComplexNumber(c, name = "Complex number") {
|
|
22
|
+
if (!c || typeof c !== "object") {
|
|
23
|
+
throw new Error(`${name} must be an object`);
|
|
24
|
+
}
|
|
25
|
+
validateNumber(c.real, `${name}.real`);
|
|
26
|
+
validateNumber(c.imag, `${name}.imag`);
|
|
27
|
+
}
|
|
28
|
+
function createComplex(real, imag = 0) {
|
|
29
|
+
validateNumber(real, "real");
|
|
30
|
+
validateNumber(imag, "imag");
|
|
31
|
+
return normalizeComplex({ real, imag });
|
|
32
|
+
}
|
|
33
|
+
function complexEquals(a, b) {
|
|
34
|
+
validateComplexNumber(a, "First complex number");
|
|
35
|
+
validateComplexNumber(b, "Second complex number");
|
|
36
|
+
return approximatelyEqual(a.real, b.real) && approximatelyEqual(a.imag, b.imag);
|
|
37
|
+
}
|
|
38
|
+
function addComplex(a, b) {
|
|
39
|
+
validateComplexNumber(a, "First complex number");
|
|
40
|
+
validateComplexNumber(b, "Second complex number");
|
|
41
|
+
return normalizeComplex({
|
|
42
|
+
real: a.real + b.real,
|
|
43
|
+
imag: a.imag + b.imag
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
function subtractComplex(a, b) {
|
|
47
|
+
validateComplexNumber(a, "First complex number");
|
|
48
|
+
validateComplexNumber(b, "Second complex number");
|
|
49
|
+
return normalizeComplex({
|
|
50
|
+
real: a.real - b.real,
|
|
51
|
+
imag: a.imag - b.imag
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function multiplyComplex(a, b) {
|
|
55
|
+
validateComplexNumber(a, "First complex number");
|
|
56
|
+
validateComplexNumber(b, "Second complex number");
|
|
57
|
+
return normalizeComplex({
|
|
58
|
+
real: a.real * b.real - a.imag * b.imag,
|
|
59
|
+
imag: a.real * b.imag + a.imag * b.real
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
function divideComplex(a, b) {
|
|
63
|
+
validateComplexNumber(a, "Numerator complex number");
|
|
64
|
+
validateComplexNumber(b, "Denominator complex number");
|
|
65
|
+
const denominator = b.real * b.real + b.imag * b.imag;
|
|
66
|
+
if (isApproximatelyZero(denominator)) {
|
|
67
|
+
throw new Error("Cannot divide by zero or near-zero complex number");
|
|
68
|
+
}
|
|
69
|
+
return normalizeComplex({
|
|
70
|
+
real: (a.real * b.real + a.imag * b.imag) / denominator,
|
|
71
|
+
imag: (a.imag * b.real - a.real * b.imag) / denominator
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
function magnitudeComplex(c) {
|
|
75
|
+
validateComplexNumber(c);
|
|
76
|
+
const magnitude = Math.sqrt(c.real * c.real + c.imag * c.imag);
|
|
77
|
+
return isApproximatelyZero(magnitude) ? 0 : magnitude;
|
|
78
|
+
}
|
|
79
|
+
function conjugateComplex(c) {
|
|
80
|
+
validateComplexNumber(c);
|
|
81
|
+
return normalizeComplex({
|
|
82
|
+
real: c.real,
|
|
83
|
+
imag: -c.imag
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
function argumentComplex(c) {
|
|
87
|
+
validateComplexNumber(c);
|
|
88
|
+
if (isApproximatelyZero(c.real) && isApproximatelyZero(c.imag)) {
|
|
89
|
+
return 0;
|
|
90
|
+
}
|
|
91
|
+
return Math.atan2(c.imag, c.real);
|
|
92
|
+
}
|
|
93
|
+
function toPolarComplex(c) {
|
|
94
|
+
validateComplexNumber(c);
|
|
95
|
+
return {
|
|
96
|
+
magnitude: magnitudeComplex(c),
|
|
97
|
+
angle: argumentComplex(c)
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function fromPolarComplex(magnitude, angle) {
|
|
101
|
+
validateNumber(magnitude, "magnitude");
|
|
102
|
+
validateNumber(angle, "angle");
|
|
103
|
+
if (magnitude < -EPSILON) {
|
|
104
|
+
throw new Error("Magnitude must be non-negative");
|
|
105
|
+
}
|
|
106
|
+
let normalizedAngle = angle % TWO_PI;
|
|
107
|
+
if (normalizedAngle > Math.PI) normalizedAngle -= TWO_PI;
|
|
108
|
+
if (normalizedAngle <= -Math.PI) normalizedAngle += TWO_PI;
|
|
109
|
+
const mag = Math.max(0, magnitude);
|
|
110
|
+
return normalizeComplex({
|
|
111
|
+
real: mag * Math.cos(normalizedAngle),
|
|
112
|
+
imag: mag * Math.sin(normalizedAngle)
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
function sqrtComplex(c) {
|
|
116
|
+
validateComplexNumber(c);
|
|
117
|
+
if (isApproximatelyZero(c.real) && isApproximatelyZero(c.imag)) {
|
|
118
|
+
const zero = createComplex(0, 0);
|
|
119
|
+
return [zero, zero];
|
|
120
|
+
}
|
|
121
|
+
const magnitude = magnitudeComplex(c);
|
|
122
|
+
const angle = argumentComplex(c);
|
|
123
|
+
const rootMagnitude = Math.sqrt(magnitude);
|
|
124
|
+
const rootAngle1 = angle / 2;
|
|
125
|
+
const rootAngle2 = rootAngle1 + Math.PI;
|
|
126
|
+
return [
|
|
127
|
+
fromPolarComplex(rootMagnitude, rootAngle1),
|
|
128
|
+
fromPolarComplex(rootMagnitude, rootAngle2)
|
|
129
|
+
];
|
|
130
|
+
}
|
|
131
|
+
function powerComplex(c, exponent) {
|
|
132
|
+
validateComplexNumber(c);
|
|
133
|
+
validateNumber(exponent, "exponent");
|
|
134
|
+
if (isApproximatelyZero(exponent)) {
|
|
135
|
+
return createComplex(1, 0);
|
|
136
|
+
}
|
|
137
|
+
if (approximatelyEqual(exponent, 1)) {
|
|
138
|
+
return createComplex(c.real, c.imag);
|
|
139
|
+
}
|
|
140
|
+
if (approximatelyEqual(exponent, 2)) {
|
|
141
|
+
return multiplyComplex(c, c);
|
|
142
|
+
}
|
|
143
|
+
if (isApproximatelyZero(c.real) && isApproximatelyZero(c.imag)) {
|
|
144
|
+
if (exponent > 0) {
|
|
145
|
+
return createComplex(0, 0);
|
|
146
|
+
} else if (exponent < 0) {
|
|
147
|
+
throw new Error("Cannot raise zero to a negative power");
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
const polar = toPolarComplex(c);
|
|
151
|
+
const magnitude = Math.pow(polar.magnitude, exponent);
|
|
152
|
+
const safeMagnitude = magnitude < -EPSILON ? Math.abs(magnitude) : Math.max(0, magnitude);
|
|
153
|
+
const angle = polar.angle * exponent;
|
|
154
|
+
return fromPolarComplex(safeMagnitude, angle);
|
|
155
|
+
}
|
|
156
|
+
function lnComplex(c) {
|
|
157
|
+
validateComplexNumber(c);
|
|
158
|
+
const magnitude = magnitudeComplex(c);
|
|
159
|
+
if (isApproximatelyZero(magnitude)) {
|
|
160
|
+
throw new Error(
|
|
161
|
+
"Cannot take logarithm of zero or near-zero complex number"
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
const angle = argumentComplex(c);
|
|
165
|
+
return normalizeComplex({
|
|
166
|
+
real: Math.log(magnitude),
|
|
167
|
+
imag: angle
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
function expComplex(c) {
|
|
171
|
+
validateComplexNumber(c);
|
|
172
|
+
const expReal = Math.exp(c.real);
|
|
173
|
+
return normalizeComplex({
|
|
174
|
+
real: expReal * Math.cos(c.imag),
|
|
175
|
+
imag: expReal * Math.sin(c.imag)
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
function sinComplex(c) {
|
|
179
|
+
validateComplexNumber(c);
|
|
180
|
+
return normalizeComplex({
|
|
181
|
+
real: Math.sin(c.real) * Math.cosh(c.imag),
|
|
182
|
+
imag: Math.cos(c.real) * Math.sinh(c.imag)
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
function cosComplex(c) {
|
|
186
|
+
validateComplexNumber(c);
|
|
187
|
+
return normalizeComplex({
|
|
188
|
+
real: Math.cos(c.real) * Math.cosh(c.imag),
|
|
189
|
+
imag: -Math.sin(c.real) * Math.sinh(c.imag)
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
function isZeroComplex(c) {
|
|
193
|
+
validateComplexNumber(c);
|
|
194
|
+
return isApproximatelyZero(c.real) && isApproximatelyZero(c.imag);
|
|
195
|
+
}
|
|
196
|
+
function getReal(c) {
|
|
197
|
+
validateComplexNumber(c);
|
|
198
|
+
return c.real;
|
|
199
|
+
}
|
|
200
|
+
function getImag(c) {
|
|
201
|
+
validateComplexNumber(c);
|
|
202
|
+
return c.imag;
|
|
203
|
+
}
|
|
204
|
+
function negateComplex(c) {
|
|
205
|
+
validateComplexNumber(c);
|
|
206
|
+
return normalizeComplex({
|
|
207
|
+
real: -c.real,
|
|
208
|
+
imag: -c.imag
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
function reciprocalComplex(c) {
|
|
212
|
+
validateComplexNumber(c);
|
|
213
|
+
const denominator = c.real * c.real + c.imag * c.imag;
|
|
214
|
+
if (isApproximatelyZero(denominator)) {
|
|
215
|
+
throw new Error(
|
|
216
|
+
"Cannot calculate reciprocal of zero or near-zero complex number"
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
return normalizeComplex({
|
|
220
|
+
real: c.real / denominator,
|
|
221
|
+
imag: -c.imag / denominator
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
export {
|
|
225
|
+
addComplex,
|
|
226
|
+
argumentComplex,
|
|
227
|
+
complexEquals,
|
|
228
|
+
conjugateComplex,
|
|
229
|
+
cosComplex,
|
|
230
|
+
createComplex,
|
|
231
|
+
divideComplex,
|
|
232
|
+
expComplex,
|
|
233
|
+
fromPolarComplex,
|
|
234
|
+
getImag,
|
|
235
|
+
getReal,
|
|
236
|
+
isZeroComplex,
|
|
237
|
+
lnComplex,
|
|
238
|
+
magnitudeComplex,
|
|
239
|
+
multiplyComplex,
|
|
240
|
+
negateComplex,
|
|
241
|
+
powerComplex,
|
|
242
|
+
reciprocalComplex,
|
|
243
|
+
sinComplex,
|
|
244
|
+
sqrtComplex,
|
|
245
|
+
subtractComplex,
|
|
246
|
+
toPolarComplex
|
|
247
|
+
};
|