Completed
Push — develop ( 685e29...09d456 )
by Adrien
14:14
created

Engineering   F

Complexity

Total Complexity 292

Size/Duplication

Total Lines 2620
Duplicated Lines 13.89 %

Coupling/Cohesion

Components 6
Dependencies 2

Test Coverage

Coverage 88.64%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 364
loc 2620
ccs 601
cts 678
cp 0.8864
rs 0.6314
wmc 292
lcom 6
cbo 2

52 Methods

Rating   Name   Duplication   Size   Complexity  
C parseComplex() 0 47 14
B cleanComplex() 0 17 5
B nbrConversionFormat() 0 20 5
C BESSELI() 5 35 12
C BESSELJ() 5 37 12
A besselK0() 6 17 2
A besselK1() 6 17 2
C BESSELK() 31 33 11
A besselY0() 0 18 2
A besselY1() 0 15 2
C BESSELY() 31 33 11
C BINTODEC() 0 29 7
C BINTOHEX() 30 30 7
C BINTOOCT() 29 29 7
C DECTOBIN() 0 31 7
B DECTOHEX() 25 25 5
B DECTOOCT() 26 26 5
A HEXTOBIN() 15 15 3
D HEXTODEC() 10 30 9
B HEXTOOCT() 0 20 5
A OCTTOBIN() 15 15 3
C OCTTODEC() 10 25 8
A OCTTOHEX() 16 16 3
D COMPLEX() 0 41 18
A IMAGINARY() 0 8 1
A IMREAL() 0 8 1
A IMABS() 0 11 1
B IMARGUMENT() 0 20 6
A IMCONJUGATE() 0 18 2
A IMCOS() 18 18 2
A IMSIN() 16 16 2
A IMSQRT() 0 17 2
A IMLN() 0 19 4
B IMLOG10() 14 14 5
B IMLOG2() 14 14 5
A IMEXP() 0 20 4
B IMPOWER() 0 22 4
C IMDIV() 0 32 8
B IMSUB() 0 21 6
B IMSUM() 5 27 6
C IMPRODUCT() 5 27 7
A DELTA() 0 7 1
A GESTEP() 0 7 1
B erfVal() 0 22 4
A ERF() 0 16 4
B erfcVal() 0 27 4
A ERFC() 0 10 2
A getConversionGroups() 0 9 2
A getConversionGroupUnits() 0 11 4
A getConversionGroupUnitDetails() 0 14 4
A getConversionMultipliers() 0 4 1
D CONVERTUOM() 32 90 34

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Engineering often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Engineering, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace PhpSpreadsheet\Calculation;
4
5
/* EULER */
6 1
define('EULER', 2.71828182845904523536);
7
8
/**
9
 * Copyright (c) 2006 - 2016 PhpSpreadsheet
10
 *
11
 * This library is free software; you can redistribute it and/or
12
 * modify it under the terms of the GNU Lesser General Public
13
 * License as published by the Free Software Foundation; either
14
 * version 2.1 of the License, or (at your option) any later version.
15
 *
16
 * This library is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19
 * Lesser General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU Lesser General Public
22
 * License along with this library; if not, write to the Free Software
23
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24
 *
25
 * @category    PhpSpreadsheet
26
 * @copyright    Copyright (c) 2006 - 2016 PhpSpreadsheet (https://github.com/PHPOffice/PhpSpreadsheet)
27
 * @license        http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt    LGPL
28
 * @version        ##VERSION##, ##DATE##
29
 */
