Completed
Push — develop ( e1f81f...539a89 )
by Adrien
16:11
created

Engineering::IMARGUMENT()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 20
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 16
nc 6
nop 1
dl 0
loc 20
rs 8.8571
c 0
b 0
f 0
1
<?php
2
3
namespace PhpSpreadsheet\Calculation;
4
5
/** EULER */
6
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 = array(
38
        'g' => array('Group' => 'Mass', 'Unit Name' => 'Gram', 'AllowPrefix' => true),
39
        'sg' => array('Group' => 'Mass', 'Unit Name' => 'Slug', 'AllowPrefix' => false),
40
        'lbm' => array('Group' => 'Mass', 'Unit Name' => 'Pound mass (avoirdupois)', 'AllowPrefix' => false),
41
        'u' => array('Group' => 'Mass', 'Unit Name' => 'U (atomic mass unit)', 'AllowPrefix' => true),
42
        'ozm' => array('Group' => 'Mass', 'Unit Name' => 'Ounce mass (avoirdupois)', 'AllowPrefix' => false),
43
        'm' => array('Group' => 'Distance', 'Unit Name' => 'Meter', 'AllowPrefix' => true),
44
        'mi' => array('Group' => 'Distance', 'Unit Name' => 'Statute mile', 'AllowPrefix' => false),
45
        'Nmi' => array('Group' => 'Distance', 'Unit Name' => 'Nautical mile', 'AllowPrefix' => false),
46
        'in' => array('Group' => 'Distance', 'Unit Name' => 'Inch', 'AllowPrefix' => false),
47
        'ft' => array('Group' => 'Distance', 'Unit Name' => 'Foot', 'AllowPrefix' => false),
48
        'yd' => array('Group' => 'Distance', 'Unit Name' => 'Yard', 'AllowPrefix' => false),
49
        'ang' => array('Group' => 'Distance', 'Unit Name' => 'Angstrom', 'AllowPrefix' => true),
50
        'Pica' => array('Group' => 'Distance', 'Unit Name' => 'Pica (1/72 in)', 'AllowPrefix' => false),
51
        'yr' => array('Group' => 'Time', 'Unit Name' => 'Year', 'AllowPrefix' => false),
52
        'day' => array('Group' => 'Time', 'Unit Name' => 'Day', 'AllowPrefix' => false),
53
        'hr' => array('Group' => 'Time', 'Unit Name' => 'Hour', 'AllowPrefix' => false),
54
        'mn' => array('Group' => 'Time', 'Unit Name' => 'Minute', 'AllowPrefix' => false),
55
        'sec' => array('Group' => 'Time', 'Unit Name' => 'Second', 'AllowPrefix' => true),
56
        'Pa' => array('Group' => 'Pressure', 'Unit Name' => 'Pascal', 'AllowPrefix' => true),
57
        'p' => array('Group' => 'Pressure', 'Unit Name' => 'Pascal', 'AllowPrefix' => true),
58
        'atm' => array('Group' => 'Pressure', 'Unit Name' => 'Atmosphere', 'AllowPrefix' => true),
59
        'at' => array('Group' => 'Pressure', 'Unit Name' => 'Atmosphere', 'AllowPrefix' => true),
60
        'mmHg' => array('Group' => 'Pressure', 'Unit Name' => 'mm of Mercury', 'AllowPrefix' => true),
61
        'N' => array('Group' => 'Force', 'Unit Name' => 'Newton', 'AllowPrefix' => true),
62
        'dyn' => array('Group' => 'Force', 'Unit Name' => 'Dyne', 'AllowPrefix' => true),
63
        'dy' => array('Group' => 'Force', 'Unit Name' => 'Dyne', 'AllowPrefix' => true),
64
        'lbf' => array('Group' => 'Force', 'Unit Name' => 'Pound force', 'AllowPrefix' => false),
65
        'J' => array('Group' => 'Energy', 'Unit Name' => 'Joule', 'AllowPrefix' => true),
66
        'e' => array('Group' => 'Energy', 'Unit Name' => 'Erg', 'AllowPrefix' => true),
67
        'c' => array('Group' => 'Energy', 'Unit Name' => 'Thermodynamic calorie', 'AllowPrefix' => true),
68
        'cal' => array('Group' => 'Energy', 'Unit Name' => 'IT calorie', 'AllowPrefix' => true),
69
        'eV' => array('Group' => 'Energy', 'Unit Name' => 'Electron volt', 'AllowPrefix' => true),
70
        'ev' => array('Group' => 'Energy', 'Unit Name' => 'Electron volt', 'AllowPrefix' => true),
71
        'HPh' => array('Group' => 'Energy', 'Unit Name' => 'Horsepower-hour', 'AllowPrefix' => false),
72
        'hh' => array('Group' => 'Energy', 'Unit Name' => 'Horsepower-hour', 'AllowPrefix' => false),
73
        'Wh' => array('Group' => 'Energy', 'Unit Name' => 'Watt-hour', 'AllowPrefix' => true),
74
        'wh' => array('Group' => 'Energy', 'Unit Name' => 'Watt-hour', 'AllowPrefix' => true),
75
        'flb' => array('Group' => 'Energy', 'Unit Name' => 'Foot-pound', 'AllowPrefix' => false),
76
        'BTU' => array('Group' => 'Energy', 'Unit Name' => 'BTU', 'AllowPrefix' => false),
77
        'btu' => array('Group' => 'Energy', 'Unit Name' => 'BTU', 'AllowPrefix' => false),
78
        'HP' => array('Group' => 'Power', 'Unit Name' => 'Horsepower', 'AllowPrefix' => false),
79
        'h' => array('Group' => 'Power', 'Unit Name' => 'Horsepower', 'AllowPrefix' => false),
80
        'W' => array('Group' => 'Power', 'Unit Name' => 'Watt', 'AllowPrefix' => true),
81
        'w' => array('Group' => 'Power', 'Unit Name' => 'Watt', 'AllowPrefix' => true),
82
        'T' => array('Group' => 'Magnetism', 'Unit Name' => 'Tesla', 'AllowPrefix' => true),
83
        'ga' => array('Group' => 'Magnetism', 'Unit Name' => 'Gauss', 'AllowPrefix' => true),
84
        'C' => array('Group' => 'Temperature', 'Unit Name' => 'Celsius', 'AllowPrefix' => false),
85
        'cel' => array('Group' => 'Temperature', 'Unit Name' => 'Celsius', 'AllowPrefix' => false),
86
        'F' => array('Group' => 'Temperature', 'Unit Name' => 'Fahrenheit', 'AllowPrefix' => false),
87
        'fah' => array('Group' => 'Temperature', 'Unit Name' => 'Fahrenheit', 'AllowPrefix' => false),
88
        'K' => array('Group' => 'Temperature', 'Unit Name' => 'Kelvin', 'AllowPrefix' => false),
89
        'kel' => array('Group' => 'Temperature', 'Unit Name' => 'Kelvin', 'AllowPrefix' => false),
90
        'tsp' => array('Group' => 'Liquid', 'Unit Name' => 'Teaspoon', 'AllowPrefix' => false),
91
        'tbs' => array('Group' => 'Liquid', 'Unit Name' => 'Tablespoon', 'AllowPrefix' => false),
92
        'oz' => array('Group' => 'Liquid', 'Unit Name' => 'Fluid Ounce', 'AllowPrefix' => false),
93
        'cup' => array('Group' => 'Liquid', 'Unit Name' => 'Cup', 'AllowPrefix' => false),
94
        'pt' => array('Group' => 'Liquid', 'Unit Name' => 'U.S. Pint', 'AllowPrefix' => false),
95
        'us_pt' => array('Group' => 'Liquid', 'Unit Name' => 'U.S. Pint', 'AllowPrefix' => false),
96
        'uk_pt' => array('Group' => 'Liquid', 'Unit Name' => 'U.K. Pint', 'AllowPrefix' => false),
97
        'qt' => array('Group' => 'Liquid', 'Unit Name' => 'Quart', 'AllowPrefix' => false),
98
        'gal' => array('Group' => 'Liquid', 'Unit Name' => 'Gallon', 'AllowPrefix' => false),
99
        'l' => array('Group' => 'Liquid', 'Unit Name' => 'Litre', 'AllowPrefix' => true),
100
        'lt' => array('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 = array(
109
        'Y' => array('multiplier' => 1E24, 'name' => 'yotta'),
110
        'Z' => array('multiplier' => 1E21, 'name' => 'zetta'),
111
        'E' => array('multiplier' => 1E18, 'name' => 'exa'),
112
        'P' => array('multiplier' => 1E15, 'name' => 'peta'),
113
        'T' => array('multiplier' => 1E12, 'name' => 'tera'),
114
        'G' => array('multiplier' => 1E9, 'name' => 'giga'),
115
        'M' => array('multiplier' => 1E6, 'name' => 'mega'),
116
        'k' => array('multiplier' => 1E3, 'name' => 'kilo'),
117
        'h' => array('multiplier' => 1E2, 'name' => 'hecto'),
118
        'e' => array('multiplier' => 1E1, 'name' => 'deka'),
119
        'd' => array('multiplier' => 1E-1, 'name' => 'deci'),
120
        'c' => array('multiplier' => 1E-2, 'name' => 'centi'),
121
        'm' => array('multiplier' => 1E-3, 'name' => 'milli'),
122
        'u' => array('multiplier' => 1E-6, 'name' => 'micro'),
123
        'n' => array('multiplier' => 1E-9, 'name' => 'nano'),
124
        'p' => array('multiplier' => 1E-12, 'name' => 'pico'),
125
        'f' => array('multiplier' => 1E-15, 'name' => 'femto'),
126
        'a' => array('multiplier' => 1E-18, 'name' => 'atto'),
127
        'z' => array('multiplier' => 1E-21, 'name' => 'zepto'),
128
        'y' => array('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 = array(
137
        'Mass' => array(
138
            'g' => array(
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' => array(
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' => array(
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' => array(
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' => array(
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' => array(
175
            'm' => array(
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' => array(
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' => array(
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' => array(
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' => array(
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' => array(
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' => array(
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' => array(
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' => array(
257
            'yr' => array(
258
                'yr' => 1.0,
259
                'day' => 365.25,
260
                'hr' => 8766.0,
261
                'mn' => 525960.0,
262
                'sec' => 31557600.0,
263
            ),
264
            'day' => array(
265
                'yr' => 2.73785078713210E-03,
266
                'day' => 1.0,
267
                'hr' => 24.0,
268
                'mn' => 1440.0,
269
                'sec' => 86400.0,
270
            ),
271
            'hr' => array(
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' => array(
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' => array(
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' => array(
294
            'Pa' => array(
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' => array(
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' => array(
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' => array(
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' => array(
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' => array(
331
            'N' => array(
332
                'N' => 1.0,
333
                'dyn' => 1.0E+5,
334
                'dy' => 1.0E+5,
335
                'lbf' => 2.24808923655339E-01,
336
            ),
337
            'dyn' => array(
338
                'N' => 1.0E-5,
339
                'dyn' => 1.0,
340
                'dy' => 1.0,
341
                'lbf' => 2.24808923655339E-06,
342
            ),
343
            'dy' => array(
344
                'N' => 1.0E-5,
345
                'dyn' => 1.0,
346
                'dy' => 1.0,
347
                'lbf' => 2.24808923655339E-06,
348
            ),
349
            'lbf' => array(
350
                'N' => 4.448222,
351
                'dyn' => 4.448222E+5,
352
                'dy' => 4.448222E+5,
353
                'lbf' => 1.0,
354
            ),
355
        ),
356
        'Energy' => array(
357
            'J' => array(
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' => array(
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' => array(
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' => array(
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' => array(
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' => array(
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' => array(
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' => array(
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' => array(
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' => array(
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' => array(
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' => array(
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' => array(
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' => array(
554
            'HP' => array(
555
                'HP' => 1.0,
556
                'h' => 1.0,
557
                'W' => 7.45701000000000E+02,
558
                'w' => 7.45701000000000E+02,
559
            ),
560
            'h' => array(
561
                'HP' => 1.0,
562
                'h' => 1.0,
563
                'W' => 7.45701000000000E+02,
564
                'w' => 7.45701000000000E+02,
565
            ),
566
            'W' => array(
567
                'HP' => 1.34102006031908E-03,
568
                'h' => 1.34102006031908E-03,
569
                'W' => 1.0,
570
                'w' => 1.0,
571
            ),
572
            'w' => array(
573
                'HP' => 1.34102006031908E-03,
574
                'h' => 1.34102006031908E-03,
575
                'W' => 1.0,
576
                'w' => 1.0,
577
            ),
578
        ),
579
        'Magnetism' => array(
580
            'T' => array(
581
                'T' => 1.0,
582
                'ga' => 10000.0,
583
            ),
584
            'ga' => array(
585
                'T' => 0.0001,
586
                'ga' => 1.0,
587
            ),
588
        ),
589
        'Liquid' => array(
590
            'tsp' => array(
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' => array(
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' => array(
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' => array(
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' => array(
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' => array(
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' => array(
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' => array(
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' => array(
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' => array(
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' => array(
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
    /**
738
     * parseComplex
739
     *
740
     * Parses a complex number into its real and imaginary parts, and an I or J suffix
741
     *
742
     * @param    string $complexNumber The complex number
743
     * @return    string[]    Indexed on "real", "imaginary" and "suffix"
744
     */
745
    public static function parseComplex($complexNumber)
746
    {
747
        $workString = (string)$complexNumber;
748
749
        $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...
750
        //    Extract the suffix, if there is one
751
        $suffix = substr($workString, -1);
752
        if (!is_numeric($suffix)) {
753
            $workString = substr($workString, 0, -1);
754
        } else {
755
            $suffix = '';
756
        }
757
758
        //    Split the input into its Real and Imaginary components
759
        $leadingSign = 0;
760
        if (strlen($workString) > 0) {
761
            $leadingSign = (($workString{0} == '+') || ($workString{0} == '-')) ? 1 : 0;
762
        }
763
        $power = '';
764
        $realNumber = strtok($workString, '+-');
765
        if (strtoupper(substr($realNumber, -1)) == 'E') {
766
            $power = strtok('+-');
767
            ++$leadingSign;
768
        }
769
770
        $realNumber = substr($workString, 0, strlen($realNumber) + strlen($power) + $leadingSign);
771
772
        if ($suffix != '') {
773
            $imaginary = substr($workString, strlen($realNumber));
774
775
            if (($imaginary == '') && (($realNumber == '') || ($realNumber == '+') || ($realNumber == '-'))) {
776
                $imaginary = $realNumber . '1';
777
                $realNumber = '0';
778
            } elseif ($imaginary == '') {
779
                $imaginary = $realNumber;
780
                $realNumber = '0';
781
            } elseif (($imaginary == '+') || ($imaginary == '-')) {
782
                $imaginary .= '1';
783
            }
784
        }
785
786
        return array(
787
            'real' => $realNumber,
788
            'imaginary' => $imaginary,
789
            'suffix' => $suffix
790
        );
791
    }
792
793
794
    /**
795
     * Cleans the leading characters in a complex number string
796
     *
797
     * @param    string $complexNumber The complex number to clean
798
     * @return    string        The "cleaned" complex number
799
     */
800
    private static function cleanComplex($complexNumber)
801
    {
802
        if ($complexNumber{0} == '+') {
803
            $complexNumber = substr($complexNumber, 1);
804
        }
805
        if ($complexNumber{0} == '0') {
806
            $complexNumber = substr($complexNumber, 1);
807
        }
808
        if ($complexNumber{0} == '.') {
809
            $complexNumber = '0' . $complexNumber;
810
        }
811
        if ($complexNumber{0} == '+') {
812
            $complexNumber = substr($complexNumber, 1);
813
        }
814
        return $complexNumber;
815
    }
816
817
    /**
818
     * Formats a number base string value with leading zeroes
819
     *
820
     * @param    string $xVal The "number" to pad
821
     * @param    integer $places The length that we want to pad this value
822
     * @return    string        The padded "number"
823
     */
824
    private static function nbrConversionFormat($xVal, $places)
825
    {
826
        if (!is_null($places)) {
827
            if (is_numeric($places)) {
828
                $places = (int)$places;
829
            } else {
830
                return Functions::VALUE();
831
            }
832
            if ($places < 0) {
833
                return Functions::NAN();
834
            }
835
            if (strlen($xVal) <= $places) {
836
                return substr(str_pad($xVal, $places, '0', STR_PAD_LEFT), -10);
837
            } else {
838
                return Functions::NAN();
839
            }
840
        }
841
842
        return substr($xVal, -10);
843
    }
844
845
    /**
846
     *    BESSELI
847
     *
848
     *    Returns the modified Bessel function In(x), which is equivalent to the Bessel function evaluated
849
     *        for purely imaginary arguments
850
     *
851
     *    Excel Function:
852
     *        BESSELI(x,ord)
853
     *
854
     * @access    public
855
     * @category Engineering Functions
856
     * @param    float $x The value at which to evaluate the function.
857
     *                                If x is nonnumeric, BESSELI returns the #VALUE! error value.
858
     * @param    integer $ord The order of the Bessel function.
859
     *                                If ord is not an integer, it is truncated.
860
     *                                If $ord is nonnumeric, BESSELI returns the #VALUE! error value.
861
     *                                If $ord < 0, BESSELI returns the #NUM! error value.
862
     * @return    float
863
     *
864
     */
865
    public static function BESSELI($x, $ord)
866
    {
867
        $x = (is_null($x)) ? 0.0 : Functions::flattenSingleValue($x);
868
        $ord = (is_null($ord)) ? 0.0 : Functions::flattenSingleValue($ord);
869
870
        if ((is_numeric($x)) && (is_numeric($ord))) {
871
            $ord = floor($ord);
872
            if ($ord < 0) {
873
                return Functions::NAN();
874
            }
875
876
            if (abs($x) <= 30) {
877
                $fResult = $fTerm = pow($x / 2, $ord) / MathTrig::FACT($ord);
878
                $ordK = 1;
879
                $fSqrX = ($x * $x) / 4;
880 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...
881
                    $fTerm *= $fSqrX;
882
                    $fTerm /= ($ordK * ($ordK + $ord));
883
                    $fResult += $fTerm;
884
                } while ((abs($fTerm) > 1e-12) && (++$ordK < 100));
885
            } else {
886
                $f_2_PI = 2 * M_PI;
887
888
                $fXAbs = abs($x);
889
                $fResult = exp($fXAbs) / sqrt($f_2_PI * $fXAbs);
890
                if (($ord & 1) && ($x < 0)) {
891
                    $fResult = -$fResult;
892
                }
893
            }
894
            return (is_nan($fResult)) ? Functions::NAN() : $fResult;
895
        }
896
        return Functions::VALUE();
897
    }
898
899
900
    /**
901
     *    BESSELJ
902
     *
903
     *    Returns the Bessel function
904
     *
905
     *    Excel Function:
906
     *        BESSELJ(x,ord)
907
     *
908
     * @access    public
909
     * @category Engineering Functions
910
     * @param    float $x The value at which to evaluate the function.
911
     *                                If x is nonnumeric, BESSELJ returns the #VALUE! error value.
912
     * @param    integer $ord The order of the Bessel function. If n is not an integer, it is truncated.
913
     *                                If $ord is nonnumeric, BESSELJ returns the #VALUE! error value.
914
     *                                If $ord < 0, BESSELJ returns the #NUM! error value.
915
     * @return    float
916
     *
917
     */
918
    public static function BESSELJ($x, $ord)
919
    {
920
        $x = (is_null($x)) ? 0.0 : Functions::flattenSingleValue($x);
921
        $ord = (is_null($ord)) ? 0.0 : Functions::flattenSingleValue($ord);
922
923
        if ((is_numeric($x)) && (is_numeric($ord))) {
924
            $ord = floor($ord);
925
            if ($ord < 0) {
926
                return Functions::NAN();
927
            }
928
929
            $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...
930
            if (abs($x) <= 30) {
931
                $fResult = $fTerm = pow($x / 2, $ord) / MathTrig::FACT($ord);
932
                $ordK = 1;
933
                $fSqrX = ($x * $x) / -4;
934 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...
935
                    $fTerm *= $fSqrX;
936
                    $fTerm /= ($ordK * ($ordK + $ord));
937
                    $fResult += $fTerm;
938
                } while ((abs($fTerm) > 1e-12) && (++$ordK < 100));
939
            } else {
940
                $f_PI_DIV_2 = M_PI / 2;
941
                $f_PI_DIV_4 = M_PI / 4;
942
943
                $fXAbs = abs($x);
944
                $fResult = sqrt(M_2DIVPI / $fXAbs) * cos($fXAbs - $ord * $f_PI_DIV_2 - $f_PI_DIV_4);
945
                if (($ord & 1) && ($x < 0)) {
946
                    $fResult = -$fResult;
947
                }
948
            }
949
            return (is_nan($fResult)) ? Functions::NAN() : $fResult;
950
        }
951
        return Functions::VALUE();
952
    }
953
954
955
    private static function besselK0($fNum)
956
    {
957
        if ($fNum <= 2) {
958
            $fNum2 = $fNum * 0.5;
959
            $y = ($fNum2 * $fNum2);
960
            $fRet = -log($fNum2) * self::BESSELI($fNum, 0) +
961
                (-0.57721566 + $y * (0.42278420 + $y * (0.23069756 + $y * (0.3488590e-1 + $y * (0.262698e-2 + $y *
962
                                    (0.10750e-3 + $y * 0.74e-5))))));
963 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...
964
            $y = 2 / $fNum;
965
            $fRet = exp(-$fNum) / sqrt($fNum) *
966
                (1.25331414 + $y * (-0.7832358e-1 + $y * (0.2189568e-1 + $y * (-0.1062446e-1 + $y *
967
                                (0.587872e-2 + $y * (-0.251540e-2 + $y * 0.53208e-3))))));
968
        }
969
        return $fRet;
970
    }
971
972
973
    private static function besselK1($fNum)
974
    {
975
        if ($fNum <= 2) {
976
            $fNum2 = $fNum * 0.5;
977
            $y = ($fNum2 * $fNum2);
978
            $fRet = log($fNum2) * self::BESSELI($fNum, 1) +
979
                (1 + $y * (0.15443144 + $y * (-0.67278579 + $y * (-0.18156897 + $y * (-0.1919402e-1 + $y *
980
                                    (-0.110404e-2 + $y * (-0.4686e-4))))))) / $fNum;
981 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...
982
            $y = 2 / $fNum;
983
            $fRet = exp(-$fNum) / sqrt($fNum) *
984
                (1.25331414 + $y * (0.23498619 + $y * (-0.3655620e-1 + $y * (0.1504268e-1 + $y * (-0.780353e-2 + $y *
985
                                    (0.325614e-2 + $y * (-0.68245e-3)))))));
986
        }
987
        return $fRet;
988
    }
989
990
991
    /**
992
     *    BESSELK
993
     *
994
     *    Returns the modified Bessel function Kn(x), which is equivalent to the Bessel functions evaluated
995
     *        for purely imaginary arguments.
996
     *
997
     *    Excel Function:
998
     *        BESSELK(x,ord)
999
     *
1000
     * @access    public
1001
     * @category Engineering Functions
1002
     * @param    float $x The value at which to evaluate the function.
1003
     *                                If x is nonnumeric, BESSELK returns the #VALUE! error value.
1004
     * @param    integer $ord The order of the Bessel function. If n is not an integer, it is truncated.
1005
     *                                If $ord is nonnumeric, BESSELK returns the #VALUE! error value.
1006
     *                                If $ord < 0, BESSELK returns the #NUM! error value.
1007
     * @return    float
1008
     *
1009
     */
1010 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...
1011
    {
1012
        $x = (is_null($x)) ? 0.0 : Functions::flattenSingleValue($x);
1013
        $ord = (is_null($ord)) ? 0.0 : Functions::flattenSingleValue($ord);
1014
1015
        if ((is_numeric($x)) && (is_numeric($ord))) {
1016
            if (($ord < 0) || ($x == 0.0)) {
1017
                return Functions::NAN();
1018
            }
1019
1020
            switch (floor($ord)) {
1021
                case 0:
1022
                    $fBk = self::besselK0($x);
1023
                    break;
1024
                case 1:
1025
                    $fBk = self::besselK1($x);
1026
                    break;
1027
                default:
1028
                    $fTox = 2 / $x;
1029
                    $fBkm = self::besselK0($x);
1030
                    $fBk = self::besselK1($x);
1031
                    for ($n = 1; $n < $ord; ++$n) {
1032
                        $fBkp = $fBkm + $n * $fTox * $fBk;
1033
                        $fBkm = $fBk;
1034
                        $fBk = $fBkp;
1035
                    }
1036
            }
1037
            return (is_nan($fBk)) ? Functions::NAN() : $fBk;
1038
        }
1039
        return Functions::VALUE();
1040
    }
1041
1042
1043
    private static function besselY0($fNum)
1044
    {
1045
        if ($fNum < 8.0) {
1046
            $y = ($fNum * $fNum);
1047
            $f1 = -2957821389.0 + $y * (7062834065.0 + $y * (-512359803.6 + $y * (10879881.29 + $y * (-86327.92757 + $y * 228.4622733))));
1048
            $f2 = 40076544269.0 + $y * (745249964.8 + $y * (7189466.438 + $y * (47447.26470 + $y * (226.1030244 + $y))));
1049
            $fRet = $f1 / $f2 + 0.636619772 * self::BESSELJ($fNum, 0) * log($fNum);
1050
        } else {
1051
            $z = 8.0 / $fNum;
1052
            $y = ($z * $z);
1053
            $xx = $fNum - 0.785398164;
1054
            $f1 = 1 + $y * (-0.1098628627e-2 + $y * (0.2734510407e-4 + $y * (-0.2073370639e-5 + $y * 0.2093887211e-6)));
1055
            $f2 = -0.1562499995e-1 + $y * (0.1430488765e-3 + $y * (-0.6911147651e-5 + $y * (0.7621095161e-6 + $y * (-0.934945152e-7))));
1056
            $fRet = sqrt(0.636619772 / $fNum) * (sin($xx) * $f1 + $z * cos($xx) * $f2);
1057
        }
1058
        return $fRet;
1059
    }
1060
1061
1062
    private static function besselY1($fNum)
1063
    {
1064
        if ($fNum < 8.0) {
1065
            $y = ($fNum * $fNum);
1066
            $f1 = $fNum * (-0.4900604943e13 + $y * (0.1275274390e13 + $y * (-0.5153438139e11 + $y * (0.7349264551e9 + $y *
1067
                                (-0.4237922726e7 + $y * 0.8511937935e4)))));
1068
            $f2 = 0.2499580570e14 + $y * (0.4244419664e12 + $y * (0.3733650367e10 + $y * (0.2245904002e8 + $y *
1069
                            (0.1020426050e6 + $y * (0.3549632885e3 + $y)))));
1070
            $fRet = $f1 / $f2 + 0.636619772 * (self::BESSELJ($fNum, 1) * log($fNum) - 1 / $fNum);
1071
        } else {
1072
            $fRet = sqrt(0.636619772 / $fNum) * sin($fNum - 2.356194491);
1073
        }
1074
        return $fRet;
1075
    }
1076
1077
1078
    /**
1079
     *    BESSELY
1080
     *
1081
     *    Returns the Bessel function, which is also called the Weber function or the Neumann function.
1082
     *
1083
     *    Excel Function:
1084
     *        BESSELY(x,ord)
1085
     *
1086
     * @access    public
1087
     * @category Engineering Functions
1088
     * @param    float $x The value at which to evaluate the function.
1089
     *                                If x is nonnumeric, BESSELK returns the #VALUE! error value.
1090
     * @param    integer $ord The order of the Bessel function. If n is not an integer, it is truncated.
1091
     *                                If $ord is nonnumeric, BESSELK returns the #VALUE! error value.
1092
     *                                If $ord < 0, BESSELK returns the #NUM! error value.
1093
     *
1094
     * @return    float
1095
     */
1096 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...
1097
    {
1098
        $x = (is_null($x)) ? 0.0 : Functions::flattenSingleValue($x);
1099
        $ord = (is_null($ord)) ? 0.0 : Functions::flattenSingleValue($ord);
1100
1101
        if ((is_numeric($x)) && (is_numeric($ord))) {
1102
            if (($ord < 0) || ($x == 0.0)) {
1103
                return Functions::NAN();
1104
            }
1105
1106
            switch (floor($ord)) {
1107
                case 0:
1108
                    $fBy = self::besselY0($x);
1109
                    break;
1110
                case 1:
1111
                    $fBy = self::besselY1($x);
1112
                    break;
1113
                default:
1114
                    $fTox = 2 / $x;
1115
                    $fBym = self::besselY0($x);
1116
                    $fBy = self::besselY1($x);
1117
                    for ($n = 1; $n < $ord; ++$n) {
1118
                        $fByp = $n * $fTox * $fBy - $fBym;
1119
                        $fBym = $fBy;
1120
                        $fBy = $fByp;
1121
                    }
1122
            }
1123
            return (is_nan($fBy)) ? Functions::NAN() : $fBy;
1124
        }
1125
        return Functions::VALUE();
1126
    }
1127
1128
1129
    /**
1130
     * BINTODEC
1131
     *
1132
     * Return a binary value as decimal.
1133
     *
1134
     * Excel Function:
1135
     *        BIN2DEC(x)
1136
     *
1137
     * @access    public
1138
     * @category Engineering Functions
1139
     * @param    string $x The binary number (as a string) that you want to convert. The number
1140
     *                                cannot contain more than 10 characters (10 bits). The most significant
1141
     *                                bit of number is the sign bit. The remaining 9 bits are magnitude bits.
1142
     *                                Negative numbers are represented using two's-complement notation.
1143
     *                                If number is not a valid binary number, or if number contains more than
1144
     *                                10 characters (10 bits), BIN2DEC returns the #NUM! error value.
1145
     * @return    string
1146
     */
1147
    public static function BINTODEC($x)
1148
    {
1149
        $x = Functions::flattenSingleValue($x);
1150
1151
        if (is_bool($x)) {
1152
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
1153
                $x = (int)$x;
1154
            } else {
1155
                return Functions::VALUE();
1156
            }
1157
        }
1158
        if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) {
1159
            $x = floor($x);
1160
        }
1161
        $x = (string)$x;
1162
        if (strlen($x) > preg_match_all('/[01]/', $x, $out)) {
1163
            return Functions::NAN();
1164
        }
1165
        if (strlen($x) > 10) {
1166
            return Functions::NAN();
1167
        } elseif (strlen($x) == 10) {
1168
            //    Two's Complement
1169
            $x = substr($x, -9);
1170
            return '-' . (512 - bindec($x));
1171
        }
1172
        return bindec($x);
1173
    }
1174
1175
1176
    /**
1177
     * BINTOHEX
1178
     *
1179
     * Return a binary value as hex.
1180
     *
1181
     * Excel Function:
1182
     *        BIN2HEX(x[,places])
1183
     *
1184
     * @access    public
1185
     * @category Engineering Functions
1186
     * @param    string $x The binary number (as a string) that you want to convert. The number
1187
     *                                cannot contain more than 10 characters (10 bits). The most significant
1188
     *                                bit of number is the sign bit. The remaining 9 bits are magnitude bits.
1189
     *                                Negative numbers are represented using two's-complement notation.
1190
     *                                If number is not a valid binary number, or if number contains more than
1191
     *                                10 characters (10 bits), BIN2HEX returns the #NUM! error value.
1192
     * @param    integer $places The number of characters to use. If places is omitted, BIN2HEX uses the
1193
     *                                minimum number of characters necessary. Places is useful for padding the
1194
     *                                return value with leading 0s (zeros).
1195
     *                                If places is not an integer, it is truncated.
1196
     *                                If places is nonnumeric, BIN2HEX returns the #VALUE! error value.
1197
     *                                If places is negative, BIN2HEX returns the #NUM! error value.
1198
     * @return    string
1199
     */
1200 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...
1201
    {
1202
        $x = Functions::flattenSingleValue($x);
1203
        $places = Functions::flattenSingleValue($places);
1204
1205
        // Argument X
1206
        if (is_bool($x)) {
1207
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
1208
                $x = (int)$x;
1209
            } else {
1210
                return Functions::VALUE();
1211
            }
1212
        }
1213
        if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) {
1214
            $x = floor($x);
1215
        }
1216
        $x = (string)$x;
1217
        if (strlen($x) > preg_match_all('/[01]/', $x, $out)) {
1218
            return Functions::NAN();
1219
        }
1220
        if (strlen($x) > 10) {
1221
            return Functions::NAN();
1222
        } elseif (strlen($x) == 10) {
1223
            //    Two's Complement
1224
            return str_repeat('F', 8) . substr(strtoupper(dechex(bindec(substr($x, -9)))), -2);
1225
        }
1226
        $hexVal = (string)strtoupper(dechex(bindec($x)));
1227
1228
        return self::nbrConversionFormat($hexVal, $places);
1229
    }
1230
1231
1232
    /**
1233
     * BINTOOCT
1234
     *
1235
     * Return a binary value as octal.
1236
     *
1237
     * Excel Function:
1238
     *        BIN2OCT(x[,places])
1239
     *
1240
     * @access    public
1241
     * @category Engineering Functions
1242
     * @param    string $x The binary number (as a string) that you want to convert. The number
1243
     *                                cannot contain more than 10 characters (10 bits). The most significant
1244
     *                                bit of number is the sign bit. The remaining 9 bits are magnitude bits.
1245
     *                                Negative numbers are represented using two's-complement notation.
1246
     *                                If number is not a valid binary number, or if number contains more than
1247
     *                                10 characters (10 bits), BIN2OCT returns the #NUM! error value.
1248
     * @param    integer $places The number of characters to use. If places is omitted, BIN2OCT uses the
1249
     *                                minimum number of characters necessary. Places is useful for padding the
1250
     *                                return value with leading 0s (zeros).
1251
     *                                If places is not an integer, it is truncated.
1252
     *                                If places is nonnumeric, BIN2OCT returns the #VALUE! error value.
1253
     *                                If places is negative, BIN2OCT returns the #NUM! error value.
1254
     * @return    string
1255
     */
1256 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...
1257
    {
1258
        $x = Functions::flattenSingleValue($x);
1259
        $places = Functions::flattenSingleValue($places);
1260
1261
        if (is_bool($x)) {
1262
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
1263
                $x = (int)$x;
1264
            } else {
1265
                return Functions::VALUE();
1266
            }
1267
        }
1268
        if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) {
1269
            $x = floor($x);
1270
        }
1271
        $x = (string)$x;
1272
        if (strlen($x) > preg_match_all('/[01]/', $x, $out)) {
1273
            return Functions::NAN();
1274
        }
1275
        if (strlen($x) > 10) {
1276
            return Functions::NAN();
1277
        } elseif (strlen($x) == 10) {
1278
            //    Two's Complement
1279
            return str_repeat('7', 7) . substr(strtoupper(decoct(bindec(substr($x, -9)))), -3);
1280
        }
1281
        $octVal = (string)decoct(bindec($x));
1282
1283
        return self::nbrConversionFormat($octVal, $places);
1284
    }
1285
1286
1287
    /**
1288
     * DECTOBIN
1289
     *
1290
     * Return a decimal value as binary.
1291
     *
1292
     * Excel Function:
1293
     *        DEC2BIN(x[,places])
1294
     *
1295
     * @access    public
1296
     * @category Engineering Functions
1297
     * @param    string $x The decimal integer you want to convert. If number is negative,
1298
     *                                valid place values are ignored and DEC2BIN returns a 10-character
1299
     *                                (10-bit) binary number in which the most significant bit is the sign
1300
     *                                bit. The remaining 9 bits are magnitude bits. Negative numbers are
1301
     *                                represented using two's-complement notation.
1302
     *                                If number < -512 or if number > 511, DEC2BIN returns the #NUM! error
1303
     *                                value.
1304
     *                                If number is nonnumeric, DEC2BIN returns the #VALUE! error value.
1305
     *                                If DEC2BIN requires more than places characters, it returns the #NUM!
1306
     *                                error value.
1307
     * @param    integer $places The number of characters to use. If places is omitted, DEC2BIN uses
1308
     *                                the minimum number of characters necessary. Places is useful for
1309
     *                                padding the return value with leading 0s (zeros).
1310
     *                                If places is not an integer, it is truncated.
1311
     *                                If places is nonnumeric, DEC2BIN returns the #VALUE! error value.
1312
     *                                If places is zero or negative, DEC2BIN returns the #NUM! error value.
1313
     * @return    string
1314
     */
1315
    public static function DECTOBIN($x, $places = null)
1316
    {
1317
        $x = Functions::flattenSingleValue($x);
1318
        $places = Functions::flattenSingleValue($places);
1319
1320
        if (is_bool($x)) {
1321
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
1322
                $x = (int)$x;
1323
            } else {
1324
                return Functions::VALUE();
1325
            }
1326
        }
1327
        $x = (string)$x;
1328
        if (strlen($x) > preg_match_all('/[-0123456789.]/', $x, $out)) {
1329
            return Functions::VALUE();
1330
        }
1331
1332
        $x = (string)floor($x);
1333
        if ($x < -512 || $x > 511) {
1334
            return Functions::NAN();
1335
        }
1336
1337
        $r = decbin($x);
1338
        // Two's Complement
1339
        $r = substr($r, -10);
1340
        if (strlen($r) >= 11) {
1341
            return Functions::NAN();
1342
        }
1343
1344
        return self::nbrConversionFormat($r, $places);
1345
    }
1346
1347
1348
    /**
1349
     * DECTOHEX
1350
     *
1351
     * Return a decimal value as hex.
1352
     *
1353
     * Excel Function:
1354
     *        DEC2HEX(x[,places])
1355
     *
1356
     * @access    public
1357
     * @category Engineering Functions
1358
     * @param    string $x The decimal integer you want to convert. If number is negative,
1359
     *                                places is ignored and DEC2HEX returns a 10-character (40-bit)
1360
     *                                hexadecimal number in which the most significant bit is the sign
1361
     *                                bit. The remaining 39 bits are magnitude bits. Negative numbers
1362
     *                                are represented using two's-complement notation.
1363
     *                                If number < -549,755,813,888 or if number > 549,755,813,887,
1364
     *                                DEC2HEX returns the #NUM! error value.
1365
     *                                If number is nonnumeric, DEC2HEX returns the #VALUE! error value.
1366
     *                                If DEC2HEX requires more than places characters, it returns the
1367
     *                                #NUM! error value.
1368
     * @param    integer $places The number of characters to use. If places is omitted, DEC2HEX uses
1369
     *                                the minimum number of characters necessary. Places is useful for
1370
     *                                padding the return value with leading 0s (zeros).
1371
     *                                If places is not an integer, it is truncated.
1372
     *                                If places is nonnumeric, DEC2HEX returns the #VALUE! error value.
1373
     *                                If places is zero or negative, DEC2HEX returns the #NUM! error value.
1374
     * @return    string
1375
     */
1376 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...
1377
    {
1378
        $x = Functions::flattenSingleValue($x);
1379
        $places = Functions::flattenSingleValue($places);
1380
1381
        if (is_bool($x)) {
1382
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
1383
                $x = (int)$x;
1384
            } else {
1385
                return Functions::VALUE();
1386
            }
1387
        }
1388
        $x = (string)$x;
1389
        if (strlen($x) > preg_match_all('/[-0123456789.]/', $x, $out)) {
1390
            return Functions::VALUE();
1391
        }
1392
        $x = (string)floor($x);
1393
        $r = strtoupper(dechex($x));
1394
        if (strlen($r) == 8) {
1395
            //    Two's Complement
1396
            $r = 'FF' . $r;
1397
        }
1398
1399
        return self::nbrConversionFormat($r, $places);
1400
    }
