Completed
Push — develop ( 2922a1...cfa1fe )
by Adrien
24:40
created

Engineering::BESSELY()   C

Complexity

Conditions 11
Paths 32

Size

Total Lines 33
Code Lines 23

Duplication

Lines 33
Ratio 100 %

Code Coverage

Tests 22
CRAP Score 11

Importance

Changes 0
Metric Value
cc 11
eloc 23
nc 32
nop 2
dl 33
loc 33
rs 5.2653
c 0
b 0
f 0
ccs 22
cts 22
cp 1
crap 11

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace PhpOffice\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 354
    public static function parseComplex($complexNumber)
745
    {
746 354
        $workString = (string) $complexNumber;
747
748 354
        $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
        //    Extract the suffix, if there is one
750 354
        $suffix = substr($workString, -1);
751 354
        if (!is_numeric($suffix)) {
752 289
            $workString = substr($workString, 0, -1);
753
        } else {
754 142
            $suffix = '';
755
        }
756
757
        //    Split the input into its Real and Imaginary components
758 354
        $leadingSign = 0;
759 354
        if (strlen($workString) > 0) {
760 345
            $leadingSign = (($workString{0} == '+') || ($workString{0} == '-')) ? 1 : 0;
761
        }
762 354
        $power = '';
763 354
        $realNumber = strtok($workString, '+-');
764 354
        if (strtoupper(substr($realNumber, -1)) == 'E') {
765 8
            $power = strtok('+-');
766 8
            ++$leadingSign;
767
        }
768
769 354
        $realNumber = substr($workString, 0, strlen($realNumber) + strlen($power) + $leadingSign);
770
771 354
        if ($suffix != '') {
772 289
            $imaginary = substr($workString, strlen($realNumber));
773
774 289
            if (($imaginary == '') && (($realNumber == '') || ($realNumber == '+') || ($realNumber == '-'))) {
775 24
                $imaginary = $realNumber . '1';
776 24
                $realNumber = '0';
777 269
            } elseif ($imaginary == '') {
778 30
                $imaginary = $realNumber;
779 30
                $realNumber = '0';
780 243
            } elseif (($imaginary == '+') || ($imaginary == '-')) {
781 96
                $imaginary .= '1';
782
            }
783
        }
784
785
        return [
786 354
            'real' => $realNumber,
787 354
            'imaginary' => $imaginary,
788 354
            'suffix' => $suffix,
789
        ];
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 38
    private static function cleanComplex($complexNumber)
799
    {
800 38
        if ($complexNumber{0} == '+') {
801
            $complexNumber = substr($complexNumber, 1);
802
        }
803 38
        if ($complexNumber{0} == '0') {
804 4
            $complexNumber = substr($complexNumber, 1);
805
        }
806 38
        if ($complexNumber{0} == '.') {
807 4
            $complexNumber = '0' . $complexNumber;
808
        }
809 38
        if ($complexNumber{0} == '+') {
810
            $complexNumber = substr($complexNumber, 1);
811
        }
812
813 38
        return $complexNumber;
814
    }
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 82
    private static function nbrConversionFormat($xVal, $places)
824
    {
825 82
        if (!is_null($places)) {
826 22
            if (is_numeric($places)) {
827 18
                $places = (int) $places;
828
            } else {
829 4
                return Functions::VALUE();
830
            }
831 18
            if ($places < 0) {
832 4
                return Functions::NAN();
833
            }
834 14
            if (strlen($xVal) <= $places) {
835 14
                return substr(str_pad($xVal, $places, '0', STR_PAD_LEFT), -10);
836
            } else {
837
                return Functions::NAN();
838
            }
839
        }
840
841 60
        return substr($xVal, -10);
842
    }
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 74
    public static function BESSELI($x, $ord)
863
    {
864 74
        $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 70
            $ord = floor($ord);
869 70
            if ($ord < 0) {
870 2
                return Functions::NAN();
871
            }
872
873 68
            if (abs($x) <= 30) {
874 68
                $fResult = $fTerm = pow($x / 2, $ord) / MathTrig::FACT($ord);
875 68
                $ordK = 1;
876 68
                $fSqrX = ($x * $x) / 4;
877 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 68
                    $fResult += $fTerm;
881 68
                } while ((abs($fTerm) > 1e-12) && (++$ordK < 100));
882
            } else {
883
                $f_2_PI = 2 * M_PI;
884
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 68
            return (is_nan($fResult)) ? Functions::NAN() : $fResult;
893
        }
894
895 4
        return Functions::VALUE();
896
    }
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 50
    public static function BESSELJ($x, $ord)
915
    {
916 50
        $x = (is_null($x)) ? 0.0 : Functions::flattenSingleValue($x);
917 50
        $ord = (is_null($ord)) ? 0.0 : Functions::flattenSingleValue($ord);
918
919 50
        if ((is_numeric($x)) && (is_numeric($ord))) {
920 48
            $ord = floor($ord);
921 48
            if ($ord < 0) {
922 1
                return Functions::NAN();
923
            }
924
925 47
            $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 47
            if (abs($x) <= 30) {
927 47
                $fResult = $fTerm = pow($x / 2, $ord) / MathTrig::FACT($ord);
928 47
                $ordK = 1;
929 47
                $fSqrX = ($x * $x) / -4;
930 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 47
                } while ((abs($fTerm) > 1e-12) && (++$ordK < 100));
935
            } else {
936
                $f_PI_DIV_2 = M_PI / 2;
937
                $f_PI_DIV_4 = M_PI / 4;
938
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 47
            return (is_nan($fResult)) ? Functions::NAN() : $fResult;
947
        }
948
949 2
        return Functions::VALUE();
950
    }
951
952 22
    private static function besselK0($fNum)