30
class Engineering
31
{
32
    /**
33
     * Details of the Units of measure that can be used in CONVERTUOM()
34
     *
35
     * @var mixed[]
36
     */
37
    private static $conversionUnits = [
38
        'g' => ['Group' => 'Mass', 'Unit Name' => 'Gram', 'AllowPrefix' => true],
39
        'sg' => ['Group' => 'Mass', 'Unit Name' => 'Slug', 'AllowPrefix' => false],
40
        'lbm' => ['Group' => 'Mass', 'Unit Name' => 'Pound mass (avoirdupois)', 'AllowPrefix' => false],
41
        'u' => ['Group' => 'Mass', 'Unit Name' => 'U (atomic mass unit)', 'AllowPrefix' => true],
42
        'ozm' => ['Group' => 'Mass', 'Unit Name' => 'Ounce mass (avoirdupois)', 'AllowPrefix' => false],
43
        'm' => ['Group' => 'Distance', 'Unit Name' => 'Meter', 'AllowPrefix' => true],
44
        'mi' => ['Group' => 'Distance', 'Unit Name' => 'Statute mile', 'AllowPrefix' => false],
45
        'Nmi' => ['Group' => 'Distance', 'Unit Name' => 'Nautical mile', 'AllowPrefix' => false],
46
        'in' => ['Group' => 'Distance', 'Unit Name' => 'Inch', 'AllowPrefix' => false],
47
        'ft' => ['Group' => 'Distance', 'Unit Name' => 'Foot', 'AllowPrefix' => false],
48
        'yd' => ['Group' => 'Distance', 'Unit Name' => 'Yard', 'AllowPrefix' => false],
49
        'ang' => ['Group' => 'Distance', 'Unit Name' => 'Angstrom', 'AllowPrefix' => true],
50
        'Pica' => ['Group' => 'Distance', 'Unit Name' => 'Pica (1/72 in)', 'AllowPrefix' => false],
51
        'yr' => ['Group' => 'Time', 'Unit Name' => 'Year', 'AllowPrefix' => false],
52
        'day' => ['Group' => 'Time', 'Unit Name' => 'Day', 'AllowPrefix' => false],
53
        'hr' => ['Group' => 'Time', 'Unit Name' => 'Hour', 'AllowPrefix' => false],
54
        'mn' => ['Group' => 'Time', 'Unit Name' => 'Minute', 'AllowPrefix' => false],
55
        'sec' => ['Group' => 'Time', 'Unit Name' => 'Second', 'AllowPrefix' => true],
56
        'Pa' => ['Group' => 'Pressure', 'Unit Name' => 'Pascal', 'AllowPrefix' => true],
57
        'p' => ['Group' => 'Pressure', 'Unit Name' => 'Pascal', 'AllowPrefix' => true],
58
        'atm' => ['Group' => 'Pressure', 'Unit Name' => 'Atmosphere', 'AllowPrefix' => true],
59
        'at' => ['Group' => 'Pressure', 'Unit Name' => 'Atmosphere', 'AllowPrefix' => true],
60
        'mmHg' => ['Group' => 'Pressure', 'Unit Name' => 'mm of Mercury', 'AllowPrefix' => true],
61
        'N' => ['Group' => 'Force', 'Unit Name' => 'Newton', 'AllowPrefix' => true],
62
        'dyn' => ['Group' => 'Force', 'Unit Name' => 'Dyne', 'AllowPrefix' => true],
63
        'dy' => ['Group' => 'Force', 'Unit Name' => 'Dyne', 'AllowPrefix' => true],
64
        'lbf' => ['Group' => 'Force', 'Unit Name' => 'Pound force', 'AllowPrefix' => false],
65
        'J' => ['Group' => 'Energy', 'Unit Name' => 'Joule', 'AllowPrefix' => true],
66
        'e' => ['Group' => 'Energy', 'Unit Name' => 'Erg', 'AllowPrefix' => true],
67
        'c' => ['Group' => 'Energy', 'Unit Name' => 'Thermodynamic calorie', 'AllowPrefix' => true],
68
        'cal' => ['Group' => 'Energy', 'Unit Name' => 'IT calorie', 'AllowPrefix' => true],
69
        'eV' => ['Group' => 'Energy', 'Unit Name' => 'Electron volt', 'AllowPrefix' => true],
70
        'ev' => ['Group' => 'Energy', 'Unit Name' => 'Electron volt', 'AllowPrefix' => true],
71
        'HPh' => ['Group' => 'Energy', 'Unit Name' => 'Horsepower-hour', 'AllowPrefix' => false],
72
        'hh' => ['Group' => 'Energy', 'Unit Name' => 'Horsepower-hour', 'AllowPrefix' => false],
73
        'Wh' => ['Group' => 'Energy', 'Unit Name' => 'Watt-hour', 'AllowPrefix' => true],
74
        'wh' => ['Group' => 'Energy', 'Unit Name' => 'Watt-hour', 'AllowPrefix' => true],
75
        'flb' => ['Group' => 'Energy', 'Unit Name' => 'Foot-pound', 'AllowPrefix' => false],
76
        'BTU' => ['Group' => 'Energy', 'Unit Name' => 'BTU', 'AllowPrefix' => false],
77
        'btu' => ['Group' => 'Energy', 'Unit Name' => 'BTU', 'AllowPrefix' => false],
78
        'HP' => ['Group' => 'Power', 'Unit Name' => 'Horsepower', 'AllowPrefix' => false],
79
        'h' => ['Group' => 'Power', 'Unit Name' => 'Horsepower', 'AllowPrefix' => false],
80
        'W' => ['Group' => 'Power', 'Unit Name' => 'Watt', 'AllowPrefix' => true],
81
        'w' => ['Group' => 'Power', 'Unit Name' => 'Watt', 'AllowPrefix' => true],
82
        'T' => ['Group' => 'Magnetism', 'Unit Name' => 'Tesla', 'AllowPrefix' => true],
83
        'ga' => ['Group' => 'Magnetism', 'Unit Name' => 'Gauss', 'AllowPrefix' => true],
84
        'C' => ['Group' => 'Temperature', 'Unit Name' => 'Celsius', 'AllowPrefix' => false],
85
        'cel' => ['Group' => 'Temperature', 'Unit Name' => 'Celsius', 'AllowPrefix' => false],
86
        'F' => ['Group' => 'Temperature', 'Unit Name' => 'Fahrenheit', 'AllowPrefix' => false],
87
        'fah' => ['Group' => 'Temperature', 'Unit Name' => 'Fahrenheit', 'AllowPrefix' => false],
88
        'K' => ['Group' => 'Temperature', 'Unit Name' => 'Kelvin', 'AllowPrefix' => false],
89
        'kel' => ['Group' => 'Temperature', 'Unit Name' => 'Kelvin', 'AllowPrefix' => false],
90
        'tsp' => ['Group' => 'Liquid', 'Unit Name' => 'Teaspoon', 'AllowPrefix' => false],
91
        'tbs' => ['Group' => 'Liquid', 'Unit Name' => 'Tablespoon', 'AllowPrefix' => false],
92
        'oz' => ['Group' => 'Liquid', 'Unit Name' => 'Fluid Ounce', 'AllowPrefix' => false],
93
        'cup' => ['Group' => 'Liquid', 'Unit Name' => 'Cup', 'AllowPrefix' => false],
94
        'pt' => ['Group' => 'Liquid', 'Unit Name' => 'U.S. Pint', 'AllowPrefix' => false],
95
        'us_pt' => ['Group' => 'Liquid', 'Unit Name' => 'U.S. Pint', 'AllowPrefix' => false],
96
        'uk_pt' => ['Group' => 'Liquid', 'Unit Name' => 'U.K. Pint', 'AllowPrefix' => false],
97
        'qt' => ['Group' => 'Liquid', 'Unit Name' => 'Quart', 'AllowPrefix' => false],
98
        'gal' => ['Group' => 'Liquid', 'Unit Name' => 'Gallon', 'AllowPrefix' => false],
99
        'l' => ['Group' => 'Liquid', 'Unit Name' => 'Litre', 'AllowPrefix' => true],
100
        'lt' => ['Group' => 'Liquid', 'Unit Name' => 'Litre', 'AllowPrefix' => true],
101
    ];
102
103
    /**
104
     * Details of the Multiplier prefixes that can be used with Units of Measure in CONVERTUOM()
105
     *
106
     * @var mixed[]
107
     */
108
    private static $conversionMultipliers = [
109
        'Y' => ['multiplier' => 1E24, 'name' => 'yotta'],
110
        'Z' => ['multiplier' => 1E21, 'name' => 'zetta'],
111
        'E' => ['multiplier' => 1E18, 'name' => 'exa'],
112
        'P' => ['multiplier' => 1E15, 'name' => 'peta'],
113
        'T' => ['multiplier' => 1E12, 'name' => 'tera'],
114
        'G' => ['multiplier' => 1E9, 'name' => 'giga'],
115
        'M' => ['multiplier' => 1E6, 'name' => 'mega'],
116
        'k' => ['multiplier' => 1E3, 'name' => 'kilo'],
117
        'h' => ['multiplier' => 1E2, 'name' => 'hecto'],
118
        'e' => ['multiplier' => 1E1, 'name' => 'deka'],
119
        'd' => ['multiplier' => 1E-1, 'name' => 'deci'],
120
        'c' => ['multiplier' => 1E-2, 'name' => 'centi'],
121
        'm' => ['multiplier' => 1E-3, 'name' => 'milli'],
122
        'u' => ['multiplier' => 1E-6, 'name' => 'micro'],
123
        'n' => ['multiplier' => 1E-9, 'name' => 'nano'],
124
        'p' => ['multiplier' => 1E-12, 'name' => 'pico'],
125
        'f' => ['multiplier' => 1E-15, 'name' => 'femto'],
126
        'a' => ['multiplier' => 1E-18, 'name' => 'atto'],
127
        'z' => ['multiplier' => 1E-21, 'name' => 'zepto'],
128
        'y' => ['multiplier' => 1E-24, 'name' => 'yocto'],
129
    ];
130
131
    /**
132
     * Details of the Units of measure conversion factors, organised by group
133
     *
134
     * @var mixed[]
135
     */
136
    private static $unitConversions = [
137
        'Mass' => [
138
            'g' => [
139
                'g' => 1.0,
140
                'sg' => 6.85220500053478E-05,
141
                'lbm' => 2.20462291469134E-03,
142
                'u' => 6.02217000000000E+23,
143
                'ozm' => 3.52739718003627E-02,
144
            ],
145
            'sg' => [
146
                'g' => 1.45938424189287E+04,
147
                'sg' => 1.0,
148
                'lbm' => 3.21739194101647E+01,
149
                'u' => 8.78866000000000E+27,
150
                'ozm' => 5.14782785944229E+02,
151
            ],
152
            'lbm' => [
153
                'g' => 4.5359230974881148E+02,
154
                'sg' => 3.10810749306493E-02,
155
                'lbm' => 1.0,
156
                'u' => 2.73161000000000E+26,
157
                'ozm' => 1.60000023429410E+01,
158
            ],
159
            'u' => [
160
                'g' => 1.66053100460465E-24,
161
                'sg' => 1.13782988532950E-28,
162
                'lbm' => 3.66084470330684E-27,
163
                'u' => 1.0,
164
                'ozm' => 5.85735238300524E-26,
165
            ],
166
            'ozm' => [
167
                'g' => 2.83495152079732E+01,
168
                'sg' => 1.94256689870811E-03,
169
                'lbm' => 6.24999908478882E-02,
170
                'u' => 1.70725600000000E+25,
171
                'ozm' => 1.0,
172
            ],
173
        ],
174
        'Distance' => [
175
            'm' => [
176
                'm' => 1.0,
177
                'mi' => 6.21371192237334E-04,
178
                'Nmi' => 5.39956803455724E-04,
179
                'in' => 3.93700787401575E+01,
180
                'ft' => 3.28083989501312E+00,
181
                'yd' => 1.09361329797891E+00,
182
                'ang' => 1.00000000000000E+10,
183
                'Pica' => 2.83464566929116E+03,
184
            ],
185
            'mi' => [
186
                'm' => 1.60934400000000E+03,
187
                'mi' => 1.0,
188
                'Nmi' => 8.68976241900648E-01,
189
                'in' => 6.33600000000000E+04,
190
                'ft' => 5.28000000000000E+03,
191
                'yd' => 1.76000000000000E+03,
192
                'ang' => 1.60934400000000E+13,
193
                'Pica' => 4.56191999999971E+06,
194
            ],
195
            'Nmi' => [
196
                'm' => 1.85200000000000E+03,
197
                'mi' => 1.15077944802354E+00,
198
                'Nmi' => 1.0,
199
                'in' => 7.29133858267717E+04,
200
                'ft' => 6.07611548556430E+03,
201
                'yd' => 2.02537182785694E+03,
202
                'ang' => 1.85200000000000E+13,
203
                'Pica' => 5.24976377952723E+06,
204
            ],
205
            'in' => [
206
                'm' => 2.54000000000000E-02,
207
                'mi' => 1.57828282828283E-05,
208
                'Nmi' => 1.37149028077754E-05,
209
                'in' => 1.0,
210
                'ft' => 8.33333333333333E-02,
211
                'yd' => 2.77777777686643E-02,
212
                'ang' => 2.54000000000000E+08,
213
                'Pica' => 7.19999999999955E+01,
214
            ],
215
            'ft' => [
216
                'm' => 3.04800000000000E-01,
217
                'mi' => 1.89393939393939E-04,
218
                'Nmi' => 1.64578833693305E-04,
219
                'in' => 1.20000000000000E+01,
220
                'ft' => 1.0,
221
                'yd' => 3.33333333223972E-01,
222
                'ang' => 3.04800000000000E+09,
223
                'Pica' => 8.63999999999946E+02,
224
            ],
225
            'yd' => [
226
                'm' => 9.14400000300000E-01,
227
                'mi' => 5.68181818368230E-04,
228
                'Nmi' => 4.93736501241901E-04,
229
                'in' => 3.60000000118110E+01,
230
                'ft' => 3.00000000000000E+00,
231
                'yd' => 1.0,
232
                'ang' => 9.14400000300000E+09,
233
                'Pica' => 2.59200000085023E+03,
234
            ],
235
            'ang' => [
236
                'm' => 1.00000000000000E-10,
237
                'mi' => 6.21371192237334E-14,
238
                'Nmi' => 5.39956803455724E-14,
239
                'in' => 3.93700787401575E-09,
240
                'ft' => 3.28083989501312E-10,
241
                'yd' => 1.09361329797891E-10,
242
                'ang' => 1.0,
243
                'Pica' => 2.83464566929116E-07,
244
            ],
245
            'Pica' => [
246
                'm' => 3.52777777777800E-04,
247
                'mi' => 2.19205948372629E-07,
248
                'Nmi' => 1.90484761219114E-07,
249
                'in' => 1.38888888888898E-02,
250
                'ft' => 1.15740740740748E-03,
251
                'yd' => 3.85802469009251E-04,
252
                'ang' => 3.52777777777800E+06,
253
                'Pica' => 1.0,
254
            ],
255
        ],
256
        'Time' => [
257
            'yr' => [
258
                'yr' => 1.0,
259
                'day' => 365.25,
260
                'hr' => 8766.0,
261
                'mn' => 525960.0,
262
                'sec' => 31557600.0,
263
            ],
264
            'day' => [
265
                'yr' => 2.73785078713210E-03,
266
                'day' => 1.0,
267
                'hr' => 24.0,
268
                'mn' => 1440.0,
269
                'sec' => 86400.0,
270
            ],
271
            'hr' => [
272
                'yr' => 1.14077116130504E-04,
273
                'day' => 4.16666666666667E-02,
274
                'hr' => 1.0,
275
                'mn' => 60.0,
276
                'sec' => 3600.0,
277
            ],
278
            'mn' => [
279
                'yr' => 1.90128526884174E-06,
280
                'day' => 6.94444444444444E-04,
281
                'hr' => 1.66666666666667E-02,
282
                'mn' => 1.0,
283
                'sec' => 60.0,
284
            ],
285
            'sec' => [
286
                'yr' => 3.16880878140289E-08,
287
                'day' => 1.15740740740741E-05,
288
                'hr' => 2.77777777777778E-04,
289
                'mn' => 1.66666666666667E-02,
290
                'sec' => 1.0,
291
            ],
292
        ],
293
        'Pressure' => [
294
            'Pa' => [
295
                'Pa' => 1.0,
296
                'p' => 1.0,
297
                'atm' => 9.86923299998193E-06,
298
                'at' => 9.86923299998193E-06,
299
                'mmHg' => 7.50061707998627E-03,
300
            ],
301
            'p' => [
302
                'Pa' => 1.0,
303
                'p' => 1.0,
304
                'atm' => 9.86923299998193E-06,
305
                'at' => 9.86923299998193E-06,
306
                'mmHg' => 7.50061707998627E-03,
307
            ],
308
            'atm' => [
309
                'Pa' => 1.01324996583000E+05,
310
                'p' => 1.01324996583000E+05,
311
                'atm' => 1.0,
312
                'at' => 1.0,
313
                'mmHg' => 760.0,
314
            ],
315
            'at' => [
316
                'Pa' => 1.01324996583000E+05,
317
                'p' => 1.01324996583000E+05,
318
                'atm' => 1.0,
319
                'at' => 1.0,
320
                'mmHg' => 760.0,
321
            ],
322
            'mmHg' => [
323
                'Pa' => 1.33322363925000E+02,
324
                'p' => 1.33322363925000E+02,
325
                'atm' => 1.31578947368421E-03,
326
                'at' => 1.31578947368421E-03,
327
                'mmHg' => 1.0,
328
            ],
329
        ],
330
        'Force' => [
331
            'N' => [
332
                'N' => 1.0,
333
                'dyn' => 1.0E+5,
334
                'dy' => 1.0E+5,
335
                'lbf' => 2.24808923655339E-01,
336
            ],
337
            'dyn' => [
338
                'N' => 1.0E-5,
339
                'dyn' => 1.0,
340
                'dy' => 1.0,
341
                'lbf' => 2.24808923655339E-06,
342
            ],
343
            'dy' => [
344
                'N' => 1.0E-5,
345
                'dyn' => 1.0,
346
                'dy' => 1.0,
347
                'lbf' => 2.24808923655339E-06,
348
            ],
349
            'lbf' => [
350
                'N' => 4.448222,
351
                'dyn' => 4.448222E+5,
352
                'dy' => 4.448222E+5,
353
                'lbf' => 1.0,
354
            ],
355
        ],
356
        'Energy' => [
357
            'J' => [
358
                'J' => 1.0,
359
                'e' => 9.99999519343231E+06,
360
                'c' => 2.39006249473467E-01,
361
                'cal' => 2.38846190642017E-01,
362
                'eV' => 6.24145700000000E+18,
363
                'ev' => 6.24145700000000E+18,
364
                'HPh' => 3.72506430801000E-07,
365
                'hh' => 3.72506430801000E-07,
366
                'Wh' => 2.77777916238711E-04,
367
                'wh' => 2.77777916238711E-04,
368
                'flb' => 2.37304222192651E+01,
369
                'BTU' => 9.47815067349015E-04,
370
                'btu' => 9.47815067349015E-04,
371
            ],
372
            'e' => [
373
                'J' => 1.00000048065700E-07,
374
                'e' => 1.0,
375
                'c' => 2.39006364353494E-08,
376
                'cal' => 2.38846305445111E-08,
377
                'eV' => 6.24146000000000E+11,
378
                'ev' => 6.24146000000000E+11,
379
                'HPh' => 3.72506609848824E-14,
380
                'hh' => 3.72506609848824E-14,
381
                'Wh' => 2.77778049754611E-11,
382
                'wh' => 2.77778049754611E-11,
383
                'flb' => 2.37304336254586E-06,
384
                'BTU' => 9.47815522922962E-11,
385
                'btu' => 9.47815522922962E-11,
386
            ],
387
            'c' => [
388
                'J' => 4.18399101363672E+00,
389
                'e' => 4.18398900257312E+07,
390
                'c' => 1.0,
391
                'cal' => 9.99330315287563E-01,
392
                'eV' => 2.61142000000000E+19,
393
                'ev' => 2.61142000000000E+19,
394
                'HPh' => 1.55856355899327E-06,
395
                'hh' => 1.55856355899327E-06,
396
                'Wh' => 1.16222030532950E-03,
397
                'wh' => 1.16222030532950E-03,
398
                'flb' => 9.92878733152102E+01,
399
                'BTU' => 3.96564972437776E-03,
400
                'btu' => 3.96564972437776E-03,
401
            ],
402
            'cal' => [
403
                'J' => 4.18679484613929E+00,
404
                'e' => 4.18679283372801E+07,
405
                'c' => 1.00067013349059E+00,
406
                'cal' => 1.0,
407
                'eV' => 2.61317000000000E+19,
408
                'ev' => 2.61317000000000E+19,
409
                'HPh' => 1.55960800463137E-06,
410
                'hh' => 1.55960800463137E-06,
411
                'Wh' => 1.16299914807955E-03,
412
                'wh' => 1.16299914807955E-03,
413
                'flb' => 9.93544094443283E+01,
414
                'BTU' => 3.96830723907002E-03,
415
                'btu' => 3.96830723907002E-03,
416
            ],
417
            'eV' => [
418
                'J' => 1.60219000146921E-19,
419
                'e' => 1.60218923136574E-12,
420
                'c' => 3.82933423195043E-20,
421
                'cal' => 3.82676978535648E-20,
422
                'eV' => 1.0,
423
                'ev' => 1.0,
424
                'HPh' => 5.96826078912344E-26,
425
                'hh' => 5.96826078912344E-26,
426
                'Wh' => 4.45053000026614E-23,
427
                'wh' => 4.45053000026614E-23,
428
                'flb' => 3.80206452103492E-18,
429
                'BTU' => 1.51857982414846E-22,
430
                'btu' => 1.51857982414846E-22,
431
            ],
432
            'ev' => [
433
                'J' => 1.60219000146921E-19,
434
                'e' => 1.60218923136574E-12,
435
                'c' => 3.82933423195043E-20,
436
                'cal' => 3.82676978535648E-20,
437
                'eV' => 1.0,
438
                'ev' => 1.0,
439
                'HPh' => 5.96826078912344E-26,
440
                'hh' => 5.96826078912344E-26,
441
                'Wh' => 4.45053000026614E-23,
442
                'wh' => 4.45053000026614E-23,
443
                'flb' => 3.80206452103492E-18,
444
                'BTU' => 1.51857982414846E-22,
445
                'btu' => 1.51857982414846E-22,
446
            ],
447
            'HPh' => [
448
                'J' => 2.68451741316170E+06,
449
                'e' => 2.68451612283024E+13,
450
                'c' => 6.41616438565991E+05,
451
                'cal' => 6.41186757845835E+05,
452
                'eV' => 1.67553000000000E+25,
453
                'ev' => 1.67553000000000E+25,
454
                'HPh' => 1.0,
455
                'hh' => 1.0,
456
                'Wh' => 7.45699653134593E+02,
457
                'wh' => 7.45699653134593E+02,
458
                'flb' => 6.37047316692964E+07,
459
                'BTU' => 2.54442605275546E+03,
460
                'btu' => 2.54442605275546E+03,
461
            ],
462
            'hh' => [
463
                'J' => 2.68451741316170E+06,
464
                'e' => 2.68451612283024E+13,
465
                'c' => 6.41616438565991E+05,
466
                'cal' => 6.41186757845835E+05,
467
                'eV' => 1.67553000000000E+25,
468
                'ev' => 1.67553000000000E+25,
469
                'HPh' => 1.0,
470
                'hh' => 1.0,
471
                'Wh' => 7.45699653134593E+02,
472
                'wh' => 7.45699653134593E+02,
473
                'flb' => 6.37047316692964E+07,
474
                'BTU' => 2.54442605275546E+03,
475
                'btu' => 2.54442605275546E+03,
476
            ],
477
            'Wh' => [
478
                'J' => 3.59999820554720E+03,
479
                'e' => 3.59999647518369E+10,
480
                'c' => 8.60422069219046E+02,
481
                'cal' => 8.59845857713046E+02,
482
                'eV' => 2.24692340000000E+22,
483
                'ev' => 2.24692340000000E+22,
484
                'HPh' => 1.34102248243839E-03,
485
                'hh' => 1.34102248243839E-03,
486
                'Wh' => 1.0,
487
                'wh' => 1.0,
488
                'flb' => 8.54294774062316E+04,
489
                'BTU' => 3.41213254164705E+00,
490
                'btu' => 3.41213254164705E+00,
491
            ],
492
            'wh' => [
493
                'J' => 3.59999820554720E+03,
494
                'e' => 3.59999647518369E+10,
495
                'c' => 8.60422069219046E+02,
496
                'cal' => 8.59845857713046E+02,
497
                'eV' => 2.24692340000000E+22,
498
                'ev' => 2.24692340000000E+22,
499
                'HPh' => 1.34102248243839E-03,
500
                'hh' => 1.34102248243839E-03,
501
                'Wh' => 1.0,
502
                'wh' => 1.0,
503
                'flb' => 8.54294774062316E+04,
504
                'BTU' => 3.41213254164705E+00,
505
                'btu' => 3.41213254164705E+00,
506
            ],
507
            'flb' => [
508
                'J' => 4.21400003236424E-02,
509
                'e' => 4.21399800687660E+05,
510
                'c' => 1.00717234301644E-02,
511
                'cal' => 1.00649785509554E-02,
512
                'eV' => 2.63015000000000E+17,
513
                'ev' => 2.63015000000000E+17,
514
                'HPh' => 1.56974211145130E-08,
515
                'hh' => 1.56974211145130E-08,
516
                'Wh' => 1.17055614802000E-05,
517
                'wh' => 1.17055614802000E-05,
518
                'flb' => 1.0,
519
                'BTU' => 3.99409272448406E-05,
520
                'btu' => 3.99409272448406E-05,
521
            ],
522
            'BTU' => [
523
                'J' => 1.05505813786749E+03,
524
                'e' => 1.05505763074665E+10,
525
                'c' => 2.52165488508168E+02,
526
                'cal' => 2.51996617135510E+02,
527
                'eV' => 6.58510000000000E+21,
528
                'ev' => 6.58510000000000E+21,
529
                'HPh' => 3.93015941224568E-04,
530
                'hh' => 3.93015941224568E-04,
531
                'Wh' => 2.93071851047526E-01,
532
                'wh' => 2.93071851047526E-01,
533
                'flb' => 2.50369750774671E+04,
534
                'BTU' => 1.0,
535
                'btu' => 1.0,
536
            ],
537
            'btu' => [
538
                'J' => 1.05505813786749E+03,
539
                'e' => 1.05505763074665E+10,
540
                'c' => 2.52165488508168E+02,
541
                'cal' => 2.51996617135510E+02,
542
                'eV' => 6.58510000000000E+21,
543
                'ev' => 6.58510000000000E+21,
544
                'HPh' => 3.93015941224568E-04,
545
                'hh' => 3.93015941224568E-04,
546
                'Wh' => 2.93071851047526E-01,
547
                'wh' => 2.93071851047526E-01,
548
                'flb' => 2.50369750774671E+04,
549
                'BTU' => 1.0,
550
                'btu' => 1.0,
551
            ],
552
        ],
553
        'Power' => [
554
            'HP' => [
555
                'HP' => 1.0,
556
                'h' => 1.0,
557
                'W' => 7.45701000000000E+02,
558
                'w' => 7.45701000000000E+02,
559
            ],
560
            'h' => [
561
                'HP' => 1.0,
562
                'h' => 1.0,
563
                'W' => 7.45701000000000E+02,
564
                'w' => 7.45701000000000E+02,
565
            ],
566
            'W' => [
567
                'HP' => 1.34102006031908E-03,
568
                'h' => 1.34102006031908E-03,
569
                'W' => 1.0,
570
                'w' => 1.0,
571
            ],
572
            'w' => [
573
                'HP' => 1.34102006031908E-03,
574
                'h' => 1.34102006031908E-03,
575
                'W' => 1.0,
576
                'w' => 1.0,
577
            ],
578
        ],
579
        'Magnetism' => [
580
            'T' => [
581
                'T' => 1.0,
582
                'ga' => 10000.0,
583
            ],
584
            'ga' => [
585
                'T' => 0.0001,
586
                'ga' => 1.0,
587
            ],
588
        ],
589
        'Liquid' => [
590
            'tsp' => [
591
                'tsp' => 1.0,
592
                'tbs' => 3.33333333333333E-01,
593
                'oz' => 1.66666666666667E-01,
594
                'cup' => 2.08333333333333E-02,
595
                'pt' => 1.04166666666667E-02,
596
                'us_pt' => 1.04166666666667E-02,
597
                'uk_pt' => 8.67558516821960E-03,
598
                'qt' => 5.20833333333333E-03,
599
                'gal' => 1.30208333333333E-03,
600
                'l' => 4.92999408400710E-03,
601
                'lt' => 4.92999408400710E-03,
602
            ],
603
            'tbs' => [
604
                'tsp' => 3.00000000000000E+00,
605
                'tbs' => 1.0,
606
                'oz' => 5.00000000000000E-01,
607
                'cup' => 6.25000000000000E-02,
608
                'pt' => 3.12500000000000E-02,
609
                'us_pt' => 3.12500000000000E-02,
610
                'uk_pt' => 2.60267555046588E-02,
611
                'qt' => 1.56250000000000E-02,
612
                'gal' => 3.90625000000000E-03,
613
                'l' => 1.47899822520213E-02,
614
                'lt' => 1.47899822520213E-02,
615
            ],
616
            'oz' => [
617
                'tsp' => 6.00000000000000E+00,
618
                'tbs' => 2.00000000000000E+00,
619
                'oz' => 1.0,
620
                'cup' => 1.25000000000000E-01,
621
                'pt' => 6.25000000000000E-02,
622
                'us_pt' => 6.25000000000000E-02,
623
                'uk_pt' => 5.20535110093176E-02,
624
                'qt' => 3.12500000000000E-02,
625
                'gal' => 7.81250000000000E-03,
626
                'l' => 2.95799645040426E-02,
627
                'lt' => 2.95799645040426E-02,
628
            ],
629
            'cup' => [
630
                'tsp' => 4.80000000000000E+01,
631
                'tbs' => 1.60000000000000E+01,
632
                'oz' => 8.00000000000000E+00,
633
                'cup' => 1.0,
634
                'pt' => 5.00000000000000E-01,
635
                'us_pt' => 5.00000000000000E-01,
636
                'uk_pt' => 4.16428088074541E-01,
637
                'qt' => 2.50000000000000E-01,
638
                'gal' => 6.25000000000000E-02,
639
                'l' => 2.36639716032341E-01,
640
                'lt' => 2.36639716032341E-01,
641
            ],
642
            'pt' => [
643
                'tsp' => 9.60000000000000E+01,
644
                'tbs' => 3.20000000000000E+01,
645
                'oz' => 1.60000000000000E+01,
646
                'cup' => 2.00000000000000E+00,
647
                'pt' => 1.0,
648
                'us_pt' => 1.0,
649
                'uk_pt' => 8.32856176149081E-01,
650
                'qt' => 5.00000000000000E-01,
651
                'gal' => 1.25000000000000E-01,
652
                'l' => 4.73279432064682E-01,
653
                'lt' => 4.73279432064682E-01,
654
            ],
655
            'us_pt' => [
656
                'tsp' => 9.60000000000000E+01,
657
                'tbs' => 3.20000000000000E+01,
658
                'oz' => 1.60000000000000E+01,
659
                'cup' => 2.00000000000000E+00,
660
                'pt' => 1.0,
661
                'us_pt' => 1.0,
662
                'uk_pt' => 8.32856176149081E-01,
663
                'qt' => 5.00000000000000E-01,
664
                'gal' => 1.25000000000000E-01,
665
                'l' => 4.73279432064682E-01,
666
                'lt' => 4.73279432064682E-01,
667
            ],
668
            'uk_pt' => [
669
                'tsp' => 1.15266000000000E+02,
670
                'tbs' => 3.84220000000000E+01,
671
                'oz' => 1.92110000000000E+01,
672
                'cup' => 2.40137500000000E+00,
673
                'pt' => 1.20068750000000E+00,
674
                'us_pt' => 1.20068750000000E+00,
675
                'uk_pt' => 1.0,
676
                'qt' => 6.00343750000000E-01,
677
                'gal' => 1.50085937500000E-01,
678
                'l' => 5.68260698087162E-01,
679
                'lt' => 5.68260698087162E-01,
680
            ],
681
            'qt' => [
682
                'tsp' => 1.92000000000000E+02,
683
                'tbs' => 6.40000000000000E+01,
684
                'oz' => 3.20000000000000E+01,
685
                'cup' => 4.00000000000000E+00,
686
                'pt' => 2.00000000000000E+00,
687
                'us_pt' => 2.00000000000000E+00,
688
                'uk_pt' => 1.66571235229816E+00,
689
                'qt' => 1.0,
690
                'gal' => 2.50000000000000E-01,
691
                'l' => 9.46558864129363E-01,
692
                'lt' => 9.46558864129363E-01,
693
            ],
694
            'gal' => [
695
                'tsp' => 7.68000000000000E+02,
696
                'tbs' => 2.56000000000000E+02,
697
                'oz' => 1.28000000000000E+02,
698
                'cup' => 1.60000000000000E+01,
699
                'pt' => 8.00000000000000E+00,
700
                'us_pt' => 8.00000000000000E+00,
701
                'uk_pt' => 6.66284940919265E+00,
702
                'qt' => 4.00000000000000E+00,
703
                'gal' => 1.0,
704
                'l' => 3.78623545651745E+00,
705
                'lt' => 3.78623545651745E+00,
706
            ],
707
            'l' => [
708
                'tsp' => 2.02840000000000E+02,
709
                'tbs' => 6.76133333333333E+01,
710
                'oz' => 3.38066666666667E+01,
711
                'cup' => 4.22583333333333E+00,
712
                'pt' => 2.11291666666667E+00,
713
                'us_pt' => 2.11291666666667E+00,
714
                'uk_pt' => 1.75975569552166E+00,
715
                'qt' => 1.05645833333333E+00,
716
                'gal' => 2.64114583333333E-01,
717
                'l' => 1.0,
718
                'lt' => 1.0,
719
            ],
720
            'lt' => [
721
                'tsp' => 2.02840000000000E+02,
722
                'tbs' => 6.76133333333333E+01,
723
                'oz' => 3.38066666666667E+01,
724
                'cup' => 4.22583333333333E+00,
725
                'pt' => 2.11291666666667E+00,
726
                'us_pt' => 2.11291666666667E+00,
727
                'uk_pt' => 1.75975569552166E+00,
728
                'qt' => 1.05645833333333E+00,
729
                'gal' => 2.64114583333333E-01,
730
                'l' => 1.0,
731
                'lt' => 1.0,
732
            ],
733
        ],
734
    ];
735
736
    /**
737
     * parseComplex
738
     *
739
     * Parses a complex number into its real and imaginary parts, and an I or J suffix
740
     *
741
     * @param    string $complexNumber The complex number
742
     * @return    string[]    Indexed on "real", "imaginary" and "suffix"
743
     */
744
    public static function parseComplex($complexNumber)
745 354
    {
746
        $workString = (string) $complexNumber;
747 354
748
        $realNumber = $imaginary = 0;
0 ignored issues
show
Unused Code introduced by
$realNumber is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
749 354
        //    Extract the suffix, if there is one
750
        $suffix = substr($workString, -1);
751 354
        if (!is_numeric($suffix)) {
752 354
            $workString = substr($workString, 0, -1);
753 289
        } else {
754
            $suffix = '';
755 142
        }
756
757
        //    Split the input into its Real and Imaginary components
758
        $leadingSign = 0;
759 354
        if (strlen($workString) > 0) {
760 354
            $leadingSign = (($workString{0} == '+') || ($workString{0} == '-')) ? 1 : 0;
761 345
        }
762
        $power = '';
763 354
        $realNumber = strtok($workString, '+-');
764 354
        if (strtoupper(substr($realNumber, -1)) == 'E') {
765 354
            $power = strtok('+-');
766 8
            ++$leadingSign;
767 8
        }
768
769
        $realNumber = substr($workString, 0, strlen($realNumber) + strlen($power) + $leadingSign);
770 354
771
        if ($suffix != '') {
772 354
            $imaginary = substr($workString, strlen($realNumber));
773 289
774
            if (($imaginary == '') && (($realNumber == '') || ($realNumber == '+') || ($realNumber == '-'))) {
775 289
                $imaginary = $realNumber . '1';
776 24
                $realNumber = '0';
777 24
            } elseif ($imaginary == '') {
778 269
                $imaginary = $realNumber;
779 30
                $realNumber = '0';
780 30
            } elseif (($imaginary == '+') || ($imaginary == '-')) {
781 243
                $imaginary .= '1';
782 96
            }
783
        }
784
785
        return [
786
            'real' => $realNumber,
787 354
            'imaginary' => $imaginary,
788 354
            'suffix' => $suffix,
789 354
        ];
790
    }
791
792
    /**
793
     * Cleans the leading characters in a complex number string
794
     *
795
     * @param    string $complexNumber The complex number to clean
796
     * @return    string        The "cleaned" complex number
797
     */
798
    private static function cleanComplex($complexNumber)
799
    {
800 38
        if ($complexNumber{0} == '+') {
801
            $complexNumber = substr($complexNumber, 1);
802 38
        }
803
        if ($complexNumber{0} == '0') {
804
            $complexNumber = substr($complexNumber, 1);
805 38
        }
806 4
        if ($complexNumber{0} == '.') {
807
            $complexNumber = '0' . $complexNumber;
808 38
        }
809 4
        if ($complexNumber{0} == '+') {
810
            $complexNumber = substr($complexNumber, 1);
811 38
        }
812
813
        return $complexNumber;
814 38
    }
815
816
    /**
817
     * Formats a number base string value with leading zeroes
818
     *
819
     * @param    string $xVal The "number" to pad
820
     * @param    int $places The length that we want to pad this value
821
     * @return    string        The padded "number"
822
     */
823
    private static function nbrConversionFormat($xVal, $places)
824 82
    {
825
        if (!is_null($places)) {
826 82
            if (is_numeric($places)) {
827 22
                $places = (int) $places;
828 18
            } else {
829
                return Functions::VALUE();
830 4
            }
831
            if ($places < 0) {
832 18
                return Functions::NAN();
833 4
            }
834
            if (strlen($xVal) <= $places) {
835 14
                return substr(str_pad($xVal, $places, '0', STR_PAD_LEFT), -10);
836 14
            } else {
837
                return Functions::NAN();
838
            }
839
        }
840
841
        return substr($xVal, -10);
842 60
    }
843
844
    /**
845
     *    BESSELI
846
     *
847
     *    Returns the modified Bessel function In(x), which is equivalent to the Bessel function evaluated
848
     *        for purely imaginary arguments
849
     *
850
     *    Excel Function:
851
     *        BESSELI(x,ord)
852
     *
853
     * @category Engineering Functions
854
     * @param    float $x The value at which to evaluate the function.
855
     *                                If x is nonnumeric, BESSELI returns the #VALUE! error value.
856
     * @param    int $ord The order of the Bessel function.
857
     *                                If ord is not an integer, it is truncated.
858
     *                                If $ord is nonnumeric, BESSELI returns the #VALUE! error value.
859
     *                                If $ord < 0, BESSELI returns the #NUM! error value.
860
     * @return    float
861
     */
862
    public static function BESSELI($x, $ord)
863
    {
864
        $x = (is_null($x)) ? 0.0 : Functions::flattenSingleValue($x);
865 74
        $ord = (is_null($ord)) ? 0.0 : Functions::flattenSingleValue($ord);
866
867 74
        if ((is_numeric($x)) && (is_numeric($ord))) {
868 74
            $ord = floor($ord);
869
            if ($ord < 0) {
870 74
                return Functions::NAN();
871 70
            }
872 70
873 2
            if (abs($x) <= 30) {
874
                $fResult = $fTerm = pow($x / 2, $ord) / MathTrig::FACT($ord);
875
                $ordK = 1;
876 68
                $fSqrX = ($x * $x) / 4;
877 68 View Code Duplication
                do {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
878 68
                    $fTerm *= $fSqrX;
879 68
                    $fTerm /= ($ordK * ($ordK + $ord));
880
                    $fResult += $fTerm;
881 68
                } while ((abs($fTerm) > 1e-12) && (++$ordK < 100));
882 68
            } else {
883 68
                $f_2_PI = 2 * M_PI;
884 68
885
                $fXAbs = abs($x);
886
                $fResult = exp($fXAbs) / sqrt($f_2_PI * $fXAbs);
887
                if (($ord & 1) && ($x < 0)) {
888
                    $fResult = -$fResult;
889
                }
890
            }
891
892
            return (is_nan($fResult)) ? Functions::NAN() : $fResult;
893
        }
894 68
895
        return Functions::VALUE();
896 4
    }
897
898
    /**
899
     *    BESSELJ
900
     *
901
     *    Returns the Bessel function
902
     *
903
     *    Excel Function:
904
     *        BESSELJ(x,ord)
905
     *
906
     * @category Engineering Functions
907
     * @param    float $x The value at which to evaluate the function.
908
     *                                If x is nonnumeric, BESSELJ returns the #VALUE! error value.
909
     * @param    int $ord The order of the Bessel function. If n is not an integer, it is truncated.
910
     *                                If $ord is nonnumeric, BESSELJ returns the #VALUE! error value.
911
     *                                If $ord < 0, BESSELJ returns the #NUM! error value.
912
     * @return    float
913
     */
914
    public static function BESSELJ($x, $ord)
915
    {
916
        $x = (is_null($x)) ? 0.0 : Functions::flattenSingleValue($x);
917
        $ord = (is_null($ord)) ? 0.0 : Functions::flattenSingleValue($ord);
918 50
919
        if ((is_numeric($x)) && (is_numeric($ord))) {
920 50
            $ord = floor($ord);
921 50
            if ($ord < 0) {
922
                return Functions::NAN();
923 50
            }
924 48
925 48
            $fResult = 0;
0 ignored issues
show
Unused Code introduced by
$fResult is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
926 1
            if (abs($x) <= 30) {
927
                $fResult = $fTerm = pow($x / 2, $ord) / MathTrig::FACT($ord);
928
                $ordK = 1;
929 47
                $fSqrX = ($x * $x) / -4;
930 47 View Code Duplication
                do {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
931 47
                    $fTerm *= $fSqrX;
932 47
                    $fTerm /= ($ordK * ($ordK + $ord));
933 47
                    $fResult += $fTerm;
934
                } while ((abs($fTerm) > 1e-12) && (++$ordK < 100));
935 47
            } else {
936 47
                $f_PI_DIV_2 = M_PI / 2;
937 47
                $f_PI_DIV_4 = M_PI / 4;
938 47
939
                $fXAbs = abs($x);
940
                $fResult = sqrt(M_2DIVPI / $fXAbs) * cos($fXAbs - $ord * $f_PI_DIV_2 - $f_PI_DIV_4);
941
                if (($ord & 1) && ($x < 0)) {
942
                    $fResult = -$fResult;
943
                }
944
            }
945
946
            return (is_nan($fResult)) ? Functions::NAN() : $fResult;
947
        }
948
949 47
        return Functions::VALUE();
950
    }
951 2
952
    private static function besselK0($fNum)
953
    {
954
        if ($fNum <= 2) {
955 22
            $fNum2 = $fNum * 0.5;
956
            $y = ($fNum2 * $fNum2);
957 22
            $fRet = -log($fNum2) * self::BESSELI($fNum, 0) +
958 14
                (-0.57721566 + $y * (0.42278420 + $y * (0.23069756 + $y * (0.3488590e-1 + $y * (0.262698e-2 + $y *
959 14
                                    (0.10750e-3 + $y * 0.74e-5))))));
960 14 View Code Duplication
        } else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
961
            $y = 2 / $fNum;
962 14
            $fRet = exp(-$fNum) / sqrt($fNum) *
963
                (1.25331414 + $y * (-0.7832358e-1 + $y * (0.2189568e-1 + $y * (-0.1062446e-1 + $y *
964 8
                                (0.587872e-2 + $y * (-0.251540e-2 + $y * 0.53208e-3))))));
965 8
        }
966
967 8
        return $fRet;
968
    }
