PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.10.1
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.10.1
4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.1.2 3.1.3 3.10.0 3.10.1 3.10.10 3.10.11 3.10.12 3.10.13 3.10.14 3.10.15 3.10.2 3.10.3 3.10.4 All 148 releases
visualizer / vendor / markbaker / complex / classes / src / Complex.php

Complex.php in Visualizer – Tables & Charts Manager with Built-in AI Generator 3.10.1, at vendor/markbaker/complex/classes/src/Complex.php

391 lines 11.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 *
5 * Class for the management of Complex numbers
6 *
7 * @copyright Copyright (c) 2013-2018 Mark Baker (https://github.com/MarkBaker/PHPComplex)
8 * @license https://opensource.org/licenses/MIT MIT
9 */
10 namespace Complex;
11
12 /**
13 * Complex Number object.
14 *
15 * @package Complex
16 *
17 * @method float abs()
18 * @method Complex acos()
19 * @method Complex acosh()
20 * @method Complex acot()
21 * @method Complex acoth()
22 * @method Complex acsc()
23 * @method Complex acsch()
24 * @method float argument()
25 * @method Complex asec()
26 * @method Complex asech()
27 * @method Complex asin()
28 * @method Complex asinh()
29 * @method Complex atan()
30 * @method Complex atanh()
31 * @method Complex conjugate()
32 * @method Complex cos()
33 * @method Complex cosh()
34 * @method Complex cot()
35 * @method Complex coth()
36 * @method Complex csc()
37 * @method Complex csch()
38 * @method Complex exp()
39 * @method Complex inverse()
40 * @method Complex ln()
41 * @method Complex log2()
42 * @method Complex log10()
43 * @method Complex negative()
44 * @method Complex pow(int|float $power)
45 * @method float rho()
46 * @method Complex sec()
47 * @method Complex sech()
48 * @method Complex sin()
49 * @method Complex sinh()
50 * @method Complex sqrt()
51 * @method Complex tan()
52 * @method Complex tanh()
53 * @method float theta()
54 * @method Complex add(...$complexValues)
55 * @method Complex subtract(...$complexValues)
56 * @method Complex multiply(...$complexValues)
57 * @method Complex divideby(...$complexValues)
58 * @method Complex divideinto(...$complexValues)
59 */
60 class Complex
61 {
62 /**
63 * @constant Euler's Number.
64 */
65 const EULER = 2.7182818284590452353602874713526624977572;
66
67 /**
68 * @constant Regexp to split an input string into real and imaginary components and suffix
69 */
70 const NUMBER_SPLIT_REGEXP =
71 '` ^
72 ( # Real part
73 [-+]?(\d+\.?\d*|\d*\.?\d+) # Real value (integer or float)
74 ([Ee][-+]?[0-2]?\d{1,3})? # Optional real exponent for scientific format
75 )
76 ( # Imaginary part
77 [-+]?(\d+\.?\d*|\d*\.?\d+) # Imaginary value (integer or float)
78 ([Ee][-+]?[0-2]?\d{1,3})? # Optional imaginary exponent for scientific format
79 )?
80 ( # Imaginary part is optional
81 ([-+]?) # Imaginary (implicit 1 or -1) only
82 ([ij]?) # Imaginary i or j - depending on whether mathematical or engineering
83 )
84 $`uix';
85
86 /**
87 * @var float $realPart The value of of this complex number on the real plane.
88 */
89 protected $realPart = 0.0;
90
91 /**
92 * @var float $imaginaryPart The value of of this complex number on the imaginary plane.
93 */
94 protected $imaginaryPart = 0.0;
95
96 /**
97 * @var string $suffix The suffix for this complex number (i or j).
98 */
99 protected $suffix;
100
101
102 /**
103 * Validates whether the argument is a valid complex number, converting scalar or array values if possible
104 *
105 * @param mixed $complexNumber The value to parse
106 * @return array
107 * @throws Exception If the argument isn't a Complex number or cannot be converted to one
108 */
109 private static function parseComplex($complexNumber)
110 {
111 // Test for real number, with no imaginary part
112 if (is_numeric($complexNumber)) {
113 return [$complexNumber, 0, null];
114 }
115
116 // Fix silly human errors
117 $complexNumber = str_replace(
118 ['+-', '-+', '++', '--'],
119 ['-', '-', '+', '+'],
120 $complexNumber
121 );
122
123 // Basic validation of string, to parse out real and imaginary parts, and any suffix
124 $validComplex = preg_match(
125 self::NUMBER_SPLIT_REGEXP,
126 $complexNumber,
127 $complexParts
128 );
129
130 if (!$validComplex) {
131 // Neither real nor imaginary part, so test to see if we actually have a suffix
132 $validComplex = preg_match('/^([\-\+]?)([ij])$/ui', $complexNumber, $complexParts);
133 if (!$validComplex) {
134 throw new Exception('Invalid complex number');
135 }
136 // We have a suffix, so set the real to 0, the imaginary to either 1 or -1 (as defined by the sign)
137 $imaginary = 1;
138 if ($complexParts[1] === '-') {
139 $imaginary = 0 - $imaginary;
140 }
141 return [0, $imaginary, $complexParts[2]];
142 }
143
144 // If we don't have an imaginary part, identify whether it should be +1 or -1...
145 if (($complexParts[4] === '') && ($complexParts[9] !== '')) {
146 if ($complexParts[7] !== $complexParts[9]) {
147 $complexParts[4] = 1;
148 if ($complexParts[8] === '-') {
149 $complexParts[4] = -1;
150 }
151 } else {
152 // ... or if we have only the real and no imaginary part
153 // (in which case our real should be the imaginary)
154 $complexParts[4] = $complexParts[1];
155 $complexParts[1] = 0;
156 }
157 }
158
159 // Return real and imaginary parts and suffix as an array, and set a default suffix if user input lazily
160 return [
161 $complexParts[1],
162 $complexParts[4],
163 !empty($complexParts[9]) ? $complexParts[9] : 'i'
164 ];
165 }
166
167
168 public function __construct($realPart = 0.0, $imaginaryPart = null, $suffix = 'i')
169 {
170 if ($imaginaryPart === null) {
171 if (is_array($realPart)) {
172 // We have an array of (potentially) real and imaginary parts, and any suffix
173 list ($realPart, $imaginaryPart, $suffix) = array_values($realPart) + [0.0, 0.0, 'i'];
174 } elseif ((is_string($realPart)) || (is_numeric($realPart))) {
175 // We've been given a string to parse to extract the real and imaginary parts, and any suffix
176 list($realPart, $imaginaryPart, $suffix) = self::parseComplex($realPart);
177 }
178 }
179
180 if ($imaginaryPart != 0.0 && empty($suffix)) {
181 $suffix = 'i';
182 } elseif ($imaginaryPart == 0.0 && !empty($suffix)) {
183 $suffix = '';
184 }
185
186 // Set parsed values in our properties
187 $this->realPart = (float) $realPart;
188 $this->imaginaryPart = (float) $imaginaryPart;
189 $this->suffix = strtolower($suffix);
190 }
191
192 /**
193 * Gets the real part of this complex number
194 *
195 * @return Float
196 */
197 public function getReal()
198 {
199 return $this->realPart;
200 }
201
202 /**
203 * Gets the imaginary part of this complex number
204 *
205 * @return Float
206 */
207 public function getImaginary()
208 {
209 return $this->imaginaryPart;
210 }
211
212 /**
213 * Gets the suffix of this complex number
214 *
215 * @return String
216 */
217 public function getSuffix()
218 {
219 return $this->suffix;
220 }
221
222 /**
223 * Returns true if this is a real value, false if a complex value
224 *
225 * @return Bool
226 */
227 public function isReal()
228 {
229 return $this->imaginaryPart == 0.0;
230 }
231
232 /**
233 * Returns true if this is a complex value, false if a real value
234 *
235 * @return Bool
236 */
237 public function isComplex()
238 {
239 return !$this->isReal();
240 }
241
242 public function format()
243 {
244 $str = "";
245 if ($this->imaginaryPart != 0.0) {
246 if (\abs($this->imaginaryPart) != 1.0) {
247 $str .= $this->imaginaryPart . $this->suffix;
248 } else {
249 $str .= (($this->imaginaryPart < 0.0) ? '-' : '') . $this->suffix;
250 }
251 }
252 if ($this->realPart != 0.0) {
253 if (($str) && ($this->imaginaryPart > 0.0)) {
254 $str = "+" . $str;
255 }
256 $str = $this->realPart . $str;
257 }
258 if (!$str) {
259 $str = "0.0";
260 }
261
262 return $str;
263 }
264
265 public function __toString()
266 {
267 return $this->format();
268 }
269
270 /**
271 * Validates whether the argument is a valid complex number, converting scalar or array values if possible
272 *
273 * @param mixed $complex The value to validate
274 * @return Complex
275 * @throws Exception If the argument isn't a Complex number or cannot be converted to one
276 */
277 public static function validateComplexArgument($complex)
278 {
279 if (is_scalar($complex) || is_array($complex)) {
280 $complex = new Complex($complex);
281 } elseif (!is_object($complex) || !($complex instanceof Complex)) {
282 throw new Exception('Value is not a valid complex number');
283 }
284
285 return $complex;
286 }
287
288 /**
289 * Returns the reverse of this complex number
290 *
291 * @return Complex
292 */
293 public function reverse()
294 {
295 return new Complex(
296 $this->imaginaryPart,
297 $this->realPart,
298 ($this->realPart == 0.0) ? null : $this->suffix
299 );
300 }
301
302 public function invertImaginary()
303 {
304 return new Complex(
305 $this->realPart,
306 $this->imaginaryPart * -1,
307 ($this->imaginaryPart == 0.0) ? null : $this->suffix
308 );
309 }
310
311 public function invertReal()
312 {
313 return new Complex(
314 $this->realPart * -1,
315 $this->imaginaryPart,
316 ($this->imaginaryPart == 0.0) ? null : $this->suffix
317 );
318 }
319
320 protected static $functions = [
321 'abs',
322 'acos',
323 'acosh',
324 'acot',
325 'acoth',
326 'acsc',
327 'acsch',
328 'argument',
329 'asec',
330 'asech',
331 'asin',
332 'asinh',
333 'atan',
334 'atanh',
335 'conjugate',
336 'cos',
337 'cosh',
338 'cot',
339 'coth',
340 'csc',
341 'csch',
342 'exp',
343 'inverse',
344 'ln',
345 'log2',
346 'log10',
347 'negative',
348 'pow',
349 'rho',
350 'sec',
351 'sech',
352 'sin',
353 'sinh',
354 'sqrt',
355 'tan',
356 'tanh',
357 'theta',
358 ];
359
360 protected static $operations = [
361 'add',
362 'subtract',
363 'multiply',
364 'divideby',
365 'divideinto',
366 ];
367
368 /**
369 * Returns the result of the function call or operation
370 *
371 * @return Complex|float
372 * @throws Exception|\InvalidArgumentException
373 */
374 public function __call($functionName, $arguments)
375 {
376 $functionName = strtolower(str_replace('_', '', $functionName));
377
378 // Test for function calls
379 if (in_array($functionName, self::$functions, true)) {
380 $functionName = "\\" . __NAMESPACE__ . "\\{$functionName}";
381 return $functionName($this, ...$arguments);
382 }
383 // Test for operation calls
384 if (in_array($functionName, self::$operations, true)) {
385 $functionName = "\\" . __NAMESPACE__ . "\\{$functionName}";
386 return $functionName($this, ...$arguments);
387 }
388 throw new Exception('Function or Operation does not exist');
389 }
390 }
391