953
    {
954 22
        if ($fNum <= 2) {
955 14
            $fNum2 = $fNum * 0.5;
956 14
            $y = ($fNum2 * $fNum2);
957 14
            $fRet = -log($fNum2) * self::BESSELI($fNum, 0) +
958
                (-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 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 8
            $y = 2 / $fNum;
962 8
            $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
        }
966
967 22
        return $fRet;
968
    }
969
970 30
    private static function besselK1($fNum)
971
    {
972 30
        if ($fNum <= 2) {
973 17
            $fNum2 = $fNum * 0.5;
974 17
            $y = ($fNum2 * $fNum2);
975 17
            $fRet = log($fNum2) * self::BESSELI($fNum, 1) +
976
                (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 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 13
            $y = 2 / $fNum;
980 13
            $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
        }
984
985 30
        return $fRet;
986
    }
987
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 38 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 38
        $x = (is_null($x)) ? 0.0 : Functions::flattenSingleValue($x);
1008 38
        $ord = (is_null($ord)) ? 0.0 : Functions::flattenSingleValue($ord);
1009
1010 38
        if ((is_numeric($x)) && (is_numeric($ord))) {
1011 36
            if (($ord < 0) || ($x == 0.0)) {
1012 4
                return Functions::NAN();
1013
            }
1014
1015 32
            switch (floor($ord)) {
1016 32
                case 0:
1017 2
                    $fBk = self::besselK0($x);
1018 2
                    break;
1019 30
                case 1:
1020 10
                    $fBk = self::besselK1($x);
1021 10
                    break;
1022
                default:
1023 20
                    $fTox = 2 / $x;
1024 20
                    $fBkm = self::besselK0($x);
1025 20
                    $fBk = self::besselK1($x);
1026 20
                    for ($n = 1; $n < $ord; ++$n) {
1027 20
                        $fBkp = $fBkm + $n * $fTox * $fBk;
1028 20
                        $fBkm = $fBk;
1029 20
                        $fBk = $fBkp;
1030
                    }
1031
            }
1032
1033 32
            return (is_nan($fBk)) ? Functions::NAN() : $fBk;
1034
        }
1035
1036 2
        return Functions::VALUE();
1037
    }
1038
1039 11
    private static function besselY0($fNum)
1040
    {
1041 11
        if ($fNum < 8.0) {
1042 10
            $y = ($fNum * $fNum);
1043 10
            $f1 = -2957821389.0 + $y * (7062834065.0 + $y * (-512359803.6 + $y * (10879881.29 + $y * (-86327.92757 + $y * 228.4622733))));
1044 10
            $f2 = 40076544269.0 + $y * (745249964.8 + $y * (7189466.438 + $y * (47447.26470 + $y * (226.1030244 + $y))));
1045 10
            $fRet = $f1 / $f2 + 0.636619772 * self::BESSELJ($fNum, 0) * log($fNum);
1046
        } else {
1047 1
            $z = 8.0 / $fNum;
1048 1
            $y = ($z * $z);
1049 1
            $xx = $fNum - 0.785398164;
1050 1
            $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
        }
1054
1055 11
        return $fRet;
1056
    }
1057
1058 16
    private static function besselY1($fNum)
1059
    {
1060 16
        if ($fNum < 8.0) {
1061 16
            $y = ($fNum * $fNum);
1062
            $f1 = $fNum * (-0.4900604943e13 + $y * (0.1275274390e13 + $y * (-0.5153438139e11 + $y * (0.7349264551e9 + $y *
1063 16
                                (-0.4237922726e7 + $y * 0.8511937935e4)))));
1064
            $f2 = 0.2499580570e14 + $y * (0.4244419664e12 + $y * (0.3733650367e10 + $y * (0.2245904002e8 + $y *
1065 16
                            (0.1020426050e6 + $y * (0.3549632885e3 + $y)))));
1066 16
            $fRet = $f1 / $f2 + 0.636619772 * (self::BESSELJ($fNum, 1) * log($fNum) - 1 / $fNum);
1067
        } else {
1068
            $fRet = sqrt(0.636619772 / $fNum) * sin($fNum - 2.356194491);
1069
        }
1070
1071 16
        return $fRet;
1072
    }
1073
1074
    /**
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 23 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 23
        $x = (is_null($x)) ? 0.0 : Functions::flattenSingleValue($x);
1094 23
        $ord = (is_null($ord)) ? 0.0 : Functions::flattenSingleValue($ord);
1095
1096 23
        if ((is_numeric($x)) && (is_numeric($ord))) {
1097 21
            if (($ord < 0) || ($x == 0.0)) {
1098 3
                return Functions::NAN();
1099
            }
1100
1101 18
            switch (floor($ord)) {
1102 18
                case 0:
1103 2
                    $fBy = self::besselY0($x);
1104 2
                    break;
1105 16
                case 1:
1106 7
                    $fBy = self::besselY1($x);
1107 7
                    break;
1108
                default:
1109 9
                    $fTox = 2 / $x;
1110 9
                    $fBym = self::besselY0($x);
1111 9
                    $fBy = self::besselY1($x);
1112 9
                    for ($n = 1; $n < $ord; ++$n) {
1113 9
                        $fByp = $n * $fTox * $fBy - $fBym;
1114 9
                        $fBym = $fBy;
1115 9
                        $fBy = $fByp;
1116
                    }
1117
            }
1118
1119 18
            return (is_nan($fBy)) ? Functions::NAN() : $fBy;
1120
        }
1121
1122 2
        return Functions::VALUE();
1123
    }
1124
1125
    /**
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 10
    public static function BINTODEC($x)
1143
    {
1144 10
        $x = Functions::flattenSingleValue($x);
1145
1146 10
        if (is_bool($x)) {
1147 1
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
1148
                $x = (int) $x;
1149
            } else {
1150 1
                return Functions::VALUE();
1151
            }
1152
        }
1153 9
        if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) {
1154
            $x = floor($x);
1155
        }
1156 9
        $x = (string) $x;
1157 9
        if (strlen($x) > preg_match_all('/[01]/', $x, $out)) {
1158 1
            return Functions::NAN();
1159
        }
1160 8
        if (strlen($x) > 10) {
1161 1
            return Functions::NAN();
1162 7
        } elseif (strlen($x) == 10) {
1163
            //    Two's Complement
1164 2
            $x = substr($x, -9);
1165
1166 2
            return '-' . (512 - bindec($x));
1167
        }
1168
1169 5
        return bindec($x);
1170
    }
1171
1172
    /**
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 14 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 14
        $x = Functions::flattenSingleValue($x);
1198 14
        $places = Functions::flattenSingleValue($places);
1199
1200
        // Argument X
1201 14
        if (is_bool($x)) {
1202 1
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
1203
                $x = (int) $x;
1204
            } else {
1205 1
                return Functions::VALUE();
1206
            }
1207
        }
1208 13
        if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) {
1209
            $x = floor($x);
1210
        }
1211 13
        $x = (string) $x;
1212 13
        if (strlen($x) > preg_match_all('/[01]/', $x, $out)) {
1213 1
            return Functions::NAN();
1214
        }
1215 12
        if (strlen($x) > 10) {
1216 1
            return Functions::NAN();
1217 11
        } elseif (strlen($x) == 10) {
1218
            //    Two's Complement
1219 2
            return str_repeat('F', 8) . substr(strtoupper(dechex(bindec(substr($x, -9)))), -2);
1220
        }
1221 9
        $hexVal = (string) strtoupper(dechex(bindec($x)));
1222
1223 9
        return self::nbrConversionFormat($hexVal, $places);
1224
    }
1225
1226
    /**
1227
     * BINTOOCT
1228
     *
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 15 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 15
        $x = Functions::flattenSingleValue($x);
1252 15
        $places = Functions::flattenSingleValue($places);
1253
1254 15
        if (is_bool($x)) {
1255 1
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
1256
                $x = (int) $x;
1257
            } else {
1258 1
                return Functions::VALUE();
1259
            }
1260
        }
1261 14
        if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) {
1262
            $x = floor($x);
1263
        }
1264 14
        $x = (string) $x;
1265 14
        if (strlen($x) > preg_match_all('/[01]/', $x, $out)) {
1266 1
            return Functions::NAN();
1267
        }
1268 13
        if (strlen($x) > 10) {
1269 1
            return Functions::NAN();
1270 12
        } elseif (strlen($x) == 10) {
1271
            //    Two's Complement
1272 2
            return str_repeat('7', 7) . substr(strtoupper(decoct(bindec(substr($x, -9)))), -3);
1273
        }
1274 10
        $octVal = (string) decoct(bindec($x));
1275
1276 10
        return self::nbrConversionFormat($octVal, $places);
1277
    }
1278
1279
    /**
1280
     * DECTOBIN
1281
     *
1282
     * Return a decimal value as binary.
1283
     *
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 41
    public static function DECTOBIN($x, $places = null)
1307
    {
1308 41
        $x = Functions::flattenSingleValue($x);
1309 41
        $places = Functions::flattenSingleValue($places);
1310
1311 41
        if (is_bool($x)) {
1312 1
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
1313
                $x = (int) $x;
1314
            } else {
1315 1
                return Functions::VALUE();
1316
            }
1317
        }
1318 40
        $x = (string) $x;
1319 40
        if (strlen($x) > preg_match_all('/[-0123456789.]/', $x, $out)) {
1320 1
            return Functions::VALUE();
1321
        }
1322
1323 39
        $x = (string) floor($x);
1324 39
        if ($x < -512 || $x > 511) {
1325 13
            return Functions::NAN();
1326
        }
1327
1328 26
        $r = decbin($x);
1329
        // Two's Complement
1330 26
        $r = substr($r, -10);
1331 26
        if (strlen($r) >= 11) {
1332
            return Functions::NAN();
1333
        }
1334
1335 26
        return self::nbrConversionFormat($r, $places);
1336
    }
1337
1338
    /**
1339
     * DECTOHEX
1340
     *
1341
     * Return a decimal value as hex.
1342
     *
1343
     * Excel Function:
1344
     *        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 15 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 15
        $x = Functions::flattenSingleValue($x);
1368 15
        $places = Functions::flattenSingleValue($places);
1369
1370 15
        if (is_bool($x)) {
1371 1
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
1372
                $x = (int) $x;
1373
            } else {
1374 1
                return Functions::VALUE();
1375
            }
1376
        }
1377 14
        $x = (string) $x;
1378 14
        if (strlen($x) > preg_match_all('/[-0123456789.]/', $x, $out)) {
1379 1
            return Functions::VALUE();
1380
        }
1381 13
        $x = (string) floor($x);
1382 13
        $r = strtoupper(dechex($x));
1383 13
        if (strlen($r) == 8) {
1384
            //    Two's Complement
1385
            $r = 'FF' . $r;
1386
        }
1387
1388 13
        return self::nbrConversionFormat($r, $places);
1389
    }
1390
1391
    /**
1392
     * DECTOOCT
1393
     *
1394
     * Return an decimal value as octal.
1395
     *
1396
     * Excel Function:
1397
     *        DEC2OCT(x[,places])
1398
     *
1399
     * @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 20 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 20
        $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 20
        $x = Functions::flattenSingleValue($x);
1422 20
        $places = Functions::flattenSingleValue($places);
1423
1424 20
        if (is_bool($x)) {
1425 1
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
1426
                $x = (int) $x;
1427
            } else {
1428 1
                return Functions::VALUE();
1429
            }
1430
        }
1431 19
        $x = (string) $x;
1432 19
        if (strlen($x) > preg_match_all('/[-0123456789.]/', $x, $out)) {
1433 1
            return Functions::VALUE();
1434
        }
1435 18
        $x = (string) floor($x);
1436 18
        $r = decoct($x);
1437 18
        if (strlen($r) == 11) {
1438
            //    Two's Complement
1439
            $r = substr($r, -10);
1440
        }
1441
1442 18
        return self::nbrConversionFormat($r, $places);
1443
    }
1444
1445
    /**
1446
     * HEXTOBIN
1447
     *
1448
     * Return a hex value as binary.
1449
     *
1450
     * Excel Function:
1451
     *        HEX2BIN(x[,places])
1452
     *
1453
     * @category Engineering Functions
1454
     * @param    string $x the hexadecimal number you want to convert.
1455
     *                  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 16 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 16
        $x = Functions::flattenSingleValue($x);
1475 16
        $places = Functions::flattenSingleValue($places);
1476
1477 16
        if (is_bool($x)) {
1478 1
            return Functions::VALUE();
1479
        }
1480 15
        $x = (string) $x;
1481 15
        if (strlen($x) > preg_match_all('/[0123456789ABCDEF]/', strtoupper($x), $out)) {
1482 2
            return Functions::NAN();
1483
        }
1484
1485 13
        return self::DECTOBIN(self::HEXTODEC($x), $places);
1486
    }
1487
1488
    /**
1489
     * HEXTODEC
1490
     *
1491
     * Return a hex value as decimal.
1492
     *
1493
     * Excel Function:
1494
     *        HEX2DEC(x)
1495
     *
1496
     * @category Engineering Functions
1497
     * @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
     *                                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 37
    public static function HEXTODEC($x)
1507
    {
1508 37
        $x = Functions::flattenSingleValue($x);
1509
1510 37
        if (is_bool($x)) {
1511 1
            return Functions::VALUE();
1512
        }
1513 36
        $x = (string) $x;
1514 36
        if (strlen($x) > preg_match_all('/[0123456789ABCDEF]/', strtoupper($x), $out)) {
1515 3
            return Functions::NAN();
1516
        }
1517
1518 33
        if (strlen($x) > 10) {
1519 1
            return Functions::NAN();
1520
        }
1521
1522 32
        $binX = '';
1523 32 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 32
            $binX .= str_pad(base_convert($char, 16, 2), 4, '0', STR_PAD_LEFT);
1525
        }
1526 32 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 5
            for ($i = 0; $i < 40; ++$i) {
1528 5
                $binX[$i] = ($binX[$i] == '1' ? '0' : '1');
1529
            }
1530
1531 5
            return (bindec($binX) + 1) * -1;
1532
        }
1533
1534 27
        return bindec($binX);
1535
    }
1536
1537
    /**
1538
     * HEXTOOCT
1539
     *
1540
     * Return a hex value as octal.
1541
     *
1542
     * Excel Function:
1543
     *        HEX2OCT(x[,places])
1544
     *
1545
     * @category Engineering Functions
1546
     * @param    string $x The hexadecimal number you want to convert. Number cannot
1547
     *                                    contain more than 10 characters. The most significant bit of
1548
     *                                    number is the sign bit. The remaining 39 bits are magnitude
1549
     *                                    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 13
    public static function HEXTOOCT($x, $places = null)
1569
    {
1570 13
        $x = Functions::flattenSingleValue($x);
1571 13
        $places = Functions::flattenSingleValue($places);
1572
1573 13
        if (is_bool($x)) {
1574 1
            return Functions::VALUE();
1575
        }
1576 12
        $x = (string) $x;
1577 12
        if (strlen($x) > preg_match_all('/[0123456789ABCDEF]/', strtoupper($x), $out)) {
1578 3
            return Functions::NAN();
1579
        }
1580
1581 9
        $decimal = self::HEXTODEC($x);
1582 9
        if ($decimal < -536870912 || $decimal > 536870911) {
1583 1
            return Functions::NAN();
1584
        }
1585
1586 8
        return self::DECTOOCT($decimal, $places);
1587
    }
1588
1589
    /**
1590
     * OCTTOBIN
1591
     *
1592
     * Return an octal value as binary.
1593
     *
1594
     * Excel Function:
1595
     *        OCT2BIN(x[,places])
1596
     *
1597
     * @category Engineering Functions
1598
     * @param    string $x The octal number you want to convert. Number may not
1599
     *                                    contain more than 10 characters. The most significant
1600
     *                                    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
     *                                    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 13 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 13
        $x = Functions::flattenSingleValue($x);
1625 13
        $places = Functions::flattenSingleValue($places);
1626
1627 13
        if (is_bool($x)) {
1628 1
            return Functions::VALUE();
1629
        }
1630 12
        $x = (string) $x;
1631 12
        if (preg_match_all('/[01234567]/', $x, $out) != strlen($x)) {
1632 2
            return Functions::NAN();
1633
        }
1634
1635 10
        return self::DECTOBIN(self::OCTTODEC($x), $places);
1636
    }
1637
1638
    /**
1639
     * OCTTODEC
1640
     *
1641
     * Return an octal value as decimal.
1642
     *
1643
     * Excel Function:
1644
     *        OCT2DEC(x)
1645
     *
1646
     * @category Engineering Functions
1647
     * @param    string $x The octal number you want to convert. Number may not contain
1648
     *                                more than 10 octal characters (30 bits). The most significant
1649
     *                                bit of number is the sign bit. The remaining 29 bits are
1650
     *                                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
     *                                #NUM! error value.
1654
     * @return    string
1655
     */
1656 25
    public static function OCTTODEC($x)
1657
    {
1658 25
        $x = Functions::flattenSingleValue($x);
1659
1660 25
        if (is_bool($x)) {
1661 1
            return Functions::VALUE();
1662
        }
1663 24
        $x = (string) $x;
1664 24
        if (preg_match_all('/[01234567]/', $x, $out) != strlen($x)) {
1665 2
            return Functions::NAN();
1666
        }
1667 22
        $binX = '';
1668 22 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 22
            $binX .= str_pad(decbin((int) $char), 3, '0', STR_PAD_LEFT);
1670
        }
1671 22 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 4
            for ($i = 0; $i < 30; ++$i) {
1673 4
                $binX[$i] = ($binX[$i] == '1' ? '0' : '1');
1674
            }
1675
1676 4
            return (bindec($binX) + 1) * -1;
1677
        }