969 22
970
    private static function besselK1($fNum)
971
    {
972
        if ($fNum <= 2) {
973 30
            $fNum2 = $fNum * 0.5;
974
            $y = ($fNum2 * $fNum2);
975 30
            $fRet = log($fNum2) * self::BESSELI($fNum, 1) +
976 17
                (1 + $y * (0.15443144 + $y * (-0.67278579 + $y * (-0.18156897 + $y * (-0.1919402e-1 + $y *
977 17
                                    (-0.110404e-2 + $y * (-0.4686e-4))))))) / $fNum;
978 17 View Code Duplication
        } else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
979
            $y = 2 / $fNum;
980 17
            $fRet = exp(-$fNum) / sqrt($fNum) *
981
                (1.25331414 + $y * (0.23498619 + $y * (-0.3655620e-1 + $y * (0.1504268e-1 + $y * (-0.780353e-2 + $y *
982 13
                                    (0.325614e-2 + $y * (-0.68245e-3)))))));
983 13
        }
984
985 13
        return $fRet;
986
    }
987 30
988
    /**
989
     *    BESSELK
990
     *
991
     *    Returns the modified Bessel function Kn(x), which is equivalent to the Bessel functions evaluated
992
     *        for purely imaginary arguments.
993
     *
994
     *    Excel Function:
995
     *        BESSELK(x,ord)
996
     *
997
     * @category Engineering Functions
998
     * @param    float $x The value at which to evaluate the function.
999
     *                                If x is nonnumeric, BESSELK returns the #VALUE! error value.
1000
     * @param    int $ord The order of the Bessel function. If n is not an integer, it is truncated.
1001
     *                                If $ord is nonnumeric, BESSELK returns the #VALUE! error value.
1002
     *                                If $ord < 0, BESSELK returns the #NUM! error value.
1003
     * @return    float
1004
     */