1401
1402
1403
    /**
1404
     * DECTOOCT
1405
     *
1406
     * Return an decimal value as octal.
1407
     *
1408
     * Excel Function:
1409
     *        DEC2OCT(x[,places])
1410
     *
1411
     * @access    public
1412
     * @category Engineering Functions
1413
     * @param    string $x The decimal integer you want to convert. If number is negative,
1414
     *                                places is ignored and DEC2OCT returns a 10-character (30-bit)
1415
     *                                octal number in which the most significant bit is the sign bit.
1416
     *                                The remaining 29 bits are magnitude bits. Negative numbers are
1417
     *                                represented using two's-complement notation.
1418
     *                                If number < -536,870,912 or if number > 536,870,911, DEC2OCT
1419
     *                                returns the #NUM! error value.
1420
     *                                If number is nonnumeric, DEC2OCT returns the #VALUE! error value.
1421
     *                                If DEC2OCT requires more than places characters, it returns the
1422
     *                                #NUM! error value.
1423
     * @param    integer $places The number of characters to use. If places is omitted, DEC2OCT uses
1424
     *                                the minimum number of characters necessary. Places is useful for
1425
     *                                padding the return value with leading 0s (zeros).
1426
     *                                If places is not an integer, it is truncated.
1427
     *                                If places is nonnumeric, DEC2OCT returns the #VALUE! error value.
1428
     *                                If places is zero or negative, DEC2OCT returns the #NUM! error value.
1429
     * @return    string
1430
     */
