Passed
Push — develop ( 57a029...1b96c9 )
by Mark
31:53
created

Engineering::IMSECH()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 5
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Calculation;
4
5
use Complex\Complex;
6
use Complex\Exception as ComplexException;
7
8
class Engineering
9
{
10
    /**
11
     * EULER.
12
     */
13
    const EULER = 2.71828182845904523536;
14
15
    /**
16
     * Details of the Units of measure that can be used in CONVERTUOM().
17
     *
18
     * @var mixed[]
19
     */
20
    private static $conversionUnits = [
21
        'g' => ['Group' => 'Mass', 'Unit Name' => 'Gram', 'AllowPrefix' => true],
22
        'sg' => ['Group' => 'Mass', 'Unit Name' => 'Slug', 'AllowPrefix' => false],
23
        'lbm' => ['Group' => 'Mass', 'Unit Name' => 'Pound mass (avoirdupois)', 'AllowPrefix' => false],
24
        'u' => ['Group' => 'Mass', 'Unit Name' => 'U (atomic mass unit)', 'AllowPrefix' => true],
25
        'ozm' => ['Group' => 'Mass', 'Unit Name' => 'Ounce mass (avoirdupois)', 'AllowPrefix' => false],
26
        'm' => ['Group' => 'Distance', 'Unit Name' => 'Meter', 'AllowPrefix' => true],
27
        'mi' => ['Group' => 'Distance', 'Unit Name' => 'Statute mile', 'AllowPrefix' => false],
28
        'Nmi' => ['Group' => 'Distance', 'Unit Name' => 'Nautical mile', 'AllowPrefix' => false],
29
        'in' => ['Group' => 'Distance', 'Unit Name' => 'Inch', 'AllowPrefix' => false],
30
        'ft' => ['Group' => 'Distance', 'Unit Name' => 'Foot', 'AllowPrefix' => false],
31
        'yd' => ['Group' => 'Distance', 'Unit Name' => 'Yard', 'AllowPrefix' => false],
32
        'ang' => ['Group' => 'Distance', 'Unit Name' => 'Angstrom', 'AllowPrefix' => true],
33
        'Pica' => ['Group' => 'Distance', 'Unit Name' => 'Pica (1/72 in)', 'AllowPrefix' => false],
34
        'yr' => ['Group' => 'Time', 'Unit Name' => 'Year', 'AllowPrefix' => false],
35
        'day' => ['Group' => 'Time', 'Unit Name' => 'Day', 'AllowPrefix' => false],
36
        'hr' => ['Group' => 'Time', 'Unit Name' => 'Hour', 'AllowPrefix' => false],
37
        'mn' => ['Group' => 'Time', 'Unit Name' => 'Minute', 'AllowPrefix' => false],
38
        'sec' => ['Group' => 'Time', 'Unit Name' => 'Second', 'AllowPrefix' => true],
39
        'Pa' => ['Group' => 'Pressure', 'Unit Name' => 'Pascal', 'AllowPrefix' => true],
40
        'p' => ['Group' => 'Pressure', 'Unit Name' => 'Pascal', 'AllowPrefix' => true],
41
        'atm' => ['Group' => 'Pressure', 'Unit Name' => 'Atmosphere', 'AllowPrefix' => true],
42
        'at' => ['Group' => 'Pressure', 'Unit Name' => 'Atmosphere', 'AllowPrefix' => true],
43
        'mmHg' => ['Group' => 'Pressure', 'Unit Name' => 'mm of Mercury', 'AllowPrefix' => true],
44
        'N' => ['Group' => 'Force', 'Unit Name' => 'Newton', 'AllowPrefix' => true],
45
        'dyn' => ['Group' => 'Force', 'Unit Name' => 'Dyne', 'AllowPrefix' => true],
46
        'dy' => ['Group' => 'Force', 'Unit Name' => 'Dyne', 'AllowPrefix' => true],
47
        'lbf' => ['Group' => 'Force', 'Unit Name' => 'Pound force', 'AllowPrefix' => false],
48
        'J' => ['Group' => 'Energy', 'Unit Name' => 'Joule', 'AllowPrefix' => true],
49
        'e' => ['Group' => 'Energy', 'Unit Name' => 'Erg', 'AllowPrefix' => true],
50
        'c' => ['Group' => 'Energy', 'Unit Name' => 'Thermodynamic calorie', 'AllowPrefix' => true],
51
        'cal' => ['Group' => 'Energy', 'Unit Name' => 'IT calorie', 'AllowPrefix' => true],
52
        'eV' => ['Group' => 'Energy', 'Unit Name' => 'Electron volt', 'AllowPrefix' => true],
53
        'ev' => ['Group' => 'Energy', 'Unit Name' => 'Electron volt', 'AllowPrefix' => true],
54
        'HPh' => ['Group' => 'Energy', 'Unit Name' => 'Horsepower-hour', 'AllowPrefix' => false],
55
        'hh' => ['Group' => 'Energy', 'Unit Name' => 'Horsepower-hour', 'AllowPrefix' => false],
56
        'Wh' => ['Group' => 'Energy', 'Unit Name' => 'Watt-hour', 'AllowPrefix' => true],
57
        'wh' => ['Group' => 'Energy', 'Unit Name' => 'Watt-hour', 'AllowPrefix' => true],
58
        'flb' => ['Group' => 'Energy', 'Unit Name' => 'Foot-pound', 'AllowPrefix' => false],
59
        'BTU' => ['Group' => 'Energy', 'Unit Name' => 'BTU', 'AllowPrefix' => false],
60
        'btu' => ['Group' => 'Energy', 'Unit Name' => 'BTU', 'AllowPrefix' => false],
61
        'HP' => ['Group' => 'Power', 'Unit Name' => 'Horsepower', 'AllowPrefix' => false],
62
        'h' => ['Group' => 'Power', 'Unit Name' => 'Horsepower', 'AllowPrefix' => false],
63
        'W' => ['Group' => 'Power', 'Unit Name' => 'Watt', 'AllowPrefix' => true],
64
        'w' => ['Group' => 'Power', 'Unit Name' => 'Watt', 'AllowPrefix' => true],
65
        'T' => ['Group' => 'Magnetism', 'Unit Name' => 'Tesla', 'AllowPrefix' => true],
66
        'ga' => ['Group' => 'Magnetism', 'Unit Name' => 'Gauss', 'AllowPrefix' => true],
67
        'C' => ['Group' => 'Temperature', 'Unit Name' => 'Celsius', 'AllowPrefix' => false],
68
        'cel' => ['Group' => 'Temperature', 'Unit Name' => 'Celsius', 'AllowPrefix' => false],
69
        'F' => ['Group' => 'Temperature', 'Unit Name' => 'Fahrenheit', 'AllowPrefix' => false],
70
        'fah' => ['Group' => 'Temperature', 'Unit Name' => 'Fahrenheit', 'AllowPrefix' => false],
71
        'K' => ['Group' => 'Temperature', 'Unit Name' => 'Kelvin', 'AllowPrefix' => false],
72
        'kel' => ['Group' => 'Temperature', 'Unit Name' => 'Kelvin', 'AllowPrefix' => false],
73
        'tsp' => ['Group' => 'Liquid', 'Unit Name' => 'Teaspoon', 'AllowPrefix' => false],
74
        'tbs' => ['Group' => 'Liquid', 'Unit Name' => 'Tablespoon', 'AllowPrefix' => false],
75
        'oz' => ['Group' => 'Liquid', 'Unit Name' => 'Fluid Ounce', 'AllowPrefix' => false],
76
        'cup' => ['Group' => 'Liquid', 'Unit Name' => 'Cup', 'AllowPrefix' => false],
77
        'pt' => ['Group' => 'Liquid', 'Unit Name' => 'U.S. Pint', 'AllowPrefix' => false],
78
        'us_pt' => ['Group' => 'Liquid', 'Unit Name' => 'U.S. Pint', 'AllowPrefix' => false],
79
        'uk_pt' => ['Group' => 'Liquid', 'Unit Name' => 'U.K. Pint', 'AllowPrefix' => false],
80
        'qt' => ['Group' => 'Liquid', 'Unit Name' => 'Quart', 'AllowPrefix' => false],
81
        'gal' => ['Group' => 'Liquid', 'Unit Name' => 'Gallon', 'AllowPrefix' => false],
82
        'l' => ['Group' => 'Liquid', 'Unit Name' => 'Litre', 'AllowPrefix' => true],
83
        'lt' => ['Group' => 'Liquid', 'Unit Name' => 'Litre', 'AllowPrefix' => true],
84
    ];
85
86
    /**
87
     * Details of the Multiplier prefixes that can be used with Units of Measure in CONVERTUOM().
88
     *
89
     * @var mixed[]
90
     */
91
    private static $conversionMultipliers = [
92
        'Y' => ['multiplier' => 1E24, 'name' => 'yotta'],
93
        'Z' => ['multiplier' => 1E21, 'name' => 'zetta'],
94
        'E' => ['multiplier' => 1E18, 'name' => 'exa'],
95
        'P' => ['multiplier' => 1E15, 'name' => 'peta'],
96
        'T' => ['multiplier' => 1E12, 'name' => 'tera'],
97
        'G' => ['multiplier' => 1E9, 'name' => 'giga'],
98
        'M' => ['multiplier' => 1E6, 'name' => 'mega'],
99
        'k' => ['multiplier' => 1E3, 'name' => 'kilo'],
100
        'h' => ['multiplier' => 1E2, 'name' => 'hecto'],
101
        'e' => ['multiplier' => 1E1, 'name' => 'deka'],
102
        'd' => ['multiplier' => 1E-1, 'name' => 'deci'],
103
        'c' => ['multiplier' => 1E-2, 'name' => 'centi'],
104
        'm' => ['multiplier' => 1E-3, 'name' => 'milli'],
105
        'u' => ['multiplier' => 1E-6, 'name' => 'micro'],
106
        'n' => ['multiplier' => 1E-9, 'name' => 'nano'],
107
        'p' => ['multiplier' => 1E-12, 'name' => 'pico'],
108
        'f' => ['multiplier' => 1E-15, 'name' => 'femto'],
109
        'a' => ['multiplier' => 1E-18, 'name' => 'atto'],
110
        'z' => ['multiplier' => 1E-21, 'name' => 'zepto'],
111
        'y' => ['multiplier' => 1E-24, 'name' => 'yocto'],
112
    ];
113
114
    /**
115
     * Details of the Units of measure conversion factors, organised by group.
116
     *
117
     * @var mixed[]
118
     */
119
    private static $unitConversions = [
120
        'Mass' => [
121
            'g' => [
122
                'g' => 1.0,
123
                'sg' => 6.85220500053478E-05,
124
                'lbm' => 2.20462291469134E-03,
125
                'u' => 6.02217000000000E+23,
126
                'ozm' => 3.52739718003627E-02,
127
            ],
128
            'sg' => [
129
                'g' => 1.45938424189287E+04,
130
                'sg' => 1.0,
131
                'lbm' => 3.21739194101647E+01,
132
                'u' => 8.78866000000000E+27,
133
                'ozm' => 5.14782785944229E+02,
134
            ],
135
            'lbm' => [
136
                'g' => 4.5359230974881148E+02,
137
                'sg' => 3.10810749306493E-02,
138
                'lbm' => 1.0,
139
                'u' => 2.73161000000000E+26,
140
                'ozm' => 1.60000023429410E+01,
141
            ],
142
            'u' => [
143
                'g' => 1.66053100460465E-24,
144
                'sg' => 1.13782988532950E-28,
145
                'lbm' => 3.66084470330684E-27,
146
                'u' => 1.0,
147
                'ozm' => 5.85735238300524E-26,
148
            ],
149
            'ozm' => [
150
                'g' => 2.83495152079732E+01,
151
                'sg' => 1.94256689870811E-03,
152
                'lbm' => 6.24999908478882E-02,
153
                'u' => 1.70725600000000E+25,
154
                'ozm' => 1.0,
155
            ],
156
        ],
157
        'Distance' => [
158
            'm' => [
159
                'm' => 1.0,
160
                'mi' => 6.21371192237334E-04,
161
                'Nmi' => 5.39956803455724E-04,
162
                'in' => 3.93700787401575E+01,
163
                'ft' => 3.28083989501312E+00,
164
                'yd' => 1.09361329797891E+00,
165
                'ang' => 1.00000000000000E+10,
166
                'Pica' => 2.83464566929116E+03,
167
            ],
168
            'mi' => [
169
                'm' => 1.60934400000000E+03,
170
                'mi' => 1.0,
171
                'Nmi' => 8.68976241900648E-01,
172
                'in' => 6.33600000000000E+04,
173
                'ft' => 5.28000000000000E+03,
174
                'yd' => 1.76000000000000E+03,
175
                'ang' => 1.60934400000000E+13,
176
                'Pica' => 4.56191999999971E+06,
177
            ],
178
            'Nmi' => [
179
                'm' => 1.85200000000000E+03,
180
                'mi' => 1.15077944802354E+00,
181
                'Nmi' => 1.0,
182
                'in' => 7.29133858267717E+04,
183
                'ft' => 6.07611548556430E+03,
184
                'yd' => 2.02537182785694E+03,
185
                'ang' => 1.85200000000000E+13,
186
                'Pica' => 5.24976377952723E+06,
187
            ],
188
            'in' => [
189
                'm' => 2.54000000000000E-02,
190
                'mi' => 1.57828282828283E-05,
191
                'Nmi' => 1.37149028077754E-05,
192
                'in' => 1.0,
193
                'ft' => 8.33333333333333E-02,
194
                'yd' => 2.77777777686643E-02,
195
                'ang' => 2.54000000000000E+08,
196
                'Pica' => 7.19999999999955E+01,
197
            ],
198
            'ft' => [
199
                'm' => 3.04800000000000E-01,
200
                'mi' => 1.89393939393939E-04,
201
                'Nmi' => 1.64578833693305E-04,
202
                'in' => 1.20000000000000E+01,
203
                'ft' => 1.0,
204
                'yd' => 3.33333333223972E-01,
205
                'ang' => 3.04800000000000E+09,
206
                'Pica' => 8.63999999999946E+02,
207
            ],
208
            'yd' => [
209
                'm' => 9.14400000300000E-01,
210
                'mi' => 5.68181818368230E-04,
211
                'Nmi' => 4.93736501241901E-04,
212
                'in' => 3.60000000118110E+01,
213
                'ft' => 3.00000000000000E+00,
214
                'yd' => 1.0,
215
                'ang' => 9.14400000300000E+09,
216
                'Pica' => 2.59200000085023E+03,
217
            ],
218
            'ang' => [
219
                'm' => 1.00000000000000E-10,
220
                'mi' => 6.21371192237334E-14,
221
                'Nmi' => 5.39956803455724E-14,
222
                'in' => 3.93700787401575E-09,
223
                'ft' => 3.28083989501312E-10,
224
                'yd' => 1.09361329797891E-10,
225
                'ang' => 1.0,
226
                'Pica' => 2.83464566929116E-07,
227
            ],
228
            'Pica' => [
229
                'm' => 3.52777777777800E-04,
230
                'mi' => 2.19205948372629E-07,
231
                'Nmi' => 1.90484761219114E-07,
232
                'in' => 1.38888888888898E-02,
233
                'ft' => 1.15740740740748E-03,
234
                'yd' => 3.85802469009251E-04,
235
                'ang' => 3.52777777777800E+06,
236
                'Pica' => 1.0,
237
            ],
238
        ],
239
        'Time' => [
240
            'yr' => [
241
                'yr' => 1.0,
242
                'day' => 365.25,
243
                'hr' => 8766.0,
244
                'mn' => 525960.0,
245
                'sec' => 31557600.0,
246
            ],
247
            'day' => [
248
                'yr' => 2.73785078713210E-03,
249
                'day' => 1.0,
250
                'hr' => 24.0,
251
                'mn' => 1440.0,
252
                'sec' => 86400.0,
253
            ],
254
            'hr' => [
255
                'yr' => 1.14077116130504E-04,
256
                'day' => 4.16666666666667E-02,
257
                'hr' => 1.0,
258
                'mn' => 60.0,
259
                'sec' => 3600.0,
260
            ],
261
            'mn' => [
262
                'yr' => 1.90128526884174E-06,
263
                'day' => 6.94444444444444E-04,
264
                'hr' => 1.66666666666667E-02,
265
                'mn' => 1.0,
266
                'sec' => 60.0,
267
            ],
268
            'sec' => [
269
                'yr' => 3.16880878140289E-08,
270
                'day' => 1.15740740740741E-05,
271
                'hr' => 2.77777777777778E-04,
272
                'mn' => 1.66666666666667E-02,
273
                'sec' => 1.0,
274
            ],
275
        ],
276
        'Pressure' => [
277
            'Pa' => [
278
                'Pa' => 1.0,
279
                'p' => 1.0,
280
                'atm' => 9.86923299998193E-06,
281
                'at' => 9.86923299998193E-06,
282
                'mmHg' => 7.50061707998627E-03,
283
            ],
284
            'p' => [
285
                'Pa' => 1.0,
286
                'p' => 1.0,
287
                'atm' => 9.86923299998193E-06,
288
                'at' => 9.86923299998193E-06,
289
                'mmHg' => 7.50061707998627E-03,
290
            ],
291
            'atm' => [
292
                'Pa' => 1.01324996583000E+05,
293
                'p' => 1.01324996583000E+05,
294
                'atm' => 1.0,
295
                'at' => 1.0,
296
                'mmHg' => 760.0,
297
            ],
298
            'at' => [
299
                'Pa' => 1.01324996583000E+05,
300
                'p' => 1.01324996583000E+05,
301
                'atm' => 1.0,
302
                'at' => 1.0,
303
                'mmHg' => 760.0,
304
            ],
305
            'mmHg' => [
306
                'Pa' => 1.33322363925000E+02,
307
                'p' => 1.33322363925000E+02,
308
                'atm' => 1.31578947368421E-03,
309
                'at' => 1.31578947368421E-03,
310
                'mmHg' => 1.0,
311
            ],
312
        ],
313
        'Force' => [
314
            'N' => [
315
                'N' => 1.0,
316
                'dyn' => 1.0E+5,
317
                'dy' => 1.0E+5,
318
                'lbf' => 2.24808923655339E-01,
319
            ],
320
            'dyn' => [
321
                'N' => 1.0E-5,
322
                'dyn' => 1.0,
323
                'dy' => 1.0,
324
                'lbf' => 2.24808923655339E-06,
325
            ],
326
            'dy' => [
327
                'N' => 1.0E-5,
328
                'dyn' => 1.0,
329
                'dy' => 1.0,
330
                'lbf' => 2.24808923655339E-06,
331
            ],
332
            'lbf' => [
333
                'N' => 4.448222,
334
                'dyn' => 4.448222E+5,
335
                'dy' => 4.448222E+5,
336
                'lbf' => 1.0,
337
            ],
338
        ],
339
        'Energy' => [
340
            'J' => [
341
                'J' => 1.0,
342
                'e' => 9.99999519343231E+06,
343
                'c' => 2.39006249473467E-01,
344
                'cal' => 2.38846190642017E-01,
345
                'eV' => 6.24145700000000E+18,
346
                'ev' => 6.24145700000000E+18,
347
                'HPh' => 3.72506430801000E-07,
348
                'hh' => 3.72506430801000E-07,
349
                'Wh' => 2.77777916238711E-04,
350
                'wh' => 2.77777916238711E-04,
351
                'flb' => 2.37304222192651E+01,
352
                'BTU' => 9.47815067349015E-04,
353
                'btu' => 9.47815067349015E-04,
354
            ],
355
            'e' => [
356
                'J' => 1.00000048065700E-07,
357
                'e' => 1.0,
358
                'c' => 2.39006364353494E-08,
359
                'cal' => 2.38846305445111E-08,
360
                'eV' => 6.24146000000000E+11,
361
                'ev' => 6.24146000000000E+11,
362
                'HPh' => 3.72506609848824E-14,
363
                'hh' => 3.72506609848824E-14,
364
                'Wh' => 2.77778049754611E-11,
365
                'wh' => 2.77778049754611E-11,
366
                'flb' => 2.37304336254586E-06,
367
                'BTU' => 9.47815522922962E-11,
368
                'btu' => 9.47815522922962E-11,
369
            ],
370
            'c' => [
371
                'J' => 4.18399101363672E+00,
372
                'e' => 4.18398900257312E+07,
373
                'c' => 1.0,
374
                'cal' => 9.99330315287563E-01,
375
                'eV' => 2.61142000000000E+19,
376
                'ev' => 2.61142000000000E+19,
377
                'HPh' => 1.55856355899327E-06,
378
                'hh' => 1.55856355899327E-06,
379
                'Wh' => 1.16222030532950E-03,
380
                'wh' => 1.16222030532950E-03,
381
                'flb' => 9.92878733152102E+01,
382
                'BTU' => 3.96564972437776E-03,
383
                'btu' => 3.96564972437776E-03,
384
            ],
385
            'cal' => [
386
                'J' => 4.18679484613929E+00,
387
                'e' => 4.18679283372801E+07,
388
                'c' => 1.00067013349059E+00,
389
                'cal' => 1.0,
390
                'eV' => 2.61317000000000E+19,
391
                'ev' => 2.61317000000000E+19,
392
                'HPh' => 1.55960800463137E-06,
393
                'hh' => 1.55960800463137E-06,
394
                'Wh' => 1.16299914807955E-03,
395
                'wh' => 1.16299914807955E-03,
396
                'flb' => 9.93544094443283E+01,
397
                'BTU' => 3.96830723907002E-03,
398
                'btu' => 3.96830723907002E-03,
399
            ],
400
            'eV' => [
401
                'J' => 1.60219000146921E-19,
402
                'e' => 1.60218923136574E-12,
403
                'c' => 3.82933423195043E-20,
404
                'cal' => 3.82676978535648E-20,
405
                'eV' => 1.0,
406
                'ev' => 1.0,
407
                'HPh' => 5.96826078912344E-26,
408
                'hh' => 5.96826078912344E-26,
409
                'Wh' => 4.45053000026614E-23,
410
                'wh' => 4.45053000026614E-23,
411
                'flb' => 3.80206452103492E-18,
412
                'BTU' => 1.51857982414846E-22,
413
                'btu' => 1.51857982414846E-22,
414
            ],
415
            'ev' => [
416
                'J' => 1.60219000146921E-19,
417
                'e' => 1.60218923136574E-12,
418
                'c' => 3.82933423195043E-20,
419
                'cal' => 3.82676978535648E-20,
420
                'eV' => 1.0,
421
                'ev' => 1.0,
422
                'HPh' => 5.96826078912344E-26,
423
                'hh' => 5.96826078912344E-26,
424
                'Wh' => 4.45053000026614E-23,
425
                'wh' => 4.45053000026614E-23,
426
                'flb' => 3.80206452103492E-18,
427
                'BTU' => 1.51857982414846E-22,
428
                'btu' => 1.51857982414846E-22,
429
            ],
430
            'HPh' => [
431
                'J' => 2.68451741316170E+06,
432
                'e' => 2.68451612283024E+13,
433
                'c' => 6.41616438565991E+05,
434
                'cal' => 6.41186757845835E+05,
435
                'eV' => 1.67553000000000E+25,
436
                'ev' => 1.67553000000000E+25,
437
                'HPh' => 1.0,
438
                'hh' => 1.0,
439
                'Wh' => 7.45699653134593E+02,
440
                'wh' => 7.45699653134593E+02,
441
                'flb' => 6.37047316692964E+07,
442
                'BTU' => 2.54442605275546E+03,
443
                'btu' => 2.54442605275546E+03,
444
            ],
445
            'hh' => [
446
                'J' => 2.68451741316170E+06,
447
                'e' => 2.68451612283024E+13,
448
                'c' => 6.41616438565991E+05,
449
                'cal' => 6.41186757845835E+05,
450
                'eV' => 1.67553000000000E+25,
451
                'ev' => 1.67553000000000E+25,
452
                'HPh' => 1.0,
453
                'hh' => 1.0,
454
                'Wh' => 7.45699653134593E+02,
455
                'wh' => 7.45699653134593E+02,
456
                'flb' => 6.37047316692964E+07,
457
                'BTU' => 2.54442605275546E+03,
458
                'btu' => 2.54442605275546E+03,
459
            ],
460
            'Wh' => [
461
                'J' => 3.59999820554720E+03,
462
                'e' => 3.59999647518369E+10,
463
                'c' => 8.60422069219046E+02,
464
                'cal' => 8.59845857713046E+02,
465
                'eV' => 2.24692340000000E+22,
466
                'ev' => 2.24692340000000E+22,
467
                'HPh' => 1.34102248243839E-03,
468
                'hh' => 1.34102248243839E-03,
469
                'Wh' => 1.0,
470
                'wh' => 1.0,
471
                'flb' => 8.54294774062316E+04,
472
                'BTU' => 3.41213254164705E+00,
473
                'btu' => 3.41213254164705E+00,
474
            ],
475
            'wh' => [
476
                'J' => 3.59999820554720E+03,
477
                'e' => 3.59999647518369E+10,
478
                'c' => 8.60422069219046E+02,
479
                'cal' => 8.59845857713046E+02,
480
                'eV' => 2.24692340000000E+22,
481
                'ev' => 2.24692340000000E+22,
482
                'HPh' => 1.34102248243839E-03,
483
                'hh' => 1.34102248243839E-03,
484
                'Wh' => 1.0,
485
                'wh' => 1.0,
486
                'flb' => 8.54294774062316E+04,
487
                'BTU' => 3.41213254164705E+00,
488
                'btu' => 3.41213254164705E+00,
489
            ],
490
            'flb' => [
491
                'J' => 4.21400003236424E-02,
492
                'e' => 4.21399800687660E+05,
493
                'c' => 1.00717234301644E-02,
494
                'cal' => 1.00649785509554E-02,
495
                'eV' => 2.63015000000000E+17,
496
                'ev' => 2.63015000000000E+17,
497
                'HPh' => 1.56974211145130E-08,
498
                'hh' => 1.56974211145130E-08,
499
                'Wh' => 1.17055614802000E-05,
500
                'wh' => 1.17055614802000E-05,
501
                'flb' => 1.0,
502
                'BTU' => 3.99409272448406E-05,
503
                'btu' => 3.99409272448406E-05,
504
            ],
505
            'BTU' => [
506
                'J' => 1.05505813786749E+03,
507
                'e' => 1.05505763074665E+10,
508
                'c' => 2.52165488508168E+02,
509
                'cal' => 2.51996617135510E+02,
510
                'eV' => 6.58510000000000E+21,
511
                'ev' => 6.58510000000000E+21,
512
                'HPh' => 3.93015941224568E-04,
513
                'hh' => 3.93015941224568E-04,
514
                'Wh' => 2.93071851047526E-01,
515
                'wh' => 2.93071851047526E-01,
516
                'flb' => 2.50369750774671E+04,
517
                'BTU' => 1.0,
518
                'btu' => 1.0,
519
            ],
520
            'btu' => [
521
                'J' => 1.05505813786749E+03,
522
                'e' => 1.05505763074665E+10,
523
                'c' => 2.52165488508168E+02,
524
                'cal' => 2.51996617135510E+02,
525
                'eV' => 6.58510000000000E+21,
526
                'ev' => 6.58510000000000E+21,
527
                'HPh' => 3.93015941224568E-04,
528
                'hh' => 3.93015941224568E-04,
529
                'Wh' => 2.93071851047526E-01,
530
                'wh' => 2.93071851047526E-01,
531
                'flb' => 2.50369750774671E+04,
532
                'BTU' => 1.0,
533
                'btu' => 1.0,
534
            ],
535
        ],
536
        'Power' => [
537
            'HP' => [
538
                'HP' => 1.0,
539
                'h' => 1.0,
540
                'W' => 7.45701000000000E+02,
541
                'w' => 7.45701000000000E+02,
542
            ],
543
            'h' => [
544
                'HP' => 1.0,
545
                'h' => 1.0,
546
                'W' => 7.45701000000000E+02,
547
                'w' => 7.45701000000000E+02,
548
            ],
549
            'W' => [
550
                'HP' => 1.34102006031908E-03,
551
                'h' => 1.34102006031908E-03,
552
                'W' => 1.0,
553
                'w' => 1.0,
554
            ],
555
            'w' => [
556
                'HP' => 1.34102006031908E-03,
557
                'h' => 1.34102006031908E-03,
558
                'W' => 1.0,
559
                'w' => 1.0,
560
            ],
561
        ],
562
        'Magnetism' => [
563
            'T' => [
564
                'T' => 1.0,
565
                'ga' => 10000.0,
566
            ],
567
            'ga' => [
568
                'T' => 0.0001,
569
                'ga' => 1.0,
570
            ],
571
        ],
572
        'Liquid' => [
573
            'tsp' => [
574
                'tsp' => 1.0,
575
                'tbs' => 3.33333333333333E-01,
576
                'oz' => 1.66666666666667E-01,
577
                'cup' => 2.08333333333333E-02,
578
                'pt' => 1.04166666666667E-02,
579
                'us_pt' => 1.04166666666667E-02,
580
                'uk_pt' => 8.67558516821960E-03,
581
                'qt' => 5.20833333333333E-03,
582
                'gal' => 1.30208333333333E-03,
583
                'l' => 4.92999408400710E-03,
584
                'lt' => 4.92999408400710E-03,
585
            ],
586
            'tbs' => [
587
                'tsp' => 3.00000000000000E+00,
588
                'tbs' => 1.0,
589
                'oz' => 5.00000000000000E-01,
590
                'cup' => 6.25000000000000E-02,
591
                'pt' => 3.12500000000000E-02,
592
                'us_pt' => 3.12500000000000E-02,
593
                'uk_pt' => 2.60267555046588E-02,
594
                'qt' => 1.56250000000000E-02,
595
                'gal' => 3.90625000000000E-03,
596
                'l' => 1.47899822520213E-02,
597
                'lt' => 1.47899822520213E-02,
598
            ],
599
            'oz' => [
600
                'tsp' => 6.00000000000000E+00,
601
                'tbs' => 2.00000000000000E+00,
602
                'oz' => 1.0,
603
                'cup' => 1.25000000000000E-01,
604
                'pt' => 6.25000000000000E-02,
605
                'us_pt' => 6.25000000000000E-02,
606
                'uk_pt' => 5.20535110093176E-02,
607
                'qt' => 3.12500000000000E-02,
608
                'gal' => 7.81250000000000E-03,
609
                'l' => 2.95799645040426E-02,
610
                'lt' => 2.95799645040426E-02,
611
            ],
612
            'cup' => [
613
                'tsp' => 4.80000000000000E+01,
614
                'tbs' => 1.60000000000000E+01,
615
                'oz' => 8.00000000000000E+00,
616
                'cup' => 1.0,
617
                'pt' => 5.00000000000000E-01,
618
                'us_pt' => 5.00000000000000E-01,
619
                'uk_pt' => 4.16428088074541E-01,
620
                'qt' => 2.50000000000000E-01,
621
                'gal' => 6.25000000000000E-02,
622
                'l' => 2.36639716032341E-01,
623
                'lt' => 2.36639716032341E-01,
624
            ],
625
            'pt' => [
626
                'tsp' => 9.60000000000000E+01,
627
                'tbs' => 3.20000000000000E+01,
628
                'oz' => 1.60000000000000E+01,
629
                'cup' => 2.00000000000000E+00,
630
                'pt' => 1.0,
631
                'us_pt' => 1.0,
632
                'uk_pt' => 8.32856176149081E-01,
633
                'qt' => 5.00000000000000E-01,
634
                'gal' => 1.25000000000000E-01,
635
                'l' => 4.73279432064682E-01,
636
                'lt' => 4.73279432064682E-01,
637
            ],
638
            'us_pt' => [
639
                'tsp' => 9.60000000000000E+01,
640
                'tbs' => 3.20000000000000E+01,
641
                'oz' => 1.60000000000000E+01,
642
                'cup' => 2.00000000000000E+00,
643
                'pt' => 1.0,
644
                'us_pt' => 1.0,
645
                'uk_pt' => 8.32856176149081E-01,
646
                'qt' => 5.00000000000000E-01,
647
                'gal' => 1.25000000000000E-01,
648
                'l' => 4.73279432064682E-01,
649
                'lt' => 4.73279432064682E-01,
650
            ],
651
            'uk_pt' => [
652
                'tsp' => 1.15266000000000E+02,
653
                'tbs' => 3.84220000000000E+01,
654
                'oz' => 1.92110000000000E+01,
655
                'cup' => 2.40137500000000E+00,
656
                'pt' => 1.20068750000000E+00,
657
                'us_pt' => 1.20068750000000E+00,
658
                'uk_pt' => 1.0,
659
                'qt' => 6.00343750000000E-01,
660
                'gal' => 1.50085937500000E-01,
661
                'l' => 5.68260698087162E-01,
662
                'lt' => 5.68260698087162E-01,
663
            ],
664
            'qt' => [
665
                'tsp' => 1.92000000000000E+02,
666
                'tbs' => 6.40000000000000E+01,
667
                'oz' => 3.20000000000000E+01,
668
                'cup' => 4.00000000000000E+00,
669
                'pt' => 2.00000000000000E+00,
670
                'us_pt' => 2.00000000000000E+00,
671
                'uk_pt' => 1.66571235229816E+00,
672
                'qt' => 1.0,
673
                'gal' => 2.50000000000000E-01,
674
                'l' => 9.46558864129363E-01,
675
                'lt' => 9.46558864129363E-01,
676
            ],
677
            'gal' => [
678
                'tsp' => 7.68000000000000E+02,
679
                'tbs' => 2.56000000000000E+02,
680
                'oz' => 1.28000000000000E+02,
681
                'cup' => 1.60000000000000E+01,
682
                'pt' => 8.00000000000000E+00,
683
                'us_pt' => 8.00000000000000E+00,
684
                'uk_pt' => 6.66284940919265E+00,
685
                'qt' => 4.00000000000000E+00,
686
                'gal' => 1.0,
687
                'l' => 3.78623545651745E+00,
688
                'lt' => 3.78623545651745E+00,
689
            ],
690
            'l' => [
691
                'tsp' => 2.02840000000000E+02,
692
                'tbs' => 6.76133333333333E+01,
693
                'oz' => 3.38066666666667E+01,
694
                'cup' => 4.22583333333333E+00,
695
                'pt' => 2.11291666666667E+00,
696
                'us_pt' => 2.11291666666667E+00,
697
                'uk_pt' => 1.75975569552166E+00,
698
                'qt' => 1.05645833333333E+00,
699
                'gal' => 2.64114583333333E-01,
700
                'l' => 1.0,
701
                'lt' => 1.0,
702
            ],
703
            'lt' => [
704
                'tsp' => 2.02840000000000E+02,
705
                'tbs' => 6.76133333333333E+01,
706
                'oz' => 3.38066666666667E+01,
707
                'cup' => 4.22583333333333E+00,
708
                'pt' => 2.11291666666667E+00,
709
                'us_pt' => 2.11291666666667E+00,
710
                'uk_pt' => 1.75975569552166E+00,
711
                'qt' => 1.05645833333333E+00,
712
                'gal' => 2.64114583333333E-01,
713
                'l' => 1.0,
714
                'lt' => 1.0,
715
            ],
716
        ],
717
    ];
718
719
    /**
720
     * parseComplex.
721
     *
722
     * Parses a complex number into its real and imaginary parts, and an I or J suffix
723
     *
724
     * @deprecated 2.0.0 No longer used by internal code. Please use the Complex\Complex class instead
725
     *
726
     * @param string $complexNumber The complex number
727
     *
728
     * @return mixed[] Indexed on "real", "imaginary" and "suffix"
729
     */
730 547
    public static function parseComplex($complexNumber)
731
    {
732 547
        $complex = new Complex($complexNumber);
733
734
        return [
735 547
            'real' => $complex->getReal(),
736 547
            'imaginary' => $complex->getImaginary(),
737 547
            'suffix' => $complex->getSuffix(),
738
        ];
739
    }
740
741
    /**
742
     * Formats a number base string value with leading zeroes.
743
     *
744
     * @param string $xVal The "number" to pad
745
     * @param int $places The length that we want to pad this value
746
     *
747
     * @return string The padded "number"
748
     */
749 82
    private static function nbrConversionFormat($xVal, $places)
750
    {
751 82
        if ($places !== null) {
0 ignored issues
show
introduced by
The condition $places !== null is always true.
Loading history...
752 22
            if (is_numeric($places)) {
0 ignored issues
show
introduced by
The condition is_numeric($places) is always true.
Loading history...
753 18
                $places = (int) $places;
754
            } else {
755 4
                return Functions::VALUE();
756
            }
757 18
            if ($places < 0) {
758 4
                return Functions::NAN();
759
            }
760 14
            if (strlen($xVal) <= $places) {
761 14
                return substr(str_pad($xVal, $places, '0', STR_PAD_LEFT), -10);
762
            }
763
764
            return Functions::NAN();
765
        }
766
767 60
        return substr($xVal, -10);
768
    }
769
770
    /**
771
     * BESSELI.
772
     *
773
     *    Returns the modified Bessel function In(x), which is equivalent to the Bessel function evaluated
774
     *        for purely imaginary arguments
775
     *
776
     *    Excel Function:
777
     *        BESSELI(x,ord)
778
     *
779
     * @category Engineering Functions
780
     *
781
     * @param float $x The value at which to evaluate the function.
782
     *                                If x is nonnumeric, BESSELI returns the #VALUE! error value.
783
     * @param int $ord The order of the Bessel function.
784
     *                                If ord is not an integer, it is truncated.
785
     *                                If $ord is nonnumeric, BESSELI returns the #VALUE! error value.
786
     *                                If $ord < 0, BESSELI returns the #NUM! error value.
787
     *
788
     * @return float
789
     */
790 74
    public static function BESSELI($x, $ord)
791
    {
792 74
        $x = ($x === null) ? 0.0 : Functions::flattenSingleValue($x);
0 ignored issues
show
introduced by
The condition $x === null is always false.
Loading history...
793 74
        $ord = ($ord === null) ? 0.0 : Functions::flattenSingleValue($ord);
0 ignored issues
show
introduced by
The condition $ord === null is always false.
Loading history...
794
795 74
        if ((is_numeric($x)) && (is_numeric($ord))) {
796 70
            $ord = floor($ord);
797 70
            if ($ord < 0) {
798 2
                return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
799
            }
800
801 68
            if (abs($x) <= 30) {
802 68
                $fResult = $fTerm = pow($x / 2, $ord) / MathTrig::FACT($ord);
803 68
                $ordK = 1;
804 68
                $fSqrX = ($x * $x) / 4;
805
                do {
806 68
                    $fTerm *= $fSqrX;
807 68
                    $fTerm /= ($ordK * ($ordK + $ord));
808 68
                    $fResult += $fTerm;
809 68
                } while ((abs($fTerm) > 1e-12) && (++$ordK < 100));
810
            } else {
811
                $f_2_PI = 2 * M_PI;
812
813
                $fXAbs = abs($x);
814
                $fResult = exp($fXAbs) / sqrt($f_2_PI * $fXAbs);
815
                if (($ord & 1) && ($x < 0)) {
816
                    $fResult = -$fResult;
817
                }
818
            }
819
820 68
            return (is_nan($fResult)) ? Functions::NAN() : $fResult;
0 ignored issues
show
Bug Best Practice introduced by
The expression return is_nan($fResult) ...tions::NAN() : $fResult also could return the type string which is incompatible with the documented return type double.
Loading history...
821
        }
822
823 4
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
824
    }
825
826
    /**
827
     * BESSELJ.
828
     *
829
     *    Returns the Bessel function
830
     *
831
     *    Excel Function:
832
     *        BESSELJ(x,ord)
833
     *
834
     * @category Engineering Functions
835
     *
836
     * @param float $x The value at which to evaluate the function.
837
     *                                If x is nonnumeric, BESSELJ returns the #VALUE! error value.
838
     * @param int $ord The order of the Bessel function. If n is not an integer, it is truncated.
839
     *                                If $ord is nonnumeric, BESSELJ returns the #VALUE! error value.
840
     *                                If $ord < 0, BESSELJ returns the #NUM! error value.
841
     *
842
     * @return float
843
     */
844 50
    public static function BESSELJ($x, $ord)
845
    {
846 50
        $x = ($x === null) ? 0.0 : Functions::flattenSingleValue($x);
0 ignored issues
show
introduced by
The condition $x === null is always false.
Loading history...
847 50
        $ord = ($ord === null) ? 0.0 : Functions::flattenSingleValue($ord);
0 ignored issues
show
introduced by
The condition $ord === null is always false.
Loading history...
848
849 50
        if ((is_numeric($x)) && (is_numeric($ord))) {
850 48
            $ord = floor($ord);
851 48
            if ($ord < 0) {
852 1
                return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
853
            }
854
855 47
            $fResult = 0;
856 47
            if (abs($x) <= 30) {
857 47
                $fResult = $fTerm = pow($x / 2, $ord) / MathTrig::FACT($ord);
858 47
                $ordK = 1;
859 47
                $fSqrX = ($x * $x) / -4;
860
                do {
861 47
                    $fTerm *= $fSqrX;
862 47
                    $fTerm /= ($ordK * ($ordK + $ord));
863 47
                    $fResult += $fTerm;
864 47
                } while ((abs($fTerm) > 1e-12) && (++$ordK < 100));
865
            } else {
866
                $f_PI_DIV_2 = M_PI / 2;
867
                $f_PI_DIV_4 = M_PI / 4;
868
869
                $fXAbs = abs($x);
870
                $fResult = sqrt(Functions::M_2DIVPI / $fXAbs) * cos($fXAbs - $ord * $f_PI_DIV_2 - $f_PI_DIV_4);
871
                if (($ord & 1) && ($x < 0)) {
872
                    $fResult = -$fResult;
873
                }
874
            }
875
876 47
            return (is_nan($fResult)) ? Functions::NAN() : $fResult;
0 ignored issues
show
Bug Best Practice introduced by
The expression return is_nan($fResult) ...tions::NAN() : $fResult also could return the type string which is incompatible with the documented return type double.
Loading history...
877
        }
878
879 2
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
880
    }
881
882 22
    private static function besselK0($fNum)
883
    {
884 22
        if ($fNum <= 2) {
885 14
            $fNum2 = $fNum * 0.5;
886 14
            $y = ($fNum2 * $fNum2);
887 14
            $fRet = -log($fNum2) * self::BESSELI($fNum, 0) +
888
                (-0.57721566 + $y * (0.42278420 + $y * (0.23069756 + $y * (0.3488590e-1 + $y * (0.262698e-2 + $y *
889 14
                                    (0.10750e-3 + $y * 0.74e-5))))));
890
        } else {
891 8
            $y = 2 / $fNum;
892 8
            $fRet = exp(-$fNum) / sqrt($fNum) *
893
                (1.25331414 + $y * (-0.7832358e-1 + $y * (0.2189568e-1 + $y * (-0.1062446e-1 + $y *
894 8
                                (0.587872e-2 + $y * (-0.251540e-2 + $y * 0.53208e-3))))));
895
        }
896
897 22
        return $fRet;
898
    }
899
900 30
    private static function besselK1($fNum)
901
    {
902 30
        if ($fNum <= 2) {
903 17
            $fNum2 = $fNum * 0.5;
904 17
            $y = ($fNum2 * $fNum2);
905 17
            $fRet = log($fNum2) * self::BESSELI($fNum, 1) +
906
                (1 + $y * (0.15443144 + $y * (-0.67278579 + $y * (-0.18156897 + $y * (-0.1919402e-1 + $y *
907 17
                                    (-0.110404e-2 + $y * (-0.4686e-4))))))) / $fNum;
908
        } else {
909 13
            $y = 2 / $fNum;
910 13
            $fRet = exp(-$fNum) / sqrt($fNum) *
911
                (1.25331414 + $y * (0.23498619 + $y * (-0.3655620e-1 + $y * (0.1504268e-1 + $y * (-0.780353e-2 + $y *
912 13
                                    (0.325614e-2 + $y * (-0.68245e-3)))))));
913
        }
914
915 30
        return $fRet;
916
    }
917
918
    /**
919
     * BESSELK.
920
     *
921
     *    Returns the modified Bessel function Kn(x), which is equivalent to the Bessel functions evaluated
922
     *        for purely imaginary arguments.
923
     *
924
     *    Excel Function:
925
     *        BESSELK(x,ord)
926
     *
927
     * @category Engineering Functions
928
     *
929
     * @param float $x The value at which to evaluate the function.
930
     *                                If x is nonnumeric, BESSELK returns the #VALUE! error value.
931
     * @param int $ord The order of the Bessel function. If n is not an integer, it is truncated.
932
     *                                If $ord is nonnumeric, BESSELK returns the #VALUE! error value.
933
     *                                If $ord < 0, BESSELK returns the #NUM! error value.
934
     *
935
     * @return float
936
     */
937 38
    public static function BESSELK($x, $ord)
938
    {
939 38
        $x = ($x === null) ? 0.0 : Functions::flattenSingleValue($x);
0 ignored issues
show
introduced by
The condition $x === null is always false.
Loading history...
940 38
        $ord = ($ord === null) ? 0.0 : Functions::flattenSingleValue($ord);
0 ignored issues
show
introduced by
The condition $ord === null is always false.
Loading history...
941
942 38
        if ((is_numeric($x)) && (is_numeric($ord))) {
943 36
            if (($ord < 0) || ($x == 0.0)) {
944 4
                return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
945
            }
946
947 32
            switch (floor($ord)) {
948 32
                case 0:
949 2
                    $fBk = self::besselK0($x);
950
951 2
                    break;
952 30
                case 1:
953 10
                    $fBk = self::besselK1($x);
954
955 10
                    break;
956
                default:
957 20
                    $fTox = 2 / $x;
958 20
                    $fBkm = self::besselK0($x);
959 20
                    $fBk = self::besselK1($x);
960 20
                    for ($n = 1; $n < $ord; ++$n) {
961 20
                        $fBkp = $fBkm + $n * $fTox * $fBk;
962 20
                        $fBkm = $fBk;
963 20
                        $fBk = $fBkp;
964
                    }
965
            }
966
967 32
            return (is_nan($fBk)) ? Functions::NAN() : $fBk;
0 ignored issues
show
Bug Best Practice introduced by
The expression return is_nan($fBk) ? Ph...Functions::NAN() : $fBk also could return the type string which is incompatible with the documented return type double.
Loading history...
968
        }
969
970 2
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
971
    }
972
973 11
    private static function besselY0($fNum)
974
    {
975 11
        if ($fNum < 8.0) {
976 10
            $y = ($fNum * $fNum);
977 10
            $f1 = -2957821389.0 + $y * (7062834065.0 + $y * (-512359803.6 + $y * (10879881.29 + $y * (-86327.92757 + $y * 228.4622733))));
978 10
            $f2 = 40076544269.0 + $y * (745249964.8 + $y * (7189466.438 + $y * (47447.26470 + $y * (226.1030244 + $y))));
979 10
            $fRet = $f1 / $f2 + 0.636619772 * self::BESSELJ($fNum, 0) * log($fNum);
980
        } else {
981 1
            $z = 8.0 / $fNum;
982 1
            $y = ($z * $z);
983 1
            $xx = $fNum - 0.785398164;
984 1
            $f1 = 1 + $y * (-0.1098628627e-2 + $y * (0.2734510407e-4 + $y * (-0.2073370639e-5 + $y * 0.2093887211e-6)));
985 1
            $f2 = -0.1562499995e-1 + $y * (0.1430488765e-3 + $y * (-0.6911147651e-5 + $y * (0.7621095161e-6 + $y * (-0.934945152e-7))));
986 1
            $fRet = sqrt(0.636619772 / $fNum) * (sin($xx) * $f1 + $z * cos($xx) * $f2);
987
        }
988
989 11
        return $fRet;
990
    }
991
992 16
    private static function besselY1($fNum)
993
    {
994 16
        if ($fNum < 8.0) {
995 16
            $y = ($fNum * $fNum);
996
            $f1 = $fNum * (-0.4900604943e13 + $y * (0.1275274390e13 + $y * (-0.5153438139e11 + $y * (0.7349264551e9 + $y *
997 16
                                (-0.4237922726e7 + $y * 0.8511937935e4)))));
998
            $f2 = 0.2499580570e14 + $y * (0.4244419664e12 + $y * (0.3733650367e10 + $y * (0.2245904002e8 + $y *
999 16
                            (0.1020426050e6 + $y * (0.3549632885e3 + $y)))));
1000 16
            $fRet = $f1 / $f2 + 0.636619772 * (self::BESSELJ($fNum, 1) * log($fNum) - 1 / $fNum);
1001
        } else {
1002
            $fRet = sqrt(0.636619772 / $fNum) * sin($fNum - 2.356194491);
1003
        }
1004
1005 16
        return $fRet;
1006
    }
1007
1008
    /**
1009
     * BESSELY.
1010
     *
1011
     * Returns the Bessel function, which is also called the Weber function or the Neumann function.
1012
     *
1013
     *    Excel Function:
1014
     *        BESSELY(x,ord)
1015
     *
1016
     * @category Engineering Functions
1017
     *
1018
     * @param float $x The value at which to evaluate the function.
1019
     *                                If x is nonnumeric, BESSELK returns the #VALUE! error value.
1020
     * @param int $ord The order of the Bessel function. If n is not an integer, it is truncated.
1021
     *                                If $ord is nonnumeric, BESSELK returns the #VALUE! error value.
1022
     *                                If $ord < 0, BESSELK returns the #NUM! error value.
1023
     *
1024
     * @return float
1025
     */
1026 23
    public static function BESSELY($x, $ord)
1027
    {
1028 23
        $x = ($x === null) ? 0.0 : Functions::flattenSingleValue($x);
0 ignored issues
show
introduced by
The condition $x === null is always false.
Loading history...
1029 23
        $ord = ($ord === null) ? 0.0 : Functions::flattenSingleValue($ord);
0 ignored issues
show
introduced by
The condition $ord === null is always false.
Loading history...
1030
1031 23
        if ((is_numeric($x)) && (is_numeric($ord))) {
1032 21
            if (($ord < 0) || ($x == 0.0)) {
1033 3
                return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
1034
            }
1035
1036 18
            switch (floor($ord)) {
1037 18
                case 0:
1038 2
                    $fBy = self::besselY0($x);
1039
1040 2
                    break;
1041 16
                case 1:
1042 7
                    $fBy = self::besselY1($x);
1043
1044 7
                    break;
1045
                default:
1046 9
                    $fTox = 2 / $x;
1047 9
                    $fBym = self::besselY0($x);
1048 9
                    $fBy = self::besselY1($x);
1049 9
                    for ($n = 1; $n < $ord; ++$n) {
1050 9
                        $fByp = $n * $fTox * $fBy - $fBym;
1051 9
                        $fBym = $fBy;
1052 9
                        $fBy = $fByp;
1053
                    }
1054
            }
1055
1056 18
            return (is_nan($fBy)) ? Functions::NAN() : $fBy;
0 ignored issues
show
Bug Best Practice introduced by
The expression return is_nan($fBy) ? Ph...Functions::NAN() : $fBy also could return the type string which is incompatible with the documented return type double.
Loading history...
1057
        }
1058
1059 2
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
1060
    }
1061
1062
    /**
1063
     * BINTODEC.
1064
     *
1065
     * Return a binary value as decimal.
1066
     *
1067
     * Excel Function:
1068
     *        BIN2DEC(x)
1069
     *
1070
     * @category Engineering Functions
1071
     *
1072
     * @param string $x The binary number (as a string) that you want to convert. The number
1073
     *                                cannot contain more than 10 characters (10 bits). The most significant
1074
     *                                bit of number is the sign bit. The remaining 9 bits are magnitude bits.
1075
     *                                Negative numbers are represented using two's-complement notation.
1076
     *                                If number is not a valid binary number, or if number contains more than
1077
     *                                10 characters (10 bits), BIN2DEC returns the #NUM! error value.
1078
     *
1079
     * @return string
1080
     */
1081 10
    public static function BINTODEC($x)
1082
    {
1083 10
        $x = Functions::flattenSingleValue($x);
1084
1085 10
        if (is_bool($x)) {
1086 1
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
1087
                $x = (int) $x;
1088
            } else {
1089 1
                return Functions::VALUE();
1090
            }
1091
        }
1092 9
        if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) {
1093
            $x = floor($x);
1 ignored issue
show
Bug introduced by
It seems like $x can also be of type string; however, parameter $value of floor() does only seem to accept double, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1093
            $x = floor(/** @scrutinizer ignore-type */ $x);
Loading history...
1094
        }