1005 View Code Duplication
    public static function BESSELK($x, $ord)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1006
    {
1007
        $x = (is_null($x)) ? 0.0 : Functions::flattenSingleValue($x);
1008
        $ord = (is_null($ord)) ? 0.0 : Functions::flattenSingleValue($ord);
1009
1010 38
        if ((is_numeric($x)) && (is_numeric($ord))) {
1011
            if (($ord < 0) || ($x == 0.0)) {
1012 38
                return Functions::NAN();
1013 38
            }
1014
1015 38
            switch (floor($ord)) {
1016 36
                case 0:
1017 4
                    $fBk = self::besselK0($x);
1018
                    break;
1019
                case 1:
1020 32
                    $fBk = self::besselK1($x);
1021 32
                    break;
1022 2
                default:
1023 2
                    $fTox = 2 / $x;
1024 30
                    $fBkm = self::besselK0($x);
1025 10
                    $fBk = self::besselK1($x);
1026 10
                    for ($n = 1; $n < $ord; ++$n) {
1027
                        $fBkp = $fBkm + $n * $fTox * $fBk;
1028 20
                        $fBkm = $fBk;
1029 20
                        $fBk = $fBkp;
1030 20
                    }
1031 20
            }
1032 20
1033 20
            return (is_nan($fBk)) ? Functions::NAN() : $fBk;
1034 20
        }
1035
1036
        return Functions::VALUE();
1037 32
    }
1038
1039 2
    private static function besselY0($fNum)
1040
    {
1041
        if ($fNum < 8.0) {
1042
            $y = ($fNum * $fNum);
1043 11
            $f1 = -2957821389.0 + $y * (7062834065.0 + $y * (-512359803.6 + $y * (10879881.29 + $y * (-86327.92757 + $y * 228.4622733))));
1044
            $f2 = 40076544269.0 + $y * (745249964.8 + $y * (7189466.438 + $y * (47447.26470 + $y * (226.1030244 + $y))));
1045 11
            $fRet = $f1 / $f2 + 0.636619772 * self::BESSELJ($fNum, 0) * log($fNum);
1046 10
        } else {
1047 10
            $z = 8.0 / $fNum;
1048 10
            $y = ($z * $z);
1049 10
            $xx = $fNum - 0.785398164;
1050
            $f1 = 1 + $y * (-0.1098628627e-2 + $y * (0.2734510407e-4 + $y * (-0.2073370639e-5 + $y * 0.2093887211e-6)));
1051 1
            $f2 = -0.1562499995e-1 + $y * (0.1430488765e-3 + $y * (-0.6911147651e-5 + $y * (0.7621095161e-6 + $y * (-0.934945152e-7))));
1052 1
            $fRet = sqrt(0.636619772 / $fNum) * (sin($xx) * $f1 + $z * cos($xx) * $f2);
1053 1
        }
1054 1
1055 1
        return $fRet;
1056 1
    }
1057
1058 11
    private static function besselY1($fNum)
1059
    {
1060
        if ($fNum < 8.0) {
1061
            $y = ($fNum * $fNum);
1062 16
            $f1 = $fNum * (-0.4900604943e13 + $y * (0.1275274390e13 + $y * (-0.5153438139e11 + $y * (0.7349264551e9 + $y *
1063
                                (-0.4237922726e7 + $y * 0.8511937935e4)))));
1064 16
            $f2 = 0.2499580570e14 + $y * (0.4244419664e12 + $y * (0.3733650367e10 + $y * (0.2245904002e8 + $y *
1065 16
                            (0.1020426050e6 + $y * (0.3549632885e3 + $y)))));
1066
            $fRet = $f1 / $f2 + 0.636619772 * (self::BESSELJ($fNum, 1) * log($fNum) - 1 / $fNum);
1067 16
        } else {
1068
            $fRet = sqrt(0.636619772 / $fNum) * sin($fNum - 2.356194491);
1069 16
        }
1070 16
1071
        return $fRet;
1072
    }
1073
1074 16
    /**
1075
     *    BESSELY
1076
     *
1077
     *    Returns the Bessel function, which is also called the Weber function or the Neumann function.
1078
     *
1079
     *    Excel Function:
1080
     *        BESSELY(x,ord)
1081
     *
1082
     * @category Engineering Functions
1083
     * @param    float $x The value at which to evaluate the function.
1084
     *                                If x is nonnumeric, BESSELK returns the #VALUE! error value.
1085
     * @param    int $ord The order of the Bessel function. If n is not an integer, it is truncated.
1086
     *                                If $ord is nonnumeric, BESSELK returns the #VALUE! error value.
1087
     *                                If $ord < 0, BESSELK returns the #NUM! error value.
1088
     *
1089
     * @return    float
1090
     */
1091 View Code Duplication
    public static function BESSELY($x, $ord)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1092
    {
1093
        $x = (is_null($x)) ? 0.0 : Functions::flattenSingleValue($x);
1094
        $ord = (is_null($ord)) ? 0.0 : Functions::flattenSingleValue($ord);
1095
1096 23
        if ((is_numeric($x)) && (is_numeric($ord))) {
1097
            if (($ord < 0) || ($x == 0.0)) {
1098 23
                return Functions::NAN();
1099 23
            }
1100
1101 23
            switch (floor($ord)) {
1102 21
                case 0:
1103 3
                    $fBy = self::besselY0($x);
1104
                    break;
1105
                case 1:
1106 18
                    $fBy = self::besselY1($x);
1107 18
                    break;
1108 2
                default:
1109 2
                    $fTox = 2 / $x;
1110 16
                    $fBym = self::besselY0($x);
1111 7
                    $fBy = self::besselY1($x);
1112 7
                    for ($n = 1; $n < $ord; ++$n) {
1113
                        $fByp = $n * $fTox * $fBy - $fBym;
1114 9
                        $fBym = $fBy;
1115 9
                        $fBy = $fByp;
1116 9
                    }
1117 9
            }
1118 9
1119 9
            return (is_nan($fBy)) ? Functions::NAN() : $fBy;
1120 9
        }
1121
1122
        return Functions::VALUE();
1123 18
    }
1124
1125 2
    /**
1126
     * BINTODEC
1127
     *
1128
     * Return a binary value as decimal.
1129
     *
1130
     * Excel Function:
1131
     *        BIN2DEC(x)
1132
     *
1133
     * @category Engineering Functions
1134
     * @param    string $x The binary number (as a string) that you want to convert. The number
1135
     *                                cannot contain more than 10 characters (10 bits). The most significant
1136
     *                                bit of number is the sign bit. The remaining 9 bits are magnitude bits.
1137
     *                                Negative numbers are represented using two's-complement notation.
1138
     *                                If number is not a valid binary number, or if number contains more than
1139
     *                                10 characters (10 bits), BIN2DEC returns the #NUM! error value.
1140
     * @return    string
1141
     */
1142
    public static function BINTODEC($x)
1143
    {
1144
        $x = Functions::flattenSingleValue($x);
1145
1146
        if (is_bool($x)) {
1147 10
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
1148
                $x = (int) $x;
1149 10
            } else {
1150
                return Functions::VALUE();
1151 10
            }
1152 1
        }
1153
        if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) {
1154
            $x = floor($x);
1155 1
        }
1156
        $x = (string) $x;
1157
        if (strlen($x) > preg_match_all('/[01]/', $x, $out)) {
1158 9
            return Functions::NAN();
1159
        }
1160
        if (strlen($x) > 10) {
1161 9
            return Functions::NAN();
1162 9
        } elseif (strlen($x) == 10) {
1163 1
            //    Two's Complement
1164
            $x = substr($x, -9);
1165 8
1166 1
            return '-' . (512 - bindec($x));
1167 7
        }
1168
1169 2
        return bindec($x);
1170 2
    }
1171
1172 5
    /**
1173
     * BINTOHEX
1174
     *
1175
     * Return a binary value as hex.
1176
     *
1177
     * Excel Function:
1178
     *        BIN2HEX(x[,places])
1179
     *
1180
     * @category Engineering Functions
1181
     * @param    string $x The binary number (as a string) that you want to convert. The number
1182
     *                                cannot contain more than 10 characters (10 bits). The most significant
1183
     *                                bit of number is the sign bit. The remaining 9 bits are magnitude bits.
1184
     *                                Negative numbers are represented using two's-complement notation.
1185
     *                                If number is not a valid binary number, or if number contains more than
1186
     *                                10 characters (10 bits), BIN2HEX returns the #NUM! error value.
1187
     * @param    int $places The number of characters to use. If places is omitted, BIN2HEX uses the
1188
     *                                minimum number of characters necessary. Places is useful for padding the
1189
     *                                return value with leading 0s (zeros).
1190
     *                                If places is not an integer, it is truncated.
1191
     *                                If places is nonnumeric, BIN2HEX returns the #VALUE! error value.
1192
     *                                If places is negative, BIN2HEX returns the #NUM! error value.
1193
     * @return    string
1194
     */
1195 View Code Duplication
    public static function BINTOHEX($x, $places = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1196
    {
1197
        $x = Functions::flattenSingleValue($x);
1198
        $places = Functions::flattenSingleValue($places);
1199
1200 14
        // Argument X
1201
        if (is_bool($x)) {
1202 14
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
1203 14
                $x = (int) $x;
1204
            } else {
1205
                return Functions::VALUE();
1206 14
            }
1207 1
        }
1208
        if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) {
1209
            $x = floor($x);
1210 1
        }
1211
        $x = (string) $x;
1212
        if (strlen($x) > preg_match_all('/[01]/', $x, $out)) {
1213 13
            return Functions::NAN();
1214
        }
1215
        if (strlen($x) > 10) {
1216 13
            return Functions::NAN();
1217 13
        } elseif (strlen($x) == 10) {
1218 1
            //    Two's Complement
1219
            return str_repeat('F', 8) . substr(strtoupper(dechex(bindec(substr($x, -9)))), -2);
1220 12
        }
1221 1
        $hexVal = (string) strtoupper(dechex(bindec($x)));
1222 11
1223
        return self::nbrConversionFormat($hexVal, $places);
1224 2
    }
