Test Failed
Push — develop ( 90366f...812a46 )
by Adrien
28:16
created

Engineering::HEXTOOCT()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 5

Importance

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

740
        if (strlen(/** @scrutinizer ignore-type */ $workString) > 0) {
Loading history...
741 345
            $leadingSign = (($workString[0] == '+') || ($workString[0] == '-')) ? 1 : 0;
742
        }
743 354
        $power = '';
744 354
        $realNumber = strtok($workString, '+-');
1 ignored issue
show
Bug introduced by
It seems like $workString can also be of type false; however, parameter $str of strtok() does only seem to accept string, 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

744
        $realNumber = strtok(/** @scrutinizer ignore-type */ $workString, '+-');
Loading history...
745 354
        if (strtoupper(substr($realNumber, -1)) == 'E') {
1 ignored issue
show
Bug introduced by
It seems like substr($realNumber, -1) can also be of type false; however, parameter $string of strtoupper() does only seem to accept string, 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

745
        if (strtoupper(/** @scrutinizer ignore-type */ substr($realNumber, -1)) == 'E') {
Loading history...
746 8
            $power = strtok('+-');
0 ignored issues
show
Bug introduced by
The call to strtok() has too few arguments starting with token. ( Ignorable by Annotation )

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

746
            $power = /** @scrutinizer ignore-call */ strtok('+-');

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
747 8
            ++$leadingSign;
748
        }
749
750 354
        $realNumber = substr($workString, 0, strlen($realNumber) + strlen($power) + $leadingSign);
1 ignored issue
show
Bug introduced by
It seems like $workString can also be of type false; however, parameter $string of substr() does only seem to accept string, 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

750
        $realNumber = substr(/** @scrutinizer ignore-type */ $workString, 0, strlen($realNumber) + strlen($power) + $leadingSign);
Loading history...
751
752 354
        if ($suffix != '') {
753 289
            $imaginary = substr($workString, strlen($realNumber));
754
755 289
            if (($imaginary == '') && (($realNumber == '') || ($realNumber == '+') || ($realNumber == '-'))) {
756 24
                $imaginary = $realNumber . '1';
1 ignored issue
show
Bug introduced by
Are you sure $realNumber of type false|string can be used in concatenation? ( Ignorable by Annotation )

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

756
                $imaginary = /** @scrutinizer ignore-type */ $realNumber . '1';
Loading history...
757 24
                $realNumber = '0';
758 269
            } elseif ($imaginary == '') {
759 30
                $imaginary = $realNumber;
760 30
                $realNumber = '0';
761 243
            } elseif (($imaginary == '+') || ($imaginary == '-')) {
762 96
                $imaginary .= '1';
763
            }
764
        }
765
766
        return [
0 ignored issues
show
Bug Best Practice introduced by
The expression return array('real' => $...y, 'suffix' => $suffix) returns an array which contains values of type false which are incompatible with the documented value type string.
Loading history...
767 354
            'real' => $realNumber,
768 354
            'imaginary' => $imaginary,
769 354
            'suffix' => $suffix,
770
        ];
771
    }
772
773
    /**
774
     * Cleans the leading characters in a complex number string.
775
     *
776
     * @param string $complexNumber The complex number to clean
777
     *
778
     * @return string The "cleaned" complex number
779
     */
780 38
    private static function cleanComplex($complexNumber)
781
    {
782 38
        if ($complexNumber[0] == '+') {
783
            $complexNumber = substr($complexNumber, 1);
784
        }
785 38
        if ($complexNumber[0] == '0') {
786 4
            $complexNumber = substr($complexNumber, 1);
1 ignored issue
show
Bug introduced by
It seems like $complexNumber can also be of type false; however, parameter $string of substr() does only seem to accept string, 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

786
            $complexNumber = substr(/** @scrutinizer ignore-type */ $complexNumber, 1);
Loading history...
787
        }
788 38
        if ($complexNumber[0] == '.') {
789 4
            $complexNumber = '0' . $complexNumber;
1 ignored issue
show
Bug introduced by
Are you sure $complexNumber of type false|string can be used in concatenation? ( Ignorable by Annotation )

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

789
            $complexNumber = '0' . /** @scrutinizer ignore-type */ $complexNumber;
Loading history...
790
        }
791 38
        if ($complexNumber[0] == '+') {
792
            $complexNumber = substr($complexNumber, 1);
793
        }
794
795 38
        return $complexNumber;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $complexNumber could also return false which is incompatible with the documented return type string. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
796
    }
797
798
    /**
799
     * Formats a number base string value with leading zeroes.
800
     *
801
     * @param string $xVal The "number" to pad
802
     * @param int $places The length that we want to pad this value
803
     *
804
     * @return string The padded "number"
805
     */
806 82
    private static function nbrConversionFormat($xVal, $places)
807
    {
808 82
        if ($places !== null) {
809 22
            if (is_numeric($places)) {
810 18
                $places = (int) $places;
811
            } else {
812 4
                return Functions::VALUE();
813
            }
814 18
            if ($places < 0) {
815 4
                return Functions::NAN();
816
            }
817 14
            if (strlen($xVal) <= $places) {
818 14
                return substr(str_pad($xVal, $places, '0', STR_PAD_LEFT), -10);
0 ignored issues
show
Bug Best Practice introduced by
The expression return substr(str_pad($x...ion\STR_PAD_LEFT), -10) could also return false which is incompatible with the documented return type string. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
819
            }
820
821
            return Functions::NAN();
822
        }
823
824 60
        return substr($xVal, -10);
825
    }
826
827
    /**
828
     * BESSELI.
829
     *
830
     *    Returns the modified Bessel function In(x), which is equivalent to the Bessel function evaluated
831
     *        for purely imaginary arguments
832
     *
833
     *    Excel Function:
834
     *        BESSELI(x,ord)
835
     *
836
     * @category Engineering Functions
837
     *
838
     * @param float $x The value at which to evaluate the function.
839
     *                                If x is nonnumeric, BESSELI returns the #VALUE! error value.
840
     * @param int $ord The order of the Bessel function.
841
     *                                If ord is not an integer, it is truncated.
842
     *                                If $ord is nonnumeric, BESSELI returns the #VALUE! error value.
843
     *                                If $ord < 0, BESSELI returns the #NUM! error value.
844
     *
845
     * @return float
846
     */
847 74
    public static function BESSELI($x, $ord)
848
    {
849 74
        $x = ($x === null) ? 0.0 : Functions::flattenSingleValue($x);
850 74
        $ord = ($ord === null) ? 0.0 : Functions::flattenSingleValue($ord);
851
852 74
        if ((is_numeric($x)) && (is_numeric($ord))) {
853 70
            $ord = floor($ord);
854 70
            if ($ord < 0) {
855 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...
856
            }
857
858 68
            if (abs($x) <= 30) {
859 68
                $fResult = $fTerm = pow($x / 2, $ord) / MathTrig::FACT($ord);
860 68
                $ordK = 1;
861 68
                $fSqrX = ($x * $x) / 4;
862 View Code Duplication
                do {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
863 68
                    $fTerm *= $fSqrX;
864 68
                    $fTerm /= ($ordK * ($ordK + $ord));
865 68
                    $fResult += $fTerm;
866 68
                } while ((abs($fTerm) > 1e-12) && (++$ordK < 100));
867
            } else {
868
                $f_2_PI = 2 * M_PI;
869
870
                $fXAbs = abs($x);
871
                $fResult = exp($fXAbs) / sqrt($f_2_PI * $fXAbs);
872
                if (($ord & 1) && ($x < 0)) {
873
                    $fResult = -$fResult;
874
                }
875
            }
876
877 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...
878
        }
879
880 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...
881
    }
882
883
    /**
884
     * BESSELJ.
885
     *
886
     *    Returns the Bessel function
887
     *
888
     *    Excel Function:
889
     *        BESSELJ(x,ord)
890
     *
891
     * @category Engineering Functions
892
     *
893
     * @param float $x The value at which to evaluate the function.
894
     *                                If x is nonnumeric, BESSELJ returns the #VALUE! error value.
895
     * @param int $ord The order of the Bessel function. If n is not an integer, it is truncated.
896
     *                                If $ord is nonnumeric, BESSELJ returns the #VALUE! error value.
897
     *                                If $ord < 0, BESSELJ returns the #NUM! error value.
898
     *
899
     * @return float
900
     */
901 50
    public static function BESSELJ($x, $ord)