1095 9
        $x = (string) $x;
1096 9
        if (strlen($x) > preg_match_all('/[01]/', $x, $out)) {
1097 1
            return Functions::NAN();
1098
        }
1099 8
        if (strlen($x) > 10) {
1100 1
            return Functions::NAN();
1101 7
        } elseif (strlen($x) == 10) {
1102
            //    Two's Complement
1103 2
            $x = substr($x, -9);
1104
1105 2
            return '-' . (512 - bindec($x));
1106
        }
1107
1108 5
        return bindec($x);
1109
    }
1110
1111
    /**
1112
     * BINTOHEX.
1113
     *
1114
     * Return a binary value as hex.
1115
     *
1116
     * Excel Function:
1117
     *        BIN2HEX(x[,places])
1118
     *
1119
     * @category Engineering Functions
1120
     *
1121
     * @param string $x The binary number (as a string) that you want to convert. The number
1122
     *                                cannot contain more than 10 characters (10 bits). The most significant
1123
     *                                bit of number is the sign bit. The remaining 9 bits are magnitude bits.
1124
     *                                Negative numbers are represented using two's-complement notation.
1125
     *                                If number is not a valid binary number, or if number contains more than
1126
     *                                10 characters (10 bits), BIN2HEX returns the #NUM! error value.
1127
     * @param int $places The number of characters to use. If places is omitted, BIN2HEX uses the
1128
     *                                minimum number of characters necessary. Places is useful for padding the
1129
     *                                return value with leading 0s (zeros).
1130
     *                                If places is not an integer, it is truncated.
1131
     *                                If places is nonnumeric, BIN2HEX returns the #VALUE! error value.
1132
     *                                If places is negative, BIN2HEX returns the #NUM! error value.
1133
     *
1134
     * @return string
1135
     */
