PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.3.2
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.3.2
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.3.2, at vendor/markbaker/complex/classes/src/Complex.php

388 lines 10.9 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 if ($imaginaryPart <> 0.0 && empty($suffix)) {
180 $suffix = 'i';
181 }
182
183 // Set parsed values in our properties
184 $this->realPart = (float) $realPart;
185 $this->imaginaryPart = (float) $imaginaryPart;
186 $this->suffix = strtolower($suffix);
187 }
188
189 /**
190 * Gets the real part of this complex number
191 *
192 * @return Float
193 */
194 public function getReal()
195 {
196 return $this->realPart;
197 }
198
199 /**
200 * Gets the imaginary part of this complex number
201 *
202 * @return Float
203 */
204 public function getImaginary()
205 {
206 return $this->imaginaryPart;
207 }
208
209 /**
210 * Gets the suffix of this complex number
211 *
212 * @return String
213 */
214 public function getSuffix()
215 {
216 return $this->suffix;
217 }
218
219 /**
220 * Returns true if this is a real value, false if a complex value
221 *
222 * @return Bool
223 */
224 public function isReal()
225 {
226 return $this->imaginaryPart == 0.0;
227 }
228
229 /**
230 * Returns true if this is a complex value, false if a real value
231 *
232 * @return Bool
233 */
234 public function isComplex()
235 {
236 return !$this->isReal();
237 }
238
239 public function format()
240 {
241 $str = "";
242 if ($this->imaginaryPart != 0.0) {
243 if (\abs($this->imaginaryPart) != 1.0) {
244 $str .= $this->imaginaryPart . $this->suffix;
245 } else {
246 $str .= (($this->imaginaryPart < 0.0) ? '-' : '') . $this->suffix;
247 }
248 }
249 if ($this->realPart != 0.0) {
250 if (($str) && ($this->imaginaryPart > 0.0)) {
251 $str = "+" . $str;
252 }
253 $str = $this->realPart . $str;
254 }
255 if (!$str) {
256 $str = "0.0";
257 }
258
259 return $str;
260 }
261
262 public function __toString()
263 {
264 return $this->format();
265 }
266
267 /**
268 * Validates whether the argument is a valid complex number, converting scalar or array values if possible
269 *
270 * @param mixed $complex The value to validate
271 * @return Complex
272 * @throws Exception If the argument isn't a Complex number or cannot be converted to one
273 */
274 public static function validateComplexArgument($complex)
275 {
276 if (is_scalar($complex) || is_array($complex)) {
277 $complex = new Complex($complex);
278 } elseif (!is_object($complex) || !($complex instanceof Complex)) {
279 throw new Exception('Value is not a valid complex number');
280 }
281
282 return $complex;
283 }
284
285 /**
286 * Returns the reverse of this complex number
287 *
288 * @return Complex
289 */
290 public function reverse()
291 {
292 return new Complex(
293 $this->imaginaryPart,
294 $this->realPart,
295 ($this->realPart == 0.0) ? null : $this->suffix
296 );
297 }
298
299 public function invertImaginary()
300 {
301 return new Complex(
302 $this->realPart,
303 $this->imaginaryPart * -1,
304 ($this->imaginaryPart == 0.0) ? null : $this->suffix
305 );
306 }
307
308 public function invertReal()
309 {
310 return new Complex(
311 $this->realPart * -1,
312 $this->imaginaryPart,
313 ($this->imaginaryPart == 0.0) ? null : $this->suffix
314 );
315 }
316
317 protected static $functions = [
318 'abs',
319 'acos',
320 'acosh',
321 'acot',
322 'acoth',
323 'acsc',
324 'acsch',
325 'argument',
326 'asec',
327 'asech',
328 'asin',
329 'asinh',
330 'atan',
331 'atanh',
332 'conjugate',
333 'cos',
334 'cosh',
335 'cot',
336 'coth',
337 'csc',
338 'csch',
339 'exp',
340 'inverse',
341 'ln',
342 'log2',
343 'log10',
344 'negative',
345 'pow',
346 'rho',
347 'sec',
348 'sech',
349 'sin',
350 'sinh',
351 'sqrt',
352 'tan',
353 'tanh',
354 'theta',
355 ];
356
357 protected static $operations = [
358 'add',
359 'subtract',
360 'multiply',
361 'divideby',
362 'divideinto',
363 ];
364
365 /**
366 * Returns the result of the function call or operation
367 *
368 * @return Complex|float
369 * @throws Exception|\InvalidArgumentException
370 */
371 public function __call($functionName, $arguments)
372 {
373 $functionName = strtolower(str_replace('_', '', $functionName));
374
375 // Test for function calls
376 if (in_array($functionName, self::$functions)) {
377 $functionName = "\\" . __NAMESPACE__ . "\\{$functionName}";
378 return $functionName($this, ...$arguments);
379 }
380 // Test for operation calls
381 if (in_array($functionName, self::$operations)) {
382 $functionName = "\\" . __NAMESPACE__ . "\\{$functionName}";
383 return $functionName($this, ...$arguments);
384 }
385 throw new Exception('Function or Operation does not exist');
386 }
387 }
388