1678
1679 18
        return bindec($binX);
1680
    }
1681
1682
    /**
1683
     * OCTTOHEX
1684
     *
1685
     * Return an octal value as hex.
1686
     *
1687
     * Excel Function:
1688
     *        OCT2HEX(x[,places])
1689
     *
1690
     * @category Engineering Functions
1691
     * @param    string $x The octal number you want to convert. Number may not contain
1692
     *                                    more than 10 octal characters (30 bits). The most significant
1693
     *                                    bit of number is the sign bit. The remaining 29 bits are
1694
     *                                    magnitude bits. Negative numbers are represented using
1695
     *                                    two's-complement notation.
1696
     *                                    If number is negative, OCT2HEX ignores places and returns a
1697
     *                                    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 9 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 9
        $x = Functions::flattenSingleValue($x);
1713 9
        $places = Functions::flattenSingleValue($places);
1714
1715 9
        if (is_bool($x)) {
1716 1
            return Functions::VALUE();
1717
        }
1718 8
        $x = (string) $x;
1719 8
        if (preg_match_all('/[01234567]/', $x, $out) != strlen($x)) {
1720 2
            return Functions::NAN();
1721
        }
1722 6
        $hexVal = strtoupper(dechex(self::OCTTODEC($x)));
1723
1724 6
        return self::nbrConversionFormat($hexVal, $places);
1725
    }
1726
1727
    /**
1728
     * COMPLEX
1729
     *
1730
     * Converts real and imaginary coefficients into a complex number of the form x + yi or x + yj.
1731
     *
1732
     * Excel Function:
1733
     *        COMPLEX(realNumber,imaginary[,places])
1734
     *
1735
     * @category Engineering Functions
1736
     * @param    float $realNumber The real coefficient of the complex number.
1737
     * @param    float $imaginary The imaginary coefficient of the complex number.
1738
     * @param    string $suffix The suffix for the imaginary component of the complex number.
1739
     *                                        If omitted, the suffix is assumed to be "i".
1740
     * @return    string
1741
     */