1136 14
    public static function BINTOHEX($x, $places = null)
1137
    {
1138 14
        $x = Functions::flattenSingleValue($x);
1139 14
        $places = Functions::flattenSingleValue($places);
1140
1141
        // Argument X
1142 14
        if (is_bool($x)) {
1143 1
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
1144
                $x = (int) $x;
1145
            } else {
1146 1
                return Functions::VALUE();
1147
            }
1148
        }
1149 13
        if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) {
1150
            $x = floor($x);
1 ignored issue
show
Bug introduced by
It seems like $x can also be of type string; however, parameter $value of floor() does only seem to accept double, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1150
            $x = floor(/** @scrutinizer ignore-type */ $x);
Loading history...
1151
        }
1152 13
        $x = (string) $x;
1153 13
        if (strlen($x) > preg_match_all('/[01]/', $x, $out)) {
1154 1
            return Functions::NAN();
1155
        }
1156 12
        if (strlen($x) > 10) {
1157 1
            return Functions::NAN();
1158 11
        } elseif (strlen($x) == 10) {
1159
            //    Two's Complement
1160 2
            return str_repeat('F', 8) . substr(strtoupper(dechex(bindec(substr($x, -9)))), -2);
1 ignored issue
show
Bug introduced by
It seems like bindec(substr($x, -9)) can also be of type double; however, parameter $number of dechex() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1160
            return str_repeat('F', 8) . substr(strtoupper(dechex(/** @scrutinizer ignore-type */ bindec(substr($x, -9)))), -2);
Loading history...
1161
        }