1225
1226 9
    /**
1227
     * BINTOOCT
1228 9
     *
1229
     * Return a binary value as octal.
1230
     *
1231
     * Excel Function:
1232
     *        BIN2OCT(x[,places])
1233
     *
1234
     * @category Engineering Functions
1235
     * @param    string $x The binary number (as a string) that you want to convert. The number
1236
     *                                cannot contain more than 10 characters (10 bits). The most significant
1237
     *                                bit of number is the sign bit. The remaining 9 bits are magnitude bits.
1238
     *                                Negative numbers are represented using two's-complement notation.
1239
     *                                If number is not a valid binary number, or if number contains more than
1240
     *                                10 characters (10 bits), BIN2OCT returns the #NUM! error value.
1241
     * @param    int $places The number of characters to use. If places is omitted, BIN2OCT uses the
1242
     *                                minimum number of characters necessary. Places is useful for padding the
1243
     *                                return value with leading 0s (zeros).
1244
     *                                If places is not an integer, it is truncated.
1245
     *                                If places is nonnumeric, BIN2OCT returns the #VALUE! error value.
1246
     *                                If places is negative, BIN2OCT returns the #NUM! error value.
1247
     * @return    string
1248
     */
1249 View Code Duplication
    public static function BINTOOCT($x, $places = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1250
    {
1251
        $x = Functions::flattenSingleValue($x);
1252
        $places = Functions::flattenSingleValue($places);
1253
1254
        if (is_bool($x)) {
1255
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
1256 15
                $x = (int) $x;
1257
            } else {
1258 15
                return Functions::VALUE();
1259 15
            }
1260
        }
1261 15
        if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) {
1262 1
            $x = floor($x);
1263
        }
1264
        $x = (string) $x;
1265 1
        if (strlen($x) > preg_match_all('/[01]/', $x, $out)) {
1266
            return Functions::NAN();
1267
        }
1268 14
        if (strlen($x) > 10) {
1269
            return Functions::NAN();
1270
        } elseif (strlen($x) == 10) {
1271 14
            //    Two's Complement
1272 14
            return str_repeat('7', 7) . substr(strtoupper(decoct(bindec(substr($x, -9)))), -3);
1273 1
        }
1274
        $octVal = (string) decoct(bindec($x));
1275 13
1276 1
        return self::nbrConversionFormat($octVal, $places);
1277 12
    }
1278
1279 2
    /**
1280
     * DECTOBIN
1281 10
     *
1282
     * Return a decimal value as binary.
1283 10
     *
1284
     * Excel Function:
1285
     *        DEC2BIN(x[,places])
1286
     *
1287
     * @category Engineering Functions
1288
     * @param    string $x The decimal integer you want to convert. If number is negative,
1289
     *                                valid place values are ignored and DEC2BIN returns a 10-character
1290
     *                                (10-bit) binary number in which the most significant bit is the sign
1291
     *                                bit. The remaining 9 bits are magnitude bits. Negative numbers are
1292
     *                                represented using two's-complement notation.
1293
     *                                If number < -512 or if number > 511, DEC2BIN returns the #NUM! error
1294
     *                                value.
1295
     *                                If number is nonnumeric, DEC2BIN returns the #VALUE! error value.
1296
     *                                If DEC2BIN requires more than places characters, it returns the #NUM!
1297
     *                                error value.
1298
     * @param    int $places The number of characters to use. If places is omitted, DEC2BIN uses
1299
     *                                the minimum number of characters necessary. Places is useful for
1300
     *                                padding the return value with leading 0s (zeros).
1301
     *                                If places is not an integer, it is truncated.
1302
     *                                If places is nonnumeric, DEC2BIN returns the #VALUE! error value.
1303
     *                                If places is zero or negative, DEC2BIN returns the #NUM! error value.
1304
     * @return    string
1305
     */
1306
    public static function DECTOBIN($x, $places = null)
1307
    {
1308
        $x = Functions::flattenSingleValue($x);
1309
        $places = Functions::flattenSingleValue($places);
1310
1311
        if (is_bool($x)) {
1312
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
1313
                $x = (int) $x;
1314
            } else {
1315 41
                return Functions::VALUE();
1316
            }
1317 41
        }
1318 41
        $x = (string) $x;
1319
        if (strlen($x) > preg_match_all('/[-0123456789.]/', $x, $out)) {
1320 41
            return Functions::VALUE();
1321 1
        }
1322
1323
        $x = (string) floor($x);
1324 1
        if ($x < -512 || $x > 511) {
1325
            return Functions::NAN();
1326
        }
1327 40
1328 40
        $r = decbin($x);
1329 1
        // Two's Complement
1330
        $r = substr($r, -10);
1331
        if (strlen($r) >= 11) {
1332 39
            return Functions::NAN();
1333 39
        }
1334 13
1335
        return self::nbrConversionFormat($r, $places);
1336
    }
1337 26
1338
    /**
1339 26
     * DECTOHEX
1340 26
     *
1341
     * Return a decimal value as hex.
1342
     *
1343
     * Excel Function:
1344 26
     *        DEC2HEX(x[,places])
1345
     *
1346
     * @category Engineering Functions
1347
     * @param    string $x The decimal integer you want to convert. If number is negative,
1348
     *                                places is ignored and DEC2HEX returns a 10-character (40-bit)
1349
     *                                hexadecimal number in which the most significant bit is the sign
1350
     *                                bit. The remaining 39 bits are magnitude bits. Negative numbers
1351
     *                                are represented using two's-complement notation.
1352
     *                                If number < -549,755,813,888 or if number > 549,755,813,887,
1353
     *                                DEC2HEX returns the #NUM! error value.
1354
     *                                If number is nonnumeric, DEC2HEX returns the #VALUE! error value.
1355
     *                                If DEC2HEX requires more than places characters, it returns the
1356
     *                                #NUM! error value.
1357
     * @param    int $places The number of characters to use. If places is omitted, DEC2HEX uses
1358
     *                                the minimum number of characters necessary. Places is useful for
1359
     *                                padding the return value with leading 0s (zeros).
1360
     *                                If places is not an integer, it is truncated.
1361
     *                                If places is nonnumeric, DEC2HEX returns the #VALUE! error value.
1362
     *                                If places is zero or negative, DEC2HEX returns the #NUM! error value.
1363
     * @return    string
1364
     */
1365 View Code Duplication
    public static function DECTOHEX($x, $places = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1366
    {
1367
        $x = Functions::flattenSingleValue($x);
1368
        $places = Functions::flattenSingleValue($places);
1369
1370
        if (is_bool($x)) {
1371
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
1372
                $x = (int) $x;
1373
            } else {
1374
                return Functions::VALUE();
1375
            }
1376 15
        }
1377
        $x = (string) $x;
1378 15
        if (strlen($x) > preg_match_all('/[-0123456789.]/', $x, $out)) {
1379 15
            return Functions::VALUE();
1380
        }
1381 15
        $x = (string) floor($x);
1382 1
        $r = strtoupper(dechex($x));
1383
        if (strlen($r) == 8) {
1384
            //    Two's Complement
1385 1
            $r = 'FF' . $r;
1386
        }
1387
1388 14
        return self::nbrConversionFormat($r, $places);
1389 14
    }
1390 1
1391
    /**
1392 13
     * DECTOOCT
1393 13
     *
1394 13
     * Return an decimal value as octal.
1395
     *
1396
     * Excel Function:
1397
     *        DEC2OCT(x[,places])
1398
     *
1399 13
     * @category Engineering Functions
1400
     * @param    string $x The decimal integer you want to convert. If number is negative,
1401
     *                                places is ignored and DEC2OCT returns a 10-character (30-bit)
1402
     *                                octal number in which the most significant bit is the sign bit.
1403
     *                                The remaining 29 bits are magnitude bits. Negative numbers are
1404
     *                                represented using two's-complement notation.
1405
     *                                If number < -536,870,912 or if number > 536,870,911, DEC2OCT
1406
     *                                returns the #NUM! error value.
1407
     *                                If number is nonnumeric, DEC2OCT returns the #VALUE! error value.
1408
     *                                If DEC2OCT requires more than places characters, it returns the
1409
     *                                #NUM! error value.
1410
     * @param    int $places The number of characters to use. If places is omitted, DEC2OCT uses
1411
     *                                the minimum number of characters necessary. Places is useful for
1412
     *                                padding the return value with leading 0s (zeros).
1413
     *                                If places is not an integer, it is truncated.
1414
     *                                If places is nonnumeric, DEC2OCT returns the #VALUE! error value.
1415
     *                                If places is zero or negative, DEC2OCT returns the #NUM! error value.
1416
     * @return    string
1417
     */
1418 View Code Duplication
    public static function DECTOOCT($x, $places = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1419
    {
1420
        $xorig = $x;
0 ignored issues
show
Unused Code introduced by
$xorig is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1421
        $x = Functions::flattenSingleValue($x);
1422
        $places = Functions::flattenSingleValue($places);
1423
1424
        if (is_bool($x)) {
1425
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
1426
                $x = (int) $x;
1427
            } else {
1428
                return Functions::VALUE();
1429
            }
1430
        }
1431 20
        $x = (string) $x;
1432
        if (strlen($x) > preg_match_all('/[-0123456789.]/', $x, $out)) {
1433 20
            return Functions::VALUE();
1434 20
        }
1435 20
        $x = (string) floor($x);
1436
        $r = decoct($x);
1437 20
        if (strlen($r) == 11) {
1438 1
            //    Two's Complement
1439
            $r = substr($r, -10);
1440
        }
1441 1
1442
        return self::nbrConversionFormat($r, $places);
1443
    }
1444 19
1445 19
    /**
1446 1
     * HEXTOBIN
1447
     *
1448 18
     * Return a hex value as binary.
1449 18
     *
1450 18
     * Excel Function:
1451
     *        HEX2BIN(x[,places])
1452
     *
1453
     * @category Engineering Functions
1454
     * @param    string $x the hexadecimal number you want to convert.
1455 18
     *                  Number cannot contain more than 10 characters.
1456
     *                  The most significant bit of number is the sign bit (40th bit from the right).
1457
     *                  The remaining 9 bits are magnitude bits.
1458
     *                  Negative numbers are represented using two's-complement notation.
1459
     *                  If number is negative, HEX2BIN ignores places and returns a 10-character binary number.
1460
     *                  If number is negative, it cannot be less than FFFFFFFE00,
1461
     *                      and if number is positive, it cannot be greater than 1FF.
1462
     *                  If number is not a valid hexadecimal number, HEX2BIN returns the #NUM! error value.
1463
     *                  If HEX2BIN requires more than places characters, it returns the #NUM! error value.
1464
     * @param    int $places The number of characters to use. If places is omitted,
1465
     *                                    HEX2BIN uses the minimum number of characters necessary. Places
1466
     *                                    is useful for padding the return value with leading 0s (zeros).
1467
     *                                    If places is not an integer, it is truncated.
1468
     *                                    If places is nonnumeric, HEX2BIN returns the #VALUE! error value.
1469
     *                                    If places is negative, HEX2BIN returns the #NUM! error value.
1470
     * @return    string
1471
     */
1472 View Code Duplication
    public static function HEXTOBIN($x, $places = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1473
    {
1474
        $x = Functions::flattenSingleValue($x);
1475
        $places = Functions::flattenSingleValue($places);
1476
1477
        if (is_bool($x)) {
1478
            return Functions::VALUE();
1479
        }
1480
        $x = (string) $x;
1481
        if (strlen($x) > preg_match_all('/[0123456789ABCDEF]/', strtoupper($x), $out)) {
1482
            return Functions::NAN();
1483
        }
1484
1485
        return self::DECTOBIN(self::HEXTODEC($x), $places);
1486
    }
1487 16
1488
    /**
1489 16
     * HEXTODEC
1490 16
     *
1491
     * Return a hex value as decimal.
1492 16
     *
1493 1
     * Excel Function:
1494
     *        HEX2DEC(x)
1495 15
     *
1496 15
     * @category Engineering Functions
1497 2
     * @param    string $x The hexadecimal number you want to convert. This number cannot
1498
     *                                contain more than 10 characters (40 bits). The most significant
1499
     *                                bit of number is the sign bit. The remaining 39 bits are magnitude
1500 13
     *                                bits. Negative numbers are represented using two's-complement
1501
     *                                notation.
1502
     *                                If number is not a valid hexadecimal number, HEX2DEC returns the
1503
     *                                #NUM! error value.
1504
     * @return    string
1505
     */
1506
    public static function HEXTODEC($x)
1507
    {
1508
        $x = Functions::flattenSingleValue($x);
1509
1510
        if (is_bool($x)) {
1511
            return Functions::VALUE();
1512
        }
1513
        $x = (string) $x;
1514
        if (strlen($x) > preg_match_all('/[0123456789ABCDEF]/', strtoupper($x), $out)) {
1515
            return Functions::NAN();
1516
        }
1517
1518
        if (strlen($x) > 10) {
1519
            return Functions::NAN();
1520
        }
1521
1522
        $binX = '';
1523 37 View Code Duplication
        foreach (str_split($x) as $char) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1524
            $binX .= str_pad(base_convert($char, 16, 2), 4, '0', STR_PAD_LEFT);
1525 37
        }
1526 View Code Duplication
        if (strlen($binX) == 40 && $binX[0] == '1') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1527 37
            for ($i = 0; $i < 40; ++$i) {
1528 1
                $binX[$i] = ($binX[$i] == '1' ? '0' : '1');
1529
            }
1530 36
1531 36
            return (bindec($binX) + 1) * -1;
1532 3
        }
1533
1534
        return bindec($binX);
1535 33
    }
1536 1
1537
    /**
1538
     * HEXTOOCT
1539 32
     *
1540 32
     * Return a hex value as octal.
1541 32
     *
1542
     * Excel Function:
1543 32
     *        HEX2OCT(x[,places])
1544 5
     *
1545 5
     * @category Engineering Functions
1546
     * @param    string $x The hexadecimal number you want to convert. Number cannot
1547 5
     *                                    contain more than 10 characters. The most significant bit of
1548
     *                                    number is the sign bit. The remaining 39 bits are magnitude
1549 27
     *                                    bits. Negative numbers are represented using two's-complement
1550
     *                                    notation.
1551
     *                                    If number is negative, HEX2OCT ignores places and returns a
1552
     *                                    10-character octal number.
1553
     *                                    If number is negative, it cannot be less than FFE0000000, and
1554
     *                                    if number is positive, it cannot be greater than 1FFFFFFF.
1555
     *                                    If number is not a valid hexadecimal number, HEX2OCT returns
1556
     *                                    the #NUM! error value.
1557
     *                                    If HEX2OCT requires more than places characters, it returns
1558
     *                                    the #NUM! error value.
1559
     * @param    int $places The number of characters to use. If places is omitted, HEX2OCT
1560
     *                                    uses the minimum number of characters necessary. Places is
1561
     *                                    useful for padding the return value with leading 0s (zeros).
1562
     *                                    If places is not an integer, it is truncated.
1563
     *                                    If places is nonnumeric, HEX2OCT returns the #VALUE! error
1564
     *                                    value.
1565
     *                                    If places is negative, HEX2OCT returns the #NUM! error value.
1566
     * @return    string
1567
     */