1431 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...
1432
    {
1433
        $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...
1434
        $x = Functions::flattenSingleValue($x);
1435
        $places = Functions::flattenSingleValue($places);
1436
1437
        if (is_bool($x)) {
1438
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
1439
                $x = (int)$x;
1440
            } else {
1441
                return Functions::VALUE();
1442
            }
1443
        }
1444
        $x = (string)$x;
1445
        if (strlen($x) > preg_match_all('/[-0123456789.]/', $x, $out)) {
1446
            return Functions::VALUE();
1447
        }
1448
        $x = (string)floor($x);
1449
        $r = decoct($x);
1450
        if (strlen($r) == 11) {
1451
            //    Two's Complement
1452
            $r = substr($r, -10);
1453
        }
1454
1455
        return self::nbrConversionFormat($r, $places);
1456
    }
1457
1458
1459
    /**
1460
     * HEXTOBIN
1461
     *
1462
     * Return a hex value as binary.
1463
     *
1464
     * Excel Function:
1465
     *        HEX2BIN(x[,places])
1466
     *
1467
     * @access    public
1468
     * @category Engineering Functions
1469
     * @param    string $x the hexadecimal number you want to convert.
1470
     *                  Number cannot contain more than 10 characters.
1471
     *                  The most significant bit of number is the sign bit (40th bit from the right).
1472
     *                  The remaining 9 bits are magnitude bits.
1473
     *                  Negative numbers are represented using two's-complement notation.
1474
     *                  If number is negative, HEX2BIN ignores places and returns a 10-character binary number.
1475
     *                  If number is negative, it cannot be less than FFFFFFFE00,
1476
     *                      and if number is positive, it cannot be greater than 1FF.
1477
     *                  If number is not a valid hexadecimal number, HEX2BIN returns the #NUM! error value.
1478
     *                  If HEX2BIN requires more than places characters, it returns the #NUM! error value.
1479
     * @param    integer $places The number of characters to use. If places is omitted,
1480
     *                                    HEX2BIN uses the minimum number of characters necessary. Places
1481
     *                                    is useful for padding the return value with leading 0s (zeros).
1482
     *                                    If places is not an integer, it is truncated.
1483
     *                                    If places is nonnumeric, HEX2BIN returns the #VALUE! error value.
1484
     *                                    If places is negative, HEX2BIN returns the #NUM! error value.
1485
     * @return    string
1486
     */