1162 9
        $hexVal = (string) strtoupper(dechex(bindec($x)));
1163
1164 9
        return self::nbrConversionFormat($hexVal, $places);
1165
    }
1166
1167
    /**
1168
     * BINTOOCT.
1169
     *
1170
     * Return a binary value as octal.
1171
     *
1172
     * Excel Function:
1173
     *        BIN2OCT(x[,places])
1174
     *
1175
     * @category Engineering Functions
1176
     *
1177
     * @param string $x The binary number (as a string) that you want to convert. The number
1178
     *                                cannot contain more than 10 characters (10 bits). The most significant
1179
     *                                bit of number is the sign bit. The remaining 9 bits are magnitude bits.
1180
     *                                Negative numbers are represented using two's-complement notation.
1181
     *                                If number is not a valid binary number, or if number contains more than
1182
     *                                10 characters (10 bits), BIN2OCT returns the #NUM! error value.
1183
     * @param int $places The number of characters to use. If places is omitted, BIN2OCT uses the
1184
     *                                minimum number of characters necessary. Places is useful for padding the
1185
     *                                return value with leading 0s (zeros).
1186
     *                                If places is not an integer, it is truncated.
1187
     *                                If places is nonnumeric, BIN2OCT returns the #VALUE! error value.
1188
     *                                If places is negative, BIN2OCT returns the #NUM! error value.
1189
     *
1190
     * @return string
1191
     */
1192 15
    public static function BINTOOCT($x, $places = null)
1193
    {
1194 15
        $x = Functions::flattenSingleValue($x);
1195 15
        $places = Functions::flattenSingleValue($places);
1196
1197 15
        if (is_bool($x)) {
1198 1
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
1199
                $x = (int) $x;
1200
            } else {
1201 1
                return Functions::VALUE();
1202
            }
1203
        }
1204 14
        if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) {
1205
            $x = floor($x);
1 ignored issue
show
Bug introduced by
It seems like $x can also be of type string; however, parameter $value of floor() does only seem to accept double, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1205
            $x = floor(/** @scrutinizer ignore-type */ $x);
Loading history...
1206
        }
1207 14
        $x = (string) $x;
1208 14
        if (strlen($x) > preg_match_all('/[01]/', $x, $out)) {
1209 1
            return Functions::NAN();
1210
        }
1211 13
        if (strlen($x) > 10) {
1212 1
            return Functions::NAN();
1213 12
        } elseif (strlen($x) == 10) {
1214
            //    Two's Complement
1215 2
            return str_repeat('7', 7) . substr(strtoupper(decoct(bindec(substr($x, -9)))), -3);
1 ignored issue
show
Bug introduced by
It seems like bindec(substr($x, -9)) can also be of type double; however, parameter $number of decoct() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1215
            return str_repeat('7', 7) . substr(strtoupper(decoct(/** @scrutinizer ignore-type */ bindec(substr($x, -9)))), -3);
Loading history...
1216
        }
1217 10
        $octVal = (string) decoct(bindec($x));
1218
1219 10
        return self::nbrConversionFormat($octVal, $places);
1220
    }