1568
    public static function HEXTOOCT($x, $places = null)
1569
    {
1570
        $x = Functions::flattenSingleValue($x);
1571
        $places = Functions::flattenSingleValue($places);
1572
1573
        if (is_bool($x)) {
1574
            return Functions::VALUE();
1575
        }
1576
        $x = (string) $x;
1577
        if (strlen($x) > preg_match_all('/[0123456789ABCDEF]/', strtoupper($x), $out)) {
1578
            return Functions::NAN();
1579
        }
1580
1581
        $decimal = self::HEXTODEC($x);
1582
        if ($decimal < -536870912 || $decimal > 536870911) {
1583
            return Functions::NAN();
1584
        }
1585 13
1586
        return self::DECTOOCT($decimal, $places);
1587 13
    }
1588 13
1589
    /**
1590 13
     * OCTTOBIN
1591 1
     *
1592
     * Return an octal value as binary.
1593 12
     *
1594 12
     * Excel Function:
1595 3
     *        OCT2BIN(x[,places])
1596
     *
1597
     * @category Engineering Functions
1598 9
     * @param    string $x The octal number you want to convert. Number may not
1599 9
     *                                    contain more than 10 characters. The most significant
1600 1
     *                                    bit of number is the sign bit. The remaining 29 bits
1601
     *                                    are magnitude bits. Negative numbers are represented
1602
     *                                    using two's-complement notation.
1603 8
     *                                    If number is negative, OCT2BIN ignores places and returns
1604
     *                                    a 10-character binary number.
1605
     *                                    If number is negative, it cannot be less than 7777777000,
1606
     *                                    and if number is positive, it cannot be greater than 777.
1607
     *                                    If number is not a valid octal number, OCT2BIN returns
1608
     *                                    the #NUM! error value.
1609
     *                                    If OCT2BIN requires more than places characters, it
1610
     *                                    returns the #NUM! error value.
1611
     * @param    int $places The number of characters to use. If places is omitted,
1612
     *                                    OCT2BIN uses the minimum number of characters necessary.
1613
     *                                    Places is useful for padding the return value with
1614
     *                                    leading 0s (zeros).
1615
     *                                    If places is not an integer, it is truncated.
1616
     *                                    If places is nonnumeric, OCT2BIN returns the #VALUE!
1617
     *                                    error value.
1618
     *                                    If places is negative, OCT2BIN returns the #NUM! error
1619
     *                                    value.
1620
     * @return    string
1621
     */
1622 View Code Duplication
    public static function OCTTOBIN($x, $places = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1623
    {
1624
        $x = Functions::flattenSingleValue($x);
1625
        $places = Functions::flattenSingleValue($places);
1626
1627
        if (is_bool($x)) {
1628
            return Functions::VALUE();
1629
        }
1630
        $x = (string) $x;
1631
        if (preg_match_all('/[01234567]/', $x, $out) != strlen($x)) {
1632
            return Functions::NAN();
1633
        }
1634
1635
        return self::DECTOBIN(self::OCTTODEC($x), $places);
1636
    }
1637
1638
    /**
1639
     * OCTTODEC
1640 13
     *
1641
     * Return an octal value as decimal.
1642 13
     *
1643 13
     * Excel Function:
1644
     *        OCT2DEC(x)
1645 13
     *
1646 1
     * @category Engineering Functions
1647
     * @param    string $x The octal number you want to convert. Number may not contain
1648 12
     *                                more than 10 octal characters (30 bits). The most significant
1649 12
     *                                bit of number is the sign bit. The remaining 29 bits are
1650 2
     *                                magnitude bits. Negative numbers are represented using
1651
     *                                two's-complement notation.
1652
     *                                If number is not a valid octal number, OCT2DEC returns the
1653 10
     *                                #NUM! error value.
1654
     * @return    string
1655
     */
1656
    public static function OCTTODEC($x)
1657
    {
1658
        $x = Functions::flattenSingleValue($x);
1659
1660
        if (is_bool($x)) {
1661
            return Functions::VALUE();
1662
        }
1663
        $x = (string) $x;
1664
        if (preg_match_all('/[01234567]/', $x, $out) != strlen($x)) {
1665
            return Functions::NAN();
1666
        }
1667
        $binX = '';
1668 View Code Duplication
        foreach (str_split($x) as $char) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1669
            $binX .= str_pad(decbin((int) $char), 3, '0', STR_PAD_LEFT);
1670
        }
1671 View Code Duplication
        if (strlen($binX) == 30 && $binX[0] == '1') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1672
            for ($i = 0; $i < 30; ++$i) {
1673
                $binX[$i] = ($binX[$i] == '1' ? '0' : '1');
1674
            }
1675
1676 25
            return (bindec($binX) + 1) * -1;
1677
        }
1678 25
1679
        return bindec($binX);
1680 25
    }
1681 1
1682
    /**
1683 24
     * OCTTOHEX
1684 24
     *
1685 2
     * Return an octal value as hex.
1686
     *
1687 22
     * Excel Function:
1688 22
     *        OCT2HEX(x[,places])
1689 22
     *
1690
     * @category Engineering Functions
1691 22
     * @param    string $x The octal number you want to convert. Number may not contain
1692 4
     *                                    more than 10 octal characters (30 bits). The most significant
1693 4
     *                                    bit of number is the sign bit. The remaining 29 bits are
1694
     *                                    magnitude bits. Negative numbers are represented using
1695 4
     *                                    two's-complement notation.
1696
     *                                    If number is negative, OCT2HEX ignores places and returns a
1697 18
     *                                    10-character hexadecimal number.
1698
     *                                    If number is not a valid octal number, OCT2HEX returns the
1699
     *                                    #NUM! error value.
1700
     *                                    If OCT2HEX requires more than places characters, it returns
1701
     *                                    the #NUM! error value.
1702
     * @param    int $places The number of characters to use. If places is omitted, OCT2HEX
1703
     *                                    uses the minimum number of characters necessary. Places is useful
1704
     *                                    for padding the return value with leading 0s (zeros).
1705
     *                                    If places is not an integer, it is truncated.
1706
     *                                    If places is nonnumeric, OCT2HEX returns the #VALUE! error value.
1707
     *                                    If places is negative, OCT2HEX returns the #NUM! error value.
1708
     * @return    string
1709
     */