1487 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...
1488
    {
1489
        $x = Functions::flattenSingleValue($x);
1490
        $places = Functions::flattenSingleValue($places);
1491
1492
        if (is_bool($x)) {
1493
            return Functions::VALUE();
1494
        }
1495
        $x = (string)$x;
1496
        if (strlen($x) > preg_match_all('/[0123456789ABCDEF]/', strtoupper($x), $out)) {
1497
            return Functions::NAN();
1498
        }
1499
1500
        return self::DECTOBIN(self::HEXTODEC($x), $places);
1501
    }
1502
1503
1504
    /**
1505
     * HEXTODEC
1506
     *
1507
     * Return a hex value as decimal.
1508
     *
1509
     * Excel Function:
1510
     *        HEX2DEC(x)
1511
     *
1512
     * @access    public
1513
     * @category Engineering Functions
1514
     * @param    string $x The hexadecimal number you want to convert. This number cannot
1515
     *                                contain more than 10 characters (40 bits). The most significant
1516
     *                                bit of number is the sign bit. The remaining 39 bits are magnitude
1517
     *                                bits. Negative numbers are represented using two's-complement
1518
     *                                notation.
1519
     *                                If number is not a valid hexadecimal number, HEX2DEC returns the
1520
     *                                #NUM! error value.
1521
     * @return    string
1522
     */