1221
1222
    /**
1223
     * DECTOBIN.
1224
     *
1225
     * Return a decimal value as binary.
1226
     *
1227
     * Excel Function:
1228
     *        DEC2BIN(x[,places])
1229
     *
1230
     * @category Engineering Functions
1231
     *
1232
     * @param string $x The decimal integer you want to convert. If number is negative,
1233
     *                                valid place values are ignored and DEC2BIN returns a 10-character
1234
     *                                (10-bit) binary number in which the most significant bit is the sign
1235
     *                                bit. The remaining 9 bits are magnitude bits. Negative numbers are
1236
     *                                represented using two's-complement notation.
1237
     *                                If number < -512 or if number > 511, DEC2BIN returns the #NUM! error
1238
     *                                value.
1239
     *                                If number is nonnumeric, DEC2BIN returns the #VALUE! error value.
1240
     *                                If DEC2BIN requires more than places characters, it returns the #NUM!
1241
     *                                error value.
1242
     * @param int $places The number of characters to use. If places is omitted, DEC2BIN uses
1243
     *                                the minimum number of characters necessary. Places is useful for
1244
     *                                padding the return value with leading 0s (zeros).
1245
     *                                If places is not an integer, it is truncated.
1246
     *                                If places is nonnumeric, DEC2BIN returns the #VALUE! error value.
1247
     *                                If places is zero or negative, DEC2BIN returns the #NUM! error value.
1248
     *
1249
     * @return string
1250
     */
1251 41
    public static function DECTOBIN($x, $places = null)
1252
    {
1253 41
        $x = Functions::flattenSingleValue($x);
1254 41
        $places = Functions::flattenSingleValue($places);
1255
1256 41
        if (is_bool($x)) {
1257 1
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
1258
                $x = (int) $x;
1259
            } else {
1260 1
                return Functions::VALUE();
1261
            }
1262
        }
1263 40
        $x = (string) $x;
1264 40
        if (strlen($x) > preg_match_all('/[-0123456789.]/', $x, $out)) {
1265 1
            return Functions::VALUE();
1266
        }
1267
1268 39
        $x = (string) floor($x);