902
    {
903 50
        $x = ($x === null) ? 0.0 : Functions::flattenSingleValue($x);
904 50
        $ord = ($ord === null) ? 0.0 : Functions::flattenSingleValue($ord);
905
906 50
        if ((is_numeric($x)) && (is_numeric($ord))) {
907 48
            $ord = floor($ord);
908 48
            if ($ord < 0) {
909 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...
910
            }
911
912 47
            $fResult = 0;
913 47
            if (abs($x) <= 30) {
914 47
                $fResult = $fTerm = pow($x / 2, $ord) / MathTrig::FACT($ord);
915 47
                $ordK = 1;
916 47
                $fSqrX = ($x * $x) / -4;
917 View Code Duplication
                do {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
918 47
                    $fTerm *= $fSqrX;
919 47
                    $fTerm /= ($ordK * ($ordK + $ord));
920 47
                    $fResult += $fTerm;
921 47
                } while ((abs($fTerm) > 1e-12) && (++$ordK < 100));
922
            } else {
923
                $f_PI_DIV_2 = M_PI / 2;
924
                $f_PI_DIV_4 = M_PI / 4;
925
926
                $fXAbs = abs($x);
927
                $fResult = sqrt(Functions::M_2DIVPI / $fXAbs) * cos($fXAbs - $ord * $f_PI_DIV_2 - $f_PI_DIV_4);
928
                if (($ord & 1) && ($x < 0)) {
929
                    $fResult = -$fResult;
930
                }
931
            }
932
933 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...
934
        }
935
936 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...
937
    }
938
939 22
    private static function besselK0($fNum)
940
    {
941 22
        if ($fNum <= 2) {
942 14
            $fNum2 = $fNum * 0.5;
943 14
            $y = ($fNum2 * $fNum2);
944 14
            $fRet = -log($fNum2) * self::BESSELI($fNum, 0) +
945
                (-0.57721566 + $y * (0.42278420 + $y * (0.23069756 + $y * (0.3488590e-1 + $y * (0.262698e-2 + $y *
946 14
                                    (0.10750e-3 + $y * 0.74e-5))))));
947 View Code Duplication
        } else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
948 8
            $y = 2 / $fNum;
949 8
            $fRet = exp(-$fNum) / sqrt($fNum) *
950
                (1.25331414 + $y * (-0.7832358e-1 + $y * (0.2189568e-1 + $y * (-0.1062446e-1 + $y *
951 8
                                (0.587872e-2 + $y * (-0.251540e-2 + $y * 0.53208e-3))))));
952
        }
953
954 22
        return $fRet;
955
    }
956
957 30
    private static function besselK1($fNum)
958
    {
959 30
        if ($fNum <= 2) {
960 17
            $fNum2 = $fNum * 0.5;
961 17
            $y = ($fNum2 * $fNum2);
962 17
            $fRet = log($fNum2) * self::BESSELI($fNum, 1) +
963
                (1 + $y * (0.15443144 + $y * (-0.67278579 + $y * (-0.18156897 + $y * (-0.1919402e-1 + $y *
964 17
                                    (-0.110404e-2 + $y * (-0.4686e-4))))))) / $fNum;
965 View Code Duplication
        } else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

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

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

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

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

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

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

Loading history...
1084
    {
1085 23
        $x = ($x === null) ? 0.0 : Functions::flattenSingleValue($x);
1086 23
        $ord = ($ord === null) ? 0.0 : Functions::flattenSingleValue($ord);
1087
1088 23
        if ((is_numeric($x)) && (is_numeric($ord))) {
1089 21
            if (($ord < 0) || ($x == 0.0)) {
1090 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...
1091
            }
1092
1093 18
            switch (floor($ord)) {
1094 18
                case 0:
1095 2
                    $fBy = self::besselY0($x);
1096
1097 2
                    break;
1098 16
                case 1:
1099 7
                    $fBy = self::besselY1($x);
1100
1101 7
                    break;
1102
                default:
1103 9
                    $fTox = 2 / $x;
1104 9
                    $fBym = self::besselY0($x);
1105 9
                    $fBy = self::besselY1($x);
1106 9
                    for ($n = 1; $n < $ord; ++$n) {
1107 9
                        $fByp = $n * $fTox * $fBy - $fBym;
1108 9
                        $fBym = $fBy;
1109 9
                        $fBy = $fByp;
1110
                    }
1111
            }
1112
1113 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...
1114
        }
1115
1116 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...
1117
    }
1118
1119
    /**
1120
     * BINTODEC.
1121
     *
1122
     * Return a binary value as decimal.
1123
     *
1124
     * Excel Function:
1125
     *        BIN2DEC(x)
1126
     *
1127
     * @category Engineering Functions
1128
     *
1129
     * @param string $x The binary number (as a string) that you want to convert. The number
1130
     *                                cannot contain more than 10 characters (10 bits). The most significant
1131
     *                                bit of number is the sign bit. The remaining 9 bits are magnitude bits.
1132
     *                                Negative numbers are represented using two's-complement notation.
1133
     *                                If number is not a valid binary number, or if number contains more than
1134
     *                                10 characters (10 bits), BIN2DEC returns the #NUM! error value.
1135
     *
1136
     * @return string
1137
     */
1138 10
    public static function BINTODEC($x)
1139
    {
1140 10
        $x = Functions::flattenSingleValue($x);
1141
1142 10
        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 9
        if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) {
1150
            $x = 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

1150
            $x = floor(/** @scrutinizer ignore-type */ $x);
Loading history...
1151
        }
1152 9
        $x = (string) $x;
1153 9
        if (strlen($x) > preg_match_all('/[01]/', $x, $out)) {
1154 1
            return Functions::NAN();
1155
        }
1156 8
        if (strlen($x) > 10) {
1157 1
            return Functions::NAN();
1158 7
        } elseif (strlen($x) == 10) {
1159
            //    Two's Complement
1160 2
            $x = substr($x, -9);
1161
1162 2
            return '-' . (512 - bindec($x));
1 ignored issue
show
Bug introduced by
It seems like $x can also be of type false; however, parameter $binary_string of bindec() does only seem to accept string, 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

1162
            return '-' . (512 - bindec(/** @scrutinizer ignore-type */ $x));
Loading history...
1163
        }
1164
1165 5
        return bindec($x);
1166
    }
1167
1168
    /**
1169
     * BINTOHEX.
1170
     *
1171
     * Return a binary value as hex.
1172
     *
1173
     * Excel Function:
1174
     *        BIN2HEX(x[,places])
1175
     *
1176
     * @category Engineering Functions
1177
     *
1178
     * @param string $x The binary number (as a string) that you want to convert. The number
1179
     *                                cannot contain more than 10 characters (10 bits). The most significant
1180
     *                                bit of number is the sign bit. The remaining 9 bits are magnitude bits.
1181
     *                                Negative numbers are represented using two's-complement notation.
1182
     *                                If number is not a valid binary number, or if number contains more than
1183
     *                                10 characters (10 bits), BIN2HEX returns the #NUM! error value.
1184
     * @param int $places The number of characters to use. If places is omitted, BIN2HEX uses the
1185
     *                                minimum number of characters necessary. Places is useful for padding the
1186
     *                                return value with leading 0s (zeros).
1187
     *                                If places is not an integer, it is truncated.
1188
     *                                If places is nonnumeric, BIN2HEX returns the #VALUE! error value.
1189
     *                                If places is negative, BIN2HEX returns the #NUM! error value.
1190
     *
1191
     * @return string
1192
     */
1193 14 View Code Duplication
    public static function BINTOHEX($x, $places = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
1194
    {
1195 14
        $x = Functions::flattenSingleValue($x);
1196 14
        $places = Functions::flattenSingleValue($places);
1197
1198
        // Argument X
1199 14
        if (is_bool($x)) {
1200 1
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
1201
                $x = (int) $x;
1202
            } else {
1203 1
                return Functions::VALUE();
1204
            }
1205
        }
1206 13
        if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) {
1207
            $x = 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

1207
            $x = floor(/** @scrutinizer ignore-type */ $x);
Loading history...
1208
        }
1209 13
        $x = (string) $x;
1210 13
        if (strlen($x) > preg_match_all('/[01]/', $x, $out)) {
1211 1
            return Functions::NAN();
1212
        }
1213 12
        if (strlen($x) > 10) {
1214 1
            return Functions::NAN();
1215 11
        } elseif (strlen($x) == 10) {
1216
            //    Two's Complement
1217 2
            return str_repeat('F', 8) . substr(strtoupper(dechex(bindec(substr($x, -9)))), -2);
3 ignored issues
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

1217
            return str_repeat('F', 8) . substr(strtoupper(dechex(/** @scrutinizer ignore-type */ bindec(substr($x, -9)))), -2);
Loading history...
Bug introduced by
It seems like substr($x, -9) can also be of type false; however, parameter $binary_string of bindec() does only seem to accept string, 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

1217
            return str_repeat('F', 8) . substr(strtoupper(dechex(bindec(/** @scrutinizer ignore-type */ substr($x, -9)))), -2);
Loading history...
Bug introduced by
Are you sure substr(strtoupper(dechex...(substr($x, -9)))), -2) of type false|string can be used in concatenation? ( Ignorable by Annotation )

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

1217
            return str_repeat('F', 8) . /** @scrutinizer ignore-type */ substr(strtoupper(dechex(bindec(substr($x, -9)))), -2);
Loading history...
1218
        }
1219 9
        $hexVal = (string) strtoupper(dechex(bindec($x)));