1523
    public static function HEXTODEC($x)
1524
    {
1525
        $x = Functions::flattenSingleValue($x);
1526
1527
        if (is_bool($x)) {
1528
            return Functions::VALUE();
1529
        }
1530
        $x = (string)$x;
1531
        if (strlen($x) > preg_match_all('/[0123456789ABCDEF]/', strtoupper($x), $out)) {
1532
            return Functions::NAN();
1533
        }
1534
1535
        if (strlen($x)> 10) {
1536
            return Functions::NAN();
1537
        }
1538
1539
        $binX = '';
1540 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...
1541
            $binX .= str_pad(base_convert($char, 16, 2), 4, '0', STR_PAD_LEFT);
1542
        }
1543 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...
1544
            for ($i = 0; $i < 40; $i++) {
1545
                $binX[$i] = ($binX[$i] == '1' ? '0' : '1');
1546
            }
1547
            return (bindec($binX) + 1) * -1;
1548
        }
1549
        return bindec($binX);
1550
    }
1551
1552
1553
    /**
1554
     * HEXTOOCT
1555
     *
1556
     * Return a hex value as octal.
1557
     *
1558
     * Excel Function:
1559
     *        HEX2OCT(x[,places])
1560
     *
1561
     * @access    public
1562
     * @category Engineering Functions
1563
     * @param    string $x The hexadecimal number you want to convert. Number cannot
1564
     *                                    contain more than 10 characters. The most significant bit of
1565
     *                                    number is the sign bit. The remaining 39 bits are magnitude
1566
     *                                    bits. Negative numbers are represented using two's-complement
1567
     *                                    notation.
1568
     *                                    If number is negative, HEX2OCT ignores places and returns a
1569
     *                                    10-character octal number.
1570
     *                                    If number is negative, it cannot be less than FFE0000000, and
1571
     *                                    if number is positive, it cannot be greater than 1FFFFFFF.
1572
     *                                    If number is not a valid hexadecimal number, HEX2OCT returns
1573
     *                                    the #NUM! error value.
1574
     *                                    If HEX2OCT requires more than places characters, it returns
1575
     *                                    the #NUM! error value.
1576
     * @param    integer $places The number of characters to use. If places is omitted, HEX2OCT
1577
     *                                    uses the minimum number of characters necessary. Places is
1578
     *                                    useful for padding the return value with leading 0s (zeros).
1579
     *                                    If places is not an integer, it is truncated.
1580
     *                                    If places is nonnumeric, HEX2OCT returns the #VALUE! error
1581
     *                                    value.
1582
     *                                    If places is negative, HEX2OCT returns the #NUM! error value.
1583
     * @return    string
1584
     */
1585
    public static function HEXTOOCT($x, $places = null)
1586
    {
1587
        $x = Functions::flattenSingleValue($x);
1588
        $places = Functions::flattenSingleValue($places);
1589
1590
        if (is_bool($x)) {
1591
            return Functions::VALUE();
1592
        }
1593
        $x = (string)$x;
1594
        if (strlen($x) > preg_match_all('/[0123456789ABCDEF]/', strtoupper($x), $out)) {
1595
            return Functions::NAN();
1596
        }
1597
1598
        $decimal = self::HEXTODEC($x);
1599
        if ($decimal < -536870912 || $decimal > 536870911) {
1600
            return Functions::NAN();
1601
        }
1602
1603
        return self::DECTOOCT($decimal, $places);
1604
    }
1605
1606
    /**
1607
     * OCTTOBIN
1608
     *
1609
     * Return an octal value as binary.
1610
     *
1611
     * Excel Function:
1612
     *        OCT2BIN(x[,places])
1613
     *
1614
     * @access    public
1615
     * @category Engineering Functions
1616
     * @param    string $x The octal number you want to convert. Number may not
1617
     *                                    contain more than 10 characters. The most significant
1618
     *                                    bit of number is the sign bit. The remaining 29 bits
1619
     *                                    are magnitude bits. Negative numbers are represented
1620
     *                                    using two's-complement notation.
1621
     *                                    If number is negative, OCT2BIN ignores places and returns
1622
     *                                    a 10-character binary number.
1623
     *                                    If number is negative, it cannot be less than 7777777000,
1624
     *                                    and if number is positive, it cannot be greater than 777.
1625
     *                                    If number is not a valid octal number, OCT2BIN returns
1626
     *                                    the #NUM! error value.
1627
     *                                    If OCT2BIN requires more than places characters, it
1628
     *                                    returns the #NUM! error value.
1629
     * @param    integer $places The number of characters to use. If places is omitted,
1630
     *                                    OCT2BIN uses the minimum number of characters necessary.
1631
     *                                    Places is useful for padding the return value with
1632
     *                                    leading 0s (zeros).
1633
     *                                    If places is not an integer, it is truncated.
1634
     *                                    If places is nonnumeric, OCT2BIN returns the #VALUE!
1635
     *                                    error value.
1636
     *                                    If places is negative, OCT2BIN returns the #NUM! error
1637
     *                                    value.
1638
     * @return    string
1639
     */
1640 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...
1641
    {
1642
        $x = Functions::flattenSingleValue($x);
1643
        $places = Functions::flattenSingleValue($places);
1644
1645
        if (is_bool($x)) {
1646
            return Functions::VALUE();
1647
        }
1648
        $x = (string)$x;
1649
        if (preg_match_all('/[01234567]/', $x, $out) != strlen($x)) {
1650
            return Functions::NAN();
1651
        }
1652
1653
        return self::DECTOBIN(self::OCTTODEC($x), $places);
1654
    }
1655
1656
1657
    /**
1658
     * OCTTODEC
1659
     *
1660
     * Return an octal value as decimal.
1661
     *
1662
     * Excel Function:
1663
     *        OCT2DEC(x)
1664
     *
1665
     * @access    public
1666
     * @category Engineering Functions
1667
     * @param    string $x The octal number you want to convert. Number may not contain
1668
     *                                more than 10 octal characters (30 bits). The most significant
1669
     *                                bit of number is the sign bit. The remaining 29 bits are
1670
     *                                magnitude bits. Negative numbers are represented using
1671
     *                                two's-complement notation.
1672
     *                                If number is not a valid octal number, OCT2DEC returns the
1673
     *                                #NUM! error value.
1674
     * @return    string
1675
     */
1676
    public static function OCTTODEC($x)
1677
    {
1678
        $x = Functions::flattenSingleValue($x);
1679
1680
        if (is_bool($x)) {
1681
            return Functions::VALUE();
1682
        }
1683
        $x = (string)$x;
1684
        if (preg_match_all('/[01234567]/', $x, $out) != strlen($x)) {
1685
            return Functions::NAN();
1686
        }
1687
        $binX = '';
1688 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...
1689
            $binX .= str_pad(decbin((int)$char), 3, '0', STR_PAD_LEFT);
1690
        }
1691 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...
1692
            for ($i = 0; $i < 30; $i++) {
1693
                $binX[$i] = ($binX[$i] == '1' ? '0' : '1');
1694
            }
1695
            return (bindec($binX) + 1) * -1;
1696
        }
1697
        return bindec($binX);
1698
    }
1699
1700
    /**
1701
     * OCTTOHEX
1702
     *
1703
     * Return an octal value as hex.
1704
     *
1705
     * Excel Function:
1706
     *        OCT2HEX(x[,places])
1707
     *
1708
     * @access    public
1709
     * @category Engineering Functions
1710
     * @param    string $x The octal number you want to convert. Number may not contain
1711
     *                                    more than 10 octal characters (30 bits). The most significant
1712
     *                                    bit of number is the sign bit. The remaining 29 bits are
1713
     *                                    magnitude bits. Negative numbers are represented using
1714
     *                                    two's-complement notation.
1715
     *                                    If number is negative, OCT2HEX ignores places and returns a
1716
     *                                    10-character hexadecimal number.
1717
     *                                    If number is not a valid octal number, OCT2HEX returns the
1718
     *                                    #NUM! error value.
1719
     *                                    If OCT2HEX requires more than places characters, it returns
1720
     *                                    the #NUM! error value.
1721
     * @param    integer $places The number of characters to use. If places is omitted, OCT2HEX
1722
     *                                    uses the minimum number of characters necessary. Places is useful
1723
     *                                    for padding the return value with leading 0s (zeros).
1724
     *                                    If places is not an integer, it is truncated.
1725
     *                                    If places is nonnumeric, OCT2HEX returns the #VALUE! error value.
1726
     *                                    If places is negative, OCT2HEX returns the #NUM! error value.
1727
     * @return    string
1728
     */
1729 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...
1730
    {
1731
        $x = Functions::flattenSingleValue($x);
1732
        $places = Functions::flattenSingleValue($places);
1733
1734
        if (is_bool($x)) {
1735
            return Functions::VALUE();
1736
        }
1737
        $x = (string)$x;
1738
        if (preg_match_all('/[01234567]/', $x, $out) != strlen($x)) {
1739
            return Functions::NAN();
1740
        }
1741
        $hexVal = strtoupper(dechex(self::OCTTODEC($x)));
1742
1743
        return self::nbrConversionFormat($hexVal, $places);
1744
    }
1745
1746
1747
    /**
1748
     * COMPLEX
1749
     *
1750
     * Converts real and imaginary coefficients into a complex number of the form x + yi or x + yj.
1751
     *
1752
     * Excel Function:
1753
     *        COMPLEX(realNumber,imaginary[,places])
1754
     *
1755
     * @access    public
1756
     * @category Engineering Functions
1757
     * @param    float $realNumber The real coefficient of the complex number.
1758
     * @param    float $imaginary The imaginary coefficient of the complex number.
1759
     * @param    string $suffix The suffix for the imaginary component of the complex number.
1760
     *                                        If omitted, the suffix is assumed to be "i".
1761
     * @return    string
1762
     */
1763
    public static function COMPLEX($realNumber = 0.0, $imaginary = 0.0, $suffix = 'i')
1764
    {
1765
        $realNumber = (is_null($realNumber)) ? 0.0 : Functions::flattenSingleValue($realNumber);
1766
        $imaginary = (is_null($imaginary)) ? 0.0 : Functions::flattenSingleValue($imaginary);
1767
        $suffix = (is_null($suffix)) ? 'i' : Functions::flattenSingleValue($suffix);
1768
1769
        if (((is_numeric($realNumber)) && (is_numeric($imaginary))) &&
1770
            (($suffix == 'i') || ($suffix == 'j') || ($suffix == ''))
1771
        ) {
1772
            $realNumber = (float)$realNumber;
1773
            $imaginary = (float)$imaginary;
1774
1775
            if ($suffix == '') {
1776
                $suffix = 'i';
1777
            }
1778
            if ($realNumber == 0.0) {
1779
                if ($imaginary == 0.0) {
1780
                    return (string)'0';
1781
                } elseif ($imaginary == 1.0) {
1782
                    return (string)$suffix;
1783
                } elseif ($imaginary == -1.0) {
1784
                    return (string)'-' . $suffix;
1785
                }
1786
                return (string)$imaginary . $suffix;
1787
            } elseif ($imaginary == 0.0) {
1788
                return (string)$realNumber;
1789
            } elseif ($imaginary == 1.0) {
1790
                return (string)$realNumber . '+' . $suffix;
1791
            } elseif ($imaginary == -1.0) {
1792
                return (string)$realNumber . '-' . $suffix;
1793
            }
1794
            if ($imaginary > 0) {
1795
                $imaginary = (string)'+' . $imaginary;
1796
            }
1797
            return (string)$realNumber . $imaginary . $suffix;
1798
        }
1799
1800
        return Functions::VALUE();
1801
    }