0 ignored issues
show
Bug introduced by
$x of type string is incompatible with the type double expected by parameter $value of floor(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1268
        $x = (string) floor(/** @scrutinizer ignore-type */ $x);
Loading history...
1269 39
        if ($x < -512 || $x > 511) {
1270 13
            return Functions::NAN();
1271
        }
1272
1273 26
        $r = decbin($x);
0 ignored issues
show
Bug introduced by
$x of type string is incompatible with the type integer expected by parameter $number of decbin(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1273
        $r = decbin(/** @scrutinizer ignore-type */ $x);
Loading history...
1274
        // Two's Complement
1275 26
        $r = substr($r, -10);
1276 26
        if (strlen($r) >= 11) {
1277
            return Functions::NAN();
1278
        }
1279
1280 26
        return self::nbrConversionFormat($r, $places);
1281
    }
1282
1283
    /**
1284
     * DECTOHEX.
1285
     *
1286
     * Return a decimal value as hex.
1287
     *
1288
     * Excel Function:
1289
     *        DEC2HEX(x[,places])
1290
     *
1291
     * @category Engineering Functions
1292
     *
1293
     * @param string $x The decimal integer you want to convert. If number is negative,
1294
     *                                places is ignored and DEC2HEX returns a 10-character (40-bit)
1295
     *                                hexadecimal number in which the most significant bit is the sign
1296
     *                                bit. The remaining 39 bits are magnitude bits. Negative numbers
1297
     *                                are represented using two's-complement notation.
1298
     *                                If number < -549,755,813,888 or if number > 549,755,813,887,
1299
     *                                DEC2HEX returns the #NUM! error value.
1300
     *                                If number is nonnumeric, DEC2HEX returns the #VALUE! error value.
1301
     *                                If DEC2HEX requires more than places characters, it returns the
1302
     *                                #NUM! error value.
1303
     * @param int $places The number of characters to use. If places is omitted, DEC2HEX uses
1304
     *                                the minimum number of characters necessary. Places is useful for
1305
     *                                padding the return value with leading 0s (zeros).
1306
     *                                If places is not an integer, it is truncated.
1307
     *                                If places is nonnumeric, DEC2HEX returns the #VALUE! error value.
1308
     *                                If places is zero or negative, DEC2HEX returns the #NUM! error value.
1309
     *
1310
     * @return string
1311
     */
1312 15
    public static function DECTOHEX($x, $places = null)
1313
    {
1314 15
        $x = Functions::flattenSingleValue($x);
1315 15
        $places = Functions::flattenSingleValue($places);
1316
1317 15
        if (is_bool($x)) {
1318 1
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
1319
                $x = (int) $x;
1320
            } else {
1321 1
                return Functions::VALUE();
1322
            }
1323
        }
1324 14
        $x = (string) $x;
1325 14
        if (strlen($x) > preg_match_all('/[-0123456789.]/', $x, $out)) {
1326 1
            return Functions::VALUE();
1327
        }
1328 13
        $x = (string) floor($x);
0 ignored issues
show
Bug introduced by
$x of type string is incompatible with the type double expected by parameter $value of floor(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1328
        $x = (string) floor(/** @scrutinizer ignore-type */ $x);
Loading history...
1329 13
        $r = strtoupper(dechex($x));
0 ignored issues
show
Bug introduced by
$x of type string is incompatible with the type integer expected by parameter $number of dechex(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1329
        $r = strtoupper(dechex(/** @scrutinizer ignore-type */ $x));
Loading history...
1330 13
        if (strlen($r) == 8) {
1331
            //    Two's Complement
1332
            $r = 'FF' . $r;
1333
        }
1334
1335 13
        return self::nbrConversionFormat($r, $places);
1336
    }
1337
1338
    /**
1339
     * DECTOOCT.
1340
     *
1341
     * Return an decimal value as octal.
1342
     *
1343
     * Excel Function:
1344
     *        DEC2OCT(x[,places])
1345
     *
1346
     * @category Engineering Functions
1347
     *
1348
     * @param string $x The decimal integer you want to convert. If number is negative,
1349
     *                                places is ignored and DEC2OCT returns a 10-character (30-bit)
1350
     *                                octal number in which the most significant bit is the sign bit.
1351
     *                                The remaining 29 bits are magnitude bits. Negative numbers are
1352
     *                                represented using two's-complement notation.
1353
     *                                If number < -536,870,912 or if number > 536,870,911, DEC2OCT
1354
     *                                returns the #NUM! error value.
1355
     *                                If number is nonnumeric, DEC2OCT returns the #VALUE! error value.
1356
     *                                If DEC2OCT requires more than places characters, it returns the
1357
     *                                #NUM! error value.
1358
     * @param int $places The number of characters to use. If places is omitted, DEC2OCT uses
1359
     *                                the minimum number of characters necessary. Places is useful for
1360
     *                                padding the return value with leading 0s (zeros).
1361
     *                                If places is not an integer, it is truncated.
1362
     *                                If places is nonnumeric, DEC2OCT returns the #VALUE! error value.
1363
     *                                If places is zero or negative, DEC2OCT returns the #NUM! error value.
1364
     *
1365
     * @return string
1366
     */
1367 20
    public static function DECTOOCT($x, $places = null)
1368
    {
1369 20
        $xorig = $x;
0 ignored issues
show
Unused Code introduced by
The assignment to $xorig is dead and can be removed.
Loading history...
1370 20
        $x = Functions::flattenSingleValue($x);
1371 20
        $places = Functions::flattenSingleValue($places);
1372
1373 20
        if (is_bool($x)) {
1374 1
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
1375
                $x = (int) $x;
1376
            } else {
1377 1
                return Functions::VALUE();
1378
            }
1379
        }
1380 19
        $x = (string) $x;
1381 19
        if (strlen($x) > preg_match_all('/[-0123456789.]/', $x, $out)) {
1382 1
            return Functions::VALUE();
1383
        }
1384 18
        $x = (string) floor($x);
0 ignored issues
show
Bug introduced by
$x of type string is incompatible with the type double expected by parameter $value of floor(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1384
        $x = (string) floor(/** @scrutinizer ignore-type */ $x);
Loading history...
1385 18
        $r = decoct($x);
0 ignored issues
show
Bug introduced by
$x of type string is incompatible with the type integer expected by parameter $number of decoct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1385
        $r = decoct(/** @scrutinizer ignore-type */ $x);
Loading history...
1386 18
        if (strlen($r) == 11) {
1387
            //    Two's Complement
1388
            $r = substr($r, -10);
1389
        }
1390
1391 18
        return self::nbrConversionFormat($r, $places);
1392
    }
1393
1394
    /**
1395
     * HEXTOBIN.
1396
     *
1397
     * Return a hex value as binary.
1398
     *
1399
     * Excel Function:
1400
     *        HEX2BIN(x[,places])
1401
     *
1402
     * @category Engineering Functions
1403
     *
1404
     * @param string $x the hexadecimal number you want to convert.
1405
     *                  Number cannot contain more than 10 characters.
1406
     *                  The most significant bit of number is the sign bit (40th bit from the right).
1407
     *                  The remaining 9 bits are magnitude bits.
1408
     *                  Negative numbers are represented using two's-complement notation.
1409
     *                  If number is negative, HEX2BIN ignores places and returns a 10-character binary number.
1410
     *                  If number is negative, it cannot be less than FFFFFFFE00,
1411
     *                      and if number is positive, it cannot be greater than 1FF.
1412
     *                  If number is not a valid hexadecimal number, HEX2BIN returns the #NUM! error value.
1413
     *                  If HEX2BIN requires more than places characters, it returns the #NUM! error value.
1414
     * @param int $places The number of characters to use. If places is omitted,
1415
     *                                    HEX2BIN uses the minimum number of characters necessary. Places
1416
     *                                    is useful for padding the return value with leading 0s (zeros).
1417
     *                                    If places is not an integer, it is truncated.
1418
     *                                    If places is nonnumeric, HEX2BIN returns the #VALUE! error value.
1419
     *                                    If places is negative, HEX2BIN returns the #NUM! error value.
1420
     *
1421
     * @return string
1422
     */
1423 16
    public static function HEXTOBIN($x, $places = null)
1424
    {
1425 16
        $x = Functions::flattenSingleValue($x);
1426 16
        $places = Functions::flattenSingleValue($places);
1427
1428 16
        if (is_bool($x)) {
1429 1
            return Functions::VALUE();
1430
        }
1431 15
        $x = (string) $x;
1432 15
        if (strlen($x) > preg_match_all('/[0123456789ABCDEF]/', strtoupper($x), $out)) {
1433 2
            return Functions::NAN();
1434
        }
1435
1436 13
        return self::DECTOBIN(self::HEXTODEC($x), $places);
1437
    }
1438
1439
    /**
1440
     * HEXTODEC.
1441
     *
1442
     * Return a hex value as decimal.
1443
     *
1444
     * Excel Function:
1445
     *        HEX2DEC(x)
1446
     *
1447
     * @category Engineering Functions
1448
     *
1449
     * @param string $x The hexadecimal number you want to convert. This number cannot
1450
     *                                contain more than 10 characters (40 bits). The most significant
1451
     *                                bit of number is the sign bit. The remaining 39 bits are magnitude
1452
     *                                bits. Negative numbers are represented using two's-complement
1453
     *                                notation.
1454
     *                                If number is not a valid hexadecimal number, HEX2DEC returns the
1455
     *                                #NUM! error value.
1456
     *
1457
     * @return string
1458
     */
1459 37
    public static function HEXTODEC($x)
1460
    {
1461 37
        $x = Functions::flattenSingleValue($x);
1462
1463 37
        if (is_bool($x)) {
1464 1
            return Functions::VALUE();
1465
        }
1466 36
        $x = (string) $x;
1467 36
        if (strlen($x) > preg_match_all('/[0123456789ABCDEF]/', strtoupper($x), $out)) {
1468 3
            return Functions::NAN();
1469
        }
1470
1471 33
        if (strlen($x) > 10) {
1472 1
            return Functions::NAN();
1473
        }
1474
1475 32
        $binX = '';
1476 32
        foreach (str_split($x) as $char) {
1477 32
            $binX .= str_pad(base_convert($char, 16, 2), 4, '0', STR_PAD_LEFT);
1478
        }
1479 32
        if (strlen($binX) == 40 && $binX[0] == '1') {
1480 5
            for ($i = 0; $i < 40; ++$i) {
1481 5
                $binX[$i] = ($binX[$i] == '1' ? '0' : '1');
1482
            }
1483
1484 5
            return (bindec($binX) + 1) * -1;
1485
        }
1486
1487 27
        return bindec($binX);
1488
    }
1489
1490
    /**
1491
     * HEXTOOCT.
1492
     *
1493
     * Return a hex value as octal.
1494
     *
1495
     * Excel Function:
1496
     *        HEX2OCT(x[,places])
1497
     *
1498
     * @category Engineering Functions
1499
     *
1500
     * @param string $x The hexadecimal number you want to convert. Number cannot
1501
     *                                    contain more than 10 characters. The most significant bit of
1502
     *                                    number is the sign bit. The remaining 39 bits are magnitude
1503
     *                                    bits. Negative numbers are represented using two's-complement
1504
     *                                    notation.
1505
     *                                    If number is negative, HEX2OCT ignores places and returns a
1506
     *                                    10-character octal number.
1507
     *                                    If number is negative, it cannot be less than FFE0000000, and
1508
     *                                    if number is positive, it cannot be greater than 1FFFFFFF.
1509
     *                                    If number is not a valid hexadecimal number, HEX2OCT returns
1510
     *                                    the #NUM! error value.
1511
     *                                    If HEX2OCT requires more than places characters, it returns
1512
     *                                    the #NUM! error value.
1513
     * @param int $places The number of characters to use. If places is omitted, HEX2OCT
1514
     *                                    uses the minimum number of characters necessary. Places is
1515
     *                                    useful for padding the return value with leading 0s (zeros).
1516
     *                                    If places is not an integer, it is truncated.
1517
     *                                    If places is nonnumeric, HEX2OCT returns the #VALUE! error
1518
     *                                    value.
1519
     *                                    If places is negative, HEX2OCT returns the #NUM! error value.
1520
     *
1521
     * @return string
1522
     */
1523 13
    public static function HEXTOOCT($x, $places = null)
1524
    {
1525 13
        $x = Functions::flattenSingleValue($x);
1526 13
        $places = Functions::flattenSingleValue($places);
1527
1528 13
        if (is_bool($x)) {
1529 1
            return Functions::VALUE();
1530
        }
1531 12
        $x = (string) $x;
1532 12
        if (strlen($x) > preg_match_all('/[0123456789ABCDEF]/', strtoupper($x), $out)) {
1533 3
            return Functions::NAN();
1534
        }
1535
1536 9
        $decimal = self::HEXTODEC($x);
1537 9
        if ($decimal < -536870912 || $decimal > 536870911) {
1538 1
            return Functions::NAN();
1539
        }
1540
1541 8
        return self::DECTOOCT($decimal, $places);
1542
    }
1543
1544
    /**
1545
     * OCTTOBIN.
1546
     *
1547
     * Return an octal value as binary.
1548
     *
1549
     * Excel Function:
1550
     *        OCT2BIN(x[,places])
1551
     *
1552
     * @category Engineering Functions
1553
     *
1554
     * @param string $x The octal number you want to convert. Number may not
1555
     *                                    contain more than 10 characters. The most significant
1556
     *                                    bit of number is the sign bit. The remaining 29 bits
1557
     *                                    are magnitude bits. Negative numbers are represented
1558
     *                                    using two's-complement notation.
1559
     *                                    If number is negative, OCT2BIN ignores places and returns
1560
     *                                    a 10-character binary number.
1561
     *                                    If number is negative, it cannot be less than 7777777000,
1562
     *                                    and if number is positive, it cannot be greater than 777.
1563
     *                                    If number is not a valid octal number, OCT2BIN returns
1564
     *                                    the #NUM! error value.
1565
     *                                    If OCT2BIN requires more than places characters, it
1566
     *                                    returns the #NUM! error value.
1567
     * @param int $places The number of characters to use. If places is omitted,
1568
     *                                    OCT2BIN uses the minimum number of characters necessary.
1569
     *                                    Places is useful for padding the return value with
1570
     *                                    leading 0s (zeros).
1571
     *                                    If places is not an integer, it is truncated.
1572
     *                                    If places is nonnumeric, OCT2BIN returns the #VALUE!
1573
     *                                    error value.
1574
     *                                    If places is negative, OCT2BIN returns the #NUM! error
1575
     *                                    value.
1576
     *
1577
     * @return string
1578
     */
1579 13
    public static function OCTTOBIN($x, $places = null)
1580
    {
1581 13
        $x = Functions::flattenSingleValue($x);
1582 13
        $places = Functions::flattenSingleValue($places);
1583
1584 13
        if (is_bool($x)) {
1585 1
            return Functions::VALUE();
1586
        }
1587 12
        $x = (string) $x;
1588 12
        if (preg_match_all('/[01234567]/', $x, $out) != strlen($x)) {
1589 2
            return Functions::NAN();
1590
        }
1591
1592 10
        return self::DECTOBIN(self::OCTTODEC($x), $places);
1593
    }
1594
1595
    /**
1596
     * OCTTODEC.
1597
     *
1598
     * Return an octal value as decimal.
1599
     *
1600
     * Excel Function:
1601
     *        OCT2DEC(x)
1602
     *
1603
     * @category Engineering Functions
1604
     *
1605
     * @param string $x The octal number you want to convert. Number may not contain
1606
     *                                more than 10 octal characters (30 bits). The most significant
1607
     *                                bit of number is the sign bit. The remaining 29 bits are
1608
     *                                magnitude bits. Negative numbers are represented using
1609
     *                                two's-complement notation.
1610
     *                                If number is not a valid octal number, OCT2DEC returns the
1611
     *                                #NUM! error value.
1612
     *
1613
     * @return string
1614
     */
1615 25
    public static function OCTTODEC($x)
1616
    {
1617 25
        $x = Functions::flattenSingleValue($x);
1618
1619 25
        if (is_bool($x)) {
1620 1
            return Functions::VALUE();
1621
        }
1622 24
        $x = (string) $x;
1623 24
        if (preg_match_all('/[01234567]/', $x, $out) != strlen($x)) {
1624 2
            return Functions::NAN();
1625
        }
1626 22
        $binX = '';
1627 22
        foreach (str_split($x) as $char) {
1628 22
            $binX .= str_pad(decbin((int) $char), 3, '0', STR_PAD_LEFT);
1629
        }
1630 22
        if (strlen($binX) == 30 && $binX[0] == '1') {
1631 4
            for ($i = 0; $i < 30; ++$i) {
1632 4
                $binX[$i] = ($binX[$i] == '1' ? '0' : '1');
1633
            }
1634
1635 4
            return (bindec($binX) + 1) * -1;
1636
        }
1637
1638 18
        return bindec($binX);
1639
    }
1640
1641
    /**
1642
     * OCTTOHEX.
1643
     *
1644
     * Return an octal value as hex.
1645
     *
1646
     * Excel Function:
1647
     *        OCT2HEX(x[,places])
1648
     *
1649
     * @category Engineering Functions
1650
     *
1651
     * @param string $x The octal number you want to convert. Number may not contain
1652
     *                                    more than 10 octal characters (30 bits). The most significant
1653
     *                                    bit of number is the sign bit. The remaining 29 bits are
1654
     *                                    magnitude bits. Negative numbers are represented using
1655
     *                                    two's-complement notation.
1656
     *                                    If number is negative, OCT2HEX ignores places and returns a
1657
     *                                    10-character hexadecimal number.
1658
     *                                    If number is not a valid octal number, OCT2HEX returns the
1659
     *                                    #NUM! error value.
1660
     *                                    If OCT2HEX requires more than places characters, it returns
1661
     *                                    the #NUM! error value.
1662
     * @param int $places The number of characters to use. If places is omitted, OCT2HEX
1663
     *                                    uses the minimum number of characters necessary. Places is useful
1664
     *                                    for padding the return value with leading 0s (zeros).
1665
     *                                    If places is not an integer, it is truncated.
1666
     *                                    If places is nonnumeric, OCT2HEX returns the #VALUE! error value.
1667
     *                                    If places is negative, OCT2HEX returns the #NUM! error value.
1668
     *
1669
     * @return string
1670
     */
1671 9
    public static function OCTTOHEX($x, $places = null)
1672
    {
1673 9
        $x = Functions::flattenSingleValue($x);
1674 9
        $places = Functions::flattenSingleValue($places);
1675
1676 9
        if (is_bool($x)) {
1677 1
            return Functions::VALUE();
1678
        }
1679 8
        $x = (string) $x;
1680 8
        if (preg_match_all('/[01234567]/', $x, $out) != strlen($x)) {
1681 2
            return Functions::NAN();
1682
        }
1683 6
        $hexVal = strtoupper(dechex(self::OCTTODEC($x)));
0 ignored issues
show
Bug introduced by
self::OCTTODEC($x) of type string is incompatible with the type integer expected by parameter $number of dechex(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1683
        $hexVal = strtoupper(dechex(/** @scrutinizer ignore-type */ self::OCTTODEC($x)));
Loading history...
1684
1685 6
        return self::nbrConversionFormat($hexVal, $places);
1686
    }
1687
1688
    /**
1689
     * COMPLEX.
1690
     *
1691
     * Converts real and imaginary coefficients into a complex number of the form x +/- yi or x +/- yj.
1692
     *
1693
     * Excel Function:
1694
     *        COMPLEX(realNumber,imaginary[,suffix])
1695
     *
1696
     * @category Engineering Functions
1697
     *
1698
     * @param float $realNumber the real coefficient of the complex number
1699
     * @param float $imaginary the imaginary coefficient of the complex number
1700
     * @param string $suffix The suffix for the imaginary component of the complex number.
1701
     *                                        If omitted, the suffix is assumed to be "i".
1702
     *
1703
     * @return string
1704
     */
1705 547
    public static function COMPLEX($realNumber = 0.0, $imaginary = 0.0, $suffix = 'i')
1706
    {
1707 547
        $realNumber = ($realNumber === null) ? 0.0 : Functions::flattenSingleValue($realNumber);
0 ignored issues
show
introduced by
The condition $realNumber === null is always false.
Loading history...
1708 547
        $imaginary = ($imaginary === null) ? 0.0 : Functions::flattenSingleValue($imaginary);
0 ignored issues
show
introduced by
The condition $imaginary === null is always false.
Loading history...
1709 547
        $suffix = ($suffix === null) ? 'i' : Functions::flattenSingleValue($suffix);
0 ignored issues
show
introduced by
The condition $suffix === null is always false.
Loading history...
1710
1711 547
        if (((is_numeric($realNumber)) && (is_numeric($imaginary))) &&
1712 547
            (($suffix == 'i') || ($suffix == 'j') || ($suffix == ''))
1713
        ) {
1714 546
            $complex = new Complex($realNumber, $imaginary, $suffix);
1715
1716 546
            return (string) $complex;
1717
        }
1718
1719 1
        return Functions::VALUE();
1720
    }
1721
1722
    /**
1723
     * IMAGINARY.
1724
     *
1725
     * Returns the imaginary coefficient of a complex number in x + yi or x + yj text format.
1726
     *
1727
     * Excel Function:
1728
     *        IMAGINARY(complexNumber)
1729
     *
1730
     * @category Engineering Functions
1731
     *
1732
     * @param string $complexNumber the complex number for which you want the imaginary
1733
     *                                         coefficient
1734
     *
1735
     * @return float
1736
     */
1737 30
    public static function IMAGINARY($complexNumber)
1738
    {
1739 30
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1740
1741 30
        return (new Complex($complexNumber))->getImaginary();
1742
    }
1743
1744
    /**
1745
     * IMREAL.
1746
     *
1747
     * Returns the real coefficient of a complex number in x + yi or x + yj text format.
1748
     *
1749
     * Excel Function:
1750
     *        IMREAL(complexNumber)
1751
     *
1752
     * @category Engineering Functions
1753
     *
1754
     * @param string $complexNumber the complex number for which you want the real coefficient
1755
     *
1756
     * @return float
1757
     */
1758 30
    public static function IMREAL($complexNumber)
1759
    {
1760 30
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1761
1762 30
        return (new Complex($complexNumber))->getReal();
1763
    }
1764
1765
    /**
1766
     * IMABS.
1767
     *
1768
     * Returns the absolute value (modulus) of a complex number in x + yi or x + yj text format.
1769
     *
1770
     * Excel Function:
1771
     *        IMABS(complexNumber)
1772
     *
1773
     * @param string $complexNumber the complex number for which you want the absolute value
1774
     *
1775
     * @return float
1776
     */
1777 27
    public static function IMABS($complexNumber)
1778
    {
1779 27
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1780
1781 27
        return (new Complex($complexNumber))->abs();
1782
    }
1783
1784
    /**
1785
     * IMARGUMENT.
1786
     *
1787
     * Returns the argument theta of a complex number, i.e. the angle in radians from the real
1788
     * axis to the representation of the number in polar coordinates.
1789
     *
1790
     * Excel Function:
1791
     *        IMARGUMENT(complexNumber)
1792
     *
1793
     * @param string $complexNumber the complex number for which you want the argument theta
1794
     *
1795
     * @return float|string
1796
     */
1797 54
    public static function IMARGUMENT($complexNumber)
1798
    {
1799 54
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1800
1801 54
        $complex = new Complex($complexNumber);
1802 54
        if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
1803 2
            return Functions::DIV0();
1804
        }
1805
1806 52
        return $complex->argument();
1807
    }
1808
1809
    /**
1810
     * IMCONJUGATE.
1811
     *
1812
     * Returns the complex conjugate of a complex number in x + yi or x + yj text format.
1813
     *
1814
     * Excel Function:
1815
     *        IMCONJUGATE(complexNumber)
1816
     *
1817
     * @param string $complexNumber the complex number for which you want the conjugate
1818
     *
1819
     * @return string
1820
     */
1821 26
    public static function IMCONJUGATE($complexNumber)
1822
    {
1823 26
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1824
1825 26
        return (string) (new Complex($complexNumber))->conjugate();
1826
    }
1827
1828
    /**
1829
     * IMCOS.
1830
     *
1831
     * Returns the cosine of a complex number in x + yi or x + yj text format.
1832
     *
1833
     * Excel Function:
1834
     *        IMCOS(complexNumber)
1835
     *
1836
     * @param string $complexNumber the complex number for which you want the cosine
1837
     *
1838
     * @return float|string
1839
     */
1840 27
    public static function IMCOS($complexNumber)
1841
    {
1842 27
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1843
1844 27
        return (string) (new Complex($complexNumber))->cos();
1845
    }
1846
1847
    /**
1848
     * IMCOSH.
1849
     *
1850
     * Returns the hyperbolic cosine of a complex number in x + yi or x + yj text format.
1851
     *
1852
     * Excel Function:
1853
     *        IMCOSH(complexNumber)
1854
     *
1855
     * @param string $complexNumber the complex number for which you want the hyperbolic cosine
1856
     *
1857
     * @return float|string
1858
     */
1859 27
    public static function IMCOSH($complexNumber)
1860
    {
1861 27
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1862
1863 27
        return (string) (new Complex($complexNumber))->cosh();
1864
    }
1865
1866
    /**
1867
     * IMCOT.
1868
     *
1869
     * Returns the cotangent of a complex number in x + yi or x + yj text format.
1870
     *
1871
     * Excel Function:
1872
     *        IMCOT(complexNumber)
1873
     *
1874
     * @param string $complexNumber the complex number for which you want the cotangent
1875
     *
1876
     * @return float|string
1877
     */
1878 27
    public static function IMCOT($complexNumber)
1879
    {
1880 27
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1881
1882 27
        return (string) (new Complex($complexNumber))->cot();
1883
    }
1884
1885
    /**
1886
     * IMCSC.
1887
     *
1888
     * Returns the cosecant of a complex number in x + yi or x + yj text format.
1889
     *
1890
     * Excel Function:
1891
     *        IMCSC(complexNumber)
1892
     *
1893
     * @param string $complexNumber the complex number for which you want the cosecant
1894
     *
1895
     * @return float|string
1896
     */
1897 27
    public static function IMCSC($complexNumber)
1898
    {
1899 27
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1900
1901 27
        return (string) (new Complex($complexNumber))->csc();
1902
    }
1903
1904
    /**
1905
     * IMCSCH.
1906
     *
1907
     * Returns the hyperbolic cosecant of a complex number in x + yi or x + yj text format.
1908
     *
1909
     * Excel Function:
1910
     *        IMCSCH(complexNumber)
1911
     *
1912
     * @param string $complexNumber the complex number for which you want the hyperbolic cosecant
1913
     *
1914
     * @return float|string
1915
     */
1916 27
    public static function IMCSCH($complexNumber)
1917
    {
1918 27
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1919
1920 27
        return (string) (new Complex($complexNumber))->csch();
1921
    }
1922
1923
    /**
1924
     * IMSIN.
1925
     *
1926
     * Returns the sine of a complex number in x + yi or x + yj text format.
1927
     *
1928
     * Excel Function:
1929
     *        IMSIN(complexNumber)
1930
     *
1931
     * @param string $complexNumber the complex number for which you want the sine
1932
     *
1933
     * @return float|string
1934
     */
1935 27
    public static function IMSIN($complexNumber)
1936
    {
1937 27
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1938
1939 27
        return (string) (new Complex($complexNumber))->sin();
1940
    }
1941
1942
    /**
1943
     * IMSINH.
1944
     *
1945
     * Returns the hyperbolic sine of a complex number in x + yi or x + yj text format.
1946
     *
1947
     * Excel Function:
1948
     *        IMSINH(complexNumber)
1949
     *
1950
     * @param string $complexNumber the complex number for which you want the hyperbolic sine
1951
     *
1952
     * @return float|string
1953
     */
1954 27
    public static function IMSINH($complexNumber)
1955
    {
1956 27
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1957
1958 27
        return (string) (new Complex($complexNumber))->sinh();
1959
    }
1960
1961
    /**
1962
     * IMSEC.
1963
     *
1964
     * Returns the secant of a complex number in x + yi or x + yj text format.
1965
     *
1966
     * Excel Function:
1967
     *        IMSEC(complexNumber)
1968
     *
1969
     * @param string $complexNumber the complex number for which you want the secant
1970
     *
1971
     * @return float|string
1972
     */
1973 27
    public static function IMSEC($complexNumber)
1974
    {
1975 27
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1976
1977 27
        return (string) (new Complex($complexNumber))->sec();
1978
    }
1979
1980
    /**
1981
     * IMSECH.
1982
     *
1983
     * Returns the hyperbolic secant of a complex number in x + yi or x + yj text format.
1984
     *
1985
     * Excel Function:
1986
     *        IMSECH(complexNumber)
1987
     *
1988
     * @param string $complexNumber the complex number for which you want the hyperbolic secant
1989
     *
1990
     * @return float|string
1991
     */
1992 27
    public static function IMSECH($complexNumber)
1993
    {
1994 27
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1995
1996 27
        return (string) (new Complex($complexNumber))->sech();
1997
    }
1998
1999
    /**
2000
     * IMTAN.
2001
     *
2002
     * Returns the tangent of a complex number in x + yi or x + yj text format.
2003
     *
2004
     * Excel Function:
2005
     *        IMTAN(complexNumber)
2006
     *
2007
     * @param string $complexNumber the complex number for which you want the tangent
2008
     *
2009
     * @return float|string
2010
     */
2011 27
    public static function IMTAN($complexNumber)
2012
    {
2013 27
        $complexNumber = Functions::flattenSingleValue($complexNumber);
2014
2015 27
        return (string) (new Complex($complexNumber))->tan();
2016
    }
2017
2018
    /**
2019
     * IMSQRT.
2020
     *
2021
     * Returns the square root of a complex number in x + yi or x + yj text format.
2022
     *
2023
     * Excel Function:
2024
     *        IMSQRT(complexNumber)
2025
     *
2026
     * @param string $complexNumber the complex number for which you want the square root
2027
     *
2028
     * @return string
2029
     */
2030 28
    public static function IMSQRT($complexNumber)
2031
    {
2032 28
        $complexNumber = Functions::flattenSingleValue($complexNumber);
2033
2034 28
        $theta = self::IMARGUMENT($complexNumber);
2035 28
        if ($theta === Functions::DIV0()) {
2036 1
            return '0';
2037
        }
2038
2039 27
        return (string) (new Complex($complexNumber))->sqrt();
2040
    }
2041
2042
    /**
2043
     * IMLN.
2044
     *
2045
     * Returns the natural logarithm of a complex number in x + yi or x + yj text format.
2046
     *
2047
     * Excel Function:
2048
     *        IMLN(complexNumber)
2049
     *
2050
     * @param string $complexNumber the complex number for which you want the natural logarithm
2051
     *
2052
     * @return string
2053
     */
2054 27
    public static function IMLN($complexNumber)
2055
    {
2056 27
        $complexNumber = Functions::flattenSingleValue($complexNumber);
2057
2058 27
        $complex = new Complex($complexNumber);
2059 27
        if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
2060 1
            return Functions::NAN();
2061
        }
2062
2063 26
        return (string) (new Complex($complexNumber))->ln();
2064
    }
2065
2066
    /**
2067
     * IMLOG10.
2068
     *
2069
     * Returns the common logarithm (base 10) of a complex number in x + yi or x + yj text format.
2070
     *
2071
     * Excel Function:
2072
     *        IMLOG10(complexNumber)
2073
     *
2074
     * @param string $complexNumber the complex number for which you want the common logarithm
2075
     *
2076
     * @return string
2077
     */
2078 27
    public static function IMLOG10($complexNumber)
2079
    {
2080 27
        $complexNumber = Functions::flattenSingleValue($complexNumber);
2081
2082 27
        $complex = new Complex($complexNumber);
2083 27
        if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
2084 1
            return Functions::NAN();
2085
        }
2086
2087 26
        return (string) (new Complex($complexNumber))->log10();
2088
    }