1220
1221 9
        return self::nbrConversionFormat($hexVal, $places);
1222
    }
1223
1224
    /**
1225
     * BINTOOCT.
1226
     *
1227
     * Return a binary value as octal.
1228
     *
1229
     * Excel Function:
1230
     *        BIN2OCT(x[,places])
1231
     *
1232
     * @category Engineering Functions
1233
     *
1234
     * @param string $x The binary number (as a string) that you want to convert. The number
1235
     *                                cannot contain more than 10 characters (10 bits). The most significant
1236
     *                                bit of number is the sign bit. The remaining 9 bits are magnitude bits.
1237
     *                                Negative numbers are represented using two's-complement notation.
1238
     *                                If number is not a valid binary number, or if number contains more than
1239
     *                                10 characters (10 bits), BIN2OCT returns the #NUM! error value.
1240
     * @param int $places The number of characters to use. If places is omitted, BIN2OCT uses the
1241
     *                                minimum number of characters necessary. Places is useful for padding the
1242
     *                                return value with leading 0s (zeros).
1243
     *                                If places is not an integer, it is truncated.
1244
     *                                If places is nonnumeric, BIN2OCT returns the #VALUE! error value.
1245
     *                                If places is negative, BIN2OCT returns the #NUM! error value.
1246
     *
1247
     * @return string
1248
     */
1249 15 View Code Duplication
    public static function BINTOOCT($x, $places = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
1250
    {
1251 15
        $x = Functions::flattenSingleValue($x);
1252 15
        $places = Functions::flattenSingleValue($places);
1253
1254 15
        if (is_bool($x)) {
1255 1
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
1256
                $x = (int) $x;
1257
            } else {
1258 1
                return Functions::VALUE();
1259
            }
1260
        }
1261 14
        if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) {
1262
            $x = floor($x);
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

1262
            $x = floor(/** @scrutinizer ignore-type */ $x);
Loading history...
1263
        }
1264 14
        $x = (string) $x;
1265 14
        if (strlen($x) > preg_match_all('/[01]/', $x, $out)) {
1266 1
            return Functions::NAN();
1267
        }
1268 13
        if (strlen($x) > 10) {
1269 1
            return Functions::NAN();
1270 12
        } elseif (strlen($x) == 10) {
1271
            //    Two's Complement
1272 2
            return str_repeat('7', 7) . substr(strtoupper(decoct(bindec(substr($x, -9)))), -3);
3 ignored issues
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

1272
            return str_repeat('7', 7) . substr(strtoupper(decoct(/** @scrutinizer ignore-type */ bindec(substr($x, -9)))), -3);
Loading history...
Bug introduced by
Are you sure substr(strtoupper(decoct...(substr($x, -9)))), -3) of type false|string can be used in concatenation? ( Ignorable by Annotation )

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

1272
            return str_repeat('7', 7) . /** @scrutinizer ignore-type */ substr(strtoupper(decoct(bindec(substr($x, -9)))), -3);
Loading history...
Bug introduced by
It seems like substr($x, -9) can also be of type false; however, parameter $binary_string of bindec() does only seem to accept string, 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

1272
            return str_repeat('7', 7) . substr(strtoupper(decoct(bindec(/** @scrutinizer ignore-type */ substr($x, -9)))), -3);
Loading history...
1273
        }
1274 10
        $octVal = (string) decoct(bindec($x));
1275
1276 10
        return self::nbrConversionFormat($octVal, $places);
1277
    }
1278
1279
    /**
1280
     * DECTOBIN.
1281
     *
1282
     * Return a decimal value as binary.
1283
     *
1284
     * Excel Function:
1285
     *        DEC2BIN(x[,places])
1286
     *
1287
     * @category Engineering Functions
1288
     *
1289
     * @param string $x The decimal integer you want to convert. If number is negative,
1290
     *                                valid place values are ignored and DEC2BIN returns a 10-character
1291
     *                                (10-bit) binary number in which the most significant bit is the sign
1292
     *                                bit. The remaining 9 bits are magnitude bits. Negative numbers are
1293
     *                                represented using two's-complement notation.
1294
     *                                If number < -512 or if number > 511, DEC2BIN returns the #NUM! error
1295
     *                                value.
1296
     *                                If number is nonnumeric, DEC2BIN returns the #VALUE! error value.
1297
     *                                If DEC2BIN requires more than places characters, it returns the #NUM!
1298
     *                                error value.
1299
     * @param int $places The number of characters to use. If places is omitted, DEC2BIN uses
1300
     *                                the minimum number of characters necessary. Places is useful for
1301
     *                                padding the return value with leading 0s (zeros).
1302
     *                                If places is not an integer, it is truncated.
1303
     *                                If places is nonnumeric, DEC2BIN returns the #VALUE! error value.
1304
     *                                If places is zero or negative, DEC2BIN returns the #NUM! error value.
1305
     *
1306
     * @return string
1307
     */
1308 41
    public static function DECTOBIN($x, $places = null)
1309
    {
1310 41
        $x = Functions::flattenSingleValue($x);
1311 41
        $places = Functions::flattenSingleValue($places);
1312
1313 41
        if (is_bool($x)) {
1314 1
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
1315
                $x = (int) $x;
1316
            } else {
1317 1
                return Functions::VALUE();
1318
            }
1319
        }
1320 40
        $x = (string) $x;
1321 40
        if (strlen($x) > preg_match_all('/[-0123456789.]/', $x, $out)) {
1322 1
            return Functions::VALUE();
1323
        }
1324
1325 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

1325
        $x = (string) floor(/** @scrutinizer ignore-type */ $x);
Loading history...
1326 39
        if ($x < -512 || $x > 511) {
1327 13
            return Functions::NAN();
1328
        }
1329
1330 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

1330
        $r = decbin(/** @scrutinizer ignore-type */ $x);
Loading history...
1331
        // Two's Complement
1332 26
        $r = substr($r, -10);
1333 26
        if (strlen($r) >= 11) {
1 ignored issue
show
Bug introduced by
It seems like $r can also be of type false; however, parameter $string of strlen() does only seem to accept string, 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

1333
        if (strlen(/** @scrutinizer ignore-type */ $r) >= 11) {
Loading history...
1334
            return Functions::NAN();
1335
        }
1336
1337 26
        return self::nbrConversionFormat($r, $places);
1 ignored issue
show
Bug introduced by
It seems like $r can also be of type false; however, parameter $xVal of PhpOffice\PhpSpreadsheet...::nbrConversionFormat() does only seem to accept string, 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

1337
        return self::nbrConversionFormat(/** @scrutinizer ignore-type */ $r, $places);
Loading history...
1338
    }
1339
1340
    /**
1341
     * DECTOHEX.
1342
     *
1343
     * Return a decimal value as hex.
1344
     *
1345
     * Excel Function:
1346
     *        DEC2HEX(x[,places])
1347
     *
1348
     * @category Engineering Functions
1349
     *
1350
     * @param string $x The decimal integer you want to convert. If number is negative,
1351
     *                                places is ignored and DEC2HEX returns a 10-character (40-bit)
1352
     *                                hexadecimal number in which the most significant bit is the sign
1353
     *                                bit. The remaining 39 bits are magnitude bits. Negative numbers
1354
     *                                are represented using two's-complement notation.
1355
     *                                If number < -549,755,813,888 or if number > 549,755,813,887,
1356
     *                                DEC2HEX returns the #NUM! error value.
1357
     *                                If number is nonnumeric, DEC2HEX returns the #VALUE! error value.
1358
     *                                If DEC2HEX requires more than places characters, it returns the
1359
     *                                #NUM! error value.
1360
     * @param int $places The number of characters to use. If places is omitted, DEC2HEX uses
1361
     *                                the minimum number of characters necessary. Places is useful for
1362
     *                                padding the return value with leading 0s (zeros).
1363
     *                                If places is not an integer, it is truncated.
1364
     *                                If places is nonnumeric, DEC2HEX returns the #VALUE! error value.
1365
     *                                If places is zero or negative, DEC2HEX returns the #NUM! error value.
1366
     *
1367
     * @return string
1368
     */
