1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace PhpSpreadsheet\Tests\Custom; |
4
|
|
|
|
5
|
|
|
use PhpSpreadsheet\Exception; |
6
|
|
|
|
7
|
|
|
class Complex |
8
|
|
|
{ |
9
|
|
|
private $realPart = 0; |
10
|
|
|
private $imaginaryPart = 0; |
11
|
|
|
private $suffix = null; |
12
|
|
|
|
13
|
|
|
public static function _parseComplex($complexNumber) |
14
|
|
|
{ |
15
|
|
|
// Test for real number, with no imaginary part |
16
|
|
|
if (is_numeric($complexNumber)) { |
17
|
|
|
return [$complexNumber, 0, null]; |
18
|
|
|
} |
19
|
|
|
|
20
|
|
|
// Fix silly human errors |
21
|
|
|
if (strpos($complexNumber, '+-') !== false) { |
22
|
|
|
$complexNumber = str_replace('+-', '-', $complexNumber); |
23
|
|
|
} |
24
|
|
|
if (strpos($complexNumber, '++') !== false) { |
25
|
|
|
$complexNumber = str_replace('++', '+', $complexNumber); |
26
|
|
|
} |
27
|
|
|
if (strpos($complexNumber, '--') !== false) { |
28
|
|
|
$complexNumber = str_replace('--', '-', $complexNumber); |
29
|
|
|
} |
30
|
|
|
|
31
|
|
|
// Basic validation of string, to parse out real and imaginary parts, and any suffix |
32
|
|
|
$validComplex = preg_match('/^([\-\+]?(\d+\.?\d*|\d*\.?\d+)([Ee][\-\+]?[0-2]?\d{1,3})?)([\-\+]?(\d+\.?\d*|\d*\.?\d+)([Ee][\-\+]?[0-2]?\d{1,3})?)?(([\-\+]?)([ij]?))$/ui', $complexNumber, $complexParts); |
33
|
|
|
|
34
|
|
|
if (!$validComplex) { |
35
|
|
|
// Neither real nor imaginary part, so test to see if we actually have a suffix |
36
|
|
|
$validComplex = preg_match('/^([\-\+]?)([ij])$/ui', $complexNumber, $complexParts); |
37
|
|
|
if (!$validComplex) { |
38
|
|
|
throw new Exception('COMPLEX: Invalid complex number'); |
39
|
|
|
} |
40
|
|
|
// We have a suffix, so set the real to 0, the imaginary to either 1 or -1 (as defined by the sign) |
41
|
|
|
$imaginary = 1; |
42
|
|
|
if ($complexParts[1] === '-') { |
43
|
|
|
$imaginary = 0 - $imaginary; |
44
|
|
|
} |
45
|
|
|
|
46
|
|
|
return [0, $imaginary, $complexParts[2]]; |
47
|
|
|
} |
48
|
|
|
|
49
|
|
|
// If we don't have an imaginary part, identify whether it should be +1 or -1... |
50
|
|
|
if (($complexParts[4] === '') && ($complexParts[9] !== '')) { |
51
|
|
|
if ($complexParts[7] !== $complexParts[9]) { |
52
|
|
|
$complexParts[4] = 1; |
53
|
|
|
if ($complexParts[8] === '-') { |
54
|
|
|
$complexParts[4] = -1; |
55
|
|
|
} |
56
|
|
|
// ... or if we have only the real and no imaginary part (in which case our real should be the imaginary) |
57
|
|
|
} else { |
58
|
|
|
$complexParts[4] = $complexParts[1]; |
59
|
|
|
$complexParts[1] = 0; |
60
|
|
|
} |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
// Return real and imaginary parts and suffix as an array, and set a default suffix if user input lazily |
64
|
|
|
return [$complexParts[1], $complexParts[4], !empty($complexParts[9]) ? $complexParts[9] : 'i']; |
65
|
|
|
} // function _parseComplex() |
|
|
|
|
66
|
|
|
|
67
|
|
|
public function __construct($realPart, $imaginaryPart = null, $suffix = 'i') |
68
|
|
|
{ |
69
|
|
|
if ($imaginaryPart === null) { |
70
|
|
|
if (is_array($realPart)) { |
71
|
|
|
// We have an array of (potentially) real and imaginary parts, and any suffix |
72
|
|
|
list($realPart, $imaginaryPart, $suffix) = array_values($realPart) + [0.0, 0.0, 'i']; |
73
|
|
|
} elseif ((is_string($realPart)) || (is_numeric($realPart))) { |
74
|
|
|
// We've been given a string to parse to extract the real and imaginary parts, and any suffix |
75
|
|
|
list($realPart, $imaginaryPart, $suffix) = self::_parseComplex($realPart); |
76
|
|
|
} |
77
|
|
|
} |
78
|
|
|
|
79
|
|
|
// Set parsed values in our properties |
80
|
|
|
$this->realPart = (float) $realPart; |
|
|
|
|
81
|
|
|
$this->imaginaryPart = (float) $imaginaryPart; |
|
|
|
|
82
|
|
|
$this->suffix = strtolower($suffix); |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
public function getReal() |
86
|
|
|
{ |
87
|
|
|
return $this->realPart; |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
public function getImaginary() |
91
|
|
|
{ |
92
|
|
|
return $this->imaginaryPart; |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
public function getSuffix() |
96
|
|
|
{ |
97
|
|
|
return $this->suffix; |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
public function __toString() |
101
|
|
|
{ |
102
|
|
|
$str = ''; |
103
|
|
|
if ($this->imaginaryPart != 0.0) { |
104
|
|
|
if (abs($this->imaginaryPart) != 1.0) { |
105
|
|
|
$str .= $this->imaginaryPart . $this->suffix; |
106
|
|
|
} else { |
107
|
|
|
$str .= (($this->imaginaryPart < 0.0) ? '-' : '') . $this->suffix; |
108
|
|
|
} |
109
|
|
|
} |
110
|
|
|
if ($this->realPart != 0.0) { |
111
|
|
|
if (($str) && ($this->imaginaryPart > 0.0)) { |
112
|
|
|
$str = '+' . $str; |
113
|
|
|
} |
114
|
|
|
$str = $this->realPart . $str; |
115
|
|
|
} |
116
|
|
|
if (!$str) { |
117
|
|
|
$str = '0.0'; |
118
|
|
|
} |
119
|
|
|
|
120
|
|
|
return $str; |
121
|
|
|
} |
122
|
|
|
} |
123
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.