1742 760
    public static function COMPLEX($realNumber = 0.0, $imaginary = 0.0, $suffix = 'i')
1743
    {
1744 760
        $realNumber = (is_null($realNumber)) ? 0.0 : Functions::flattenSingleValue($realNumber);
1745 760
        $imaginary = (is_null($imaginary)) ? 0.0 : Functions::flattenSingleValue($imaginary);
1746 760
        $suffix = (is_null($suffix)) ? 'i' : Functions::flattenSingleValue($suffix);
1747
1748 760
        if (((is_numeric($realNumber)) && (is_numeric($imaginary))) &&
1749 760
            (($suffix == 'i') || ($suffix == 'j') || ($suffix == ''))
1750
        ) {
1751 759
            $realNumber = (float) $realNumber;
1752 759
            $imaginary = (float) $imaginary;
1753
1754 759
            if ($suffix == '') {
1755
                $suffix = 'i';
1756
            }
1757 759
            if ($realNumber == 0.0) {
1758 66
                if ($imaginary == 0.0) {
1759 7
                    return (string) '0';
1760 59
                } elseif ($imaginary == 1.0) {
1761 5
                    return (string) $suffix;
1762 54
                } elseif ($imaginary == -1.0) {
1763 2
                    return (string) '-' . $suffix;
1764
                }
1765
1766 52
                return (string) $imaginary . $suffix;
1767 693
            } elseif ($imaginary == 0.0) {
1768 54
                return (string) $realNumber;
1769 639
            } elseif ($imaginary == 1.0) {
1770 45
                return (string) $realNumber . '+' . $suffix;
1771 594
            } elseif ($imaginary == -1.0) {
1772 8
                return (string) $realNumber . '-' . $suffix;
1773
            }
1774 586
            if ($imaginary > 0) {
1775 329
                $imaginary = (string) '+' . $imaginary;
1776
            }
1777
1778 586
            return (string) $realNumber . $imaginary . $suffix;
1779
        }
1780
1781 1
        return Functions::VALUE();
1782
    }