1369 15 View Code Duplication
    public static function DECTOHEX($x, $places = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
1370
    {
1371 15
        $x = Functions::flattenSingleValue($x);
1372 15
        $places = Functions::flattenSingleValue($places);
1373
1374 15
        if (is_bool($x)) {
1375 1
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
1376
                $x = (int) $x;
1377
            } else {
1378 1
                return Functions::VALUE();
1379
            }
1380
        }
1381 14
        $x = (string) $x;
1382 14
        if (strlen($x) > preg_match_all('/[-0123456789.]/', $x, $out)) {
1383 1
            return Functions::VALUE();
1384
        }
1385 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

1385
        $x = (string) floor(/** @scrutinizer ignore-type */ $x);
Loading history...
1386 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

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

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

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

Loading history...
1425
    {
1426 20
        $xorig = $x;
0 ignored issues
show
Unused Code introduced by
The assignment to $xorig is dead and can be removed.
Loading history...
1427 20
        $x = Functions::flattenSingleValue($x);
1428 20
        $places = Functions::flattenSingleValue($places);
1429
1430 20
        if (is_bool($x)) {
1431 1
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
1432
                $x = (int) $x;
1433
            } else {
1434 1
                return Functions::VALUE();
1435
            }
1436
        }
1437 19
        $x = (string) $x;
1438 19
        if (strlen($x) > preg_match_all('/[-0123456789.]/', $x, $out)) {
1439 1
            return Functions::VALUE();
1440
        }
1441 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

1441
        $x = (string) floor(/** @scrutinizer ignore-type */ $x);
Loading history...
1442 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

1442
        $r = decoct(/** @scrutinizer ignore-type */ $x);
Loading history...
1443 18
        if (strlen($r) == 11) {
1444
            //    Two's Complement
1445
            $r = substr($r, -10);
1446
        }
1447
1448 18
        return self::nbrConversionFormat($r, $places);
1 ignored issue
show
Bug introduced by
It seems like $r can also be of type false; however, parameter $xVal of PhpOffice\PhpSpreadsheet...::nbrConversionFormat() does only seem to accept string, 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

1448
        return self::nbrConversionFormat(/** @scrutinizer ignore-type */ $r, $places);
Loading history...
1449
    }
1450
1451
    /**
1452
     * HEXTOBIN.
1453
     *
1454
     * Return a hex value as binary.
1455
     *
1456
     * Excel Function:
1457
     *        HEX2BIN(x[,places])
1458
     *
1459
     * @category Engineering Functions
1460
     *
1461
     * @param string $x the hexadecimal number you want to convert.
1462
     *                  Number cannot contain more than 10 characters.
1463
     *                  The most significant bit of number is the sign bit (40th bit from the right).
1464
     *                  The remaining 9 bits are magnitude bits.
1465
     *                  Negative numbers are represented using two's-complement notation.
1466
     *                  If number is negative, HEX2BIN ignores places and returns a 10-character binary number.
1467
     *                  If number is negative, it cannot be less than FFFFFFFE00,
1468
     *                      and if number is positive, it cannot be greater than 1FF.
1469
     *                  If number is not a valid hexadecimal number, HEX2BIN returns the #NUM! error value.
1470
     *                  If HEX2BIN requires more than places characters, it returns the #NUM! error value.
1471
     * @param int $places The number of characters to use. If places is omitted,
1472
     *                                    HEX2BIN uses the minimum number of characters necessary. Places
1473
     *                                    is useful for padding the return value with leading 0s (zeros).
1474
     *                                    If places is not an integer, it is truncated.
1475
     *                                    If places is nonnumeric, HEX2BIN returns the #VALUE! error value.
1476
     *                                    If places is negative, HEX2BIN returns the #NUM! error value.
1477
     *
1478
     * @return string
1479
     */