1710 View Code Duplication
    public static function OCTTOHEX($x, $places = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1711
    {
1712
        $x = Functions::flattenSingleValue($x);
1713
        $places = Functions::flattenSingleValue($places);
1714
1715
        if (is_bool($x)) {
1716
            return Functions::VALUE();
1717
        }
1718
        $x = (string) $x;
1719
        if (preg_match_all('/[01234567]/', $x, $out) != strlen($x)) {
1720
            return Functions::NAN();
1721
        }
1722
        $hexVal = strtoupper(dechex(self::OCTTODEC($x)));
1723
1724
        return self::nbrConversionFormat($hexVal, $places);
1725
    }
1726
1727
    /**
1728
     * COMPLEX
1729 9
     *
1730
     * Converts real and imaginary coefficients into a complex number of the form x + yi or x + yj.
1731 9
     *
1732 9
     * Excel Function:
1733
     *        COMPLEX(realNumber,imaginary[,places])
1734 9
     *
1735 1
     * @category Engineering Functions
1736
     * @param    float $realNumber The real coefficient of the complex number.
1737 8
     * @param    float $imaginary The imaginary coefficient of the complex number.
1738 8
     * @param    string $suffix The suffix for the imaginary component of the complex number.
1739 2
     *                                        If omitted, the suffix is assumed to be "i".
1740
     * @return    string
1741 6
     */
1742
    public static function COMPLEX($realNumber = 0.0, $imaginary = 0.0, $suffix = 'i')
1743 6
    {
1744
        $realNumber = (is_null($realNumber)) ? 0.0 : Functions::flattenSingleValue($realNumber);
1745
        $imaginary = (is_null($imaginary)) ? 0.0 : Functions::flattenSingleValue($imaginary);
1746
        $suffix = (is_null($suffix)) ? 'i' : Functions::flattenSingleValue($suffix);
1747
1748
        if (((is_numeric($realNumber)) && (is_numeric($imaginary))) &&
1749
            (($suffix == 'i') || ($suffix == 'j') || ($suffix == ''))
1750
        ) {
1751
            $realNumber = (float) $realNumber;
1752
            $imaginary = (float) $imaginary;
1753
1754
            if ($suffix == '') {
1755
                $suffix = 'i';
1756
            }
1757
            if ($realNumber == 0.0) {
1758
                if ($imaginary == 0.0) {
1759
                    return (string) '0';
1760
                } elseif ($imaginary == 1.0) {
1761
                    return (string) $suffix;
1762
                } elseif ($imaginary == -1.0) {
1763 760
                    return (string) '-' . $suffix;
1764
                }
1765 760
1766 760
                return (string) $imaginary . $suffix;
1767 760
            } elseif ($imaginary == 0.0) {
1768
                return (string) $realNumber;
1769 760
            } elseif ($imaginary == 1.0) {
1770 760
                return (string) $realNumber . '+' . $suffix;
1771
            } elseif ($imaginary == -1.0) {
1772 759
                return (string) $realNumber . '-' . $suffix;
1773 759
            }
1774
            if ($imaginary > 0) {
1775 759
                $imaginary = (string) '+' . $imaginary;
1776
            }
1777
1778 759
            return (string) $realNumber . $imaginary . $suffix;
1779 66
        }
1780 7
1781 59
        return Functions::VALUE();
1782 5
    }
1783 54
1784 2
    /**
1785
     * IMAGINARY
1786 52
     *
1787 693
     * Returns the imaginary coefficient of a complex number in x + yi or x + yj text format.
1788 54
     *
1789 639
     * Excel Function:
1790 45
     *        IMAGINARY(complexNumber)
1791 594
     *
1792 8
     * @category Engineering Functions
1793
     * @param    string $complexNumber The complex number for which you want the imaginary
1794 586
     *                                         coefficient.
1795 329
     * @return    float
1796
     */
1797 586
    public static function IMAGINARY($complexNumber)
1798
    {
1799
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1800 1
1801
        $parsedComplex = self::parseComplex($complexNumber);
1802
1803
        return $parsedComplex['imaginary'];
1804
    }
1805
1806
    /**
1807
     * IMREAL
1808
     *
1809
     * Returns the real coefficient of a complex number in x + yi or x + yj text format.
1810
     *
1811
     * Excel Function:
1812
     *        IMREAL(complexNumber)
1813
     *
1814
     * @category Engineering Functions
1815
     * @param    string $complexNumber The complex number for which you want the real coefficient.
1816
     * @return    float
1817
     */
1818 30
    public static function IMREAL($complexNumber)
1819
    {
1820 30
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1821
1822 30
        $parsedComplex = self::parseComplex($complexNumber);
1823 30
1824
        return $parsedComplex['real'];
1825
    }
1826
1827
    /**
1828
     * IMABS
1829
     *
1830
     * Returns the absolute value (modulus) of a complex number in x + yi or x + yj text format.
1831
     *
1832
     * Excel Function:
1833
     *        IMABS(complexNumber)
1834
     *
1835
     * @param    string $complexNumber The complex number for which you want the absolute value.
1836
     * @return    float
1837
     */
1838
    public static function IMABS($complexNumber)
1839
    {
1840 30
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1841
1842 30
        $parsedComplex = self::parseComplex($complexNumber);
1843
1844 30
        return sqrt(
1845 30
            ($parsedComplex['real'] * $parsedComplex['real']) +
1846
            ($parsedComplex['imaginary'] * $parsedComplex['imaginary'])
1847
        );
1848
    }
1849
1850
    /**
1851
     * IMARGUMENT
1852
     *
1853
     * Returns the argument theta of a complex number, i.e. the angle in radians from the real
1854
     * axis to the representation of the number in polar coordinates.
1855
     *
1856
     * Excel Function:
1857
     *        IMARGUMENT(complexNumber)
1858
     *
1859
     * @param    string $complexNumber The complex number for which you want the argument theta.
1860 27
     * @return    float
1861
     */
1862 27
    public static function IMARGUMENT($complexNumber)
1863
    {
1864 27
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1865
        $parsedComplex = self::parseComplex($complexNumber);
1866 27
        if ($parsedComplex['real'] == 0.0) {
1867 27
            if ($parsedComplex['imaginary'] == 0.0) {
1868 27
                return Functions::DIV0();
1869
            } elseif ($parsedComplex['imaginary'] < 0.0) {
1870
                return M_PI / -2;
1871
            } else {
1872
                return M_PI / 2;
1873
            }
1874
        } elseif ($parsedComplex['real'] > 0.0) {
1875
            return atan($parsedComplex['imaginary'] / $parsedComplex['real']);
1876
        } elseif ($parsedComplex['imaginary'] < 0.0) {
1877
            return 0 - (M_PI - atan(abs($parsedComplex['imaginary']) / abs($parsedComplex['real'])));
1878
        } else {
1879
            return M_PI - atan($parsedComplex['imaginary'] / abs($parsedComplex['real']));
1880
        }
1881
    }
1882
1883
    /**
1884
     * IMCONJUGATE
1885 128
     *
1886
     * Returns the complex conjugate of a complex number in x + yi or x + yj text format.
1887 128
     *
1888 128
     * Excel Function:
1889 128
     *        IMCONJUGATE(complexNumber)
1890 22
     *
1891 2
     * @param    string $complexNumber The complex number for which you want the conjugate.
1892 20
     * @return    string
1893 10
     */
1894
    public static function IMCONJUGATE($complexNumber)
1895 10
    {
1896
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1897 106
1898 52
        $parsedComplex = self::parseComplex($complexNumber);
1899 54
1900 20
        if ($parsedComplex['imaginary'] == 0.0) {
1901
            return $parsedComplex['real'];
1902 34
        } else {
1903
            return self::cleanComplex(
1904
                self::COMPLEX(
1905
                    $parsedComplex['real'],
1906
                    0 - $parsedComplex['imaginary'],
1907
                    $parsedComplex['suffix']
1908
                )
1909
            );
1910
        }
1911
    }
1912
1913
    /**
1914
     * IMCOS
1915
     *
1916
     * Returns the cosine of a complex number in x + yi or x + yj text format.
1917
     *
1918 47
     * Excel Function:
1919
     *        IMCOS(complexNumber)
1920 47
     *
1921
     * @param    string $complexNumber The complex number for which you want the cosine.
1922 47
     * @return    string|float
1923
     */
1924 47 View Code Duplication
    public static function IMCOS($complexNumber)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1925 9
    {
1926
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1927 38
1928 38
        $parsedComplex = self::parseComplex($complexNumber);
1929 38
1930 38
        if ($parsedComplex['imaginary'] == 0.0) {
1931 38
            return cos($parsedComplex['real']);
1932
        } else {
1933
            return self::IMCONJUGATE(
1934
                self::COMPLEX(
1935
                    cos($parsedComplex['real']) * cosh($parsedComplex['imaginary']),
1936
                    sin($parsedComplex['real']) * sinh($parsedComplex['imaginary']),
1937
                    $parsedComplex['suffix']
1938
                )
1939
            );
1940
        }
1941
    }
1942
1943
    /**
1944
     * IMSIN
1945
     *
1946
     * Returns the sine of a complex number in x + yi or x + yj text format.
1947
     *
1948
     * Excel Function:
1949 27
     *        IMSIN(complexNumber)
1950
     *
1951 27
     * @param    string $complexNumber The complex number for which you want the sine.
1952
     * @return    string|float
1953 27
     */
1954 View Code Duplication
    public static function IMSIN($complexNumber)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1955 27
    {
1956 6
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1957
1958 21
        $parsedComplex = self::parseComplex($complexNumber);
1959 21
1960 21
        if ($parsedComplex['imaginary'] == 0.0) {
1961 21
            return sin($parsedComplex['real']);
1962 21
        } else {
1963
            return self::COMPLEX(
1964
                sin($parsedComplex['real']) * cosh($parsedComplex['imaginary']),
1965
                cos($parsedComplex['real']) * sinh($parsedComplex['imaginary']),
1966
                $parsedComplex['suffix']
1967
            );
1968
        }
1969
    }
1970
1971
    /**
1972
     * IMSQRT
1973
     *
1974
     * Returns the square root of a complex number in x + yi or x + yj text format.
1975
     *
1976
     * Excel Function:
1977
     *        IMSQRT(complexNumber)
1978
     *
1979
     * @param    string $complexNumber The complex number for which you want the square root.
1980 27
     * @return    string
1981
     */
1982 27
    public static function IMSQRT($complexNumber)
1983
    {
1984 27
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1985
1986 27
        $parsedComplex = self::parseComplex($complexNumber);
1987 6
1988
        $theta = self::IMARGUMENT($complexNumber);
1989 21
        $d1 = cos($theta / 2);
1990 21
        $d2 = sin($theta / 2);
1991 21
        $r = sqrt(sqrt(($parsedComplex['real'] * $parsedComplex['real']) + ($parsedComplex['imaginary'] * $parsedComplex['imaginary'])));
1992 21
1993
        if ($parsedComplex['suffix'] == '') {
1994
            return self::COMPLEX($d1 * $r, $d2 * $r);
1995
        } else {
1996
            return self::COMPLEX($d1 * $r, $d2 * $r, $parsedComplex['suffix']);
1997
        }
1998
    }
1999
2000
    /**
2001
     * IMLN
2002
     *
2003
     * Returns the natural logarithm of a complex number in x + yi or x + yj text format.
2004
     *
2005
     * Excel Function:
2006
     *        IMLN(complexNumber)
2007
     *
2008
     * @param    string $complexNumber The complex number for which you want the natural logarithm.
2009 28
     * @return    string
2010
     */
2011 28
    public static function IMLN($complexNumber)
2012
    {
2013 28
        $complexNumber = Functions::flattenSingleValue($complexNumber);
2014
2015 28
        $parsedComplex = self::parseComplex($complexNumber);
2016 28
2017 28
        if (($parsedComplex['real'] == 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
2018 28
            return Functions::NAN();
2019
        }
2020 28
2021 6
        $logR = log(sqrt(($parsedComplex['real'] * $parsedComplex['real']) + ($parsedComplex['imaginary'] * $parsedComplex['imaginary'])));
2022
        $t = self::IMARGUMENT($complexNumber);
2023 22
2024
        if ($parsedComplex['suffix'] == '') {
2025
            return self::COMPLEX($logR, $t);
2026
        } else {
2027
            return self::COMPLEX($logR, $t, $parsedComplex['suffix']);
2028
        }
2029
    }
2030
2031
    /**
2032
     * IMLOG10
2033
     *
2034
     * Returns the common logarithm (base 10) of a complex number in x + yi or x + yj text format.
2035
     *
2036
     * Excel Function:
2037
     *        IMLOG10(complexNumber)
2038
     *
2039 75
     * @param    string $complexNumber The complex number for which you want the common logarithm.
2040
     * @return    string
2041 75
     */
2042 View Code Duplication
    public static function IMLOG10($complexNumber)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2043 75
    {
2044
        $complexNumber = Functions::flattenSingleValue($complexNumber);
2045 75
2046 1
        $parsedComplex = self::parseComplex($complexNumber);
2047
2048
        if (($parsedComplex['real'] == 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
2049 74
            return Functions::NAN();
2050 74
        } elseif (($parsedComplex['real'] > 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
2051
            return log10($parsedComplex['real']);
2052 74
        }
2053 8
2054
        return self::IMPRODUCT(log10(EULER), self::IMLN($complexNumber));
2055 66
    }
2056
2057
    /**
2058
     * IMLOG2
2059
     *
2060
     * Returns the base-2 logarithm of a complex number in x + yi or x + yj text format.
2061
     *
2062
     * Excel Function:
2063
     *        IMLOG2(complexNumber)
2064
     *
2065
     * @param    string $complexNumber The complex number for which you want the base-2 logarithm.
2066
     * @return    string
2067
     */
2068 View Code Duplication
    public static function IMLOG2($complexNumber)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2069
    {
2070
        $complexNumber = Functions::flattenSingleValue($complexNumber);
2071 27
2072
        $parsedComplex = self::parseComplex($complexNumber);
2073 27
2074
        if (($parsedComplex['real'] == 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
2075 27
            return Functions::NAN();
2076
        } elseif (($parsedComplex['real'] > 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
2077 27
            return log($parsedComplex['real'], 2);
2078 1
        }
2079 26
2080 2
        return self::IMPRODUCT(log(EULER, 2), self::IMLN($complexNumber));
2081
    }
2082
2083 24
    /**
2084
     * IMEXP
2085
     *
2086
     * Returns the exponential of a complex number in x + yi or x + yj text format.
2087
     *
2088
     * Excel Function:
2089
     *        IMEXP(complexNumber)
2090
     *
2091
     * @param    string $complexNumber The complex number for which you want the exponential.
2092
     * @return    string
2093
     */
2094
    public static function IMEXP($complexNumber)
2095
    {
2096
        $complexNumber = Functions::flattenSingleValue($complexNumber);
2097
2098 27
        $parsedComplex = self::parseComplex($complexNumber);
2099
2100 27
        if (($parsedComplex['real'] == 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
2101
            return '1';
2102 27
        }
2103
2104 27
        $e = exp($parsedComplex['real']);
2105 1
        $eX = $e * cos($parsedComplex['imaginary']);
2106 26
        $eY = $e * sin($parsedComplex['imaginary']);
2107 2
2108
        if ($parsedComplex['suffix'] == '') {
2109
            return self::COMPLEX($eX, $eY);
2110 24
        } else {
2111
            return self::COMPLEX($eX, $eY, $parsedComplex['suffix']);
2112
        }
2113
    }
2114
2115
    /**
2116
     * IMPOWER
2117
     *
2118
     * Returns a complex number in x + yi or x + yj text format raised to a power.
2119
     *
2120
     * Excel Function:
2121
     *        IMPOWER(complexNumber,realNumber)
2122
     *
2123
     * @param    string $complexNumber The complex number you want to raise to a power.
2124
     * @param    float $realNumber The power to which you want to raise the complex number.
2125 27
     * @return    string
2126
     */
2127 27
    public static function IMPOWER($complexNumber, $realNumber)
2128
    {
2129 27
        $complexNumber = Functions::flattenSingleValue($complexNumber);
2130
        $realNumber = Functions::flattenSingleValue($realNumber);
2131 27
2132 1
        if (!is_numeric($realNumber)) {
2133
            return Functions::VALUE();
2134
        }
2135 26
2136 26
        $parsedComplex = self::parseComplex($complexNumber);
2137 26
2138
        $r = sqrt(($parsedComplex['real'] * $parsedComplex['real']) + ($parsedComplex['imaginary'] * $parsedComplex['imaginary']));
2139 26
        $rPower = pow($r, $realNumber);
2140 4
        $theta = self::IMARGUMENT($complexNumber) * $realNumber;
2141
        if ($theta == 0) {
2142 22
            return 1;
2143
        } elseif ($parsedComplex['imaginary'] == 0.0) {
2144
            return self::COMPLEX($rPower * cos($theta), $rPower * sin($theta), $parsedComplex['suffix']);
2145
        } else {
2146
            return self::COMPLEX($rPower * cos($theta), $rPower * sin($theta), $parsedComplex['suffix']);
2147
        }
2148
    }
2149
2150
    /**
2151
     * IMDIV
2152
     *
2153
     * Returns the quotient of two complex numbers in x + yi or x + yj text format.
2154
     *
2155
     * Excel Function:
2156
     *        IMDIV(complexDividend,complexDivisor)
2157
     *
2158
     * @param    string $complexDividend The complex numerator or dividend.
2159
     * @param    string $complexDivisor The complex denominator or divisor.
2160
     * @return    string
2161
     */
2162
    public static function IMDIV($complexDividend, $complexDivisor)
2163
    {
2164
        $complexDividend = Functions::flattenSingleValue($complexDividend);
2165
        $complexDivisor = Functions::flattenSingleValue($complexDivisor);
2166
2167
        $parsedComplexDividend = self::parseComplex($complexDividend);
2168
        $parsedComplexDivisor = self::parseComplex($complexDivisor);
2169
2170
        if (($parsedComplexDividend['suffix'] != '') && ($parsedComplexDivisor['suffix'] != '') &&
2171
            ($parsedComplexDividend['suffix'] != $parsedComplexDivisor['suffix'])
2172
        ) {
2173
            return Functions::NAN();
2174
        }
2175
        if (($parsedComplexDividend['suffix'] != '') && ($parsedComplexDivisor['suffix'] == '')) {
2176
            $parsedComplexDivisor['suffix'] = $parsedComplexDividend['suffix'];
2177
        }
2178
2179
        $d1 = ($parsedComplexDividend['real'] * $parsedComplexDivisor['real']) + ($parsedComplexDividend['imaginary'] * $parsedComplexDivisor['imaginary']);
2180
        $d2 = ($parsedComplexDividend['imaginary'] * $parsedComplexDivisor['real']) - ($parsedComplexDividend['real'] * $parsedComplexDivisor['imaginary']);
2181
        $d3 = ($parsedComplexDivisor['real'] * $parsedComplexDivisor['real']) + ($parsedComplexDivisor['imaginary'] * $parsedComplexDivisor['imaginary']);
2182
2183
        $r = $d1 / $d3;
2184
        $i = $d2 / $d3;
2185
2186
        if ($i > 0.0) {
2187
            return self::cleanComplex($r . '+' . $i . $parsedComplexDivisor['suffix']);
2188
        } elseif ($i < 0.0) {
2189
            return self::cleanComplex($r . $i . $parsedComplexDivisor['suffix']);
2190
        } else {
2191
            return $r;
2192
        }
2193
    }
2194
2195
    /**
2196
     * IMSUB
2197
     *
2198
     * Returns the difference of two complex numbers in x + yi or x + yj text format.
2199
     *
2200
     * Excel Function:
2201
     *        IMSUB(complexNumber1,complexNumber2)
2202
     *
2203
     * @param    string $complexNumber1 The complex number from which to subtract complexNumber2.
2204
     * @param    string $complexNumber2 The complex number to subtract from complexNumber1.
2205
     * @return    string
2206
     */
2207
    public static function IMSUB($complexNumber1, $complexNumber2)
2208
    {
2209
        $complexNumber1 = Functions::flattenSingleValue($complexNumber1);
2210
        $complexNumber2 = Functions::flattenSingleValue($complexNumber2);
2211
2212
        $parsedComplex1 = self::parseComplex($complexNumber1);
2213
        $parsedComplex2 = self::parseComplex($complexNumber2);
2214
2215
        if ((($parsedComplex1['suffix'] != '') && ($parsedComplex2['suffix'] != '')) &&
2216
            ($parsedComplex1['suffix'] != $parsedComplex2['suffix'])
2217
        ) {
2218
            return Functions::NAN();
2219
        } elseif (($parsedComplex1['suffix'] == '') && ($parsedComplex2['suffix'] != '')) {
2220
            $parsedComplex1['suffix'] = $parsedComplex2['suffix'];
2221
        }
2222
2223
        $d1 = $parsedComplex1['real'] - $parsedComplex2['real'];
2224
        $d2 = $parsedComplex1['imaginary'] - $parsedComplex2['imaginary'];
2225
2226
        return self::COMPLEX($d1, $d2, $parsedComplex1['suffix']);
2227
    }
2228
2229
    /**
2230
     * IMSUM
2231
     *
2232
     * Returns the sum of two or more complex numbers in x + yi or x + yj text format.
2233
     *
2234
     * Excel Function:
2235
     *        IMSUM(complexNumber[,complexNumber[,...]])
2236
     *
2237
     * @param    string $complexNumber,... Series of complex numbers to add
0 ignored issues
show
Bug introduced by
There is no parameter named $complexNumber,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
2238
     * @return    string
2239
     */
2240
    public static function IMSUM()
2241
    {
2242
        // Return value
2243
        $returnValue = self::parseComplex('0');
2244
        $activeSuffix = '';
2245
2246
        // Loop through the arguments
2247
        $aArgs = Functions::flattenArray(func_get_args());
2248
        foreach ($aArgs as $arg) {
2249
            $parsedComplex = self::parseComplex($arg);
2250
2251 View Code Duplication
            if ($activeSuffix == '') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2252
                $activeSuffix = $parsedComplex['suffix'];
2253
            } elseif (($parsedComplex['suffix'] != '') && ($activeSuffix != $parsedComplex['suffix'])) {
2254
                return Functions::NAN();
2255
            }
2256
2257
            $returnValue['real'] += $parsedComplex['real'];
2258
            $returnValue['imaginary'] += $parsedComplex['imaginary'];
2259
        }
2260
2261
        if ($returnValue['imaginary'] == 0.0) {
2262
            $activeSuffix = '';
2263
        }
2264
2265
        return self::COMPLEX($returnValue['real'], $returnValue['imaginary'], $activeSuffix);
2266
    }
2267
2268
    /**
2269
     * IMPRODUCT
2270
     *
2271
     * Returns the product of two or more complex numbers in x + yi or x + yj text format.
2272
     *
2273
     * Excel Function:
2274
     *        IMPRODUCT(complexNumber[,complexNumber[,...]])
2275 10
     *
2276
     * @param    string $complexNumber,... Series of complex numbers to multiply
0 ignored issues
show
Bug introduced by
There is no parameter named $complexNumber,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
2277
     * @return    string
2278 10
     */
2279 10
    public static function IMPRODUCT()
2280
    {
2281
        // Return value
2282 10
        $returnValue = self::parseComplex('1');
2283 10
        $activeSuffix = '';
2284 10
2285
        // Loop through the arguments
2286 10
        $aArgs = Functions::flattenArray(func_get_args());
2287 10
        foreach ($aArgs as $arg) {
2288 10
            $parsedComplex = self::parseComplex($arg);
2289 2
2290
            $workValue = $returnValue;
2291 View Code Duplication
            if (($parsedComplex['suffix'] != '') && ($activeSuffix == '')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2292 10
                $activeSuffix = $parsedComplex['suffix'];
2293 10
            } elseif (($parsedComplex['suffix'] != '') && ($activeSuffix != $parsedComplex['suffix'])) {
2294
                return Functions::NAN();
2295
            }
2296 8
            $returnValue['real'] = ($workValue['real'] * $parsedComplex['real']) - ($workValue['imaginary'] * $parsedComplex['imaginary']);
2297
            $returnValue['imaginary'] = ($workValue['real'] * $parsedComplex['imaginary']) + ($workValue['imaginary'] * $parsedComplex['real']);
2298
        }
2299 8
2300
        if ($returnValue['imaginary'] == 0.0) {
2301
            $activeSuffix = '';
2302
        }
2303
2304
        return self::COMPLEX($returnValue['real'], $returnValue['imaginary'], $activeSuffix);
2305
    }
2306
2307
    /**
2308
     *    DELTA
2309
     *
2310
     *    Tests whether two values are equal. Returns 1 if number1 = number2; returns 0 otherwise.
2311
     *    Use this function to filter a set of values. For example, by summing several DELTA
2312
     *    functions you calculate the count of equal pairs. This function is also known as the
2313
     *    Kronecker Delta function.
2314 63
     *
2315
     *    Excel Function:
2316
     *        DELTA(a[,b])
2317 63
     *
2318 63
     * @param    float $a The first number.
2319
     * @param    float $b The second number. If omitted, b is assumed to be zero.
2320
     * @return    int
2321 63
     */
2322 63
    public static function DELTA($a, $b = 0)
2323 63
    {
2324
        $a = Functions::flattenSingleValue($a);
2325 63
        $b = Functions::flattenSingleValue($b);
2326 63
2327 63
        return (int) ($a == $b);
2328 62
    }
2329 1
2330
    /**
2331 63
     *    GESTEP
2332 63
     *
2333
     *    Excel Function:
2334
     *        GESTEP(number[,step])
2335 62
     *
2336
     *    Returns 1 if number >= step; returns 0 (zero) otherwise
2337
     *    Use this function to filter a set of values. For example, by summing several GESTEP
2338 62
     *    functions you calculate the count of values that exceed a threshold.
2339
     *
2340
     * @param    float $number The value to test against step.
2341
     * @param    float $step The threshold value.
2342
     *                                    If you omit a value for step, GESTEP uses zero.
2343
     * @return    int
2344
     */
2345
    public static function GESTEP($number, $step = 0)
2346
    {
2347
        $number = Functions::flattenSingleValue($number);
2348
        $step = Functions::flattenSingleValue($step);
2349
2350
        return (int) ($number >= $step);
2351
    }
2352
2353
    //
2354
    //    Private method to calculate the erf value
2355
    //
2356
    private static $twoSqrtPi = 1.128379167095512574;
2357 25
2358
    public static function erfVal($x)
2359 25
    {
2360 25
        if (abs($x) > 2.2) {
2361
            return 1 - self::erfcVal($x);
2362 25
        }
2363
        $sum = $term = $x;
2364
        $xsqr = ($x * $x);
2365
        $j = 1;
2366
        do {
2367
            $term *= $xsqr / $j;
2368
            $sum -= $term / (2 * $j + 1);
2369
            ++$j;
2370
            $term *= $xsqr / $j;
2371
            $sum += $term / (2 * $j + 1);
2372
            ++$j;
2373
            if ($sum == 0.0) {
2374
                break;
2375
            }
2376
        } while (abs($term / $sum) > PRECISION);
2377
2378
        return self::$twoSqrtPi * $sum;
2379
    }
2380
2381 81
    /**
2382
     *    ERF
2383 81
     *
2384 81
     *    Returns the error function integrated between the lower and upper bound arguments.
2385
     *
2386 81
     *    Note: In Excel 2007 or earlier, if you input a negative value for the upper or lower bound arguments,
2387
     *            the function would return a #NUM! error. However, in Excel 2010, the function algorithm was
2388
     *            improved, so that it can now calculate the function for both positive and negative ranges.
2389
     *            PhpSpreadsheet follows Excel 2010 behaviour, and accepts nagative arguments.
2390
     *
2391
     *    Excel Function:
2392
     *        ERF(lower[,upper])
2393
     *
2394
     * @param    float $lower lower bound for integrating ERF
2395 148
     * @param    float $upper upper bound for integrating ERF.
2396
     *                                If omitted, ERF integrates between zero and lower_limit
2397 148
     * @return    float
2398 67
     */
2399
    public static function ERF($lower, $upper = null)
2400 123
    {
2401 123
        $lower = Functions::flattenSingleValue($lower);
2402 123
        $upper = Functions::flattenSingleValue($upper);
2403
2404 123
        if (is_numeric($lower)) {
2405 123
            if (is_null($upper)) {
2406 123
                return self::erfVal($lower);
2407 123
            }
2408 123
            if (is_numeric($upper)) {
2409 123
                return self::erfVal($upper) - self::erfVal($lower);
2410 123
            }
2411 19
        }
2412
2413 112
        return Functions::VALUE();
2414 123
    }
2415
2416
    //
2417
    //    Private method to calculate the erfc value
2418
    //
2419
    private static $oneSqrtPi = 0.564189583547756287;
2420
2421
    private static function erfcVal($x)
2422
    {
2423
        if (abs($x) < 2.2) {
2424
            return 1 - self::erfVal($x);
2425
        }
2426
        if ($x < 0) {
2427
            return 2 - self::ERFC(-$x);
2428
        }
2429
        $a = $n = 1;
2430
        $b = $c = $x;
2431
        $d = ($x * $x) + 0.5;
2432
        $q1 = $q2 = $b / $d;
0 ignored issues
show
Unused Code introduced by
$q1 is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2433
        $t = 0;
0 ignored issues
show
Unused Code introduced by
$t is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2434
        do {
2435
            $t = $a * $n + $b * $x;
2436 123
            $a = $b;
2437
            $b = $t;
2438 123
            $t = $c * $n + $d * $x;
2439 123
            $c = $d;
2440
            $d = $t;
2441 123
            $n += 0.5;
2442 120
            $q1 = $q2;
2443 37
            $q2 = $b / $d;
2444
        } while ((abs($q1 - $q2) / $q2) > PRECISION);
2445 83
2446 83
        return self::$oneSqrtPi * exp(-$x * $x) * $q2;
2447
    }
2448
2449 3
    /**
2450
     *    ERFC
2451
     *
2452
     *    Returns the complementary ERF function integrated between x and infinity
2453
     *
2454
     *    Note: In Excel 2007 or earlier, if you input a negative value for the lower bound argument,
2455
     *        the function would return a #NUM! error. However, in Excel 2010, the function algorithm was
2456
     *        improved, so that it can now calculate the function for both positive and negative x values.
2457
     *            PhpSpreadsheet follows Excel 2010 behaviour, and accepts nagative arguments.
2458 104
     *
2459
     *    Excel Function:
2460 104
     *        ERFC(x)
2461 28
     *
2462
     * @param    float $x The lower bound for integrating ERFC
2463 76
     * @return    float
2464 1
     */
2465
    public static function ERFC($x)
2466 76
    {
2467 76
        $x = Functions::flattenSingleValue($x);
2468 76
2469 76
        if (is_numeric($x)) {
2470 76
            return self::erfcVal($x);
2471
        }
2472 76
2473 76
        return Functions::VALUE();
2474 76
    }
2475 76
2476 76
    /**
2477 76
     *    getConversionGroups
2478 76
     *    Returns a list of the different conversion groups for UOM conversions
2479 76
     *
2480 76
     * @return    array
2481 76
     */
2482 76
    public static function getConversionGroups()
2483
    {
2484
        $conversionGroups = [];
2485
        foreach (self::$conversionUnits as $conversionUnit) {
2486
            $conversionGroups[] = $conversionUnit['Group'];
2487
        }
2488
2489
        return array_merge(array_unique($conversionGroups));
2490
    }
2491
2492
    /**
2493
     *    getConversionGroupUnits
2494
     *    Returns an array of units of measure, for a specified conversion group, or for all groups
2495
     *
2496
     * @param    string $group The group whose units of measure you want to retrieve
2497
     * @return    array
2498
     */
2499
    public static function getConversionGroupUnits($group = null)
2500
    {
2501
        $conversionGroups = [];
2502 41
        foreach (self::$conversionUnits as $conversionUnit => $conversionGroup) {
2503
            if ((is_null($group)) || ($conversionGroup['Group'] == $group)) {
2504 41
                $conversionGroups[$conversionGroup['Group']][] = $conversionUnit;
2505
            }
2506 41
        }
2507 38
2508
        return $conversionGroups;
2509 3
    }
2510
2511
    /**
2512
     *    getConversionGroupUnitDetails
2513
     *
2514
     * @param    string $group The group whose units of measure you want to retrieve
2515
     * @return    array
2516
     */
2517
    public static function getConversionGroupUnitDetails($group = null)
2518
    {
2519 1
        $conversionGroups = [];
2520
        foreach (self::$conversionUnits as $conversionUnit => $conversionGroup) {
2521 1
            if ((is_null($group)) || ($conversionGroup['Group'] == $group)) {
2522 1
                $conversionGroups[$conversionGroup['Group']][] = [
2523 1
                    'unit' => $conversionUnit,
2524
                    'description' => $conversionGroup['Unit Name'],
2525 1
                ];
2526
            }
2527
        }
2528
2529
        return $conversionGroups;
2530
    }
2531
2532
    /**
2533
     *    getConversionMultipliers
2534
     *    Returns an array of the Multiplier prefixes that can be used with Units of Measure in CONVERTUOM()
2535
     *
2536 1
     * @return    array of mixed
2537
     */
2538 1
    public static function getConversionMultipliers()
2539 1
    {
2540 1
        return self::$conversionMultipliers;
2541 1
    }
2542
2543
    /**
2544 1
     *    CONVERTUOM
2545
     *
2546
     *    Converts a number from one measurement system to another.
2547
     *    For example, CONVERT can translate a table of distances in miles to a table of distances
2548
     *    in kilometers.
2549
     *
2550
     *    Excel Function:
2551
     *        CONVERT(value,fromUOM,toUOM)
2552
     *
2553
     * @param    float $value The value in fromUOM to convert.
2554 1
     * @param    string $fromUOM The units for value.
2555
     * @param    string $toUOM The units for the result.
2556 1
     *
2557 1
     * @return    float
2558 1
     */
2559 1
    public static function CONVERTUOM($value, $fromUOM, $toUOM)
2560 1
    {
2561 1
        $value = Functions::flattenSingleValue($value);
2562
        $fromUOM = Functions::flattenSingleValue($fromUOM);
2563
        $toUOM = Functions::flattenSingleValue($toUOM);
2564
2565 1
        if (!is_numeric($value)) {
2566
            return Functions::VALUE();
2567
        }
2568
        $fromMultiplier = 1.0;
2569 View Code Duplication
        if (isset(self::$conversionUnits[$fromUOM])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2570
            $unitGroup1 = self::$conversionUnits[$fromUOM]['Group'];
2571
        } else {
2572
            $fromMultiplier = substr($fromUOM, 0, 1);
2573
            $fromUOM = substr($fromUOM, 1);
2574
            if (isset(self::$conversionMultipliers[$fromMultiplier])) {
2575 1
                $fromMultiplier = self::$conversionMultipliers[$fromMultiplier]['multiplier'];
2576
            } else {
2577 1
                return Functions::NA();
2578
            }
2579
            if ((isset(self::$conversionUnits[$fromUOM])) && (self::$conversionUnits[$fromUOM]['AllowPrefix'])) {
2580
                $unitGroup1 = self::$conversionUnits[$fromUOM]['Group'];
2581
            } else {
2582
                return Functions::NA();
2583
            }
2584
        }
2585
        $value *= $fromMultiplier;
2586
2587
        $toMultiplier = 1.0;
2588 View Code Duplication
        if (isset(self::$conversionUnits[$toUOM])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2589
            $unitGroup2 = self::$conversionUnits[$toUOM]['Group'];
2590
        } else {
2591
            $toMultiplier = substr($toUOM, 0, 1);
2592
            $toUOM = substr($toUOM, 1);
2593
            if (isset(self::$conversionMultipliers[$toMultiplier])) {
2594
                $toMultiplier = self::$conversionMultipliers[$toMultiplier]['multiplier'];
2595
            } else {
2596
                return Functions::NA();
2597 24
            }
2598
            if ((isset(self::$conversionUnits[$toUOM])) && (self::$conversionUnits[$toUOM]['AllowPrefix'])) {
2599 24
                $unitGroup2 = self::$conversionUnits[$toUOM]['Group'];
2600 24
            } else {
2601 24
                return Functions::NA();
2602
            }
2603 24
        }
2604 1
        if ($unitGroup1 != $unitGroup2) {
2605
            return Functions::NA();
2606 23
        }
2607 23
2608 16
        if (($fromUOM == $toUOM) && ($fromMultiplier == $toMultiplier)) {
2609
            //    We've already factored $fromMultiplier into the value, so we need
2610 7
            //        to reverse it again
2611 7
            return $value / $fromMultiplier;
2612 7
        } elseif ($unitGroup1 == 'Temperature') {
2613 6
            if (($fromUOM == 'F') || ($fromUOM == 'fah')) {
2614
                if (($toUOM == 'F') || ($toUOM == 'fah')) {
2615 1
                    return $value;
2616
                } else {
2617 6
                    $value = (($value - 32) / 1.8);
2618 5
                    if (($toUOM == 'K') || ($toUOM == 'kel')) {
2619
                        $value += 273.15;
2620 1
                    }
2621
2622
                    return $value;
2623 21
                }
2624
            } elseif ((($fromUOM == 'K') || ($fromUOM == 'kel')) &&
2625 21
                (($toUOM == 'K') || ($toUOM == 'kel'))
2626 21
            ) {
2627 14
                return $value;
2628
            } elseif ((($fromUOM == 'C') || ($fromUOM == 'cel')) &&
2629 7
                (($toUOM == 'C') || ($toUOM == 'cel'))
2630 7
            ) {
2631 7
                return $value;
2632 6
            }
2633
            if (($toUOM == 'F') || ($toUOM == 'fah')) {
2634 1
                if (($fromUOM == 'K') || ($fromUOM == 'kel')) {
2635
                    $value -= 273.15;
2636 6
                }
2637 5
2638
                return ($value * 1.8) + 32;
2639 1
            }
2640
            if (($toUOM == 'C') || ($toUOM == 'cel')) {
2641
                return $value - 273.15;
2642 19
            }
2643 2
2644
            return $value + 273.15;
2645
        }
2646 17
2647
        return ($value * self::$unitConversions[$unitGroup1][$fromUOM][$toUOM]) / $toMultiplier;
2648
    }
2649
}
2650