2089
2090
    /**
2091
     * IMLOG2.
2092
     *
2093
     * Returns the base-2 logarithm of a complex number in x + yi or x + yj text format.
2094
     *
2095
     * Excel Function:
2096
     *        IMLOG2(complexNumber)
2097
     *
2098
     * @param string $complexNumber the complex number for which you want the base-2 logarithm
2099
     *
2100
     * @return string
2101
     */
2102 27
    public static function IMLOG2($complexNumber)
2103
    {
2104 27
        $complexNumber = Functions::flattenSingleValue($complexNumber);
2105
2106 27
        $complex = new Complex($complexNumber);
2107 27
        if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) {
2108 1
            return Functions::NAN();
2109
        }
2110
2111 26
        return (string) (new Complex($complexNumber))->log2();
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
     *
2124
     * @return string
2125
     */
2126 27
    public static function IMEXP($complexNumber)
2127
    {
2128 27
        $complexNumber = Functions::flattenSingleValue($complexNumber);
2129
2130 27
        return (string) (new Complex($complexNumber))->exp();
2131
    }
2132
2133
    /**
2134
     * IMPOWER.
2135
     *
2136
     * Returns a complex number in x + yi or x + yj text format raised to a power.
2137
     *
2138
     * Excel Function:
2139
     *        IMPOWER(complexNumber,realNumber)
2140
     *
2141
     * @param string $complexNumber the complex number you want to raise to a power
2142
     * @param float $realNumber the power to which you want to raise the complex number
2143
     *
2144
     * @return string
2145
     */
2146 18
    public static function IMPOWER($complexNumber, $realNumber)
2147
    {
2148 18
        $complexNumber = Functions::flattenSingleValue($complexNumber);
2149 18
        $realNumber = Functions::flattenSingleValue($realNumber);
2150
2151 18
        if (!is_numeric($realNumber)) {
2152 1
            return Functions::VALUE();
2153
        }
2154
2155 17
        return (string) (new Complex($complexNumber))->pow($realNumber);
2156
    }
2157
2158
    /**
2159
     * IMDIV.
2160
     *
2161
     * Returns the quotient of two complex numbers in x + yi or x + yj text format.
2162
     *
2163
     * Excel Function:
2164
     *        IMDIV(complexDividend,complexDivisor)
2165
     *
2166
     * @param string $complexDividend the complex numerator or dividend
2167
     * @param string $complexDivisor the complex denominator or divisor
2168
     *
2169
     * @return string
2170
     */
2171 17
    public static function IMDIV($complexDividend, $complexDivisor)
2172
    {
2173 17
        $complexDividend = Functions::flattenSingleValue($complexDividend);
2174 17
        $complexDivisor = Functions::flattenSingleValue($complexDivisor);
2175
2176
        try {
2177 17
            return (string) (new Complex($complexDividend))->divideby(new Complex($complexDivisor));
2178 1
        } catch (ComplexException $e) {
2179 1
            return Functions::NAN();
2180
        }
2181
    }
2182
2183
    /**
2184
     * IMSUB.
2185
     *
2186
     * Returns the difference of two complex numbers in x + yi or x + yj text format.
2187
     *
2188
     * Excel Function:
2189
     *        IMSUB(complexNumber1,complexNumber2)
2190
     *
2191
     * @param string $complexNumber1 the complex number from which to subtract complexNumber2
2192
     * @param string $complexNumber2 the complex number to subtract from complexNumber1
2193
     *
2194
     * @return string
2195
     */
2196 7
    public static function IMSUB($complexNumber1, $complexNumber2)
2197
    {
2198 7
        $complexNumber1 = Functions::flattenSingleValue($complexNumber1);
2199 7
        $complexNumber2 = Functions::flattenSingleValue($complexNumber2);
2200
2201
        try {
2202 7
            return (string) (new Complex($complexNumber1))->subtract(new Complex($complexNumber2));
2203 1
        } catch (ComplexException $e) {
2204 1
            return Functions::NAN();
2205
        }
2206
    }
2207
2208
    /**
2209
     * IMSUM.
2210
     *
2211
     * Returns the sum of two or more complex numbers in x + yi or x + yj text format.
2212
     *
2213
     * Excel Function:
2214
     *        IMSUM(complexNumber[,complexNumber[,...]])
2215
     *
2216
     * @param string ...$complexNumbers Series of complex numbers to add
2217
     *
2218
     * @return string
2219
     */
2220 10
    public static function IMSUM(...$complexNumbers)
2221
    {
2222
        // Return value
2223 10
        $returnValue = new Complex(0.0);
2224 10
        $aArgs = Functions::flattenArray($complexNumbers);
2225
2226
        try {
2227
            // Loop through the arguments
2228 10
            foreach ($aArgs as $complex) {
2229 10
                $returnValue = $returnValue->add(new Complex($complex));
2230
            }
2231 2
        } catch (ComplexException $e) {
2232 2
            return Functions::NAN();
2233
        }
2234
2235 8
        return (string) $returnValue;
2236
    }
2237
2238
    /**
2239
     * IMPRODUCT.
2240
     *
2241
     * Returns the product of two or more complex numbers in x + yi or x + yj text format.
2242
     *
2243
     * Excel Function:
2244
     *        IMPRODUCT(complexNumber[,complexNumber[,...]])
2245
     *
2246
     * @param string ...$complexNumbers Series of complex numbers to multiply
2247
     *
2248
     * @return string
2249
     */
2250 15
    public static function IMPRODUCT(...$complexNumbers)
2251
    {
2252
        // Return value
2253 15
        $returnValue = new Complex(1.0);
2254 15
        $aArgs = Functions::flattenArray($complexNumbers);
2255
2256
        try {
2257
            // Loop through the arguments
2258 15
            foreach ($aArgs as $complex) {
2259 15
                $returnValue = $returnValue->multiply(new Complex($complex));
2260
            }
2261 1
        } catch (ComplexException $e) {
2262 1
            return Functions::NAN();
2263
        }
2264
2265 14
        return (string) $returnValue;
2266
    }
2267
2268
    /**
2269
     * DELTA.
2270
     *
2271
     * Tests whether two values are equal. Returns 1 if number1 = number2; returns 0 otherwise.
2272
     *    Use this function to filter a set of values. For example, by summing several DELTA
2273
     *    functions you calculate the count of equal pairs. This function is also known as the
2274
     * Kronecker Delta function.
2275
     *
2276
     *    Excel Function:
2277
     *        DELTA(a[,b])
2278
     *
2279
     * @param float $a the first number
2280
     * @param float $b The second number. If omitted, b is assumed to be zero.
2281
     *
2282
     * @return int
2283
     */
2284 25
    public static function DELTA($a, $b = 0)
2285
    {
2286 25
        $a = Functions::flattenSingleValue($a);
2287 25
        $b = Functions::flattenSingleValue($b);
2288
2289 25
        return (int) ($a == $b);
2290
    }
2291
2292
    /**
2293
     * GESTEP.
2294
     *
2295
     *    Excel Function:
2296
     *        GESTEP(number[,step])
2297
     *
2298
     *    Returns 1 if number >= step; returns 0 (zero) otherwise
2299
     *    Use this function to filter a set of values. For example, by summing several GESTEP
2300
     * functions you calculate the count of values that exceed a threshold.
2301
     *
2302
     * @param float $number the value to test against step
2303
     * @param float $step The threshold value.
2304
     *                                    If you omit a value for step, GESTEP uses zero.
2305
     *
2306
     * @return int
2307
     */
2308 81
    public static function GESTEP($number, $step = 0)
2309
    {
2310 81
        $number = Functions::flattenSingleValue($number);
2311 81
        $step = Functions::flattenSingleValue($step);
2312
2313 81
        return (int) ($number >= $step);
2314
    }
2315
2316
    //
2317
    //    Private method to calculate the erf value
2318
    //
2319
    private static $twoSqrtPi = 1.128379167095512574;
2320
2321 152
    public static function erfVal($x)
2322
    {
2323 152
        if (abs($x) > 2.2) {
2324 67
            return 1 - self::erfcVal($x);
2325
        }
2326 127
        $sum = $term = $x;
2327 127
        $xsqr = ($x * $x);
2328 127
        $j = 1;
2329
        do {
2330 127
            $term *= $xsqr / $j;
2331 127
            $sum -= $term / (2 * $j + 1);
2332 127
            ++$j;
2333 127
            $term *= $xsqr / $j;
2334 127
            $sum += $term / (2 * $j + 1);
2335 127
            ++$j;
2336 127
            if ($sum == 0.0) {
2337 20
                break;
2338
            }
2339 115
        } while (abs($term / $sum) > Functions::PRECISION);
2340
2341 127
        return self::$twoSqrtPi * $sum;
2342
    }
2343
2344
    /**
2345
     * Validate arguments passed to the bitwise functions.
2346
     *
2347
     * @param mixed $value
2348
     *
2349
     * @throws Exception
2350
     *
2351
     * @return int
2352
     */
2353 21
    private static function validateBitwiseArgument($value)
2354
    {
2355 21
        $value = Functions::flattenSingleValue($value);
2356
2357 21
        if (is_int($value)) {
2358 14
            return $value;
2359 7
        } elseif (is_numeric($value)) {
2360 3
            if ($value == (int) ($value)) {
2361 2
                $value = (int) ($value);
2362 2
                if (($value > pow(2, 48) - 1) || ($value < 0)) {
2363 1
                    throw new Exception(Functions::NAN());
2364
                }
2365
2366 2
                return $value;
2367
            }
2368
2369 1
            throw new Exception(Functions::NAN());
2370
        }
2371
2372 4
        throw new Exception(Functions::VALUE());
2373
    }
2374
2375
    /**
2376
     * BITAND.
2377
     *
2378
     * Returns the bitwise AND of two integer values.
2379
     *
2380
     * Excel Function:
2381
     *        BITAND(number1, number2)
2382
     *
2383
     * @category Engineering Functions
2384
     *
2385
     * @param int $number1
2386
     * @param int $number2
2387
     *
2388
     * @return int|string
2389
     */
2390 4
    public static function BITAND($number1, $number2)
2391
    {
2392
        try {
2393 4
            $number1 = self::validateBitwiseArgument($number1);
2394 3
            $number2 = self::validateBitwiseArgument($number2);
2395 1
        } catch (Exception $e) {
2396 1
            return $e->getMessage();
2397
        }
2398
2399 3
        return $number1 & $number2;
2400
    }
2401
2402
    /**
2403
     * BITOR.
2404
     *
2405
     * Returns the bitwise OR of two integer values.
2406
     *
2407
     * Excel Function:
2408
     *        BITOR(number1, number2)
2409
     *
2410
     * @category Engineering Functions
2411
     *
2412
     * @param int $number1
2413
     * @param int $number2
2414
     *
2415
     * @return int|string
2416
     */
2417 5
    public static function BITOR($number1, $number2)
2418
    {
2419
        try {
2420 5
            $number1 = self::validateBitwiseArgument($number1);
2421 4
            $number2 = self::validateBitwiseArgument($number2);
2422 1
        } catch (Exception $e) {
2423 1
            return $e->getMessage();
2424
        }
2425
2426 4
        return $number1 | $number2;
2427
    }