1802
1803
1804
    /**
1805
     * IMAGINARY
1806
     *
1807
     * Returns the imaginary coefficient of a complex number in x + yi or x + yj text format.
1808
     *
1809
     * Excel Function:
1810
     *        IMAGINARY(complexNumber)
1811
     *
1812
     * @access    public
1813
     * @category Engineering Functions
1814
     * @param    string $complexNumber The complex number for which you want the imaginary
1815
     *                                         coefficient.
1816
     * @return    float
1817
     */
1818
    public static function IMAGINARY($complexNumber)
1819
    {
1820
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1821
1822
        $parsedComplex = self::parseComplex($complexNumber);
1823
        return $parsedComplex['imaginary'];
1824
    }
1825
1826
1827
    /**
1828
     * IMREAL
1829
     *
1830
     * Returns the real coefficient of a complex number in x + yi or x + yj text format.
1831
     *
1832
     * Excel Function:
1833
     *        IMREAL(complexNumber)
1834
     *
1835
     * @access    public
1836
     * @category Engineering Functions
1837
     * @param    string $complexNumber The complex number for which you want the real coefficient.
1838
     * @return    float
1839
     */
1840
    public static function IMREAL($complexNumber)
1841
    {
1842
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1843
1844
        $parsedComplex = self::parseComplex($complexNumber);
1845
        return $parsedComplex['real'];
1846
    }
1847
1848
1849
    /**
1850
     * IMABS
1851
     *
1852
     * Returns the absolute value (modulus) of a complex number in x + yi or x + yj text format.
1853
     *
1854
     * Excel Function:
1855
     *        IMABS(complexNumber)
1856
     *
1857
     * @param    string $complexNumber The complex number for which you want the absolute value.
1858
     * @return    float
1859
     */
1860
    public static function IMABS($complexNumber)
1861
    {
1862
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1863
1864
        $parsedComplex = self::parseComplex($complexNumber);
1865
1866
        return sqrt(
1867
            ($parsedComplex['real'] * $parsedComplex['real']) +
1868
            ($parsedComplex['imaginary'] * $parsedComplex['imaginary'])
1869
        );
1870
    }
1871
1872
1873
    /**
1874
     * IMARGUMENT
1875
     *
1876
     * Returns the argument theta of a complex number, i.e. the angle in radians from the real
1877
     * axis to the representation of the number in polar coordinates.
1878
     *
1879
     * Excel Function:
1880
     *        IMARGUMENT(complexNumber)
1881
     *
1882
     * @param    string $complexNumber The complex number for which you want the argument theta.
1883
     * @return    float
1884
     */
1885
    public static function IMARGUMENT($complexNumber)
1886
    {
1887
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1888
        $parsedComplex = self::parseComplex($complexNumber);
1889
        if ($parsedComplex['real'] == 0.0) {
1890
            if ($parsedComplex['imaginary'] == 0.0) {
1891
                return Functions::DIV0();
1892
            } elseif ($parsedComplex['imaginary'] < 0.0) {
1893
                return M_PI / -2;
1894
            } else {
1895
                return M_PI / 2;
1896
            }
1897
        } elseif ($parsedComplex['real'] > 0.0) {
1898
            return atan($parsedComplex['imaginary'] / $parsedComplex['real']);
1899
        } elseif ($parsedComplex['imaginary'] < 0.0) {
1900
            return 0 - (M_PI - atan(abs($parsedComplex['imaginary']) / abs($parsedComplex['real'])));
1901
        } else {
1902
            return M_PI - atan($parsedComplex['imaginary'] / abs($parsedComplex['real']));
1903
        }
1904
    }
1905
1906
1907
    /**
1908
     * IMCONJUGATE
1909
     *
1910
     * Returns the complex conjugate of a complex number in x + yi or x + yj text format.
1911
     *
1912
     * Excel Function:
1913
     *        IMCONJUGATE(complexNumber)
1914
     *
1915
     * @param    string $complexNumber The complex number for which you want the conjugate.
1916
     * @return    string
1917
     */
1918
    public static function IMCONJUGATE($complexNumber)
1919
    {
1920
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1921
1922
        $parsedComplex = self::parseComplex($complexNumber);
1923
1924
        if ($parsedComplex['imaginary'] == 0.0) {
1925
            return $parsedComplex['real'];
1926
        } else {
1927
            return self::cleanComplex(
1928
                self::COMPLEX(
1929
                    $parsedComplex['real'],
1930
                    0 - $parsedComplex['imaginary'],
1931
                    $parsedComplex['suffix']
1932
                )
1933
            );
1934
        }
1935
    }
1936
1937
1938
    /**
1939
     * IMCOS
1940
     *
1941
     * Returns the cosine of a complex number in x + yi or x + yj text format.
1942
     *
1943
     * Excel Function:
1944
     *        IMCOS(complexNumber)
1945
     *
1946
     * @param    string $complexNumber The complex number for which you want the cosine.
1947
     * @return    string|float
1948
     */
1949 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...
1950
    {
1951
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1952
1953
        $parsedComplex = self::parseComplex($complexNumber);
1954
1955
        if ($parsedComplex['imaginary'] == 0.0) {
1956
            return cos($parsedComplex['real']);
1957
        } else {
1958
            return self::IMCONJUGATE(
1959
                self::COMPLEX(
1960
                    cos($parsedComplex['real']) * cosh($parsedComplex['imaginary']),
1961
                    sin($parsedComplex['real']) * sinh($parsedComplex['imaginary']),
1962
                    $parsedComplex['suffix']
1963
                )
1964
            );
1965
        }
1966
    }
1967
1968
1969
    /**
1970
     * IMSIN
1971
     *
1972
     * Returns the sine of a complex number in x + yi or x + yj text format.
1973
     *
1974
     * Excel Function:
1975
     *        IMSIN(complexNumber)
1976
     *
1977
     * @param    string $complexNumber The complex number for which you want the sine.
1978
     * @return    string|float
1979
     */
1980 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...
1981
    {
1982
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1983
1984
        $parsedComplex = self::parseComplex($complexNumber);
1985
1986
        if ($parsedComplex['imaginary'] == 0.0) {
1987
            return sin($parsedComplex['real']);
1988
        } else {
1989
            return self::COMPLEX(
1990
                sin($parsedComplex['real']) * cosh($parsedComplex['imaginary']),
1991
                cos($parsedComplex['real']) * sinh($parsedComplex['imaginary']),
1992
                $parsedComplex['suffix']
1993
            );
1994
        }
1995
    }
1996
1997
1998
    /**
1999
     * IMSQRT
2000
     *
2001
     * Returns the square root of a complex number in x + yi or x + yj text format.
2002
     *
2003
     * Excel Function:
2004
     *        IMSQRT(complexNumber)
2005
     *
2006
     * @param    string $complexNumber The complex number for which you want the square root.
2007
     * @return    string
2008
     */
2009
    public static function IMSQRT($complexNumber)
2010
    {
2011
        $complexNumber = Functions::flattenSingleValue($complexNumber);
2012
2013
        $parsedComplex = self::parseComplex($complexNumber);
2014
2015
        $theta = self::IMARGUMENT($complexNumber);
2016
        $d1 = cos($theta / 2);
2017
        $d2 = sin($theta / 2);
2018
        $r = sqrt(sqrt(($parsedComplex['real'] * $parsedComplex['real']) + ($parsedComplex['imaginary'] * $parsedComplex['imaginary'])));
2019
2020
        if ($parsedComplex['suffix'] == '') {
2021
            return self::COMPLEX($d1 * $r, $d2 * $r);
2022
        } else {
2023
            return self::COMPLEX($d1 * $r, $d2 * $r, $parsedComplex['suffix']);
2024
        }
2025
    }
2026
2027
2028
    /**
2029
     * IMLN
2030
     *
2031
     * Returns the natural logarithm of a complex number in x + yi or x + yj text format.
2032
     *
2033
     * Excel Function:
2034
     *        IMLN(complexNumber)
2035
     *
2036
     * @param    string $complexNumber The complex number for which you want the natural logarithm.
2037
     * @return    string
2038
     */
2039
    public static function IMLN($complexNumber)