1480 16 View Code Duplication
    public static function HEXTOBIN($x, $places = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Loading history...
1729
    {
1730 9
        $x = Functions::flattenSingleValue($x);
1731 9
        $places = Functions::flattenSingleValue($places);
1732
1733 9
        if (is_bool($x)) {
1734 1
            return Functions::VALUE();
1735
        }
1736 8
        $x = (string) $x;
1737 8
        if (preg_match_all('/[01234567]/', $x, $out) != strlen($x)) {
1738 2
            return Functions::NAN();
1739
        }
1740 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

1740
        $hexVal = strtoupper(dechex(/** @scrutinizer ignore-type */ self::OCTTODEC($x)));
Loading history...
1741
1742 6
        return self::nbrConversionFormat($hexVal, $places);
1743
    }
1744
1745
    /**
1746
     * COMPLEX.
1747
     *
1748
     * Converts real and imaginary coefficients into a complex number of the form x + yi or x + yj.
1749
     *
1750
     * Excel Function:
1751
     *        COMPLEX(realNumber,imaginary[,places])
1752
     *
1753
     * @category Engineering Functions
1754
     *
1755
     * @param float $realNumber the real coefficient of the complex number
1756
     * @param float $imaginary the imaginary coefficient of the complex number
1757
     * @param string $suffix The suffix for the imaginary component of the complex number.
1758
     *                                        If omitted, the suffix is assumed to be "i".
1759
     *
1760
     * @return string
1761
     */
1762 759
    public static function COMPLEX($realNumber = 0.0, $imaginary = 0.0, $suffix = 'i')
1763
    {
1764 759
        $realNumber = ($realNumber === null) ? 0.0 : Functions::flattenSingleValue($realNumber);
1765 759
        $imaginary = ($imaginary === null) ? 0.0 : Functions::flattenSingleValue($imaginary);
1766 759
        $suffix = ($suffix === null) ? 'i' : Functions::flattenSingleValue($suffix);
1767
1768 759
        if (((is_numeric($realNumber)) && (is_numeric($imaginary))) &&
1769 759
            (($suffix == 'i') || ($suffix == 'j') || ($suffix == ''))
1770
        ) {
1771 758
            $realNumber = (float) $realNumber;
1772 758
            $imaginary = (float) $imaginary;
1773
1774 758
            if ($suffix == '') {
1775
                $suffix = 'i';
1776
            }
1777 758
            if ($realNumber == 0.0) {
1778 65
                if ($imaginary == 0.0) {
1779 6
                    return (string) '0';
1780 59
                } elseif ($imaginary == 1.0) {
1781 5
                    return (string) $suffix;
1782 54
                } elseif ($imaginary == -1.0) {
1783 2
                    return (string) '-' . $suffix;
1784
                }
1785
1786 52
                return (string) $imaginary . $suffix;
1787 693
            } elseif ($imaginary == 0.0) {
1788 54
                return (string) $realNumber;
1789 639
            } elseif ($imaginary == 1.0) {
1790 45
                return (string) $realNumber . '+' . $suffix;
1791 594
            } elseif ($imaginary == -1.0) {
1792 8
                return (string) $realNumber . '-' . $suffix;
1793
            }
1794 586
            if ($imaginary > 0) {
1795 329
                $imaginary = (string) '+' . $imaginary;
1796
            }
1797
1798 586
            return (string) $realNumber . $imaginary . $suffix;
1799
        }
1800
1801 1
        return Functions::VALUE();
1802
    }
1803
1804
    /**
1805
     * IMAGINARY.
1806
     *
1807
     * Returns the imaginary coefficient of a complex number in x + yi or x + yj text format.
1808
     *
1809
     * Excel Function:
1810
     *        IMAGINARY(complexNumber)
1811
     *
1812
     * @category Engineering Functions
1813
     *
1814
     * @param string $complexNumber the complex number for which you want the imaginary
1815
     *                                         coefficient
1816
     *
1817
     * @return float
1818
     */
1819 30
    public static function IMAGINARY($complexNumber)
1820
    {
1821 30
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1822
1823 30
        $parsedComplex = self::parseComplex($complexNumber);
1824
1825 30
        return $parsedComplex['imaginary'];
0 ignored issues
show
Bug Best Practice introduced by
The expression return $parsedComplex['imaginary'] returns the type string which is incompatible with the documented return type double.
Loading history...
1826
    }
1827
1828
    /**
1829
     * IMREAL.
1830
     *
1831
     * Returns the real coefficient of a complex number in x + yi or x + yj text format.
1832
     *
1833
     * Excel Function:
1834
     *        IMREAL(complexNumber)
1835
     *
1836
     * @category Engineering Functions
1837
     *
1838
     * @param string $complexNumber the complex number for which you want the real coefficient
1839
     *
1840
     * @return float
1841
     */
1842 30
    public static function IMREAL($complexNumber)
1843
    {
1844 30
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1845
1846 30
        $parsedComplex = self::parseComplex($complexNumber);
1847
1848 30
        return $parsedComplex['real'];
0 ignored issues
show
Bug Best Practice introduced by
The expression return $parsedComplex['real'] returns the type string which is incompatible with the documented return type double.
Loading history...
1849
    }
1850
1851
    /**
1852
     * IMABS.
1853
     *
1854
     * Returns the absolute value (modulus) of a complex number in x + yi or x + yj text format.
1855
     *
1856
     * Excel Function:
1857
     *        IMABS(complexNumber)
1858
     *
1859
     * @param string $complexNumber the complex number for which you want the absolute value
1860
     *
1861
     * @return float
1862
     */
1863 27
    public static function IMABS($complexNumber)
1864
    {
1865 27
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1866
1867 27
        $parsedComplex = self::parseComplex($complexNumber);
1868
1869 27
        return sqrt(
1870 27
            ($parsedComplex['real'] * $parsedComplex['real']) +
1871 27
            ($parsedComplex['imaginary'] * $parsedComplex['imaginary'])
1872
        );
1873
    }
1874
1875
    /**
1876
     * IMARGUMENT.
1877
     *
1878
     * Returns the argument theta of a complex number, i.e. the angle in radians from the real
1879
     * axis to the representation of the number in polar coordinates.
1880
     *
1881
     * Excel Function:
1882
     *        IMARGUMENT(complexNumber)
1883
     *
1884
     * @param string $complexNumber the complex number for which you want the argument theta
1885
     *
1886
     * @return float
1887
     */
1888 128
    public static function IMARGUMENT($complexNumber)
1889
    {
1890 128
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1891 128
        $parsedComplex = self::parseComplex($complexNumber);
1892 128
        if ($parsedComplex['real'] == 0.0) {
1893 22
            if ($parsedComplex['imaginary'] == 0.0) {
1894 2
                return Functions::DIV0();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...ation\Functions::DIV0() returns the type string which is incompatible with the documented return type double.
Loading history...
1895 20
            } elseif ($parsedComplex['imaginary'] < 0.0) {
1896 10
                return M_PI / -2;
1897
            }
1898
1899 10
            return M_PI / 2;
1900 106
        } elseif ($parsedComplex['real'] > 0.0) {
1901 52
            return atan($parsedComplex['imaginary'] / $parsedComplex['real']);
1902 54
        } elseif ($parsedComplex['imaginary'] < 0.0) {
1903 20
            return 0 - (M_PI - atan(abs($parsedComplex['imaginary']) / abs($parsedComplex['real'])));
1904
        }
1905
1906 34
        return M_PI - atan($parsedComplex['imaginary'] / abs($parsedComplex['real']));
1907
    }
1908
1909
    /**
1910
     * IMCONJUGATE.
1911
     *
1912
     * Returns the complex conjugate of a complex number in x + yi or x + yj text format.
1913
     *
1914
     * Excel Function:
1915
     *        IMCONJUGATE(complexNumber)
1916
     *
1917
     * @param string $complexNumber the complex number for which you want the conjugate
1918
     *
1919
     * @return string
1920
     */
1921 47
    public static function IMCONJUGATE($complexNumber)
1922
    {
1923 47
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1924
1925 47
        $parsedComplex = self::parseComplex($complexNumber);
1926
1927 47
        if ($parsedComplex['imaginary'] == 0.0) {
1928 9
            return $parsedComplex['real'];
1929
        }
1930
1931 38
        return self::cleanComplex(
1932 38
            self::COMPLEX(
1933 38
                $parsedComplex['real'],
0 ignored issues
show
Bug introduced by
$parsedComplex['real'] of type string is incompatible with the type double expected by parameter $realNumber of PhpOffice\PhpSpreadsheet...\Engineering::COMPLEX(). ( Ignorable by Annotation )

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

1933
                /** @scrutinizer ignore-type */ $parsedComplex['real'],
Loading history...
1934 38
                0 - $parsedComplex['imaginary'],
1935 38
                $parsedComplex['suffix']
1936
            )
1937
        );
1938
    }
1939
1940
    /**
1941
     * IMCOS.
1942
     *
1943
     * Returns the cosine of a complex number in x + yi or x + yj text format.
1944
     *
1945
     * Excel Function:
1946
     *        IMCOS(complexNumber)
1947
     *
1948
     * @param string $complexNumber the complex number for which you want the cosine
1949
     *
1950
     * @return float|string
1951
     */
1952 27 View Code Duplication
    public static function IMCOS($complexNumber)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
1953
    {
1954 27
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1955
1956 27
        $parsedComplex = self::parseComplex($complexNumber);
1957
1958 27
        if ($parsedComplex['imaginary'] == 0.0) {
1959 6
            return cos($parsedComplex['real']);
0 ignored issues
show
Bug introduced by
$parsedComplex['real'] of type string is incompatible with the type double expected by parameter $arg of cos(). ( Ignorable by Annotation )

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

1959
            return cos(/** @scrutinizer ignore-type */ $parsedComplex['real']);
Loading history...
1960
        }
1961
1962 21
        return self::IMCONJUGATE(
1963 21
            self::COMPLEX(
1964 21
                cos($parsedComplex['real']) * cosh($parsedComplex['imaginary']),
0 ignored issues
show
Bug introduced by
$parsedComplex['imaginary'] of type string is incompatible with the type double expected by parameter $arg of cosh(). ( Ignorable by Annotation )

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

1964
                cos($parsedComplex['real']) * cosh(/** @scrutinizer ignore-type */ $parsedComplex['imaginary']),
Loading history...
1965 21
                sin($parsedComplex['real']) * sinh($parsedComplex['imaginary']),
0 ignored issues
show
Bug introduced by
$parsedComplex['imaginary'] of type string is incompatible with the type double expected by parameter $arg of sinh(). ( Ignorable by Annotation )

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

1965
                sin($parsedComplex['real']) * sinh(/** @scrutinizer ignore-type */ $parsedComplex['imaginary']),
Loading history...
Bug introduced by
$parsedComplex['real'] of type string is incompatible with the type double expected by parameter $arg of sin(). ( Ignorable by Annotation )

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

1965
                sin(/** @scrutinizer ignore-type */ $parsedComplex['real']) * sinh($parsedComplex['imaginary']),
Loading history...
1966 21
                $parsedComplex['suffix']
1967
            )
1968
        );
1969
    }
1970
1971
    /**
1972
     * IMSIN.
1973
     *
1974
     * Returns the sine of a complex number in x + yi or x + yj text format.
1975
     *
1976
     * Excel Function:
1977
     *        IMSIN(complexNumber)
1978
     *
1979
     * @param string $complexNumber the complex number for which you want the sine
1980
     *
1981
     * @return float|string
1982
     */
1983 27 View Code Duplication
    public static function IMSIN($complexNumber)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
1984
    {
1985 27
        $complexNumber = Functions::flattenSingleValue($complexNumber);
1986
1987 27
        $parsedComplex = self::parseComplex($complexNumber);
1988
1989 27
        if ($parsedComplex['imaginary'] == 0.0) {
1990 6
            return sin($parsedComplex['real']);
0 ignored issues
show
Bug introduced by
$parsedComplex['real'] of type string is incompatible with the type double expected by parameter $arg of sin(). ( Ignorable by Annotation )

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

1990
            return sin(/** @scrutinizer ignore-type */ $parsedComplex['real']);
Loading history...
1991
        }
1992
1993 21
        return self::COMPLEX(
1994 21
            sin($parsedComplex['real']) * cosh($parsedComplex['imaginary']),
0 ignored issues
show
Bug introduced by
$parsedComplex['imaginary'] of type string is incompatible with the type double expected by parameter $arg of cosh(). ( Ignorable by Annotation )

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

1994
            sin($parsedComplex['real']) * cosh(/** @scrutinizer ignore-type */ $parsedComplex['imaginary']),
Loading history...
1995 21
            cos($parsedComplex['real']) * sinh($parsedComplex['imaginary']),
0 ignored issues
show
Bug introduced by
$parsedComplex['real'] of type string is incompatible with the type double expected by parameter $arg of cos(). ( Ignorable by Annotation )

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

1995
            cos(/** @scrutinizer ignore-type */ $parsedComplex['real']) * sinh($parsedComplex['imaginary']),
Loading history...
Bug introduced by
$parsedComplex['imaginary'] of type string is incompatible with the type double expected by parameter $arg of sinh(). ( Ignorable by Annotation )

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

1995
            cos($parsedComplex['real']) * sinh(/** @scrutinizer ignore-type */ $parsedComplex['imaginary']),
Loading history...
1996 21
            $parsedComplex['suffix']
1997
        );
1998
    }
1999
2000
    /**
2001
     * IMSQRT.
2002
     *
2003
     * Returns the square root of a complex number in x + yi or x + yj text format.
2004
     *
2005
     * Excel Function:
2006
     *        IMSQRT(complexNumber)
2007
     *
2008
     * @param string $complexNumber the complex number for which you want the square root
2009
     *
2010
     * @return string
2011
     */
2012 28
    public static function IMSQRT($complexNumber)
2013
    {
2014 28
        $complexNumber = Functions::flattenSingleValue($complexNumber);
2015
2016 28
        $parsedComplex = self::parseComplex($complexNumber);
2017
2018 28
        $theta = self::IMARGUMENT($complexNumber);
2019 28
        if ($theta === Functions::DIV0()) {
2020 1
            return '0';
2021
        }
2022
2023 27
        $d1 = cos($theta / 2);
2024 27
        $d2 = sin($theta / 2);
2025 27
        $r = sqrt(sqrt(($parsedComplex['real'] * $parsedComplex['real']) + ($parsedComplex['imaginary'] * $parsedComplex['imaginary'])));
2026
2027 27
        if ($parsedComplex['suffix'] == '') {
2028 5
            return self::COMPLEX($d1 * $r, $d2 * $r);
2029
        }
2030
2031 22
        return self::COMPLEX($d1 * $r, $d2 * $r, $parsedComplex['suffix']);
2032
    }
2033
2034
    /**
2035
     * IMLN.
2036
     *
2037
     * Returns the natural logarithm of a complex number in x + yi or x + yj text format.
2038
     *
2039
     * Excel Function:
2040
     *        IMLN(complexNumber)
2041
     *
2042
     * @param string $complexNumber the complex number for which you want the natural logarithm
2043
     *
2044
     * @return string
2045
     */
2046 75
    public static function IMLN($complexNumber)
2047
    {
2048 75
        $complexNumber = Functions::flattenSingleValue($complexNumber);
2049
2050 75
        $parsedComplex = self::parseComplex($complexNumber);
2051
2052 75
        if (($parsedComplex['real'] == 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
2053 1
            return Functions::NAN();
2054
        }
2055
2056 74
        $logR = log(sqrt(($parsedComplex['real'] * $parsedComplex['real']) + ($parsedComplex['imaginary'] * $parsedComplex['imaginary'])));
2057 74
        $t = self::IMARGUMENT($complexNumber);
2058
2059 74
        if ($parsedComplex['suffix'] == '') {
2060 8
            return self::COMPLEX($logR, $t);
2061
        }
2062
2063 66
        return self::COMPLEX($logR, $t, $parsedComplex['suffix']);
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 View Code Duplication
    public static function IMLOG10($complexNumber)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
2079
    {
2080 27
        $complexNumber = Functions::flattenSingleValue($complexNumber);
2081
2082 27
        $parsedComplex = self::parseComplex($complexNumber);
2083
2084 27
        if (($parsedComplex['real'] == 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
2085 1
            return Functions::NAN();
2086 26
        } elseif (($parsedComplex['real'] > 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
2087 2
            return log10($parsedComplex['real']);
2088
        }
2089
2090 24
        return self::IMPRODUCT(log10(self::EULER), self::IMLN($complexNumber));
2091
    }
2092
2093
    /**
2094
     * IMLOG2.
2095
     *
2096
     * Returns the base-2 logarithm of a complex number in x + yi or x + yj text format.
2097
     *
2098
     * Excel Function:
2099
     *        IMLOG2(complexNumber)
2100
     *
2101
     * @param string $complexNumber the complex number for which you want the base-2 logarithm
2102
     *
2103
     * @return string
2104
     */
2105 27 View Code Duplication
    public static function IMLOG2($complexNumber)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
2106
    {
2107 27
        $complexNumber = Functions::flattenSingleValue($complexNumber);
2108
2109 27
        $parsedComplex = self::parseComplex($complexNumber);
2110
2111 27
        if (($parsedComplex['real'] == 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
2112 1
            return Functions::NAN();
2113 26
        } elseif (($parsedComplex['real'] > 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
2114 2
            return log($parsedComplex['real'], 2);
2115
        }
2116
2117 24
        return self::IMPRODUCT(log(self::EULER, 2), self::IMLN($complexNumber));
2118
    }
2119
2120
    /**
2121
     * IMEXP.
2122
     *
2123
     * Returns the exponential of a complex number in x + yi or x + yj text format.
2124
     *
2125
     * Excel Function:
2126
     *        IMEXP(complexNumber)
2127
     *
2128
     * @param string $complexNumber the complex number for which you want the exponential
2129
     *
2130
     * @return string
2131
     */
2132 27
    public static function IMEXP($complexNumber)
2133
    {
2134 27
        $complexNumber = Functions::flattenSingleValue($complexNumber);
2135
2136 27
        $parsedComplex = self::parseComplex($complexNumber);
2137
2138 27
        if (($parsedComplex['real'] == 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
2139 1
            return '1';
2140
        }
2141
2142 26
        $e = exp($parsedComplex['real']);
2143 26
        $eX = $e * cos($parsedComplex['imaginary']);
2144 26
        $eY = $e * sin($parsedComplex['imaginary']);
2145
2146 26
        if ($parsedComplex['suffix'] == '') {
2147 4
            return self::COMPLEX($eX, $eY);
2148
        }
2149
2150 22
        return self::COMPLEX($eX, $eY, $parsedComplex['suffix']);
2151
    }
2152
2153
    /**
2154
     * IMPOWER.
2155
     *
2156
     * Returns a complex number in x + yi or x + yj text format raised to a power.
2157
     *
2158
     * Excel Function:
2159
     *        IMPOWER(complexNumber,realNumber)
2160
     *
2161
     * @param string $complexNumber the complex number you want to raise to a power
2162
     * @param float $realNumber the power to which you want to raise the complex number
2163
     *
2164
     * @return string
2165
     */
2166
    public static function IMPOWER($complexNumber, $realNumber)
2167
    {
2168
        $complexNumber = Functions::flattenSingleValue($complexNumber);
2169
        $realNumber = Functions::flattenSingleValue($realNumber);
2170
2171
        if (!is_numeric($realNumber)) {
2172
            return Functions::VALUE();
2173
        }
2174
2175
        $parsedComplex = self::parseComplex($complexNumber);
2176
2177
        $r = sqrt(($parsedComplex['real'] * $parsedComplex['real']) + ($parsedComplex['imaginary'] * $parsedComplex['imaginary']));
2178
        $rPower = pow($r, $realNumber);
2179
        $theta = self::IMARGUMENT($complexNumber) * $realNumber;
2180
        if ($theta == 0) {
2181
            return 1;
2182
        } elseif ($parsedComplex['imaginary'] == 0.0) {
2183
            return self::COMPLEX($rPower * cos($theta), $rPower * sin($theta), $parsedComplex['suffix']);
2184
        }
2185
2186
        return self::COMPLEX($rPower * cos($theta), $rPower * sin($theta), $parsedComplex['suffix']);
2187
    }
2188
2189
    /**
2190
     * IMDIV.
2191
     *
2192
     * Returns the quotient of two complex numbers in x + yi or x + yj text format.
2193
     *
2194
     * Excel Function:
2195
     *        IMDIV(complexDividend,complexDivisor)
2196
     *
2197
     * @param string $complexDividend the complex numerator or dividend
2198
     * @param string $complexDivisor the complex denominator or divisor
2199
     *
2200
     * @return string
2201
     */
2202
    public static function IMDIV($complexDividend, $complexDivisor)
2203
    {
2204
        $complexDividend = Functions::flattenSingleValue($complexDividend);
2205
        $complexDivisor = Functions::flattenSingleValue($complexDivisor);
2206
2207
        $parsedComplexDividend = self::parseComplex($complexDividend);
2208
        $parsedComplexDivisor = self::parseComplex($complexDivisor);
2209
2210
        if (($parsedComplexDividend['suffix'] != '') && ($parsedComplexDivisor['suffix'] != '') &&
2211
            ($parsedComplexDividend['suffix'] != $parsedComplexDivisor['suffix'])
2212
        ) {
2213
            return Functions::NAN();
2214
        }
2215
        if (($parsedComplexDividend['suffix'] != '') && ($parsedComplexDivisor['suffix'] == '')) {
2216
            $parsedComplexDivisor['suffix'] = $parsedComplexDividend['suffix'];
2217
        }
2218
2219
        $d1 = ($parsedComplexDividend['real'] * $parsedComplexDivisor['real']) + ($parsedComplexDividend['imaginary'] * $parsedComplexDivisor['imaginary']);
2220
        $d2 = ($parsedComplexDividend['imaginary'] * $parsedComplexDivisor['real']) - ($parsedComplexDividend['real'] * $parsedComplexDivisor['imaginary']);
2221
        $d3 = ($parsedComplexDivisor['real'] * $parsedComplexDivisor['real']) + ($parsedComplexDivisor['imaginary'] * $parsedComplexDivisor['imaginary']);
2222
2223
        $r = $d1 / $d3;
2224
        $i = $d2 / $d3;
2225
2226
        if ($i > 0.0) {
2227
            return self::cleanComplex($r . '+' . $i . $parsedComplexDivisor['suffix']);
2228
        } elseif ($i < 0.0) {
2229
            return self::cleanComplex($r . $i . $parsedComplexDivisor['suffix']);
2230
        }
2231
2232
        return $r;
2233
    }
2234
2235
    /**
2236
     * IMSUB.
2237
     *
2238
     * Returns the difference of two complex numbers in x + yi or x + yj text format.
2239
     *
2240
     * Excel Function:
2241
     *        IMSUB(complexNumber1,complexNumber2)
2242
     *
2243
     * @param string $complexNumber1 the complex number from which to subtract complexNumber2
2244
     * @param string $complexNumber2 the complex number to subtract from complexNumber1
2245
     *
2246
     * @return string
2247
     */
2248
    public static function IMSUB($complexNumber1, $complexNumber2)
2249
    {
2250
        $complexNumber1 = Functions::flattenSingleValue($complexNumber1);
2251
        $complexNumber2 = Functions::flattenSingleValue($complexNumber2);
2252
2253
        $parsedComplex1 = self::parseComplex($complexNumber1);
2254
        $parsedComplex2 = self::parseComplex($complexNumber2);
2255
2256
        if ((($parsedComplex1['suffix'] != '') && ($parsedComplex2['suffix'] != '')) &&
2257
            ($parsedComplex1['suffix'] != $parsedComplex2['suffix'])
2258
        ) {
2259
            return Functions::NAN();
2260
        } elseif (($parsedComplex1['suffix'] == '') && ($parsedComplex2['suffix'] != '')) {
2261
            $parsedComplex1['suffix'] = $parsedComplex2['suffix'];
2262
        }
2263
2264
        $d1 = $parsedComplex1['real'] - $parsedComplex2['real'];
2265
        $d2 = $parsedComplex1['imaginary'] - $parsedComplex2['imaginary'];
2266
2267
        return self::COMPLEX($d1, $d2, $parsedComplex1['suffix']);
2268
    }
2269
2270
    /**
2271
     * IMSUM.
2272
     *
2273
     * Returns the sum of two or more complex numbers in x + yi or x + yj text format.
2274
     *
2275
     * Excel Function:
2276
     *        IMSUM(complexNumber[,complexNumber[,...]])
2277
     *
2278
     * @param string ...$complexNumbers Series of complex numbers to add
2279
     *
2280
     * @return string
2281
     */
2282 10
    public static function IMSUM(...$complexNumbers)
2283
    {
2284
        // Return value
2285 10
        $returnValue = self::parseComplex('0');
2286 10
        $activeSuffix = '';
2287
2288
        // Loop through the arguments
2289 10
        $aArgs = Functions::flattenArray($complexNumbers);
2290 10
        foreach ($aArgs as $arg) {
2291 10
            $parsedComplex = self::parseComplex($arg);
2292
2293 10 View Code Duplication
            if ($activeSuffix == '') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
2294 10
                $activeSuffix = $parsedComplex['suffix'];
2295 10
            } elseif (($parsedComplex['suffix'] != '') && ($activeSuffix != $parsedComplex['suffix'])) {
2296 2
                return Functions::NAN();
2297
            }
2298
2299 10
            $returnValue['real'] += $parsedComplex['real'];
2300 10
            $returnValue['imaginary'] += $parsedComplex['imaginary'];
2301
        }
2302
2303 8
        if ($returnValue['imaginary'] == 0.0) {
2304
            $activeSuffix = '';
2305
        }
2306
2307 8
        return self::COMPLEX($returnValue['real'], $returnValue['imaginary'], $activeSuffix);
2308
    }
2309
2310
    /**
2311
     * IMPRODUCT.
2312
     *
2313
     * Returns the product of two or more complex numbers in x + yi or x + yj text format.
2314
     *
2315
     * Excel Function:
2316
     *        IMPRODUCT(complexNumber[,complexNumber[,...]])
2317
     *
2318
     * @param string ...$complexNumbers Series of complex numbers to multiply
2319
     *
2320
     * @return string
2321
     */
2322 63
    public static function IMPRODUCT(...$complexNumbers)
2323
    {
2324
        // Return value
2325 63
        $returnValue = self::parseComplex('1');
2326 63
        $activeSuffix = '';
2327
2328
        // Loop through the arguments
2329 63
        $aArgs = Functions::flattenArray($complexNumbers);
2330 63
        foreach ($aArgs as $arg) {
2331 63
            $parsedComplex = self::parseComplex($arg);
2332
2333 63
            $workValue = $returnValue;
2334 63 View Code Duplication
            if (($parsedComplex['suffix'] != '') && ($activeSuffix == '')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
2335 63
                $activeSuffix = $parsedComplex['suffix'];
2336 62
            } elseif (($parsedComplex['suffix'] != '') && ($activeSuffix != $parsedComplex['suffix'])) {
2337 1
                return Functions::NAN();
2338
            }
2339 63
            $returnValue['real'] = ($workValue['real'] * $parsedComplex['real']) - ($workValue['imaginary'] * $parsedComplex['imaginary']);
2340 63
            $returnValue['imaginary'] = ($workValue['real'] * $parsedComplex['imaginary']) + ($workValue['imaginary'] * $parsedComplex['real']);
2341
        }
2342
2343 62
        if ($returnValue['imaginary'] == 0.0) {
2344
            $activeSuffix = '';
2345
        }
2346
2347 62
        return self::COMPLEX($returnValue['real'], $returnValue['imaginary'], $activeSuffix);
2348
    }
2349
2350
    /**
2351
     * DELTA.
2352
     *
2353
     * Tests whether two values are equal. Returns 1 if number1 = number2; returns 0 otherwise.
2354
     *    Use this function to filter a set of values. For example, by summing several DELTA
2355
     *    functions you calculate the count of equal pairs. This function is also known as the
2356
     * Kronecker Delta function.
2357
     *
2358
     *    Excel Function:
2359
     *        DELTA(a[,b])
2360
     *
2361
     * @param float $a the first number
2362
     * @param float $b The second number. If omitted, b is assumed to be zero.
2363
     *
2364
     * @return int
2365
     */
2366 25
    public static function DELTA($a, $b = 0)
2367
    {
2368 25
        $a = Functions::flattenSingleValue($a);
2369 25
        $b = Functions::flattenSingleValue($b);
2370
2371 25
        return (int) ($a == $b);
2372
    }
2373
2374
    /**
2375
     * GESTEP.
2376
     *
2377
     *    Excel Function:
2378
     *        GESTEP(number[,step])
2379
     *
2380
     *    Returns 1 if number >= step; returns 0 (zero) otherwise
2381
     *    Use this function to filter a set of values. For example, by summing several GESTEP
2382
     * functions you calculate the count of values that exceed a threshold.
2383
     *
2384
     * @param float $number the value to test against step
2385
     * @param float $step The threshold value.
2386
     *                                    If you omit a value for step, GESTEP uses zero.
2387
     *
2388
     * @return int
2389
     */
2390 81
    public static function GESTEP($number, $step = 0)
2391
    {
2392 81
        $number = Functions::flattenSingleValue($number);
2393 81
        $step = Functions::flattenSingleValue($step);
2394
2395 81
        return (int) ($number >= $step);
2396
    }
2397
2398
    //
2399
    //    Private method to calculate the erf value
2400
    //
2401
    private static $twoSqrtPi = 1.128379167095512574;
2402
2403 148
    public static function erfVal($x)
2404
    {
2405 148
        if (abs($x) > 2.2) {
2406 67
            return 1 - self::erfcVal($x);
2407
        }
2408 123
        $sum = $term = $x;
2409 123
        $xsqr = ($x * $x);
2410 123
        $j = 1;
2411
        do {
2412 123
            $term *= $xsqr / $j;
2413 123
            $sum -= $term / (2 * $j + 1);
2414 123
            ++$j;
2415 123
            $term *= $xsqr / $j;
2416 123
            $sum += $term / (2 * $j + 1);
2417 123
            ++$j;
2418 123
            if ($sum == 0.0) {
2419 19
                break;
2420
            }
2421 112
        } while (abs($term / $sum) > Functions::PRECISION);
2422
2423 123
        return self::$twoSqrtPi * $sum;
2424
    }
2425
2426
    /**
2427
     * ERF.
2428
     *
2429
     * Returns the error function integrated between the lower and upper bound arguments.
2430
     *
2431
     *    Note: In Excel 2007 or earlier, if you input a negative value for the upper or lower bound arguments,
2432
     *            the function would return a #NUM! error. However, in Excel 2010, the function algorithm was
2433
     *            improved, so that it can now calculate the function for both positive and negative ranges.
2434
     *            PhpSpreadsheet follows Excel 2010 behaviour, and accepts nagative arguments.
2435
     *
2436
     *    Excel Function:
2437
     *        ERF(lower[,upper])
2438
     *
2439
     * @param float $lower lower bound for integrating ERF
2440
     * @param float $upper upper bound for integrating ERF.
2441
     *                                If omitted, ERF integrates between zero and lower_limit
2442
     *
2443
     * @return float
2444
     */
2445 123
    public static function ERF($lower, $upper = null)
2446
    {
2447 123
        $lower = Functions::flattenSingleValue($lower);
2448 123
        $upper = Functions::flattenSingleValue($upper);
2449
2450 123
        if (is_numeric($lower)) {
2451 120
            if ($upper === null) {
2452 37
                return self::erfVal($lower);
2453
            }
2454 83
            if (is_numeric($upper)) {
2455 83
                return self::erfVal($upper) - self::erfVal($lower);
2456
            }
2457
        }
2458
2459 3
        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...
2460
    }
2461
2462
    //
2463
    //    Private method to calculate the erfc value
2464
    //
2465
    private static $oneSqrtPi = 0.564189583547756287;
2466
2467 104
    private static function erfcVal($x)
2468
    {
2469 104
        if (abs($x) < 2.2) {
2470 28
            return 1 - self::erfVal($x);
2471
        }
2472 76
        if ($x < 0) {
2473 1
            return 2 - self::ERFC(-$x);
2474
        }
2475 76
        $a = $n = 1;
2476 76
        $b = $c = $x;
2477 76
        $d = ($x * $x) + 0.5;
2478 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...
2479 76
        $t = 0;
0 ignored issues
show
Unused Code introduced by
The assignment to $t is dead and can be removed.
Loading history...
2480
        do {
2481 76
            $t = $a * $n + $b * $x;
2482 76
            $a = $b;
2483 76
            $b = $t;
2484 76
            $t = $c * $n + $d * $x;
2485 76
            $c = $d;
2486 76
            $d = $t;
2487 76
            $n += 0.5;
2488 76
            $q1 = $q2;
2489 76
            $q2 = $b / $d;
2490 76
        } while ((abs($q1 - $q2) / $q2) > Functions::PRECISION);
2491
2492 76
        return self::$oneSqrtPi * exp(-$x * $x) * $q2;
2493
    }
2494
2495
    /**
2496
     * ERFC.
2497
     *
2498
     *    Returns the complementary ERF function integrated between x and infinity
2499
     *
2500
     *    Note: In Excel 2007 or earlier, if you input a negative value for the lower bound argument,
2501
     *        the function would return a #NUM! error. However, in Excel 2010, the function algorithm was
2502
     *        improved, so that it can now calculate the function for both positive and negative x values.
2503
     *            PhpSpreadsheet follows Excel 2010 behaviour, and accepts nagative arguments.
2504
     *
2505
     *    Excel Function:
2506
     *        ERFC(x)
2507
     *
2508
     * @param float $x The lower bound for integrating ERFC
2509
     *
2510
     * @return float
2511
     */
2512 41
    public static function ERFC($x)
2513
    {
2514 41
        $x = Functions::flattenSingleValue($x);
2515
2516 41
        if (is_numeric($x)) {
2517 38
            return self::erfcVal($x);
2518
        }
2519
2520 3
        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...
2521
    }
2522
2523
    /**
2524
     *    getConversionGroups
2525
     * Returns a list of the different conversion groups for UOM conversions.
2526
     *
2527
     * @return array
2528
     */
2529 1
    public static function getConversionGroups()
2530
    {
2531 1
        $conversionGroups = [];
2532 1
        foreach (self::$conversionUnits as $conversionUnit) {
2533 1
            $conversionGroups[] = $conversionUnit['Group'];
2534
        }
2535
2536 1
        return array_merge(array_unique($conversionGroups));
2537
    }
2538
2539
    /**
2540
     *    getConversionGroupUnits
2541
     * Returns an array of units of measure, for a specified conversion group, or for all groups.
2542
     *
2543
     * @param string $group The group whose units of measure you want to retrieve
2544
     *
2545
     * @return array
2546
     */
2547 1
    public static function getConversionGroupUnits($group = null)
2548
    {
2549 1
        $conversionGroups = [];
2550 1
        foreach (self::$conversionUnits as $conversionUnit => $conversionGroup) {
2551 1
            if (($group === null) || ($conversionGroup['Group'] == $group)) {
2552 1
                $conversionGroups[$conversionGroup['Group']][] = $conversionUnit;
2553
            }
2554
        }
2555
2556 1
        return $conversionGroups;
2557
    }
2558
2559
    /**
2560
     * getConversionGroupUnitDetails.
2561
     *
2562
     * @param string $group The group whose units of measure you want to retrieve
2563
     *
2564
     * @return array
2565
     */
2566 1
    public static function getConversionGroupUnitDetails($group = null)
2567
    {
2568 1
        $conversionGroups = [];
2569 1
        foreach (self::$conversionUnits as $conversionUnit => $conversionGroup) {
2570 1
            if (($group === null) || ($conversionGroup['Group'] == $group)) {
2571 1
                $conversionGroups[$conversionGroup['Group']][] = [
2572 1
                    'unit' => $conversionUnit,
2573 1
                    'description' => $conversionGroup['Unit Name'],
2574
                ];
2575
            }
2576
        }
2577
2578 1
        return $conversionGroups;
2579
    }
2580
2581
    /**
2582
     *    getConversionMultipliers
2583
     * Returns an array of the Multiplier prefixes that can be used with Units of Measure in CONVERTUOM().
2584
     *
2585
     * @return array of mixed
2586
     */
2587 1
    public static function getConversionMultipliers()
2588
    {
2589 1
        return self::$conversionMultipliers;
2590
    }
2591
2592
    /**
2593
     * CONVERTUOM.
2594
     *
2595
     * Converts a number from one measurement system to another.
2596
     *    For example, CONVERT can translate a table of distances in miles to a table of distances
2597
     * in kilometers.
2598
     *
2599
     *    Excel Function:
2600
     *        CONVERT(value,fromUOM,toUOM)
2601
     *
2602
     * @param float $value the value in fromUOM to convert
2603
     * @param string $fromUOM the units for value
2604
     * @param string $toUOM the units for the result
2605
     *
2606
     * @return float
2607
     */
2608 24
    public static function CONVERTUOM($value, $fromUOM, $toUOM)
2609
    {
2610 24
        $value = Functions::flattenSingleValue($value);
2611 24
        $fromUOM = Functions::flattenSingleValue($fromUOM);
2612 24
        $toUOM = Functions::flattenSingleValue($toUOM);
2613
2614 24
        if (!is_numeric($value)) {
2615 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...
2616
        }
2617 23
        $fromMultiplier = 1.0;
2618 23 View Code Duplication
        if (isset(self::$conversionUnits[$fromUOM])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
2619 16
            $unitGroup1 = self::$conversionUnits[$fromUOM]['Group'];
2620
        } else {
2621 7
            $fromMultiplier = substr($fromUOM, 0, 1);
2622 7
            $fromUOM = substr($fromUOM, 1);
2623 7
            if (isset(self::$conversionMultipliers[$fromMultiplier])) {
2624 6
                $fromMultiplier = self::$conversionMultipliers[$fromMultiplier]['multiplier'];
2625
            } else {
2626 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...
2627
            }
2628 6
            if ((isset(self::$conversionUnits[$fromUOM])) && (self::$conversionUnits[$fromUOM]['AllowPrefix'])) {
2629 5
                $unitGroup1 = self::$conversionUnits[$fromUOM]['Group'];
2630
            } else {
2631 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...
2632
            }
2633
        }
2634 21
        $value *= $fromMultiplier;
2635
2636 21
        $toMultiplier = 1.0;
2637 21 View Code Duplication
        if (isset(self::$conversionUnits[$toUOM])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
2638 14
            $unitGroup2 = self::$conversionUnits[$toUOM]['Group'];
2639
        } else {
2640 7
            $toMultiplier = substr($toUOM, 0, 1);
2641 7
            $toUOM = substr($toUOM, 1);
2642 7
            if (isset(self::$conversionMultipliers[$toMultiplier])) {
2643 6
                $toMultiplier = self::$conversionMultipliers[$toMultiplier]['multiplier'];
2644
            } else {
2645 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...
2646
            }
2647 6
            if ((isset(self::$conversionUnits[$toUOM])) && (self::$conversionUnits[$toUOM]['AllowPrefix'])) {
2648 5
                $unitGroup2 = self::$conversionUnits[$toUOM]['Group'];
2649
            } else {
2650 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...
2651
            }
2652
        }
2653 19
        if ($unitGroup1 != $unitGroup2) {
2654 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...
2655
        }
2656
2657 17
        if (($fromUOM == $toUOM) && ($fromMultiplier == $toMultiplier)) {
2658
            //    We've already factored $fromMultiplier into the value, so we need
2659
            //        to reverse it again
2660 3
            return $value / $fromMultiplier;
2661 14
        } elseif ($unitGroup1 == 'Temperature') {
2662 9
            if (($fromUOM == 'F') || ($fromUOM == 'fah')) {
2663 3
                if (($toUOM == 'F') || ($toUOM == 'fah')) {
2664 1
                    return $value;
2665
                }
2666 2
                $value = (($value - 32) / 1.8);
2667 2
                if (($toUOM == 'K') || ($toUOM == 'kel')) {
2668 1
                    $value += 273.15;
2669
                }
2670
2671 2
                return $value;
2672 6
            } elseif ((($fromUOM == 'K') || ($fromUOM == 'kel')) &&
2673 6
                (($toUOM == 'K') || ($toUOM == 'kel'))
2674
            ) {
2675 1
                return $value;
2676 5
            } elseif ((($fromUOM == 'C') || ($fromUOM == 'cel')) &&
2677 5
                (($toUOM == 'C') || ($toUOM == 'cel'))
2678
            ) {
2679 1
                return $value;
2680
            }
2681 4
            if (($toUOM == 'F') || ($toUOM == 'fah')) {
2682 2
                if (($fromUOM == 'K') || ($fromUOM == 'kel')) {
2683 1
                    $value -= 273.15;
2684
                }
2685
2686 2
                return ($value * 1.8) + 32;
2687
            }
2688 2
            if (($toUOM == 'C') || ($toUOM == 'cel')) {
2689 1
                return $value - 273.15;
2690
            }
2691
2692 1
            return $value + 273.15;
2693
        }
2694
2695 5
        return ($value * self::$unitConversions[$unitGroup1][$fromUOM][$toUOM]) / $toMultiplier;
2696
    }
2697
}
2698