2428
2429
    /**
2430
     * BITXOR.
2431
     *
2432
     * Returns the bitwise XOR of two integer values.
2433
     *
2434
     * Excel Function:
2435
     *        BITXOR(number1, number2)
2436
     *
2437
     * @category Engineering Functions
2438
     *
2439
     * @param int $number1
2440
     * @param int $number2
2441
     *
2442
     * @return int|string
2443
     */
2444 5
    public static function BITXOR($number1, $number2)
2445
    {
2446
        try {
2447 5
            $number1 = self::validateBitwiseArgument($number1);
2448 4
            $number2 = self::validateBitwiseArgument($number2);
2449 2
        } catch (Exception $e) {
2450 2
            return $e->getMessage();
2451
        }
2452
2453 3
        return $number1 ^ $number2;
2454
    }
2455
2456
    /**
2457
     * BITLSHIFT.
2458
     *
2459
     * Returns the number value shifted left by shift_amount bits.
2460
     *
2461
     * Excel Function:
2462
     *        BITLSHIFT(number, shift_amount)
2463
     *
2464
     * @category Engineering Functions
2465
     *
2466
     * @param int $number
2467
     * @param int $shiftAmount
2468
     *
2469
     * @return int|string
2470
     */
2471 4
    public static function BITLSHIFT($number, $shiftAmount)
2472
    {
2473
        try {
2474 4
            $number = self::validateBitwiseArgument($number);
2475 1
        } catch (Exception $e) {
2476 1
            return $e->getMessage();
2477
        }
2478
2479 3
        $shiftAmount = Functions::flattenSingleValue($shiftAmount);
2480
2481 3
        $result = $number << $shiftAmount;
2482 3
        if ($result > pow(2, 48) - 1) {
2483 1
            return Functions::NAN();
2484
        }
2485
2486 2
        return $result;
2487
    }
2488
2489
    /**
2490
     * BITRSHIFT.
2491
     *
2492
     * Returns the number value shifted right by shift_amount bits.
2493
     *
2494
     * Excel Function:
2495
     *        BITRSHIFT(number, shift_amount)
2496
     *
2497
     * @category Engineering Functions
2498
     *
2499
     * @param int $number
2500
     * @param int $shiftAmount
2501
     *
2502
     * @return int|string
2503
     */
2504 3
    public static function BITRSHIFT($number, $shiftAmount)
2505
    {
2506
        try {
2507 3
            $number = self::validateBitwiseArgument($number);
2508 1
        } catch (Exception $e) {
2509 1
            return $e->getMessage();
2510
        }
2511
2512 2
        $shiftAmount = Functions::flattenSingleValue($shiftAmount);
2513
2514 2
        return $number >> $shiftAmount;
2515
    }
2516
2517
    /**
2518
     * ERF.
2519
     *
2520
     * Returns the error function integrated between the lower and upper bound arguments.
2521
     *
2522
     *    Note: In Excel 2007 or earlier, if you input a negative value for the upper or lower bound arguments,
2523
     *            the function would return a #NUM! error. However, in Excel 2010, the function algorithm was
2524
     *            improved, so that it can now calculate the function for both positive and negative ranges.
2525
     *            PhpSpreadsheet follows Excel 2010 behaviour, and accepts negative arguments.
2526
     *
2527
     *    Excel Function:
2528
     *        ERF(lower[,upper])
2529
     *
2530
     * @param float $lower lower bound for integrating ERF
2531
     * @param float $upper upper bound for integrating ERF.
2532
     *                                If omitted, ERF integrates between zero and lower_limit
2533
     *
2534
     * @return float|string
2535
     */
2536 127
    public static function ERF($lower, $upper = null)
2537
    {
2538 127
        $lower = Functions::flattenSingleValue($lower);
2539 127
        $upper = Functions::flattenSingleValue($upper);
2540
2541 127
        if (is_numeric($lower)) {
2542 124
            if ($upper === null) {
2543 41
                return self::erfVal($lower);
2544
            }
2545 83
            if (is_numeric($upper)) {
2546 83
                return self::erfVal($upper) - self::erfVal($lower);
2547
            }
2548
        }
2549
2550 3
        return Functions::VALUE();
2551
    }
2552
2553
    /**
2554
     * ERFPRECISE.
2555
     *
2556
     * Returns the error function integrated between the lower and upper bound arguments.
2557
     *
2558
     *    Excel Function:
2559
     *        ERF.PRECISE(limit)
2560
     *
2561
     * @param float $limit bound for integrating ERF
2562
     *
2563
     * @return float|string
2564
     */
2565 4
    public static function ERFPRECISE($limit)
2566
    {
2567 4
        $limit = Functions::flattenSingleValue($limit);
2568
2569 4
        return self::ERF($limit);
2570
    }
2571
2572
    //
2573
    //    Private method to calculate the erfc value
2574
    //
2575
    private static $oneSqrtPi = 0.564189583547756287;
2576
2577 104
    private static function erfcVal($x)
2578
    {
2579 104
        if (abs($x) < 2.2) {
2580 28
            return 1 - self::erfVal($x);
2581
        }
2582 76
        if ($x < 0) {
2583 1
            return 2 - self::ERFC(-$x);
2584
        }
2585 76
        $a = $n = 1;
2586 76
        $b = $c = $x;
2587 76
        $d = ($x * $x) + 0.5;
2588 76
        $q1 = $q2 = $b / $d;
0 ignored issues
show
Unused Code introduced by
The assignment to $q1 is dead and can be removed.
Loading history...
2589 76
        $t = 0;
0 ignored issues
show
Unused Code introduced by
The assignment to $t is dead and can be removed.
Loading history...
2590
        do {
2591 76
            $t = $a * $n + $b * $x;
2592 76
            $a = $b;
2593 76
            $b = $t;
2594 76
            $t = $c * $n + $d * $x;
2595 76
            $c = $d;
2596 76
            $d = $t;
2597 76
            $n += 0.5;
2598 76
            $q1 = $q2;
2599 76
            $q2 = $b / $d;
2600 76
        } while ((abs($q1 - $q2) / $q2) > Functions::PRECISION);
2601
2602 76
        return self::$oneSqrtPi * exp(-$x * $x) * $q2;
2603
    }
2604
2605
    /**
2606
     * ERFC.
2607
     *
2608
     *    Returns the complementary ERF function integrated between x and infinity
2609
     *
2610
     *    Note: In Excel 2007 or earlier, if you input a negative value for the lower bound argument,
2611
     *        the function would return a #NUM! error. However, in Excel 2010, the function algorithm was
2612
     *        improved, so that it can now calculate the function for both positive and negative x values.
2613
     *            PhpSpreadsheet follows Excel 2010 behaviour, and accepts nagative arguments.
2614
     *
2615
     *    Excel Function:
2616
     *        ERFC(x)
2617
     *
2618
     * @param float $x The lower bound for integrating ERFC
2619
     *
2620
     * @return float|string
2621
     */
2622 41
    public static function ERFC($x)
2623
    {
2624 41
        $x = Functions::flattenSingleValue($x);
2625
2626 41
        if (is_numeric($x)) {
2627 38
            return self::erfcVal($x);
2628
        }
2629
2630 3
        return Functions::VALUE();
2631
    }
2632
2633
    /**
2634
     *    getConversionGroups
2635
     * Returns a list of the different conversion groups for UOM conversions.
2636
     *
2637
     * @return array
2638
     */
2639 1
    public static function getConversionGroups()
2640
    {
2641 1
        $conversionGroups = [];
2642 1
        foreach (self::$conversionUnits as $conversionUnit) {
2643 1
            $conversionGroups[] = $conversionUnit['Group'];
2644
        }
2645
2646 1
        return array_merge(array_unique($conversionGroups));
2647
    }
2648
2649
    /**
2650
     *    getConversionGroupUnits
2651
     * Returns an array of units of measure, for a specified conversion group, or for all groups.
2652
     *
2653
     * @param string $group The group whose units of measure you want to retrieve
2654
     *
2655
     * @return array
2656
     */
2657 1
    public static function getConversionGroupUnits($group = null)
2658
    {
2659 1
        $conversionGroups = [];
2660 1
        foreach (self::$conversionUnits as $conversionUnit => $conversionGroup) {
2661 1
            if (($group === null) || ($conversionGroup['Group'] == $group)) {
2662 1
                $conversionGroups[$conversionGroup['Group']][] = $conversionUnit;
2663
            }
2664
        }
2665
2666 1
        return $conversionGroups;
2667
    }
2668
2669
    /**
2670
     * getConversionGroupUnitDetails.
2671
     *
2672
     * @param string $group The group whose units of measure you want to retrieve
2673
     *
2674
     * @return array
2675
     */
2676 1
    public static function getConversionGroupUnitDetails($group = null)
2677
    {
2678 1
        $conversionGroups = [];
2679 1
        foreach (self::$conversionUnits as $conversionUnit => $conversionGroup) {
2680 1
            if (($group === null) || ($conversionGroup['Group'] == $group)) {
2681 1
                $conversionGroups[$conversionGroup['Group']][] = [
2682 1
                    'unit' => $conversionUnit,
2683 1
                    'description' => $conversionGroup['Unit Name'],
2684
                ];
2685
            }
2686
        }
2687
2688 1
        return $conversionGroups;
2689
    }
2690
2691
    /**
2692
     *    getConversionMultipliers
2693
     * Returns an array of the Multiplier prefixes that can be used with Units of Measure in CONVERTUOM().
2694
     *
2695
     * @return array of mixed
2696
     */
2697 1
    public static function getConversionMultipliers()
2698
    {
2699 1
        return self::$conversionMultipliers;
2700
    }
2701
2702
    /**
2703
     * CONVERTUOM.
2704
     *
2705
     * Converts a number from one measurement system to another.
2706
     *    For example, CONVERT can translate a table of distances in miles to a table of distances
2707
     * in kilometers.
2708
     *
2709
     *    Excel Function:
2710
     *        CONVERT(value,fromUOM,toUOM)
2711
     *
2712
     * @param float $value the value in fromUOM to convert
2713
     * @param string $fromUOM the units for value
2714
     * @param string $toUOM the units for the result
2715
     *
2716
     * @return float
2717
     */
2718 24
    public static function CONVERTUOM($value, $fromUOM, $toUOM)
2719
    {
2720 24
        $value = Functions::flattenSingleValue($value);
2721 24
        $fromUOM = Functions::flattenSingleValue($fromUOM);
2722 24
        $toUOM = Functions::flattenSingleValue($toUOM);
2723
2724 24
        if (!is_numeric($value)) {
2725 1
            return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
2726
        }
2727 23
        $fromMultiplier = 1.0;
2728 23
        if (isset(self::$conversionUnits[$fromUOM])) {
2729 16
            $unitGroup1 = self::$conversionUnits[$fromUOM]['Group'];
2730
        } else {
2731 7
            $fromMultiplier = substr($fromUOM, 0, 1);
2732 7
            $fromUOM = substr($fromUOM, 1);
2733 7
            if (isset(self::$conversionMultipliers[$fromMultiplier])) {
2734 6
                $fromMultiplier = self::$conversionMultipliers[$fromMultiplier]['multiplier'];
2735
            } else {
2736 1
                return Functions::NA();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...ulation\Functions::NA() returns the type string which is incompatible with the documented return type double.
Loading history...
2737
            }
2738 6
            if ((isset(self::$conversionUnits[$fromUOM])) && (self::$conversionUnits[$fromUOM]['AllowPrefix'])) {
2739 5
                $unitGroup1 = self::$conversionUnits[$fromUOM]['Group'];
2740
            } else {
2741 1
                return Functions::NA();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...ulation\Functions::NA() returns the type string which is incompatible with the documented return type double.
Loading history...
2742
            }
2743
        }
2744 21
        $value *= $fromMultiplier;
2745
2746 21
        $toMultiplier = 1.0;
2747 21
        if (isset(self::$conversionUnits[$toUOM])) {
2748 14
            $unitGroup2 = self::$conversionUnits[$toUOM]['Group'];
2749
        } else {
2750 7
            $toMultiplier = substr($toUOM, 0, 1);
2751 7
            $toUOM = substr($toUOM, 1);
2752 7
            if (isset(self::$conversionMultipliers[$toMultiplier])) {
2753 6
                $toMultiplier = self::$conversionMultipliers[$toMultiplier]['multiplier'];
2754
            } else {
2755 1
                return Functions::NA();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...ulation\Functions::NA() returns the type string which is incompatible with the documented return type double.
Loading history...
2756
            }
2757 6
            if ((isset(self::$conversionUnits[$toUOM])) && (self::$conversionUnits[$toUOM]['AllowPrefix'])) {
2758 5
                $unitGroup2 = self::$conversionUnits[$toUOM]['Group'];
2759
            } else {
2760 1
                return Functions::NA();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...ulation\Functions::NA() returns the type string which is incompatible with the documented return type double.
Loading history...
2761
            }
2762
        }
2763 19
        if ($unitGroup1 != $unitGroup2) {
2764 2
            return Functions::NA();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...ulation\Functions::NA() returns the type string which is incompatible with the documented return type double.
Loading history...
2765
        }
2766
2767 17
        if (($fromUOM == $toUOM) && ($fromMultiplier == $toMultiplier)) {
2768
            //    We've already factored $fromMultiplier into the value, so we need
2769
            //        to reverse it again
2770 3
            return $value / $fromMultiplier;
2771 14
        } elseif ($unitGroup1 == 'Temperature') {
2772 9
            if (($fromUOM == 'F') || ($fromUOM == 'fah')) {
2773 3
                if (($toUOM == 'F') || ($toUOM == 'fah')) {
2774 1
                    return $value;
2775
                }
2776 2
                $value = (($value - 32) / 1.8);
2777 2
                if (($toUOM == 'K') || ($toUOM == 'kel')) {
2778 1
                    $value += 273.15;
2779
                }
2780
2781 2
                return $value;
2782 6
            } elseif ((($fromUOM == 'K') || ($fromUOM == 'kel')) &&
2783 6
                (($toUOM == 'K') || ($toUOM == 'kel'))
2784
            ) {
2785 1
                return $value;
2786 5
            } elseif ((($fromUOM == 'C') || ($fromUOM == 'cel')) &&
2787 5
                (($toUOM == 'C') || ($toUOM == 'cel'))
2788
            ) {
2789 1
                return $value;
2790
            }
2791 4
            if (($toUOM == 'F') || ($toUOM == 'fah')) {
2792 2
                if (($fromUOM == 'K') || ($fromUOM == 'kel')) {
2793 1
                    $value -= 273.15;
2794
                }
2795
2796 2
                return ($value * 1.8) + 32;
2797
            }
2798 2
            if (($toUOM == 'C') || ($toUOM == 'cel')) {
2799 1
                return $value - 273.15;
2800
            }
2801
2802 1
            return $value + 273.15;
2803
        }
2804
2805 5
        return ($value * self::$unitConversions[$unitGroup1][$fromUOM][$toUOM]) / $toMultiplier;
2806
    }
2807
}
2808