2040
    {
2041
        $complexNumber = Functions::flattenSingleValue($complexNumber);
2042
2043
        $parsedComplex = self::parseComplex($complexNumber);
2044
2045
        if (($parsedComplex['real'] == 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
2046
            return Functions::NAN();
2047
        }
2048
2049
        $logR = log(sqrt(($parsedComplex['real'] * $parsedComplex['real']) + ($parsedComplex['imaginary'] * $parsedComplex['imaginary'])));
2050
        $t = self::IMARGUMENT($complexNumber);
2051
2052
        if ($parsedComplex['suffix'] == '') {
2053
            return self::COMPLEX($logR, $t);
2054
        } else {
2055
            return self::COMPLEX($logR, $t, $parsedComplex['suffix']);
2056
        }
2057
    }
2058
2059
2060
    /**
2061
     * IMLOG10
2062
     *
2063
     * Returns the common logarithm (base 10) of a complex number in x + yi or x + yj text format.
2064
     *
2065
     * Excel Function:
2066
     *        IMLOG10(complexNumber)
2067
     *
2068
     * @param    string $complexNumber The complex number for which you want the common logarithm.
2069
     * @return    string
2070
     */
2071 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...
2072
    {
2073
        $complexNumber = Functions::flattenSingleValue($complexNumber);
2074
2075
        $parsedComplex = self::parseComplex($complexNumber);
2076
2077
        if (($parsedComplex['real'] == 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
2078
            return Functions::NAN();
2079
        } elseif (($parsedComplex['real'] > 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
2080
            return log10($parsedComplex['real']);
2081
        }
2082
2083
        return self::IMPRODUCT(log10(EULER), self::IMLN($complexNumber));
2084
    }
2085
2086
2087
    /**
2088
     * IMLOG2
2089
     *
2090
     * Returns the base-2 logarithm of a complex number in x + yi or x + yj text format.
2091
     *
2092
     * Excel Function:
2093
     *        IMLOG2(complexNumber)
2094
     *
2095
     * @param    string $complexNumber The complex number for which you want the base-2 logarithm.
2096
     * @return    string
2097
     */
2098 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...
2099
    {
2100
        $complexNumber = Functions::flattenSingleValue($complexNumber);
2101
2102
        $parsedComplex = self::parseComplex($complexNumber);
2103
2104
        if (($parsedComplex['real'] == 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
2105
            return Functions::NAN();
2106
        } elseif (($parsedComplex['real'] > 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
2107
            return log($parsedComplex['real'], 2);
2108
        }
2109
2110
        return self::IMPRODUCT(log(EULER, 2), self::IMLN($complexNumber));
2111
    }
2112
2113
2114
    /**
2115
     * IMEXP
2116
     *
2117
     * Returns the exponential of a complex number in x + yi or x + yj text format.
2118
     *
2119
     * Excel Function:
2120
     *        IMEXP(complexNumber)
2121
     *
2122
     * @param    string $complexNumber The complex number for which you want the exponential.
2123
     * @return    string
2124
     */
2125
    public static function IMEXP($complexNumber)
2126
    {
2127
        $complexNumber = Functions::flattenSingleValue($complexNumber);
2128
2129
        $parsedComplex = self::parseComplex($complexNumber);
2130
2131
        if (($parsedComplex['real'] == 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
2132
            return '1';
2133
        }
2134
2135
        $e = exp($parsedComplex['real']);
2136
        $eX = $e * cos($parsedComplex['imaginary']);
2137
        $eY = $e * sin($parsedComplex['imaginary']);
2138
2139
        if ($parsedComplex['suffix'] == '') {
2140
            return self::COMPLEX($eX, $eY);
2141
        } else {
2142
            return self::COMPLEX($eX, $eY, $parsedComplex['suffix']);
2143
        }
2144
    }
2145
2146
2147
    /**
2148
     * IMPOWER
2149
     *
2150
     * Returns a complex number in x + yi or x + yj text format raised to a power.
2151
     *
2152
     * Excel Function:
2153
     *        IMPOWER(complexNumber,realNumber)
2154
     *
2155
     * @param    string $complexNumber The complex number you want to raise to a power.
2156
     * @param    float $realNumber The power to which you want to raise the complex number.
2157
     * @return    string
2158
     */
2159
    public static function IMPOWER($complexNumber, $realNumber)
2160
    {
2161
        $complexNumber = Functions::flattenSingleValue($complexNumber);
2162
        $realNumber = Functions::flattenSingleValue($realNumber);
2163
2164
        if (!is_numeric($realNumber)) {
2165
            return Functions::VALUE();
2166
        }
2167
2168
        $parsedComplex = self::parseComplex($complexNumber);
2169
2170
        $r = sqrt(($parsedComplex['real'] * $parsedComplex['real']) + ($parsedComplex['imaginary'] * $parsedComplex['imaginary']));
2171
        $rPower = pow($r, $realNumber);
2172
        $theta = self::IMARGUMENT($complexNumber) * $realNumber;
2173
        if ($theta == 0) {
2174
            return 1;
2175
        } elseif ($parsedComplex['imaginary'] == 0.0) {
2176
            return self::COMPLEX($rPower * cos($theta), $rPower * sin($theta), $parsedComplex['suffix']);
2177
        } else {
2178
            return self::COMPLEX($rPower * cos($theta), $rPower * sin($theta), $parsedComplex['suffix']);
2179
        }
2180
    }
2181
2182
2183
    /**
2184
     * IMDIV
2185
     *
2186
     * Returns the quotient of two complex numbers in x + yi or x + yj text format.
2187
     *
2188
     * Excel Function:
2189
     *        IMDIV(complexDividend,complexDivisor)
2190
     *
2191
     * @param    string $complexDividend The complex numerator or dividend.
2192
     * @param    string $complexDivisor The complex denominator or divisor.
2193
     * @return    string
2194
     */
2195
    public static function IMDIV($complexDividend, $complexDivisor)
2196
    {
2197
        $complexDividend = Functions::flattenSingleValue($complexDividend);
2198
        $complexDivisor = Functions::flattenSingleValue($complexDivisor);
2199
2200
        $parsedComplexDividend = self::parseComplex($complexDividend);
2201
        $parsedComplexDivisor = self::parseComplex($complexDivisor);
2202
2203
        if (($parsedComplexDividend['suffix'] != '') && ($parsedComplexDivisor['suffix'] != '') &&
2204
            ($parsedComplexDividend['suffix'] != $parsedComplexDivisor['suffix'])
2205
        ) {
2206
            return Functions::NAN();
2207
        }
2208
        if (($parsedComplexDividend['suffix'] != '') && ($parsedComplexDivisor['suffix'] == '')) {
2209
            $parsedComplexDivisor['suffix'] = $parsedComplexDividend['suffix'];
2210
        }
2211
2212
        $d1 = ($parsedComplexDividend['real'] * $parsedComplexDivisor['real']) + ($parsedComplexDividend['imaginary'] * $parsedComplexDivisor['imaginary']);
2213
        $d2 = ($parsedComplexDividend['imaginary'] * $parsedComplexDivisor['real']) - ($parsedComplexDividend['real'] * $parsedComplexDivisor['imaginary']);
2214
        $d3 = ($parsedComplexDivisor['real'] * $parsedComplexDivisor['real']) + ($parsedComplexDivisor['imaginary'] * $parsedComplexDivisor['imaginary']);
2215
2216
        $r = $d1 / $d3;
2217
        $i = $d2 / $d3;
2218
2219
        if ($i > 0.0) {
2220
            return self::cleanComplex($r . '+' . $i . $parsedComplexDivisor['suffix']);
2221
        } elseif ($i < 0.0) {
2222
            return self::cleanComplex($r . $i . $parsedComplexDivisor['suffix']);
2223
        } else {
2224
            return $r;
2225
        }
2226
    }
2227
2228
2229
    /**
2230
     * IMSUB
2231
     *
2232
     * Returns the difference of two complex numbers in x + yi or x + yj text format.
2233
     *
2234
     * Excel Function:
2235
     *        IMSUB(complexNumber1,complexNumber2)
2236
     *
2237
     * @param    string $complexNumber1 The complex number from which to subtract complexNumber2.
2238
     * @param    string $complexNumber2 The complex number to subtract from complexNumber1.
2239
     * @return    string
2240
     */
2241
    public static function IMSUB($complexNumber1, $complexNumber2)
2242
    {
2243
        $complexNumber1 = Functions::flattenSingleValue($complexNumber1);
2244
        $complexNumber2 = Functions::flattenSingleValue($complexNumber2);
2245
2246
        $parsedComplex1 = self::parseComplex($complexNumber1);
2247
        $parsedComplex2 = self::parseComplex($complexNumber2);
2248
2249
        if ((($parsedComplex1['suffix'] != '') && ($parsedComplex2['suffix'] != '')) &&
2250
            ($parsedComplex1['suffix'] != $parsedComplex2['suffix'])
2251
        ) {
2252
            return Functions::NAN();
2253
        } elseif (($parsedComplex1['suffix'] == '') && ($parsedComplex2['suffix'] != '')) {
2254
            $parsedComplex1['suffix'] = $parsedComplex2['suffix'];
2255
        }
2256
2257
        $d1 = $parsedComplex1['real'] - $parsedComplex2['real'];
2258
        $d2 = $parsedComplex1['imaginary'] - $parsedComplex2['imaginary'];
2259
2260
        return self::COMPLEX($d1, $d2, $parsedComplex1['suffix']);
2261
    }
2262
2263
2264
    /**
2265
     * IMSUM
2266
     *
2267
     * Returns the sum of two or more complex numbers in x + yi or x + yj text format.
2268
     *
2269
     * Excel Function:
2270
     *        IMSUM(complexNumber[,complexNumber[,...]])
2271
     *
2272
     * @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...
2273
     * @return    string
2274
     */
2275
    public static function IMSUM()
2276
    {
2277
        // Return value
2278
        $returnValue = self::parseComplex('0');
2279
        $activeSuffix = '';
2280
2281
        // Loop through the arguments
2282
        $aArgs = Functions::flattenArray(func_get_args());
2283
        foreach ($aArgs as $arg) {
2284
            $parsedComplex = self::parseComplex($arg);
2285
2286 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...
2287
                $activeSuffix = $parsedComplex['suffix'];
2288
            } elseif (($parsedComplex['suffix'] != '') && ($activeSuffix != $parsedComplex['suffix'])) {
2289
                return Functions::NAN();
2290
            }
2291
2292
            $returnValue['real'] += $parsedComplex['real'];
2293
            $returnValue['imaginary'] += $parsedComplex['imaginary'];
2294
        }
2295
2296
        if ($returnValue['imaginary'] == 0.0) {
2297
            $activeSuffix = '';
2298
        }
2299
        return self::COMPLEX($returnValue['real'], $returnValue['imaginary'], $activeSuffix);
2300
    }
2301
2302
2303
    /**
2304
     * IMPRODUCT
2305
     *
2306
     * Returns the product of two or more complex numbers in x + yi or x + yj text format.
2307
     *
2308
     * Excel Function:
2309
     *        IMPRODUCT(complexNumber[,complexNumber[,...]])
2310
     *
2311
     * @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...
2312
     * @return    string
2313
     */
2314
    public static function IMPRODUCT()
2315
    {
2316
        // Return value
2317
        $returnValue = self::parseComplex('1');
2318
        $activeSuffix = '';
2319
2320
        // Loop through the arguments
2321
        $aArgs = Functions::flattenArray(func_get_args());
2322
        foreach ($aArgs as $arg) {
2323
            $parsedComplex = self::parseComplex($arg);
2324
2325
            $workValue = $returnValue;
2326 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...
2327
                $activeSuffix = $parsedComplex['suffix'];
2328
            } elseif (($parsedComplex['suffix'] != '') && ($activeSuffix != $parsedComplex['suffix'])) {
2329
                return Functions::NAN();
2330
            }
2331
            $returnValue['real'] = ($workValue['real'] * $parsedComplex['real']) - ($workValue['imaginary'] * $parsedComplex['imaginary']);
2332
            $returnValue['imaginary'] = ($workValue['real'] * $parsedComplex['imaginary']) + ($workValue['imaginary'] * $parsedComplex['real']);
2333
        }
2334
2335
        if ($returnValue['imaginary'] == 0.0) {
2336
            $activeSuffix = '';
2337
        }
2338
        return self::COMPLEX($returnValue['real'], $returnValue['imaginary'], $activeSuffix);
2339
    }
2340
2341
2342
    /**
2343
     *    DELTA
2344
     *
2345
     *    Tests whether two values are equal. Returns 1 if number1 = number2; returns 0 otherwise.
2346
     *    Use this function to filter a set of values. For example, by summing several DELTA
2347
     *    functions you calculate the count of equal pairs. This function is also known as the
2348
     *    Kronecker Delta function.
2349
     *
2350
     *    Excel Function:
2351
     *        DELTA(a[,b])
2352
     *
2353
     * @param    float $a The first number.
2354
     * @param    float $b The second number. If omitted, b is assumed to be zero.
2355
     * @return    int
2356
     */
2357
    public static function DELTA($a, $b = 0)
2358
    {
2359
        $a = Functions::flattenSingleValue($a);
2360
        $b = Functions::flattenSingleValue($b);
2361
2362
        return (int)($a == $b);
2363
    }
2364
2365
2366
    /**
2367
     *    GESTEP
2368
     *
2369
     *    Excel Function:
2370
     *        GESTEP(number[,step])
2371
     *
2372
     *    Returns 1 if number >= step; returns 0 (zero) otherwise
2373
     *    Use this function to filter a set of values. For example, by summing several GESTEP
2374
     *    functions you calculate the count of values that exceed a threshold.
2375
     *
2376
     * @param    float $number The value to test against step.
2377
     * @param    float $step The threshold value.
2378
     *                                    If you omit a value for step, GESTEP uses zero.
2379
     * @return    int
2380
     */
2381
    public static function GESTEP($number, $step = 0)
2382
    {
2383
        $number = Functions::flattenSingleValue($number);
2384
        $step = Functions::flattenSingleValue($step);
2385
2386
        return (int)($number >= $step);
2387
    }
2388
2389
2390
    //
2391
    //    Private method to calculate the erf value
2392
    //
2393
    private static $twoSqrtPi = 1.128379167095512574;
2394
2395
    public static function erfVal($x)
2396
    {
2397
        if (abs($x) > 2.2) {
2398
            return 1 - self::erfcVal($x);
2399
        }
2400
        $sum = $term = $x;
2401
        $xsqr = ($x * $x);
2402
        $j = 1;
2403
        do {
2404
            $term *= $xsqr / $j;
2405
            $sum -= $term / (2 * $j + 1);
2406
            ++$j;
2407
            $term *= $xsqr / $j;
2408
            $sum += $term / (2 * $j + 1);
2409
            ++$j;
2410
            if ($sum == 0.0) {
2411
                break;
2412
            }
2413
        } while (abs($term / $sum) > PRECISION);
2414
        return self::$twoSqrtPi * $sum;
2415
    }
2416
2417
2418
    /**
2419
     *    ERF
2420
     *
2421
     *    Returns the error function integrated between the lower and upper bound arguments.
2422
     *
2423
     *    Note: In Excel 2007 or earlier, if you input a negative value for the upper or lower bound arguments,
2424
     *            the function would return a #NUM! error. However, in Excel 2010, the function algorithm was
2425
     *            improved, so that it can now calculate the function for both positive and negative ranges.
2426
     *            PhpSpreadsheet follows Excel 2010 behaviour, and accepts nagative arguments.
2427
     *
2428
     *    Excel Function:
2429
     *        ERF(lower[,upper])
2430
     *
2431
     * @param    float $lower lower bound for integrating ERF
2432
     * @param    float $upper upper bound for integrating ERF.
2433
     *                                If omitted, ERF integrates between zero and lower_limit
2434
     * @return    float
2435
     */
2436
    public static function ERF($lower, $upper = null)
2437
    {
2438
        $lower = Functions::flattenSingleValue($lower);
2439
        $upper = Functions::flattenSingleValue($upper);
2440
2441
        if (is_numeric($lower)) {
2442
            if (is_null($upper)) {
2443
                return self::erfVal($lower);
2444
            }
2445
            if (is_numeric($upper)) {
2446
                return self::erfVal($upper) - self::erfVal($lower);
2447
            }
2448
        }
2449
        return Functions::VALUE();
2450
    }
2451
2452
2453
    //
2454
    //    Private method to calculate the erfc value
2455
    //
2456
    private static $oneSqrtPi = 0.564189583547756287;
2457
2458
    private static function erfcVal($x)
2459
    {
2460
        if (abs($x) < 2.2) {
2461
            return 1 - self::erfVal($x);
2462
        }
2463
        if ($x < 0) {
2464
            return 2 - self::ERFC(-$x);
2465
        }
2466
        $a = $n = 1;
2467
        $b = $c = $x;
2468
        $d = ($x * $x) + 0.5;
2469
        $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...
2470
        $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...
2471
        do {
2472
            $t = $a * $n + $b * $x;
2473
            $a = $b;
2474
            $b = $t;
2475
            $t = $c * $n + $d * $x;
2476
            $c = $d;
2477
            $d = $t;
2478
            $n += 0.5;
2479
            $q1 = $q2;
2480
            $q2 = $b / $d;
2481
        } while ((abs($q1 - $q2) / $q2) > PRECISION);
2482
        return self::$oneSqrtPi * exp(-$x * $x) * $q2;
2483
    }
2484
2485
2486
    /**
2487
     *    ERFC
2488
     *
2489
     *    Returns the complementary ERF function integrated between x and infinity
2490
     *
2491
     *    Note: In Excel 2007 or earlier, if you input a negative value for the lower bound argument,
2492
     *        the function would return a #NUM! error. However, in Excel 2010, the function algorithm was
2493
     *        improved, so that it can now calculate the function for both positive and negative x values.
2494
     *            PhpSpreadsheet follows Excel 2010 behaviour, and accepts nagative arguments.
2495
     *
2496
     *    Excel Function:
2497
     *        ERFC(x)
2498
     *
2499
     * @param    float $x The lower bound for integrating ERFC
2500
     * @return    float
2501
     */
2502
    public static function ERFC($x)
2503
    {
2504
        $x = Functions::flattenSingleValue($x);
2505
2506
        if (is_numeric($x)) {
2507
            return self::erfcVal($x);
2508
        }
2509
        return Functions::VALUE();
2510
    }
2511
2512
2513
    /**
2514
     *    getConversionGroups
2515
     *    Returns a list of the different conversion groups for UOM conversions
2516
     *
2517
     * @return    array
2518
     */
2519
    public static function getConversionGroups()
2520
    {
2521
        $conversionGroups = array();
2522
        foreach (self::$conversionUnits as $conversionUnit) {
2523
            $conversionGroups[] = $conversionUnit['Group'];
2524
        }
2525
        return array_merge(array_unique($conversionGroups));
2526
    }
2527
2528
2529
    /**
2530
     *    getConversionGroupUnits
2531
     *    Returns an array of units of measure, for a specified conversion group, or for all groups
2532
     *
2533
     * @param    string $group The group whose units of measure you want to retrieve
2534
     * @return    array
2535
     */
2536
    public static function getConversionGroupUnits($group = null)
2537
    {
2538
        $conversionGroups = array();
2539
        foreach (self::$conversionUnits as $conversionUnit => $conversionGroup) {
2540
            if ((is_null($group)) || ($conversionGroup['Group'] == $group)) {
2541
                $conversionGroups[$conversionGroup['Group']][] = $conversionUnit;
2542
            }
2543
        }
2544
        return $conversionGroups;
2545
    }
2546
2547
2548
    /**
2549
     *    getConversionGroupUnitDetails
2550
     *
2551
     * @param    string $group The group whose units of measure you want to retrieve
2552
     * @return    array
2553
     */
2554
    public static function getConversionGroupUnitDetails($group = null)
2555
    {
2556
        $conversionGroups = array();
2557
        foreach (self::$conversionUnits as $conversionUnit => $conversionGroup) {
2558
            if ((is_null($group)) || ($conversionGroup['Group'] == $group)) {
2559
                $conversionGroups[$conversionGroup['Group']][] = array(
2560
                    'unit' => $conversionUnit,
2561
                    'description' => $conversionGroup['Unit Name']
2562
                );
2563
            }
2564
        }
2565
        return $conversionGroups;
2566
    }
2567
2568
2569
    /**
2570
     *    getConversionMultipliers
2571
     *    Returns an array of the Multiplier prefixes that can be used with Units of Measure in CONVERTUOM()
2572
     *
2573
     * @return    array of mixed
2574
     */
2575
    public static function getConversionMultipliers()
2576
    {
2577
        return self::$conversionMultipliers;
2578
    }
2579
2580
2581
    /**
2582
     *    CONVERTUOM
2583
     *
2584
     *    Converts a number from one measurement system to another.
2585
     *    For example, CONVERT can translate a table of distances in miles to a table of distances
2586
     *    in kilometers.
2587
     *
2588
     *    Excel Function:
2589
     *        CONVERT(value,fromUOM,toUOM)
2590
     *
2591
     * @param    float $value The value in fromUOM to convert.
2592
     * @param    string $fromUOM The units for value.
2593
     * @param    string $toUOM The units for the result.
2594
     *
2595
     * @return    float
2596
     */
2597
    public static function CONVERTUOM($value, $fromUOM, $toUOM)
2598
    {
2599
        $value = Functions::flattenSingleValue($value);
2600
        $fromUOM = Functions::flattenSingleValue($fromUOM);
2601
        $toUOM = Functions::flattenSingleValue($toUOM);
2602
2603
        if (!is_numeric($value)) {
2604
            return Functions::VALUE();
2605
        }
2606
        $fromMultiplier = 1.0;
2607 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...
2608
            $unitGroup1 = self::$conversionUnits[$fromUOM]['Group'];
2609
        } else {
2610
            $fromMultiplier = substr($fromUOM, 0, 1);
2611
            $fromUOM = substr($fromUOM, 1);
2612
            if (isset(self::$conversionMultipliers[$fromMultiplier])) {
2613
                $fromMultiplier = self::$conversionMultipliers[$fromMultiplier]['multiplier'];
2614
            } else {
2615
                return Functions::NA();
2616
            }
2617
            if ((isset(self::$conversionUnits[$fromUOM])) && (self::$conversionUnits[$fromUOM]['AllowPrefix'])) {
2618
                $unitGroup1 = self::$conversionUnits[$fromUOM]['Group'];
2619
            } else {
2620
                return Functions::NA();
2621
            }
2622
        }
2623
        $value *= $fromMultiplier;
2624
2625
        $toMultiplier = 1.0;
2626 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...
2627
            $unitGroup2 = self::$conversionUnits[$toUOM]['Group'];
2628
        } else {
2629
            $toMultiplier = substr($toUOM, 0, 1);
2630
            $toUOM = substr($toUOM, 1);
2631
            if (isset(self::$conversionMultipliers[$toMultiplier])) {
2632
                $toMultiplier = self::$conversionMultipliers[$toMultiplier]['multiplier'];
2633
            } else {
2634
                return Functions::NA();
2635
            }
2636
            if ((isset(self::$conversionUnits[$toUOM])) && (self::$conversionUnits[$toUOM]['AllowPrefix'])) {
2637
                $unitGroup2 = self::$conversionUnits[$toUOM]['Group'];
2638
            } else {
2639
                return Functions::NA();
2640
            }
2641
        }
2642
        if ($unitGroup1 != $unitGroup2) {
2643
            return Functions::NA();
2644
        }
2645
2646
        if (($fromUOM == $toUOM) && ($fromMultiplier == $toMultiplier)) {
2647
            //    We've already factored $fromMultiplier into the value, so we need
2648
            //        to reverse it again
2649
            return $value / $fromMultiplier;
2650
        } elseif ($unitGroup1 == 'Temperature') {
2651
            if (($fromUOM == 'F') || ($fromUOM == 'fah')) {
2652
                if (($toUOM == 'F') || ($toUOM == 'fah')) {
2653
                    return $value;
2654
                } else {
2655
                    $value = (($value - 32) / 1.8);
2656
                    if (($toUOM == 'K') || ($toUOM == 'kel')) {
2657
                        $value += 273.15;
2658
                    }
2659
                    return $value;
2660
                }
2661
            } elseif ((($fromUOM == 'K') || ($fromUOM == 'kel')) &&
2662
                (($toUOM == 'K') || ($toUOM == 'kel'))
2663
            ) {
2664
                return $value;
2665
            } elseif ((($fromUOM == 'C') || ($fromUOM == 'cel')) &&
2666
                (($toUOM == 'C') || ($toUOM == 'cel'))
2667
            ) {
2668
                return $value;
2669
            }
2670
            if (($toUOM == 'F') || ($toUOM == 'fah')) {
2671
                if (($fromUOM == 'K') || ($fromUOM == 'kel')) {
2672
                    $value -= 273.15;
2673
                }
2674
                return ($value * 1.8) + 32;
2675
            }
2676
            if (($toUOM == 'C') || ($toUOM == 'cel')) {
2677
                return $value - 273.15;
2678
            }
2679
            return $value + 273.15;
2680
        }
2681
        return ($value * self::$unitConversions[$unitGroup1][$fromUOM][$toUOM]) / $toMultiplier;
2682
    }
2683
}
2684