1783
1784
    /**
1785
     * IMAGINARY
1786
     *
1787
     * Returns the imaginary coefficient of a complex number in x + yi or x + yj text format.
1788
     *
1789
     * Excel Function:
1790
     *        IMAGINARY(complexNumber)
1791
     *
1792
     * @category Engineering Functions
1793
     * @param    string $complexNumber The complex number for which you want the imaginary
1794
     *                                         coefficient.
1795
     * @return    float
1796
     */
1797 30
    public static function IMAGINARY($complexNumber)
1798
    {
1799 30
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1800
1801 30
        $parsedComplex = self::parseComplex($complexNumber);
1802
1803 30
        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
1824 30
        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 27
    public static function IMABS($complexNumber)
1839
    {
1840 27
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1841
1842 27
        $parsedComplex = self::parseComplex($complexNumber);
1843
1844 27
        return sqrt(
1845 27
            ($parsedComplex['real'] * $parsedComplex['real']) +
1846 27
            ($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
     * @return    float
1861
     */
1862 128
    public static function IMARGUMENT($complexNumber)
1863
    {
1864 128
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1865 128
        $parsedComplex = self::parseComplex($complexNumber);
1866 128
        if ($parsedComplex['real'] == 0.0) {
1867 22
            if ($parsedComplex['imaginary'] == 0.0) {
1868 2
                return Functions::DIV0();
1869 20
            } elseif ($parsedComplex['imaginary'] < 0.0) {
1870 10
                return M_PI / -2;
1871
            } else {
1872 10
                return M_PI / 2;
1873
            }
1874 106
        } elseif ($parsedComplex['real'] > 0.0) {
1875 52
            return atan($parsedComplex['imaginary'] / $parsedComplex['real']);
1876 54
        } elseif ($parsedComplex['imaginary'] < 0.0) {
1877 20
            return 0 - (M_PI - atan(abs($parsedComplex['imaginary']) / abs($parsedComplex['real'])));
1878
        } else {
1879 34
            return M_PI - atan($parsedComplex['imaginary'] / abs($parsedComplex['real']));
1880
        }
1881
    }
1882
1883
    /**
1884
     * IMCONJUGATE
1885
     *
1886
     * Returns the complex conjugate of a complex number in x + yi or x + yj text format.
1887
     *
1888
     * Excel Function:
1889
     *        IMCONJUGATE(complexNumber)
1890
     *
1891
     * @param    string $complexNumber The complex number for which you want the conjugate.
1892
     * @return    string
1893
     */
1894 47
    public static function IMCONJUGATE($complexNumber)
1895
    {
1896 47
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1897
1898 47
        $parsedComplex = self::parseComplex($complexNumber);
1899
1900 47
        if ($parsedComplex['imaginary'] == 0.0) {
1901 9
            return $parsedComplex['real'];
1902
        } else {
1903 38
            return self::cleanComplex(
1904 38
                self::COMPLEX(
1905 38
                    $parsedComplex['real'],
1906 38
                    0 - $parsedComplex['imaginary'],
1907 38
                    $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
     * Excel Function:
1919
     *        IMCOS(complexNumber)
1920
     *
1921
     * @param    string $complexNumber The complex number for which you want the cosine.
1922
     * @return    string|float
1923
     */
1924 27 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
    {
1926 27
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1927
1928 27
        $parsedComplex = self::parseComplex($complexNumber);
1929
1930 27
        if ($parsedComplex['imaginary'] == 0.0) {
1931 6
            return cos($parsedComplex['real']);
1932
        } else {
1933 21
            return self::IMCONJUGATE(
1934 21
                self::COMPLEX(
1935 21
                    cos($parsedComplex['real']) * cosh($parsedComplex['imaginary']),
1936 21
                    sin($parsedComplex['real']) * sinh($parsedComplex['imaginary']),
1937 21
                    $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
     *        IMSIN(complexNumber)
1950
     *
1951
     * @param    string $complexNumber The complex number for which you want the sine.
1952
     * @return    string|float
1953
     */
1954 27 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
    {
1956 27
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1957
1958 27
        $parsedComplex = self::parseComplex($complexNumber);
1959
1960 27
        if ($parsedComplex['imaginary'] == 0.0) {
1961 6
            return sin($parsedComplex['real']);
1962
        } else {
1963 21
            return self::COMPLEX(
1964 21
                sin($parsedComplex['real']) * cosh($parsedComplex['imaginary']),
1965 21
                cos($parsedComplex['real']) * sinh($parsedComplex['imaginary']),
1966 21
                $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
     * @return    string
1981
     */
1982 28
    public static function IMSQRT($complexNumber)
1983
    {
1984 28
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1985
1986 28
        $parsedComplex = self::parseComplex($complexNumber);
1987
1988 28
        $theta = self::IMARGUMENT($complexNumber);
1989 28
        $d1 = cos($theta / 2);
1990 28
        $d2 = sin($theta / 2);
1991 28
        $r = sqrt(sqrt(($parsedComplex['real'] * $parsedComplex['real']) + ($parsedComplex['imaginary'] * $parsedComplex['imaginary'])));
1992
1993 28
        if ($parsedComplex['suffix'] == '') {
1994 6
            return self::COMPLEX($d1 * $r, $d2 * $r);
1995
        } else {
1996 22
            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
     * @return    string
2010
     */
2011 75
    public static function IMLN($complexNumber)
2012
    {
2013 75
        $complexNumber = Functions::flattenSingleValue($complexNumber);
2014
2015 75
        $parsedComplex = self::parseComplex($complexNumber);
2016
2017 75
        if (($parsedComplex['real'] == 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
2018 1
            return Functions::NAN();
2019
        }
2020
2021 74
        $logR = log(sqrt(($parsedComplex['real'] * $parsedComplex['real']) + ($parsedComplex['imaginary'] * $parsedComplex['imaginary'])));
2022 74
        $t = self::IMARGUMENT($complexNumber);
2023
2024 74
        if ($parsedComplex['suffix'] == '') {
2025 8
            return self::COMPLEX($logR, $t);
2026
        } else {
2027 66
            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
     * @param    string $complexNumber The complex number for which you want the common logarithm.
2040
     * @return    string
2041
     */
2042 27 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
    {
2044 27
        $complexNumber = Functions::flattenSingleValue($complexNumber);
2045
2046 27
        $parsedComplex = self::parseComplex($complexNumber);
2047
2048 27
        if (($parsedComplex['real'] == 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
2049 1
            return Functions::NAN();
2050 26
        } elseif (($parsedComplex['real'] > 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
2051 2
            return log10($parsedComplex['real']);
2052
        }
2053
2054 24
        return self::IMPRODUCT(log10(EULER), self::IMLN($complexNumber));
2055
    }
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 27 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 27
        $complexNumber = Functions::flattenSingleValue($complexNumber);
2071
2072 27
        $parsedComplex = self::parseComplex($complexNumber);
2073
2074 27
        if (($parsedComplex['real'] == 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
2075 1
            return Functions::NAN();
2076 26
        } elseif (($parsedComplex['real'] > 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
2077 2
            return log($parsedComplex['real'], 2);
2078
        }
2079
2080 24
        return self::IMPRODUCT(log(EULER, 2), self::IMLN($complexNumber));
2081
    }
2082
2083
    /**
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 27
    public static function IMEXP($complexNumber)
2095
    {
2096 27
        $complexNumber = Functions::flattenSingleValue($complexNumber);
2097
2098 27
        $parsedComplex = self::parseComplex($complexNumber);
2099
2100 27
        if (($parsedComplex['real'] == 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
2101 1
            return '1';
2102
        }
2103
2104 26
        $e = exp($parsedComplex['real']);
2105 26
        $eX = $e * cos($parsedComplex['imaginary']);
2106 26
        $eY = $e * sin($parsedComplex['imaginary']);
2107
2108 26
        if ($parsedComplex['suffix'] == '') {
2109 4
            return self::COMPLEX($eX, $eY);
2110
        } else {
2111 22
            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
     * @return    string
2126
     */
2127
    public static function IMPOWER($complexNumber, $realNumber)
2128
    {
2129
        $complexNumber = Functions::flattenSingleValue($complexNumber);
2130
        $realNumber = Functions::flattenSingleValue($realNumber);
2131
2132
        if (!is_numeric($realNumber)) {
2133
            return Functions::VALUE();
2134
        }
2135
2136
        $parsedComplex = self::parseComplex($complexNumber);
2137
2138
        $r = sqrt(($parsedComplex['real'] * $parsedComplex['real']) + ($parsedComplex['imaginary'] * $parsedComplex['imaginary']));
2139
        $rPower = pow($r, $realNumber);
2140
        $theta = self::IMARGUMENT($complexNumber) * $realNumber;
2141
        if ($theta == 0) {
2142
            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 10
    public static function IMSUM()
2241
    {
2242
        // Return value
2243 10
        $returnValue = self::parseComplex('0');
2244 10
        $activeSuffix = '';
2245
2246
        // Loop through the arguments
2247 10
        $aArgs = Functions::flattenArray(func_get_args());
2248 10
        foreach ($aArgs as $arg) {
2249 10
            $parsedComplex = self::parseComplex($arg);
2250
2251 10 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 10
                $activeSuffix = $parsedComplex['suffix'];
2253 10
            } elseif (($parsedComplex['suffix'] != '') && ($activeSuffix != $parsedComplex['suffix'])) {
2254 2
                return Functions::NAN();
2255
            }
2256
2257 10
            $returnValue['real'] += $parsedComplex['real'];
2258 10
            $returnValue['imaginary'] += $parsedComplex['imaginary'];
2259
        }
2260
2261 8
        if ($returnValue['imaginary'] == 0.0) {
2262
            $activeSuffix = '';
2263
        }
2264
2265 8
        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
     *
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
     */
2279 63
    public static function IMPRODUCT()
2280
    {
2281
        // Return value
2282 63
        $returnValue = self::parseComplex('1');
2283 63
        $activeSuffix = '';
2284
2285
        // Loop through the arguments
2286 63
        $aArgs = Functions::flattenArray(func_get_args());
2287 63
        foreach ($aArgs as $arg) {
2288 63
            $parsedComplex = self::parseComplex($arg);
2289
2290 63
            $workValue = $returnValue;
2291 63 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 63
                $activeSuffix = $parsedComplex['suffix'];
2293 62
            } elseif (($parsedComplex['suffix'] != '') && ($activeSuffix != $parsedComplex['suffix'])) {
2294 1
                return Functions::NAN();
2295
            }
2296 63
            $returnValue['real'] = ($workValue['real'] * $parsedComplex['real']) - ($workValue['imaginary'] * $parsedComplex['imaginary']);
2297 63
            $returnValue['imaginary'] = ($workValue['real'] * $parsedComplex['imaginary']) + ($workValue['imaginary'] * $parsedComplex['real']);
2298
        }
2299
2300 62
        if ($returnValue['imaginary'] == 0.0) {
2301
            $activeSuffix = '';
2302
        }
2303
2304 62
        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
     *
2315
     *    Excel Function:
2316
     *        DELTA(a[,b])
2317
     *
2318
     * @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
     */
2322 25
    public static function DELTA($a, $b = 0)
2323
    {
2324 25
        $a = Functions::flattenSingleValue($a);
2325 25
        $b = Functions::flattenSingleValue($b);
2326
2327 25
        return (int) ($a == $b);
2328
    }
2329
2330
    /**
2331
     *    GESTEP
2332
     *
2333
     *    Excel Function:
2334
     *        GESTEP(number[,step])
2335
     *
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
     *    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 81
    public static function GESTEP($number, $step = 0)
2346
    {
2347 81
        $number = Functions::flattenSingleValue($number);
2348 81
        $step = Functions::flattenSingleValue($step);
2349
2350 81
        return (int) ($number >= $step);
2351
    }
2352
2353
    //
2354
    //    Private method to calculate the erf value
2355
    //
2356
    private static $twoSqrtPi = 1.128379167095512574;
2357
2358 148
    public static function erfVal($x)
2359
    {
2360 148
        if (abs($x) > 2.2) {
2361 67
            return 1 - self::erfcVal($x);
2362
        }
2363 123
        $sum = $term = $x;
2364 123
        $xsqr = ($x * $x);
2365 123
        $j = 1;
2366
        do {
2367 123
            $term *= $xsqr / $j;
2368 123
            $sum -= $term / (2 * $j + 1);
2369 123
            ++$j;
2370 123
            $term *= $xsqr / $j;
2371 123
            $sum += $term / (2 * $j + 1);
2372 123
            ++$j;
2373 123
            if ($sum == 0.0) {
2374 19
                break;
2375
            }
2376 112
        } while (abs($term / $sum) > PRECISION);
2377
2378 123
        return self::$twoSqrtPi * $sum;
2379
    }
2380
2381
    /**
2382
     *    ERF
2383
     *
2384
     *    Returns the error function integrated between the lower and upper bound arguments.
2385
     *
2386
     *    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
     * @param    float $upper upper bound for integrating ERF.
2396
     *                                If omitted, ERF integrates between zero and lower_limit
2397
     * @return    float
2398
     */
2399 123
    public static function ERF($lower, $upper = null)
2400
    {
2401 123
        $lower = Functions::flattenSingleValue($lower);
2402 123
        $upper = Functions::flattenSingleValue($upper);
2403
2404 123
        if (is_numeric($lower)) {
2405 120
            if (is_null($upper)) {
2406 37
                return self::erfVal($lower);
2407
            }
2408 83
            if (is_numeric($upper)) {
2409 83
                return self::erfVal($upper) - self::erfVal($lower);
2410
            }
2411
        }
2412
2413 3
        return Functions::VALUE();
2414
    }
2415
2416
    //
2417
    //    Private method to calculate the erfc value
2418
    //
2419
    private static $oneSqrtPi = 0.564189583547756287;
2420
2421 104
    private static function erfcVal($x)
2422
    {
2423 104
        if (abs($x) < 2.2) {
2424 28
            return 1 - self::erfVal($x);
2425
        }
2426 76
        if ($x < 0) {
2427 1
            return 2 - self::ERFC(-$x);
2428
        }
2429 76
        $a = $n = 1;
2430 76
        $b = $c = $x;
2431 76
        $d = ($x * $x) + 0.5;
2432 76
        $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 76
        $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 76
            $t = $a * $n + $b * $x;
2436 76
            $a = $b;
2437 76
            $b = $t;
2438 76
            $t = $c * $n + $d * $x;
2439 76
            $c = $d;
2440 76
            $d = $t;
2441 76
            $n += 0.5;
2442 76
            $q1 = $q2;
2443 76
            $q2 = $b / $d;
2444 76
        } while ((abs($q1 - $q2) / $q2) > PRECISION);
2445
2446 76
        return self::$oneSqrtPi * exp(-$x * $x) * $q2;
2447
    }
2448
2449
    /**
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
     *
2459
     *    Excel Function:
2460
     *        ERFC(x)
2461
     *
2462
     * @param    float $x The lower bound for integrating ERFC
2463
     * @return    float
2464
     */
2465 41
    public static function ERFC($x)
2466
    {
2467 41
        $x = Functions::flattenSingleValue($x);
2468
2469 41
        if (is_numeric($x)) {
2470 38
            return self::erfcVal($x);
2471
        }
2472
2473 3
        return Functions::VALUE();
2474
    }
2475
2476
    /**
2477
     *    getConversionGroups
2478
     *    Returns a list of the different conversion groups for UOM conversions
2479
     *
2480
     * @return    array
2481
     */
2482 1
    public static function getConversionGroups()
2483
    {
2484 1
        $conversionGroups = [];
2485 1
        foreach (self::$conversionUnits as $conversionUnit) {
2486 1
            $conversionGroups[] = $conversionUnit['Group'];
2487
        }
2488
2489 1
        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 1
    public static function getConversionGroupUnits($group = null)
2500
    {
2501 1
        $conversionGroups = [];
2502 1
        foreach (self::$conversionUnits as $conversionUnit => $conversionGroup) {
2503 1
            if ((is_null($group)) || ($conversionGroup['Group'] == $group)) {
2504 1
                $conversionGroups[$conversionGroup['Group']][] = $conversionUnit;
2505
            }
2506
        }
2507
2508 1
        return $conversionGroups;
2509
    }
2510
2511
    /**
2512
     *    getConversionGroupUnitDetails
2513
     *
2514
     * @param    string $group The group whose units of measure you want to retrieve
2515
     * @return    array
2516
     */
2517 1
    public static function getConversionGroupUnitDetails($group = null)
2518
    {
2519 1
        $conversionGroups = [];
2520 1
        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 1
                    'description' => $conversionGroup['Unit Name'],
2525
                ];
2526
            }
2527
        }
2528
2529 1
        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
     * @return    array of mixed
2537
     */
2538 1
    public static function getConversionMultipliers()
2539
    {
2540 1
        return self::$conversionMultipliers;
2541
    }
2542
2543
    /**
2544
     *    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
     * @param    string $fromUOM The units for value.
2555
     * @param    string $toUOM The units for the result.
2556
     *
2557
     * @return    float
2558
     */
2559 24
    public static function CONVERTUOM($value, $fromUOM, $toUOM)
2560
    {
2561 24
        $value = Functions::flattenSingleValue($value);
2562 24
        $fromUOM = Functions::flattenSingleValue($fromUOM);
2563 24
        $toUOM = Functions::flattenSingleValue($toUOM);
2564
2565 24
        if (!is_numeric($value)) {
2566 1
            return Functions::VALUE();
2567
        }
2568 23
        $fromMultiplier = 1.0;
2569 23 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 16
            $unitGroup1 = self::$conversionUnits[$fromUOM]['Group'];
2571
        } else {
2572 7
            $fromMultiplier = substr($fromUOM, 0, 1);
2573 7
            $fromUOM = substr($fromUOM, 1);
2574 7
            if (isset(self::$conversionMultipliers[$fromMultiplier])) {
2575 6
                $fromMultiplier = self::$conversionMultipliers[$fromMultiplier]['multiplier'];
2576
            } else {
2577 1
                return Functions::NA();
2578
            }
2579 6
            if ((isset(self::$conversionUnits[$fromUOM])) && (self::$conversionUnits[$fromUOM]['AllowPrefix'])) {
2580 5
                $unitGroup1 = self::$conversionUnits[$fromUOM]['Group'];
2581
            } else {
2582 1
                return Functions::NA();
2583
            }
2584
        }
2585 21
        $value *= $fromMultiplier;
2586
2587 21
        $toMultiplier = 1.0;
2588 21 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 14
            $unitGroup2 = self::$conversionUnits[$toUOM]['Group'];
2590
        } else {
2591 7
            $toMultiplier = substr($toUOM, 0, 1);
2592 7
            $toUOM = substr($toUOM, 1);
2593 7
            if (isset(self::$conversionMultipliers[$toMultiplier])) {
2594 6
                $toMultiplier = self::$conversionMultipliers[$toMultiplier]['multiplier'];
2595
            } else {
2596 1
                return Functions::NA();
2597
            }
2598 6
            if ((isset(self::$conversionUnits[$toUOM])) && (self::$conversionUnits[$toUOM]['AllowPrefix'])) {
2599 5
                $unitGroup2 = self::$conversionUnits[$toUOM]['Group'];
2600
            } else {
2601 1
                return Functions::NA();
2602
            }
2603
        }
2604 19
        if ($unitGroup1 != $unitGroup2) {
2605 2
            return Functions::NA();
2606
        }
2607
2608 17
        if (($fromUOM == $toUOM) && ($fromMultiplier == $toMultiplier)) {
2609
            //    We've already factored $fromMultiplier into the value, so we need
2610
            //        to reverse it again
2611 3
            return $value / $fromMultiplier;
2612 14
        } elseif ($unitGroup1 == 'Temperature') {
2613 9
            if (($fromUOM == 'F') || ($fromUOM == 'fah')) {
2614 3
                if (($toUOM == 'F') || ($toUOM == 'fah')) {
2615 1
                    return $value;
2616
                } else {
2617 2
                    $value = (($value - 32) / 1.8);
2618 2
                    if (($toUOM == 'K') || ($toUOM == 'kel')) {
2619 1
                        $value += 273.15;
2620
                    }
2621
2622 2
                    return $value;
2623
                }
2624 6
            } elseif ((($fromUOM == 'K') || ($fromUOM == 'kel')) &&
2625 6
                (($toUOM == 'K') || ($toUOM == 'kel'))
2626
            ) {
2627 1
                return $value;
2628 5
            } elseif ((($fromUOM == 'C') || ($fromUOM == 'cel')) &&
2629 5
                (($toUOM == 'C') || ($toUOM == 'cel'))
2630
            ) {
2631 1
                return $value;
2632
            }
2633 4
            if (($toUOM == 'F') || ($toUOM == 'fah')) {
2634 2
                if (($fromUOM == 'K') || ($fromUOM == 'kel')) {
2635 1
                    $value -= 273.15;
2636
                }
2637
2638 2
                return ($value * 1.8) + 32;
2639
            }
2640 2
            if (($toUOM == 'C') || ($toUOM == 'cel')) {
2641 1
                return $value - 273.15;
2642
            }
2643
2644 1
            return $value + 273.15;
2645
        }
2646
2647 5
        return ($value * self::$unitConversions[$unitGroup1][$fromUOM][$toUOM]) / $toMultiplier;
2648
    }
2649
}
2650