Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403]
1 <?php 2 3 namespace PhpOffice\PhpSpreadsheet\Calculation; 4 5 use Complex\Complex; 6 use Complex\Exception as ComplexException; 7 8 class Engineering 9 { 10 /** 11 * EULER. 12 */ 13 const EULER = 2.71828182845904523536; 14 15 /** 16 * Details of the Units of measure that can be used in CONVERTUOM(). 17 * 18 * @var mixed[] 19 */ 20 private static $conversionUnits = [ 21 'g' => ['Group' => 'Mass', 'Unit Name' => 'Gram', 'AllowPrefix' => true], 22 'sg' => ['Group' => 'Mass', 'Unit Name' => 'Slug', 'AllowPrefix' => false], 23 'lbm' => ['Group' => 'Mass', 'Unit Name' => 'Pound mass (avoirdupois)', 'AllowPrefix' => false], 24 'u' => ['Group' => 'Mass', 'Unit Name' => 'U (atomic mass unit)', 'AllowPrefix' => true], 25 'ozm' => ['Group' => 'Mass', 'Unit Name' => 'Ounce mass (avoirdupois)', 'AllowPrefix' => false], 26 'm' => ['Group' => 'Distance', 'Unit Name' => 'Meter', 'AllowPrefix' => true], 27 'mi' => ['Group' => 'Distance', 'Unit Name' => 'Statute mile', 'AllowPrefix' => false], 28 'Nmi' => ['Group' => 'Distance', 'Unit Name' => 'Nautical mile', 'AllowPrefix' => false], 29 'in' => ['Group' => 'Distance', 'Unit Name' => 'Inch', 'AllowPrefix' => false], 30 'ft' => ['Group' => 'Distance', 'Unit Name' => 'Foot', 'AllowPrefix' => false], 31 'yd' => ['Group' => 'Distance', 'Unit Name' => 'Yard', 'AllowPrefix' => false], 32 'ang' => ['Group' => 'Distance', 'Unit Name' => 'Angstrom', 'AllowPrefix' => true], 33 'Pica' => ['Group' => 'Distance', 'Unit Name' => 'Pica (1/72 in)', 'AllowPrefix' => false], 34 'yr' => ['Group' => 'Time', 'Unit Name' => 'Year', 'AllowPrefix' => false], 35 'day' => ['Group' => 'Time', 'Unit Name' => 'Day', 'AllowPrefix' => false], 36 'hr' => ['Group' => 'Time', 'Unit Name' => 'Hour', 'AllowPrefix' => false], 37 'mn' => ['Group' => 'Time', 'Unit Name' => 'Minute', 'AllowPrefix' => false], 38 'sec' => ['Group' => 'Time', 'Unit Name' => 'Second', 'AllowPrefix' => true], 39 'Pa' => ['Group' => 'Pressure', 'Unit Name' => 'Pascal', 'AllowPrefix' => true], 40 'p' => ['Group' => 'Pressure', 'Unit Name' => 'Pascal', 'AllowPrefix' => true], 41 'atm' => ['Group' => 'Pressure', 'Unit Name' => 'Atmosphere', 'AllowPrefix' => true], 42 'at' => ['Group' => 'Pressure', 'Unit Name' => 'Atmosphere', 'AllowPrefix' => true], 43 'mmHg' => ['Group' => 'Pressure', 'Unit Name' => 'mm of Mercury', 'AllowPrefix' => true], 44 'N' => ['Group' => 'Force', 'Unit Name' => 'Newton', 'AllowPrefix' => true], 45 'dyn' => ['Group' => 'Force', 'Unit Name' => 'Dyne', 'AllowPrefix' => true], 46 'dy' => ['Group' => 'Force', 'Unit Name' => 'Dyne', 'AllowPrefix' => true], 47 'lbf' => ['Group' => 'Force', 'Unit Name' => 'Pound force', 'AllowPrefix' => false], 48 'J' => ['Group' => 'Energy', 'Unit Name' => 'Joule', 'AllowPrefix' => true], 49 'e' => ['Group' => 'Energy', 'Unit Name' => 'Erg', 'AllowPrefix' => true], 50 'c' => ['Group' => 'Energy', 'Unit Name' => 'Thermodynamic calorie', 'AllowPrefix' => true], 51 'cal' => ['Group' => 'Energy', 'Unit Name' => 'IT calorie', 'AllowPrefix' => true], 52 'eV' => ['Group' => 'Energy', 'Unit Name' => 'Electron volt', 'AllowPrefix' => true], 53 'ev' => ['Group' => 'Energy', 'Unit Name' => 'Electron volt', 'AllowPrefix' => true], 54 'HPh' => ['Group' => 'Energy', 'Unit Name' => 'Horsepower-hour', 'AllowPrefix' => false], 55 'hh' => ['Group' => 'Energy', 'Unit Name' => 'Horsepower-hour', 'AllowPrefix' => false], 56 'Wh' => ['Group' => 'Energy', 'Unit Name' => 'Watt-hour', 'AllowPrefix' => true], 57 'wh' => ['Group' => 'Energy', 'Unit Name' => 'Watt-hour', 'AllowPrefix' => true], 58 'flb' => ['Group' => 'Energy', 'Unit Name' => 'Foot-pound', 'AllowPrefix' => false], 59 'BTU' => ['Group' => 'Energy', 'Unit Name' => 'BTU', 'AllowPrefix' => false], 60 'btu' => ['Group' => 'Energy', 'Unit Name' => 'BTU', 'AllowPrefix' => false], 61 'HP' => ['Group' => 'Power', 'Unit Name' => 'Horsepower', 'AllowPrefix' => false], 62 'h' => ['Group' => 'Power', 'Unit Name' => 'Horsepower', 'AllowPrefix' => false], 63 'W' => ['Group' => 'Power', 'Unit Name' => 'Watt', 'AllowPrefix' => true], 64 'w' => ['Group' => 'Power', 'Unit Name' => 'Watt', 'AllowPrefix' => true], 65 'T' => ['Group' => 'Magnetism', 'Unit Name' => 'Tesla', 'AllowPrefix' => true], 66 'ga' => ['Group' => 'Magnetism', 'Unit Name' => 'Gauss', 'AllowPrefix' => true], 67 'C' => ['Group' => 'Temperature', 'Unit Name' => 'Celsius', 'AllowPrefix' => false], 68 'cel' => ['Group' => 'Temperature', 'Unit Name' => 'Celsius', 'AllowPrefix' => false], 69 'F' => ['Group' => 'Temperature', 'Unit Name' => 'Fahrenheit', 'AllowPrefix' => false], 70 'fah' => ['Group' => 'Temperature', 'Unit Name' => 'Fahrenheit', 'AllowPrefix' => false], 71 'K' => ['Group' => 'Temperature', 'Unit Name' => 'Kelvin', 'AllowPrefix' => false], 72 'kel' => ['Group' => 'Temperature', 'Unit Name' => 'Kelvin', 'AllowPrefix' => false], 73 'tsp' => ['Group' => 'Liquid', 'Unit Name' => 'Teaspoon', 'AllowPrefix' => false], 74 'tbs' => ['Group' => 'Liquid', 'Unit Name' => 'Tablespoon', 'AllowPrefix' => false], 75 'oz' => ['Group' => 'Liquid', 'Unit Name' => 'Fluid Ounce', 'AllowPrefix' => false], 76 'cup' => ['Group' => 'Liquid', 'Unit Name' => 'Cup', 'AllowPrefix' => false], 77 'pt' => ['Group' => 'Liquid', 'Unit Name' => 'U.S. Pint', 'AllowPrefix' => false], 78 'us_pt' => ['Group' => 'Liquid', 'Unit Name' => 'U.S. Pint', 'AllowPrefix' => false], 79 'uk_pt' => ['Group' => 'Liquid', 'Unit Name' => 'U.K. Pint', 'AllowPrefix' => false], 80 'qt' => ['Group' => 'Liquid', 'Unit Name' => 'Quart', 'AllowPrefix' => false], 81 'gal' => ['Group' => 'Liquid', 'Unit Name' => 'Gallon', 'AllowPrefix' => false], 82 'l' => ['Group' => 'Liquid', 'Unit Name' => 'Litre', 'AllowPrefix' => true], 83 'lt' => ['Group' => 'Liquid', 'Unit Name' => 'Litre', 'AllowPrefix' => true], 84 ]; 85 86 /** 87 * Details of the Multiplier prefixes that can be used with Units of Measure in CONVERTUOM(). 88 * 89 * @var mixed[] 90 */ 91 private static $conversionMultipliers = [ 92 'Y' => ['multiplier' => 1E24, 'name' => 'yotta'], 93 'Z' => ['multiplier' => 1E21, 'name' => 'zetta'], 94 'E' => ['multiplier' => 1E18, 'name' => 'exa'], 95 'P' => ['multiplier' => 1E15, 'name' => 'peta'], 96 'T' => ['multiplier' => 1E12, 'name' => 'tera'], 97 'G' => ['multiplier' => 1E9, 'name' => 'giga'], 98 'M' => ['multiplier' => 1E6, 'name' => 'mega'], 99 'k' => ['multiplier' => 1E3, 'name' => 'kilo'], 100 'h' => ['multiplier' => 1E2, 'name' => 'hecto'], 101 'e' => ['multiplier' => 1E1, 'name' => 'deka'], 102 'd' => ['multiplier' => 1E-1, 'name' => 'deci'], 103 'c' => ['multiplier' => 1E-2, 'name' => 'centi'], 104 'm' => ['multiplier' => 1E-3, 'name' => 'milli'], 105 'u' => ['multiplier' => 1E-6, 'name' => 'micro'], 106 'n' => ['multiplier' => 1E-9, 'name' => 'nano'], 107 'p' => ['multiplier' => 1E-12, 'name' => 'pico'], 108 'f' => ['multiplier' => 1E-15, 'name' => 'femto'], 109 'a' => ['multiplier' => 1E-18, 'name' => 'atto'], 110 'z' => ['multiplier' => 1E-21, 'name' => 'zepto'], 111 'y' => ['multiplier' => 1E-24, 'name' => 'yocto'], 112 ]; 113 114 /** 115 * Details of the Units of measure conversion factors, organised by group. 116 * 117 * @var mixed[] 118 */ 119 private static $unitConversions = [ 120 'Mass' => [ 121 'g' => [ 122 'g' => 1.0, 123 'sg' => 6.85220500053478E-05, 124 'lbm' => 2.20462291469134E-03, 125 'u' => 6.02217000000000E+23, 126 'ozm' => 3.52739718003627E-02, 127 ], 128 'sg' => [ 129 'g' => 1.45938424189287E+04, 130 'sg' => 1.0, 131 'lbm' => 3.21739194101647E+01, 132 'u' => 8.78866000000000E+27, 133 'ozm' => 5.14782785944229E+02, 134 ], 135 'lbm' => [ 136 'g' => 4.5359230974881148E+02, 137 'sg' => 3.10810749306493E-02, 138 'lbm' => 1.0, 139 'u' => 2.73161000000000E+26, 140 'ozm' => 1.60000023429410E+01, 141 ], 142 'u' => [ 143 'g' => 1.66053100460465E-24, 144 'sg' => 1.13782988532950E-28, 145 'lbm' => 3.66084470330684E-27, 146 'u' => 1.0, 147 'ozm' => 5.85735238300524E-26, 148 ], 149 'ozm' => [ 150 'g' => 2.83495152079732E+01, 151 'sg' => 1.94256689870811E-03, 152 'lbm' => 6.24999908478882E-02, 153 'u' => 1.70725600000000E+25, 154 'ozm' => 1.0, 155 ], 156 ], 157 'Distance' => [ 158 'm' => [ 159 'm' => 1.0, 160 'mi' => 6.21371192237334E-04, 161 'Nmi' => 5.39956803455724E-04, 162 'in' => 3.93700787401575E+01, 163 'ft' => 3.28083989501312E+00, 164 'yd' => 1.09361329797891E+00, 165 'ang' => 1.00000000000000E+10, 166 'Pica' => 2.83464566929116E+03, 167 ], 168 'mi' => [ 169 'm' => 1.60934400000000E+03, 170 'mi' => 1.0, 171 'Nmi' => 8.68976241900648E-01, 172 'in' => 6.33600000000000E+04, 173 'ft' => 5.28000000000000E+03, 174 'yd' => 1.76000000000000E+03, 175 'ang' => 1.60934400000000E+13, 176 'Pica' => 4.56191999999971E+06, 177 ], 178 'Nmi' => [ 179 'm' => 1.85200000000000E+03, 180 'mi' => 1.15077944802354E+00, 181 'Nmi' => 1.0, 182 'in' => 7.29133858267717E+04, 183 'ft' => 6.07611548556430E+03, 184 'yd' => 2.02537182785694E+03, 185 'ang' => 1.85200000000000E+13, 186 'Pica' => 5.24976377952723E+06, 187 ], 188 'in' => [ 189 'm' => 2.54000000000000E-02, 190 'mi' => 1.57828282828283E-05, 191 'Nmi' => 1.37149028077754E-05, 192 'in' => 1.0, 193 'ft' => 8.33333333333333E-02, 194 'yd' => 2.77777777686643E-02, 195 'ang' => 2.54000000000000E+08, 196 'Pica' => 7.19999999999955E+01, 197 ], 198 'ft' => [ 199 'm' => 3.04800000000000E-01, 200 'mi' => 1.89393939393939E-04, 201 'Nmi' => 1.64578833693305E-04, 202 'in' => 1.20000000000000E+01, 203 'ft' => 1.0, 204 'yd' => 3.33333333223972E-01, 205 'ang' => 3.04800000000000E+09, 206 'Pica' => 8.63999999999946E+02, 207 ], 208 'yd' => [ 209 'm' => 9.14400000300000E-01, 210 'mi' => 5.68181818368230E-04, 211 'Nmi' => 4.93736501241901E-04, 212 'in' => 3.60000000118110E+01, 213 'ft' => 3.00000000000000E+00, 214 'yd' => 1.0, 215 'ang' => 9.14400000300000E+09, 216 'Pica' => 2.59200000085023E+03, 217 ], 218 'ang' => [ 219 'm' => 1.00000000000000E-10, 220 'mi' => 6.21371192237334E-14, 221 'Nmi' => 5.39956803455724E-14, 222 'in' => 3.93700787401575E-09, 223 'ft' => 3.28083989501312E-10, 224 'yd' => 1.09361329797891E-10, 225 'ang' => 1.0, 226 'Pica' => 2.83464566929116E-07, 227 ], 228 'Pica' => [ 229 'm' => 3.52777777777800E-04, 230 'mi' => 2.19205948372629E-07, 231 'Nmi' => 1.90484761219114E-07, 232 'in' => 1.38888888888898E-02, 233 'ft' => 1.15740740740748E-03, 234 'yd' => 3.85802469009251E-04, 235 'ang' => 3.52777777777800E+06, 236 'Pica' => 1.0, 237 ], 238 ], 239 'Time' => [ 240 'yr' => [ 241 'yr' => 1.0, 242 'day' => 365.25, 243 'hr' => 8766.0, 244 'mn' => 525960.0, 245 'sec' => 31557600.0, 246 ], 247 'day' => [ 248 'yr' => 2.73785078713210E-03, 249 'day' => 1.0, 250 'hr' => 24.0, 251 'mn' => 1440.0, 252 'sec' => 86400.0, 253 ], 254 'hr' => [ 255 'yr' => 1.14077116130504E-04, 256 'day' => 4.16666666666667E-02, 257 'hr' => 1.0, 258 'mn' => 60.0, 259 'sec' => 3600.0, 260 ], 261 'mn' => [ 262 'yr' => 1.90128526884174E-06, 263 'day' => 6.94444444444444E-04, 264 'hr' => 1.66666666666667E-02, 265 'mn' => 1.0, 266 'sec' => 60.0, 267 ], 268 'sec' => [ 269 'yr' => 3.16880878140289E-08, 270 'day' => 1.15740740740741E-05, 271 'hr' => 2.77777777777778E-04, 272 'mn' => 1.66666666666667E-02, 273 'sec' => 1.0, 274 ], 275 ], 276 'Pressure' => [ 277 'Pa' => [ 278 'Pa' => 1.0, 279 'p' => 1.0, 280 'atm' => 9.86923299998193E-06, 281 'at' => 9.86923299998193E-06, 282 'mmHg' => 7.50061707998627E-03, 283 ], 284 'p' => [ 285 'Pa' => 1.0, 286 'p' => 1.0, 287 'atm' => 9.86923299998193E-06, 288 'at' => 9.86923299998193E-06, 289 'mmHg' => 7.50061707998627E-03, 290 ], 291 'atm' => [ 292 'Pa' => 1.01324996583000E+05, 293 'p' => 1.01324996583000E+05, 294 'atm' => 1.0, 295 'at' => 1.0, 296 'mmHg' => 760.0, 297 ], 298 'at' => [ 299 'Pa' => 1.01324996583000E+05, 300 'p' => 1.01324996583000E+05, 301 'atm' => 1.0, 302 'at' => 1.0, 303 'mmHg' => 760.0, 304 ], 305 'mmHg' => [ 306 'Pa' => 1.33322363925000E+02, 307 'p' => 1.33322363925000E+02, 308 'atm' => 1.31578947368421E-03, 309 'at' => 1.31578947368421E-03, 310 'mmHg' => 1.0, 311 ], 312 ], 313 'Force' => [ 314 'N' => [ 315 'N' => 1.0, 316 'dyn' => 1.0E+5, 317 'dy' => 1.0E+5, 318 'lbf' => 2.24808923655339E-01, 319 ], 320 'dyn' => [ 321 'N' => 1.0E-5, 322 'dyn' => 1.0, 323 'dy' => 1.0, 324 'lbf' => 2.24808923655339E-06, 325 ], 326 'dy' => [ 327 'N' => 1.0E-5, 328 'dyn' => 1.0, 329 'dy' => 1.0, 330 'lbf' => 2.24808923655339E-06, 331 ], 332 'lbf' => [ 333 'N' => 4.448222, 334 'dyn' => 4.448222E+5, 335 'dy' => 4.448222E+5, 336 'lbf' => 1.0, 337 ], 338 ], 339 'Energy' => [ 340 'J' => [ 341 'J' => 1.0, 342 'e' => 9.99999519343231E+06, 343 'c' => 2.39006249473467E-01, 344 'cal' => 2.38846190642017E-01, 345 'eV' => 6.24145700000000E+18, 346 'ev' => 6.24145700000000E+18, 347 'HPh' => 3.72506430801000E-07, 348 'hh' => 3.72506430801000E-07, 349 'Wh' => 2.77777916238711E-04, 350 'wh' => 2.77777916238711E-04, 351 'flb' => 2.37304222192651E+01, 352 'BTU' => 9.47815067349015E-04, 353 'btu' => 9.47815067349015E-04, 354 ], 355 'e' => [ 356 'J' => 1.00000048065700E-07, 357 'e' => 1.0, 358 'c' => 2.39006364353494E-08, 359 'cal' => 2.38846305445111E-08, 360 'eV' => 6.24146000000000E+11, 361 'ev' => 6.24146000000000E+11, 362 'HPh' => 3.72506609848824E-14, 363 'hh' => 3.72506609848824E-14, 364 'Wh' => 2.77778049754611E-11, 365 'wh' => 2.77778049754611E-11, 366 'flb' => 2.37304336254586E-06, 367 'BTU' => 9.47815522922962E-11, 368 'btu' => 9.47815522922962E-11, 369 ], 370 'c' => [ 371 'J' => 4.18399101363672E+00, 372 'e' => 4.18398900257312E+07, 373 'c' => 1.0, 374 'cal' => 9.99330315287563E-01, 375 'eV' => 2.61142000000000E+19, 376 'ev' => 2.61142000000000E+19, 377 'HPh' => 1.55856355899327E-06, 378 'hh' => 1.55856355899327E-06, 379 'Wh' => 1.16222030532950E-03, 380 'wh' => 1.16222030532950E-03, 381 'flb' => 9.92878733152102E+01, 382 'BTU' => 3.96564972437776E-03, 383 'btu' => 3.96564972437776E-03, 384 ], 385 'cal' => [ 386 'J' => 4.18679484613929E+00, 387 'e' => 4.18679283372801E+07, 388 'c' => 1.00067013349059E+00, 389 'cal' => 1.0, 390 'eV' => 2.61317000000000E+19, 391 'ev' => 2.61317000000000E+19, 392 'HPh' => 1.55960800463137E-06, 393 'hh' => 1.55960800463137E-06, 394 'Wh' => 1.16299914807955E-03, 395 'wh' => 1.16299914807955E-03, 396 'flb' => 9.93544094443283E+01, 397 'BTU' => 3.96830723907002E-03, 398 'btu' => 3.96830723907002E-03, 399 ], 400 'eV' => [ 401 'J' => 1.60219000146921E-19, 402 'e' => 1.60218923136574E-12, 403 'c' => 3.82933423195043E-20, 404 'cal' => 3.82676978535648E-20, 405 'eV' => 1.0, 406 'ev' => 1.0, 407 'HPh' => 5.96826078912344E-26, 408 'hh' => 5.96826078912344E-26, 409 'Wh' => 4.45053000026614E-23, 410 'wh' => 4.45053000026614E-23, 411 'flb' => 3.80206452103492E-18, 412 'BTU' => 1.51857982414846E-22, 413 'btu' => 1.51857982414846E-22, 414 ], 415 'ev' => [ 416 'J' => 1.60219000146921E-19, 417 'e' => 1.60218923136574E-12, 418 'c' => 3.82933423195043E-20, 419 'cal' => 3.82676978535648E-20, 420 'eV' => 1.0, 421 'ev' => 1.0, 422 'HPh' => 5.96826078912344E-26, 423 'hh' => 5.96826078912344E-26, 424 'Wh' => 4.45053000026614E-23, 425 'wh' => 4.45053000026614E-23, 426 'flb' => 3.80206452103492E-18, 427 'BTU' => 1.51857982414846E-22, 428 'btu' => 1.51857982414846E-22, 429 ], 430 'HPh' => [ 431 'J' => 2.68451741316170E+06, 432 'e' => 2.68451612283024E+13, 433 'c' => 6.41616438565991E+05, 434 'cal' => 6.41186757845835E+05, 435 'eV' => 1.67553000000000E+25, 436 'ev' => 1.67553000000000E+25, 437 'HPh' => 1.0, 438 'hh' => 1.0, 439 'Wh' => 7.45699653134593E+02, 440 'wh' => 7.45699653134593E+02, 441 'flb' => 6.37047316692964E+07, 442 'BTU' => 2.54442605275546E+03, 443 'btu' => 2.54442605275546E+03, 444 ], 445 'hh' => [ 446 'J' => 2.68451741316170E+06, 447 'e' => 2.68451612283024E+13, 448 'c' => 6.41616438565991E+05, 449 'cal' => 6.41186757845835E+05, 450 'eV' => 1.67553000000000E+25, 451 'ev' => 1.67553000000000E+25, 452 'HPh' => 1.0, 453 'hh' => 1.0, 454 'Wh' => 7.45699653134593E+02, 455 'wh' => 7.45699653134593E+02, 456 'flb' => 6.37047316692964E+07, 457 'BTU' => 2.54442605275546E+03, 458 'btu' => 2.54442605275546E+03, 459 ], 460 'Wh' => [ 461 'J' => 3.59999820554720E+03, 462 'e' => 3.59999647518369E+10, 463 'c' => 8.60422069219046E+02, 464 'cal' => 8.59845857713046E+02, 465 'eV' => 2.24692340000000E+22, 466 'ev' => 2.24692340000000E+22, 467 'HPh' => 1.34102248243839E-03, 468 'hh' => 1.34102248243839E-03, 469 'Wh' => 1.0, 470 'wh' => 1.0, 471 'flb' => 8.54294774062316E+04, 472 'BTU' => 3.41213254164705E+00, 473 'btu' => 3.41213254164705E+00, 474 ], 475 'wh' => [ 476 'J' => 3.59999820554720E+03, 477 'e' => 3.59999647518369E+10, 478 'c' => 8.60422069219046E+02, 479 'cal' => 8.59845857713046E+02, 480 'eV' => 2.24692340000000E+22, 481 'ev' => 2.24692340000000E+22, 482 'HPh' => 1.34102248243839E-03, 483 'hh' => 1.34102248243839E-03, 484 'Wh' => 1.0, 485 'wh' => 1.0, 486 'flb' => 8.54294774062316E+04, 487 'BTU' => 3.41213254164705E+00, 488 'btu' => 3.41213254164705E+00, 489 ], 490 'flb' => [ 491 'J' => 4.21400003236424E-02, 492 'e' => 4.21399800687660E+05, 493 'c' => 1.00717234301644E-02, 494 'cal' => 1.00649785509554E-02, 495 'eV' => 2.63015000000000E+17, 496 'ev' => 2.63015000000000E+17, 497 'HPh' => 1.56974211145130E-08, 498 'hh' => 1.56974211145130E-08, 499 'Wh' => 1.17055614802000E-05, 500 'wh' => 1.17055614802000E-05, 501 'flb' => 1.0, 502 'BTU' => 3.99409272448406E-05, 503 'btu' => 3.99409272448406E-05, 504 ], 505 'BTU' => [ 506 'J' => 1.05505813786749E+03, 507 'e' => 1.05505763074665E+10, 508 'c' => 2.52165488508168E+02, 509 'cal' => 2.51996617135510E+02, 510 'eV' => 6.58510000000000E+21, 511 'ev' => 6.58510000000000E+21, 512 'HPh' => 3.93015941224568E-04, 513 'hh' => 3.93015941224568E-04, 514 'Wh' => 2.93071851047526E-01, 515 'wh' => 2.93071851047526E-01, 516 'flb' => 2.50369750774671E+04, 517 'BTU' => 1.0, 518 'btu' => 1.0, 519 ], 520 'btu' => [ 521 'J' => 1.05505813786749E+03, 522 'e' => 1.05505763074665E+10, 523 'c' => 2.52165488508168E+02, 524 'cal' => 2.51996617135510E+02, 525 'eV' => 6.58510000000000E+21, 526 'ev' => 6.58510000000000E+21, 527 'HPh' => 3.93015941224568E-04, 528 'hh' => 3.93015941224568E-04, 529 'Wh' => 2.93071851047526E-01, 530 'wh' => 2.93071851047526E-01, 531 'flb' => 2.50369750774671E+04, 532 'BTU' => 1.0, 533 'btu' => 1.0, 534 ], 535 ], 536 'Power' => [ 537 'HP' => [ 538 'HP' => 1.0, 539 'h' => 1.0, 540 'W' => 7.45701000000000E+02, 541 'w' => 7.45701000000000E+02, 542 ], 543 'h' => [ 544 'HP' => 1.0, 545 'h' => 1.0, 546 'W' => 7.45701000000000E+02, 547 'w' => 7.45701000000000E+02, 548 ], 549 'W' => [ 550 'HP' => 1.34102006031908E-03, 551 'h' => 1.34102006031908E-03, 552 'W' => 1.0, 553 'w' => 1.0, 554 ], 555 'w' => [ 556 'HP' => 1.34102006031908E-03, 557 'h' => 1.34102006031908E-03, 558 'W' => 1.0, 559 'w' => 1.0, 560 ], 561 ], 562 'Magnetism' => [ 563 'T' => [ 564 'T' => 1.0, 565 'ga' => 10000.0, 566 ], 567 'ga' => [ 568 'T' => 0.0001, 569 'ga' => 1.0, 570 ], 571 ], 572 'Liquid' => [ 573 'tsp' => [ 574 'tsp' => 1.0, 575 'tbs' => 3.33333333333333E-01, 576 'oz' => 1.66666666666667E-01, 577 'cup' => 2.08333333333333E-02, 578 'pt' => 1.04166666666667E-02, 579 'us_pt' => 1.04166666666667E-02, 580 'uk_pt' => 8.67558516821960E-03, 581 'qt' => 5.20833333333333E-03, 582 'gal' => 1.30208333333333E-03, 583 'l' => 4.92999408400710E-03, 584 'lt' => 4.92999408400710E-03, 585 ], 586 'tbs' => [ 587 'tsp' => 3.00000000000000E+00, 588 'tbs' => 1.0, 589 'oz' => 5.00000000000000E-01, 590 'cup' => 6.25000000000000E-02, 591 'pt' => 3.12500000000000E-02, 592 'us_pt' => 3.12500000000000E-02, 593 'uk_pt' => 2.60267555046588E-02, 594 'qt' => 1.56250000000000E-02, 595 'gal' => 3.90625000000000E-03, 596 'l' => 1.47899822520213E-02, 597 'lt' => 1.47899822520213E-02, 598 ], 599 'oz' => [ 600 'tsp' => 6.00000000000000E+00, 601 'tbs' => 2.00000000000000E+00, 602 'oz' => 1.0, 603 'cup' => 1.25000000000000E-01, 604 'pt' => 6.25000000000000E-02, 605 'us_pt' => 6.25000000000000E-02, 606 'uk_pt' => 5.20535110093176E-02, 607 'qt' => 3.12500000000000E-02, 608 'gal' => 7.81250000000000E-03, 609 'l' => 2.95799645040426E-02, 610 'lt' => 2.95799645040426E-02, 611 ], 612 'cup' => [ 613 'tsp' => 4.80000000000000E+01, 614 'tbs' => 1.60000000000000E+01, 615 'oz' => 8.00000000000000E+00, 616 'cup' => 1.0, 617 'pt' => 5.00000000000000E-01, 618 'us_pt' => 5.00000000000000E-01, 619 'uk_pt' => 4.16428088074541E-01, 620 'qt' => 2.50000000000000E-01, 621 'gal' => 6.25000000000000E-02, 622 'l' => 2.36639716032341E-01, 623 'lt' => 2.36639716032341E-01, 624 ], 625 'pt' => [ 626 'tsp' => 9.60000000000000E+01, 627 'tbs' => 3.20000000000000E+01, 628 'oz' => 1.60000000000000E+01, 629 'cup' => 2.00000000000000E+00, 630 'pt' => 1.0, 631 'us_pt' => 1.0, 632 'uk_pt' => 8.32856176149081E-01, 633 'qt' => 5.00000000000000E-01, 634 'gal' => 1.25000000000000E-01, 635 'l' => 4.73279432064682E-01, 636 'lt' => 4.73279432064682E-01, 637 ], 638 'us_pt' => [ 639 'tsp' => 9.60000000000000E+01, 640 'tbs' => 3.20000000000000E+01, 641 'oz' => 1.60000000000000E+01, 642 'cup' => 2.00000000000000E+00, 643 'pt' => 1.0, 644 'us_pt' => 1.0, 645 'uk_pt' => 8.32856176149081E-01, 646 'qt' => 5.00000000000000E-01, 647 'gal' => 1.25000000000000E-01, 648 'l' => 4.73279432064682E-01, 649 'lt' => 4.73279432064682E-01, 650 ], 651 'uk_pt' => [ 652 'tsp' => 1.15266000000000E+02, 653 'tbs' => 3.84220000000000E+01, 654 'oz' => 1.92110000000000E+01, 655 'cup' => 2.40137500000000E+00, 656 'pt' => 1.20068750000000E+00, 657 'us_pt' => 1.20068750000000E+00, 658 'uk_pt' => 1.0, 659 'qt' => 6.00343750000000E-01, 660 'gal' => 1.50085937500000E-01, 661 'l' => 5.68260698087162E-01, 662 'lt' => 5.68260698087162E-01, 663 ], 664 'qt' => [ 665 'tsp' => 1.92000000000000E+02, 666 'tbs' => 6.40000000000000E+01, 667 'oz' => 3.20000000000000E+01, 668 'cup' => 4.00000000000000E+00, 669 'pt' => 2.00000000000000E+00, 670 'us_pt' => 2.00000000000000E+00, 671 'uk_pt' => 1.66571235229816E+00, 672 'qt' => 1.0, 673 'gal' => 2.50000000000000E-01, 674 'l' => 9.46558864129363E-01, 675 'lt' => 9.46558864129363E-01, 676 ], 677 'gal' => [ 678 'tsp' => 7.68000000000000E+02, 679 'tbs' => 2.56000000000000E+02, 680 'oz' => 1.28000000000000E+02, 681 'cup' => 1.60000000000000E+01, 682 'pt' => 8.00000000000000E+00, 683 'us_pt' => 8.00000000000000E+00, 684 'uk_pt' => 6.66284940919265E+00, 685 'qt' => 4.00000000000000E+00, 686 'gal' => 1.0, 687 'l' => 3.78623545651745E+00, 688 'lt' => 3.78623545651745E+00, 689 ], 690 'l' => [ 691 'tsp' => 2.02840000000000E+02, 692 'tbs' => 6.76133333333333E+01, 693 'oz' => 3.38066666666667E+01, 694 'cup' => 4.22583333333333E+00, 695 'pt' => 2.11291666666667E+00, 696 'us_pt' => 2.11291666666667E+00, 697 'uk_pt' => 1.75975569552166E+00, 698 'qt' => 1.05645833333333E+00, 699 'gal' => 2.64114583333333E-01, 700 'l' => 1.0, 701 'lt' => 1.0, 702 ], 703 'lt' => [ 704 'tsp' => 2.02840000000000E+02, 705 'tbs' => 6.76133333333333E+01, 706 'oz' => 3.38066666666667E+01, 707 'cup' => 4.22583333333333E+00, 708 'pt' => 2.11291666666667E+00, 709 'us_pt' => 2.11291666666667E+00, 710 'uk_pt' => 1.75975569552166E+00, 711 'qt' => 1.05645833333333E+00, 712 'gal' => 2.64114583333333E-01, 713 'l' => 1.0, 714 'lt' => 1.0, 715 ], 716 ], 717 ]; 718 719 /** 720 * parseComplex. 721 * 722 * Parses a complex number into its real and imaginary parts, and an I or J suffix 723 * 724 * @deprecated 2.0.0 No longer used by internal code. Please use the Complex\Complex class instead 725 * 726 * @param string $complexNumber The complex number 727 * 728 * @return mixed[] Indexed on "real", "imaginary" and "suffix" 729 */ 730 public static function parseComplex($complexNumber) 731 { 732 $complex = new Complex($complexNumber); 733 734 return [ 735 'real' => $complex->getReal(), 736 'imaginary' => $complex->getImaginary(), 737 'suffix' => $complex->getSuffix(), 738 ]; 739 } 740 741 /** 742 * Formats a number base string value with leading zeroes. 743 * 744 * @param string $xVal The "number" to pad 745 * @param int $places The length that we want to pad this value 746 * 747 * @return string The padded "number" 748 */ 749 private static function nbrConversionFormat($xVal, $places) 750 { 751 if ($places !== null) { 752 if (is_numeric($places)) { 753 $places = (int) $places; 754 } else { 755 return Functions::VALUE(); 756 } 757 if ($places < 0) { 758 return Functions::NAN(); 759 } 760 if (strlen($xVal) <= $places) { 761 return substr(str_pad($xVal, $places, '0', STR_PAD_LEFT), -10); 762 } 763 764 return Functions::NAN(); 765 } 766 767 return substr($xVal, -10); 768 } 769 770 /** 771 * BESSELI. 772 * 773 * Returns the modified Bessel function In(x), which is equivalent to the Bessel function evaluated 774 * for purely imaginary arguments 775 * 776 * Excel Function: 777 * BESSELI(x,ord) 778 * 779 * @category Engineering Functions 780 * 781 * @param float $x The value at which to evaluate the function. 782 * If x is nonnumeric, BESSELI returns the #VALUE! error value. 783 * @param int $ord The order of the Bessel function. 784 * If ord is not an integer, it is truncated. 785 * If $ord is nonnumeric, BESSELI returns the #VALUE! error value. 786 * If $ord < 0, BESSELI returns the #NUM! error value. 787 * 788 * @return float 789 */ 790 public static function BESSELI($x, $ord) 791 { 792 $x = ($x === null) ? 0.0 : Functions::flattenSingleValue($x); 793 $ord = ($ord === null) ? 0.0 : Functions::flattenSingleValue($ord); 794 795 if ((is_numeric($x)) && (is_numeric($ord))) { 796 $ord = floor($ord); 797 if ($ord < 0) { 798 return Functions::NAN(); 799 } 800 801 if (abs($x) <= 30) { 802 $fResult = $fTerm = pow($x / 2, $ord) / MathTrig::FACT($ord); 803 $ordK = 1; 804 $fSqrX = ($x * $x) / 4; 805 do { 806 $fTerm *= $fSqrX; 807 $fTerm /= ($ordK * ($ordK + $ord)); 808 $fResult += $fTerm; 809 } while ((abs($fTerm) > 1e-12) && (++$ordK < 100)); 810 } else { 811 $f_2_PI = 2 * M_PI; 812 813 $fXAbs = abs($x); 814 $fResult = exp($fXAbs) / sqrt($f_2_PI * $fXAbs); 815 if (($ord & 1) && ($x < 0)) { 816 $fResult = -$fResult; 817 } 818 } 819 820 return (is_nan($fResult)) ? Functions::NAN() : $fResult; 821 } 822 823 return Functions::VALUE(); 824 } 825 826 /** 827 * BESSELJ. 828 * 829 * Returns the Bessel function 830 * 831 * Excel Function: 832 * BESSELJ(x,ord) 833 * 834 * @category Engineering Functions 835 * 836 * @param float $x The value at which to evaluate the function. 837 * If x is nonnumeric, BESSELJ returns the #VALUE! error value. 838 * @param int $ord The order of the Bessel function. If n is not an integer, it is truncated. 839 * If $ord is nonnumeric, BESSELJ returns the #VALUE! error value. 840 * If $ord < 0, BESSELJ returns the #NUM! error value. 841 * 842 * @return float 843 */ 844 public static function BESSELJ($x, $ord) 845 { 846 $x = ($x === null) ? 0.0 : Functions::flattenSingleValue($x); 847 $ord = ($ord === null) ? 0.0 : Functions::flattenSingleValue($ord); 848 849 if ((is_numeric($x)) && (is_numeric($ord))) { 850 $ord = floor($ord); 851 if ($ord < 0) { 852 return Functions::NAN(); 853 } 854 855 $fResult = 0; 856 if (abs($x) <= 30) { 857 $fResult = $fTerm = pow($x / 2, $ord) / MathTrig::FACT($ord); 858 $ordK = 1; 859 $fSqrX = ($x * $x) / -4; 860 do { 861 $fTerm *= $fSqrX; 862 $fTerm /= ($ordK * ($ordK + $ord)); 863 $fResult += $fTerm; 864 } while ((abs($fTerm) > 1e-12) && (++$ordK < 100)); 865 } else { 866 $f_PI_DIV_2 = M_PI / 2; 867 $f_PI_DIV_4 = M_PI / 4; 868 869 $fXAbs = abs($x); 870 $fResult = sqrt(Functions::M_2DIVPI / $fXAbs) * cos($fXAbs - $ord * $f_PI_DIV_2 - $f_PI_DIV_4); 871 if (($ord & 1) && ($x < 0)) { 872 $fResult = -$fResult; 873 } 874 } 875 876 return (is_nan($fResult)) ? Functions::NAN() : $fResult; 877 } 878 879 return Functions::VALUE(); 880 } 881 882 private static function besselK0($fNum) 883 { 884 if ($fNum <= 2) { 885 $fNum2 = $fNum * 0.5; 886 $y = ($fNum2 * $fNum2); 887 $fRet = -log($fNum2) * self::BESSELI($fNum, 0) + 888 (-0.57721566 + $y * (0.42278420 + $y * (0.23069756 + $y * (0.3488590e-1 + $y * (0.262698e-2 + $y * 889 (0.10750e-3 + $y * 0.74e-5)))))); 890 } else { 891 $y = 2 / $fNum; 892 $fRet = exp(-$fNum) / sqrt($fNum) * 893 (1.25331414 + $y * (-0.7832358e-1 + $y * (0.2189568e-1 + $y * (-0.1062446e-1 + $y * 894 (0.587872e-2 + $y * (-0.251540e-2 + $y * 0.53208e-3)))))); 895 } 896 897 return $fRet; 898 } 899 900 private static function besselK1($fNum) 901 { 902 if ($fNum <= 2) { 903 $fNum2 = $fNum * 0.5; 904 $y = ($fNum2 * $fNum2); 905 $fRet = log($fNum2) * self::BESSELI($fNum, 1) + 906 (1 + $y * (0.15443144 + $y * (-0.67278579 + $y * (-0.18156897 + $y * (-0.1919402e-1 + $y * 907 (-0.110404e-2 + $y * (-0.4686e-4))))))) / $fNum; 908 } else { 909 $y = 2 / $fNum; 910 $fRet = exp(-$fNum) / sqrt($fNum) * 911 (1.25331414 + $y * (0.23498619 + $y * (-0.3655620e-1 + $y * (0.1504268e-1 + $y * (-0.780353e-2 + $y * 912 (0.325614e-2 + $y * (-0.68245e-3))))))); 913 } 914 915 return $fRet; 916 } 917 918 /** 919 * BESSELK. 920 * 921 * Returns the modified Bessel function Kn(x), which is equivalent to the Bessel functions evaluated 922 * for purely imaginary arguments. 923 * 924 * Excel Function: 925 * BESSELK(x,ord) 926 * 927 * @category Engineering Functions 928 * 929 * @param float $x The value at which to evaluate the function. 930 * If x is nonnumeric, BESSELK returns the #VALUE! error value. 931 * @param int $ord The order of the Bessel function. If n is not an integer, it is truncated. 932 * If $ord is nonnumeric, BESSELK returns the #VALUE! error value. 933 * If $ord < 0, BESSELK returns the #NUM! error value. 934 * 935 * @return float 936 */ 937 public static function BESSELK($x, $ord) 938 { 939 $x = ($x === null) ? 0.0 : Functions::flattenSingleValue($x); 940 $ord = ($ord === null) ? 0.0 : Functions::flattenSingleValue($ord); 941 942 if ((is_numeric($x)) && (is_numeric($ord))) { 943 if (($ord < 0) || ($x == 0.0)) { 944 return Functions::NAN(); 945 } 946 947 switch (floor($ord)) { 948 case 0: 949 $fBk = self::besselK0($x); 950 951 break; 952 case 1: 953 $fBk = self::besselK1($x); 954 955 break; 956 default: 957 $fTox = 2 / $x; 958 $fBkm = self::besselK0($x); 959 $fBk = self::besselK1($x); 960 for ($n = 1; $n < $ord; ++$n) { 961 $fBkp = $fBkm + $n * $fTox * $fBk; 962 $fBkm = $fBk; 963 $fBk = $fBkp; 964 } 965 } 966 967 return (is_nan($fBk)) ? Functions::NAN() : $fBk; 968 } 969 970 return Functions::VALUE(); 971 } 972 973 private static function besselY0($fNum) 974 { 975 if ($fNum < 8.0) { 976 $y = ($fNum * $fNum); 977 $f1 = -2957821389.0 + $y * (7062834065.0 + $y * (-512359803.6 + $y * (10879881.29 + $y * (-86327.92757 + $y * 228.4622733)))); 978 $f2 = 40076544269.0 + $y * (745249964.8 + $y * (7189466.438 + $y * (47447.26470 + $y * (226.1030244 + $y)))); 979 $fRet = $f1 / $f2 + 0.636619772 * self::BESSELJ($fNum, 0) * log($fNum); 980 } else { 981 $z = 8.0 / $fNum; 982 $y = ($z * $z); 983 $xx = $fNum - 0.785398164; 984 $f1 = 1 + $y * (-0.1098628627e-2 + $y * (0.2734510407e-4 + $y * (-0.2073370639e-5 + $y * 0.2093887211e-6))); 985 $f2 = -0.1562499995e-1 + $y * (0.1430488765e-3 + $y * (-0.6911147651e-5 + $y * (0.7621095161e-6 + $y * (-0.934945152e-7)))); 986 $fRet = sqrt(0.636619772 / $fNum) * (sin($xx) * $f1 + $z * cos($xx) * $f2); 987 } 988 989 return $fRet; 990 } 991 992 private static function besselY1($fNum) 993 { 994 if ($fNum < 8.0) { 995 $y = ($fNum * $fNum); 996 $f1 = $fNum * (-0.4900604943e13 + $y * (0.1275274390e13 + $y * (-0.5153438139e11 + $y * (0.7349264551e9 + $y * 997 (-0.4237922726e7 + $y * 0.8511937935e4))))); 998 $f2 = 0.2499580570e14 + $y * (0.4244419664e12 + $y * (0.3733650367e10 + $y * (0.2245904002e8 + $y * 999 (0.1020426050e6 + $y * (0.3549632885e3 + $y))))); 1000 $fRet = $f1 / $f2 + 0.636619772 * (self::BESSELJ($fNum, 1) * log($fNum) - 1 / $fNum); 1001 } else { 1002 $fRet = sqrt(0.636619772 / $fNum) * sin($fNum - 2.356194491); 1003 } 1004 1005 return $fRet; 1006 } 1007 1008 /** 1009 * BESSELY. 1010 * 1011 * Returns the Bessel function, which is also called the Weber function or the Neumann function. 1012 * 1013 * Excel Function: 1014 * BESSELY(x,ord) 1015 * 1016 * @category Engineering Functions 1017 * 1018 * @param float $x The value at which to evaluate the function. 1019 * If x is nonnumeric, BESSELK returns the #VALUE! error value. 1020 * @param int $ord The order of the Bessel function. If n is not an integer, it is truncated. 1021 * If $ord is nonnumeric, BESSELK returns the #VALUE! error value. 1022 * If $ord < 0, BESSELK returns the #NUM! error value. 1023 * 1024 * @return float 1025 */ 1026 public static function BESSELY($x, $ord) 1027 { 1028 $x = ($x === null) ? 0.0 : Functions::flattenSingleValue($x); 1029 $ord = ($ord === null) ? 0.0 : Functions::flattenSingleValue($ord); 1030 1031 if ((is_numeric($x)) && (is_numeric($ord))) { 1032 if (($ord < 0) || ($x == 0.0)) { 1033 return Functions::NAN(); 1034 } 1035 1036 switch (floor($ord)) { 1037 case 0: 1038 $fBy = self::besselY0($x); 1039 1040 break; 1041 case 1: 1042 $fBy = self::besselY1($x); 1043 1044 break; 1045 default: 1046 $fTox = 2 / $x; 1047 $fBym = self::besselY0($x); 1048 $fBy = self::besselY1($x); 1049 for ($n = 1; $n < $ord; ++$n) { 1050 $fByp = $n * $fTox * $fBy - $fBym; 1051 $fBym = $fBy; 1052 $fBy = $fByp; 1053 } 1054 } 1055 1056 return (is_nan($fBy)) ? Functions::NAN() : $fBy; 1057 } 1058 1059 return Functions::VALUE(); 1060 } 1061 1062 /** 1063 * BINTODEC. 1064 * 1065 * Return a binary value as decimal. 1066 * 1067 * Excel Function: 1068 * BIN2DEC(x) 1069 * 1070 * @category Engineering Functions 1071 * 1072 * @param string $x The binary number (as a string) that you want to convert. The number 1073 * cannot contain more than 10 characters (10 bits). The most significant 1074 * bit of number is the sign bit. The remaining 9 bits are magnitude bits. 1075 * Negative numbers are represented using two's-complement notation. 1076 * If number is not a valid binary number, or if number contains more than 1077 * 10 characters (10 bits), BIN2DEC returns the #NUM! error value. 1078 * 1079 * @return string 1080 */ 1081 public static function BINTODEC($x) 1082 { 1083 $x = Functions::flattenSingleValue($x); 1084 1085 if (is_bool($x)) { 1086 if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) { 1087 $x = (int) $x; 1088 } else { 1089 return Functions::VALUE(); 1090 } 1091 } 1092 if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) { 1093 $x = floor($x); 1094 } 1095 $x = (string) $x; 1096 if (strlen($x) > preg_match_all('/[01]/', $x, $out)) { 1097 return Functions::NAN(); 1098 } 1099 if (strlen($x) > 10) { 1100 return Functions::NAN(); 1101 } elseif (strlen($x) == 10) { 1102 // Two's Complement 1103 $x = substr($x, -9); 1104 1105 return '-' . (512 - bindec($x)); 1106 } 1107 1108 return bindec($x); 1109 } 1110 1111 /** 1112 * BINTOHEX. 1113 * 1114 * Return a binary value as hex. 1115 * 1116 * Excel Function: 1117 * BIN2HEX(x[,places]) 1118 * 1119 * @category Engineering Functions 1120 * 1121 * @param string $x The binary number (as a string) that you want to convert. The number 1122 * cannot contain more than 10 characters (10 bits). The most significant 1123 * bit of number is the sign bit. The remaining 9 bits are magnitude bits. 1124 * Negative numbers are represented using two's-complement notation. 1125 * If number is not a valid binary number, or if number contains more than 1126 * 10 characters (10 bits), BIN2HEX returns the #NUM! error value. 1127 * @param int $places The number of characters to use. If places is omitted, BIN2HEX uses the 1128 * minimum number of characters necessary. Places is useful for padding the 1129 * return value with leading 0s (zeros). 1130 * If places is not an integer, it is truncated. 1131 * If places is nonnumeric, BIN2HEX returns the #VALUE! error value. 1132 * If places is negative, BIN2HEX returns the #NUM! error value. 1133 * 1134 * @return string 1135 */ 1136 public static function BINTOHEX($x, $places = null) 1137 { 1138 $x = Functions::flattenSingleValue($x); 1139 $places = Functions::flattenSingleValue($places); 1140 1141 // Argument X 1142 if (is_bool($x)) { 1143 if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) { 1144 $x = (int) $x; 1145 } else { 1146 return Functions::VALUE(); 1147 } 1148 } 1149 if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) { 1150 $x = floor($x); 1151 } 1152 $x = (string) $x; 1153 if (strlen($x) > preg_match_all('/[01]/', $x, $out)) { 1154 return Functions::NAN(); 1155 } 1156 if (strlen($x) > 10) { 1157 return Functions::NAN(); 1158 } elseif (strlen($x) == 10) { 1159 // Two's Complement 1160 return str_repeat('F', 8) . substr(strtoupper(dechex(bindec(substr($x, -9)))), -2); 1161 } 1162 $hexVal = (string) strtoupper(dechex(bindec($x))); 1163 1164 return self::nbrConversionFormat($hexVal, $places); 1165 } 1166 1167 /** 1168 * BINTOOCT. 1169 * 1170 * Return a binary value as octal. 1171 * 1172 * Excel Function: 1173 * BIN2OCT(x[,places]) 1174 * 1175 * @category Engineering Functions 1176 * 1177 * @param string $x The binary number (as a string) that you want to convert. The number 1178 * cannot contain more than 10 characters (10 bits). The most significant 1179 * bit of number is the sign bit. The remaining 9 bits are magnitude bits. 1180 * Negative numbers are represented using two's-complement notation. 1181 * If number is not a valid binary number, or if number contains more than 1182 * 10 characters (10 bits), BIN2OCT returns the #NUM! error value. 1183 * @param int $places The number of characters to use. If places is omitted, BIN2OCT uses the 1184 * minimum number of characters necessary. Places is useful for padding the 1185 * return value with leading 0s (zeros). 1186 * If places is not an integer, it is truncated. 1187 * If places is nonnumeric, BIN2OCT returns the #VALUE! error value. 1188 * If places is negative, BIN2OCT returns the #NUM! error value. 1189 * 1190 * @return string 1191 */ 1192 public static function BINTOOCT($x, $places = null) 1193 { 1194 $x = Functions::flattenSingleValue($x); 1195 $places = Functions::flattenSingleValue($places); 1196 1197 if (is_bool($x)) { 1198 if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) { 1199 $x = (int) $x; 1200 } else { 1201 return Functions::VALUE(); 1202 } 1203 } 1204 if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) { 1205 $x = floor($x); 1206 } 1207 $x = (string) $x; 1208 if (strlen($x) > preg_match_all('/[01]/', $x, $out)) { 1209 return Functions::NAN(); 1210 } 1211 if (strlen($x) > 10) { 1212 return Functions::NAN(); 1213 } elseif (strlen($x) == 10) { 1214 // Two's Complement 1215 return str_repeat('7', 7) . substr(strtoupper(decoct(bindec(substr($x, -9)))), -3); 1216 } 1217 $octVal = (string) decoct(bindec($x)); 1218 1219 return self::nbrConversionFormat($octVal, $places); 1220 } 1221 1222 /** 1223 * DECTOBIN. 1224 * 1225 * Return a decimal value as binary. 1226 * 1227 * Excel Function: 1228 * DEC2BIN(x[,places]) 1229 * 1230 * @category Engineering Functions 1231 * 1232 * @param string $x The decimal integer you want to convert. If number is negative, 1233 * valid place values are ignored and DEC2BIN returns a 10-character 1234 * (10-bit) binary number in which the most significant bit is the sign 1235 * bit. The remaining 9 bits are magnitude bits. Negative numbers are 1236 * represented using two's-complement notation. 1237 * If number < -512 or if number > 511, DEC2BIN returns the #NUM! error 1238 * value. 1239 * If number is nonnumeric, DEC2BIN returns the #VALUE! error value. 1240 * If DEC2BIN requires more than places characters, it returns the #NUM! 1241 * error value. 1242 * @param int $places The number of characters to use. If places is omitted, DEC2BIN uses 1243 * the minimum number of characters necessary. Places is useful for 1244 * padding the return value with leading 0s (zeros). 1245 * If places is not an integer, it is truncated. 1246 * If places is nonnumeric, DEC2BIN returns the #VALUE! error value. 1247 * If places is zero or negative, DEC2BIN returns the #NUM! error value. 1248 * 1249 * @return string 1250 */ 1251 public static function DECTOBIN($x, $places = null) 1252 { 1253 $x = Functions::flattenSingleValue($x); 1254 $places = Functions::flattenSingleValue($places); 1255 1256 if (is_bool($x)) { 1257 if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) { 1258 $x = (int) $x; 1259 } else { 1260 return Functions::VALUE(); 1261 } 1262 } 1263 $x = (string) $x; 1264 if (strlen($x) > preg_match_all('/[-0123456789.]/', $x, $out)) { 1265 return Functions::VALUE(); 1266 } 1267 1268 $x = (string) floor($x); 1269 if ($x < -512 || $x > 511) { 1270 return Functions::NAN(); 1271 } 1272 1273 $r = decbin($x); 1274 // Two's Complement 1275 $r = substr($r, -10); 1276 if (strlen($r) >= 11) { 1277 return Functions::NAN(); 1278 } 1279 1280 return self::nbrConversionFormat($r, $places); 1281 } 1282 1283 /** 1284 * DECTOHEX. 1285 * 1286 * Return a decimal value as hex. 1287 * 1288 * Excel Function: 1289 * DEC2HEX(x[,places]) 1290 * 1291 * @category Engineering Functions 1292 * 1293 * @param string $x The decimal integer you want to convert. If number is negative, 1294 * places is ignored and DEC2HEX returns a 10-character (40-bit) 1295 * hexadecimal number in which the most significant bit is the sign 1296 * bit. The remaining 39 bits are magnitude bits. Negative numbers 1297 * are represented using two's-complement notation. 1298 * If number < -549,755,813,888 or if number > 549,755,813,887, 1299 * DEC2HEX returns the #NUM! error value. 1300 * If number is nonnumeric, DEC2HEX returns the #VALUE! error value. 1301 * If DEC2HEX requires more than places characters, it returns the 1302 * #NUM! error value. 1303 * @param int $places The number of characters to use. If places is omitted, DEC2HEX uses 1304 * the minimum number of characters necessary. Places is useful for 1305 * padding the return value with leading 0s (zeros). 1306 * If places is not an integer, it is truncated. 1307 * If places is nonnumeric, DEC2HEX returns the #VALUE! error value. 1308 * If places is zero or negative, DEC2HEX returns the #NUM! error value. 1309 * 1310 * @return string 1311 */ 1312 public static function DECTOHEX($x, $places = null) 1313 { 1314 $x = Functions::flattenSingleValue($x); 1315 $places = Functions::flattenSingleValue($places); 1316 1317 if (is_bool($x)) { 1318 if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) { 1319 $x = (int) $x; 1320 } else { 1321 return Functions::VALUE(); 1322 } 1323 } 1324 $x = (string) $x; 1325 if (strlen($x) > preg_match_all('/[-0123456789.]/', $x, $out)) { 1326 return Functions::VALUE(); 1327 } 1328 $x = (string) floor($x); 1329 $r = strtoupper(dechex($x)); 1330 if (strlen($r) == 8) { 1331 // Two's Complement 1332 $r = 'FF' . $r; 1333 } 1334 1335 return self::nbrConversionFormat($r, $places); 1336 } 1337 1338 /** 1339 * DECTOOCT. 1340 * 1341 * Return an decimal value as octal. 1342 * 1343 * Excel Function: 1344 * DEC2OCT(x[,places]) 1345 * 1346 * @category Engineering Functions 1347 * 1348 * @param string $x The decimal integer you want to convert. If number is negative, 1349 * places is ignored and DEC2OCT returns a 10-character (30-bit) 1350 * octal number in which the most significant bit is the sign bit. 1351 * The remaining 29 bits are magnitude bits. Negative numbers are 1352 * represented using two's-complement notation. 1353 * If number < -536,870,912 or if number > 536,870,911, DEC2OCT 1354 * returns the #NUM! error value. 1355 * If number is nonnumeric, DEC2OCT returns the #VALUE! error value. 1356 * If DEC2OCT requires more than places characters, it returns the 1357 * #NUM! error value. 1358 * @param int $places The number of characters to use. If places is omitted, DEC2OCT uses 1359 * the minimum number of characters necessary. Places is useful for 1360 * padding the return value with leading 0s (zeros). 1361 * If places is not an integer, it is truncated. 1362 * If places is nonnumeric, DEC2OCT returns the #VALUE! error value. 1363 * If places is zero or negative, DEC2OCT returns the #NUM! error value. 1364 * 1365 * @return string 1366 */ 1367 public static function DECTOOCT($x, $places = null) 1368 { 1369 $xorig = $x; 1370 $x = Functions::flattenSingleValue($x); 1371 $places = Functions::flattenSingleValue($places); 1372 1373 if (is_bool($x)) { 1374 if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) { 1375 $x = (int) $x; 1376 } else { 1377 return Functions::VALUE(); 1378 } 1379 } 1380 $x = (string) $x; 1381 if (strlen($x) > preg_match_all('/[-0123456789.]/', $x, $out)) { 1382 return Functions::VALUE(); 1383 } 1384 $x = (string) floor($x); 1385 $r = decoct($x); 1386 if (strlen($r) == 11) { 1387 // Two's Complement 1388 $r = substr($r, -10); 1389 } 1390 1391 return self::nbrConversionFormat($r, $places); 1392 } 1393 1394 /** 1395 * HEXTOBIN. 1396 * 1397 * Return a hex value as binary. 1398 * 1399 * Excel Function: 1400 * HEX2BIN(x[,places]) 1401 * 1402 * @category Engineering Functions 1403 * 1404 * @param string $x the hexadecimal number you want to convert. 1405 * Number cannot contain more than 10 characters. 1406 * The most significant bit of number is the sign bit (40th bit from the right). 1407 * The remaining 9 bits are magnitude bits. 1408 * Negative numbers are represented using two's-complement notation. 1409 * If number is negative, HEX2BIN ignores places and returns a 10-character binary number. 1410 * If number is negative, it cannot be less than FFFFFFFE00, 1411 * and if number is positive, it cannot be greater than 1FF. 1412 * If number is not a valid hexadecimal number, HEX2BIN returns the #NUM! error value. 1413 * If HEX2BIN requires more than places characters, it returns the #NUM! error value. 1414 * @param int $places The number of characters to use. If places is omitted, 1415 * HEX2BIN uses the minimum number of characters necessary. Places 1416 * is useful for padding the return value with leading 0s (zeros). 1417 * If places is not an integer, it is truncated. 1418 * If places is nonnumeric, HEX2BIN returns the #VALUE! error value. 1419 * If places is negative, HEX2BIN returns the #NUM! error value. 1420 * 1421 * @return string 1422 */ 1423 public static function HEXTOBIN($x, $places = null) 1424 { 1425 $x = Functions::flattenSingleValue($x); 1426 $places = Functions::flattenSingleValue($places); 1427 1428 if (is_bool($x)) { 1429 return Functions::VALUE(); 1430 } 1431 $x = (string) $x; 1432 if (strlen($x) > preg_match_all('/[0123456789ABCDEF]/', strtoupper($x), $out)) { 1433 return Functions::NAN(); 1434 } 1435 1436 return self::DECTOBIN(self::HEXTODEC($x), $places); 1437 } 1438 1439 /** 1440 * HEXTODEC. 1441 * 1442 * Return a hex value as decimal. 1443 * 1444 * Excel Function: 1445 * HEX2DEC(x) 1446 * 1447 * @category Engineering Functions 1448 * 1449 * @param string $x The hexadecimal number you want to convert. This number cannot 1450 * contain more than 10 characters (40 bits). The most significant 1451 * bit of number is the sign bit. The remaining 39 bits are magnitude 1452 * bits. Negative numbers are represented using two's-complement 1453 * notation. 1454 * If number is not a valid hexadecimal number, HEX2DEC returns the 1455 * #NUM! error value. 1456 * 1457 * @return string 1458 */ 1459 public static function HEXTODEC($x) 1460 { 1461 $x = Functions::flattenSingleValue($x); 1462 1463 if (is_bool($x)) { 1464 return Functions::VALUE(); 1465 } 1466 $x = (string) $x; 1467 if (strlen($x) > preg_match_all('/[0123456789ABCDEF]/', strtoupper($x), $out)) { 1468 return Functions::NAN(); 1469 } 1470 1471 if (strlen($x) > 10) { 1472 return Functions::NAN(); 1473 } 1474 1475 $binX = ''; 1476 foreach (str_split($x) as $char) { 1477 $binX .= str_pad(base_convert($char, 16, 2), 4, '0', STR_PAD_LEFT); 1478 } 1479 if (strlen($binX) == 40 && $binX[0] == '1') { 1480 for ($i = 0; $i < 40; ++$i) { 1481 $binX[$i] = ($binX[$i] == '1' ? '0' : '1'); 1482 } 1483 1484 return (bindec($binX) + 1) * -1; 1485 } 1486 1487 return bindec($binX); 1488 } 1489 1490 /** 1491 * HEXTOOCT. 1492 * 1493 * Return a hex value as octal. 1494 * 1495 * Excel Function: 1496 * HEX2OCT(x[,places]) 1497 * 1498 * @category Engineering Functions 1499 * 1500 * @param string $x The hexadecimal number you want to convert. Number cannot 1501 * contain more than 10 characters. The most significant bit of 1502 * number is the sign bit. The remaining 39 bits are magnitude 1503 * bits. Negative numbers are represented using two's-complement 1504 * notation. 1505 * If number is negative, HEX2OCT ignores places and returns a 1506 * 10-character octal number. 1507 * If number is negative, it cannot be less than FFE0000000, and 1508 * if number is positive, it cannot be greater than 1FFFFFFF. 1509 * If number is not a valid hexadecimal number, HEX2OCT returns 1510 * the #NUM! error value. 1511 * If HEX2OCT requires more than places characters, it returns 1512 * the #NUM! error value. 1513 * @param int $places The number of characters to use. If places is omitted, HEX2OCT 1514 * uses the minimum number of characters necessary. Places is 1515 * useful for padding the return value with leading 0s (zeros). 1516 * If places is not an integer, it is truncated. 1517 * If places is nonnumeric, HEX2OCT returns the #VALUE! error 1518 * value. 1519 * If places is negative, HEX2OCT returns the #NUM! error value. 1520 * 1521 * @return string 1522 */ 1523 public static function HEXTOOCT($x, $places = null) 1524 { 1525 $x = Functions::flattenSingleValue($x); 1526 $places = Functions::flattenSingleValue($places); 1527 1528 if (is_bool($x)) { 1529 return Functions::VALUE(); 1530 } 1531 $x = (string) $x; 1532 if (strlen($x) > preg_match_all('/[0123456789ABCDEF]/', strtoupper($x), $out)) { 1533 return Functions::NAN(); 1534 } 1535 1536 $decimal = self::HEXTODEC($x); 1537 if ($decimal < -536870912 || $decimal > 536870911) { 1538 return Functions::NAN(); 1539 } 1540 1541 return self::DECTOOCT($decimal, $places); 1542 } 1543 1544 /** 1545 * OCTTOBIN. 1546 * 1547 * Return an octal value as binary. 1548 * 1549 * Excel Function: 1550 * OCT2BIN(x[,places]) 1551 * 1552 * @category Engineering Functions 1553 * 1554 * @param string $x The octal number you want to convert. Number may not 1555 * contain more than 10 characters. The most significant 1556 * bit of number is the sign bit. The remaining 29 bits 1557 * are magnitude bits. Negative numbers are represented 1558 * using two's-complement notation. 1559 * If number is negative, OCT2BIN ignores places and returns 1560 * a 10-character binary number. 1561 * If number is negative, it cannot be less than 7777777000, 1562 * and if number is positive, it cannot be greater than 777. 1563 * If number is not a valid octal number, OCT2BIN returns 1564 * the #NUM! error value. 1565 * If OCT2BIN requires more than places characters, it 1566 * returns the #NUM! error value. 1567 * @param int $places The number of characters to use. If places is omitted, 1568 * OCT2BIN uses the minimum number of characters necessary. 1569 * Places is useful for padding the return value with 1570 * leading 0s (zeros). 1571 * If places is not an integer, it is truncated. 1572 * If places is nonnumeric, OCT2BIN returns the #VALUE! 1573 * error value. 1574 * If places is negative, OCT2BIN returns the #NUM! error 1575 * value. 1576 * 1577 * @return string 1578 */ 1579 public static function OCTTOBIN($x, $places = null) 1580 { 1581 $x = Functions::flattenSingleValue($x); 1582 $places = Functions::flattenSingleValue($places); 1583 1584 if (is_bool($x)) { 1585 return Functions::VALUE(); 1586 } 1587 $x = (string) $x; 1588 if (preg_match_all('/[01234567]/', $x, $out) != strlen($x)) { 1589 return Functions::NAN(); 1590 } 1591 1592 return self::DECTOBIN(self::OCTTODEC($x), $places); 1593 } 1594 1595 /** 1596 * OCTTODEC. 1597 * 1598 * Return an octal value as decimal. 1599 * 1600 * Excel Function: 1601 * OCT2DEC(x) 1602 * 1603 * @category Engineering Functions 1604 * 1605 * @param string $x The octal number you want to convert. Number may not contain 1606 * more than 10 octal characters (30 bits). The most significant 1607 * bit of number is the sign bit. The remaining 29 bits are 1608 * magnitude bits. Negative numbers are represented using 1609 * two's-complement notation. 1610 * If number is not a valid octal number, OCT2DEC returns the 1611 * #NUM! error value. 1612 * 1613 * @return string 1614 */ 1615 public static function OCTTODEC($x) 1616 { 1617 $x = Functions::flattenSingleValue($x); 1618 1619 if (is_bool($x)) { 1620 return Functions::VALUE(); 1621 } 1622 $x = (string) $x; 1623 if (preg_match_all('/[01234567]/', $x, $out) != strlen($x)) { 1624 return Functions::NAN(); 1625 } 1626 $binX = ''; 1627 foreach (str_split($x) as $char) { 1628 $binX .= str_pad(decbin((int) $char), 3, '0', STR_PAD_LEFT); 1629 } 1630 if (strlen($binX) == 30 && $binX[0] == '1') { 1631 for ($i = 0; $i < 30; ++$i) { 1632 $binX[$i] = ($binX[$i] == '1' ? '0' : '1'); 1633 } 1634 1635 return (bindec($binX) + 1) * -1; 1636 } 1637 1638 return bindec($binX); 1639 } 1640 1641 /** 1642 * OCTTOHEX. 1643 * 1644 * Return an octal value as hex. 1645 * 1646 * Excel Function: 1647 * OCT2HEX(x[,places]) 1648 * 1649 * @category Engineering Functions 1650 * 1651 * @param string $x The octal number you want to convert. Number may not contain 1652 * more than 10 octal characters (30 bits). The most significant 1653 * bit of number is the sign bit. The remaining 29 bits are 1654 * magnitude bits. Negative numbers are represented using 1655 * two's-complement notation. 1656 * If number is negative, OCT2HEX ignores places and returns a 1657 * 10-character hexadecimal number. 1658 * If number is not a valid octal number, OCT2HEX returns the 1659 * #NUM! error value. 1660 * If OCT2HEX requires more than places characters, it returns 1661 * the #NUM! error value. 1662 * @param int $places The number of characters to use. If places is omitted, OCT2HEX 1663 * uses the minimum number of characters necessary. Places is useful 1664 * for padding the return value with leading 0s (zeros). 1665 * If places is not an integer, it is truncated. 1666 * If places is nonnumeric, OCT2HEX returns the #VALUE! error value. 1667 * If places is negative, OCT2HEX returns the #NUM! error value. 1668 * 1669 * @return string 1670 */ 1671 public static function OCTTOHEX($x, $places = null) 1672 { 1673 $x = Functions::flattenSingleValue($x); 1674 $places = Functions::flattenSingleValue($places); 1675 1676 if (is_bool($x)) { 1677 return Functions::VALUE(); 1678 } 1679 $x = (string) $x; 1680 if (preg_match_all('/[01234567]/', $x, $out) != strlen($x)) { 1681 return Functions::NAN(); 1682 } 1683 $hexVal = strtoupper(dechex(self::OCTTODEC($x))); 1684 1685 return self::nbrConversionFormat($hexVal, $places); 1686 } 1687 1688 /** 1689 * COMPLEX. 1690 * 1691 * Converts real and imaginary coefficients into a complex number of the form x +/- yi or x +/- yj. 1692 * 1693 * Excel Function: 1694 * COMPLEX(realNumber,imaginary[,suffix]) 1695 * 1696 * @category Engineering Functions 1697 * 1698 * @param float $realNumber the real coefficient of the complex number 1699 * @param float $imaginary the imaginary coefficient of the complex number 1700 * @param string $suffix The suffix for the imaginary component of the complex number. 1701 * If omitted, the suffix is assumed to be "i". 1702 * 1703 * @return string 1704 */ 1705 public static function COMPLEX($realNumber = 0.0, $imaginary = 0.0, $suffix = 'i') 1706 { 1707 $realNumber = ($realNumber === null) ? 0.0 : Functions::flattenSingleValue($realNumber); 1708 $imaginary = ($imaginary === null) ? 0.0 : Functions::flattenSingleValue($imaginary); 1709 $suffix = ($suffix === null) ? 'i' : Functions::flattenSingleValue($suffix); 1710 1711 if (((is_numeric($realNumber)) && (is_numeric($imaginary))) && 1712 (($suffix == 'i') || ($suffix == 'j') || ($suffix == '')) 1713 ) { 1714 $complex = new Complex($realNumber, $imaginary, $suffix); 1715 1716 return (string) $complex; 1717 } 1718 1719 return Functions::VALUE(); 1720 } 1721 1722 /** 1723 * IMAGINARY. 1724 * 1725 * Returns the imaginary coefficient of a complex number in x + yi or x + yj text format. 1726 * 1727 * Excel Function: 1728 * IMAGINARY(complexNumber) 1729 * 1730 * @category Engineering Functions 1731 * 1732 * @param string $complexNumber the complex number for which you want the imaginary 1733 * coefficient 1734 * 1735 * @return float 1736 */ 1737 public static function IMAGINARY($complexNumber) 1738 { 1739 $complexNumber = Functions::flattenSingleValue($complexNumber); 1740 1741 return (new Complex($complexNumber))->getImaginary(); 1742 } 1743 1744 /** 1745 * IMREAL. 1746 * 1747 * Returns the real coefficient of a complex number in x + yi or x + yj text format. 1748 * 1749 * Excel Function: 1750 * IMREAL(complexNumber) 1751 * 1752 * @category Engineering Functions 1753 * 1754 * @param string $complexNumber the complex number for which you want the real coefficient 1755 * 1756 * @return float 1757 */ 1758 public static function IMREAL($complexNumber) 1759 { 1760 $complexNumber = Functions::flattenSingleValue($complexNumber); 1761 1762 return (new Complex($complexNumber))->getReal(); 1763 } 1764 1765 /** 1766 * IMABS. 1767 * 1768 * Returns the absolute value (modulus) of a complex number in x + yi or x + yj text format. 1769 * 1770 * Excel Function: 1771 * IMABS(complexNumber) 1772 * 1773 * @param string $complexNumber the complex number for which you want the absolute value 1774 * 1775 * @return float 1776 */ 1777 public static function IMABS($complexNumber) 1778 { 1779 $complexNumber = Functions::flattenSingleValue($complexNumber); 1780 1781 return (new Complex($complexNumber))->abs(); 1782 } 1783 1784 /** 1785 * IMARGUMENT. 1786 * 1787 * Returns the argument theta of a complex number, i.e. the angle in radians from the real 1788 * axis to the representation of the number in polar coordinates. 1789 * 1790 * Excel Function: 1791 * IMARGUMENT(complexNumber) 1792 * 1793 * @param string $complexNumber the complex number for which you want the argument theta 1794 * 1795 * @return float|string 1796 */ 1797 public static function IMARGUMENT($complexNumber) 1798 { 1799 $complexNumber = Functions::flattenSingleValue($complexNumber); 1800 1801 $complex = new Complex($complexNumber); 1802 if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) { 1803 return Functions::DIV0(); 1804 } 1805 1806 return $complex->argument(); 1807 } 1808 1809 /** 1810 * IMCONJUGATE. 1811 * 1812 * Returns the complex conjugate of a complex number in x + yi or x + yj text format. 1813 * 1814 * Excel Function: 1815 * IMCONJUGATE(complexNumber) 1816 * 1817 * @param string $complexNumber the complex number for which you want the conjugate 1818 * 1819 * @return string 1820 */ 1821 public static function IMCONJUGATE($complexNumber) 1822 { 1823 $complexNumber = Functions::flattenSingleValue($complexNumber); 1824 1825 return (string) (new Complex($complexNumber))->conjugate(); 1826 } 1827 1828 /** 1829 * IMCOS. 1830 * 1831 * Returns the cosine of a complex number in x + yi or x + yj text format. 1832 * 1833 * Excel Function: 1834 * IMCOS(complexNumber) 1835 * 1836 * @param string $complexNumber the complex number for which you want the cosine 1837 * 1838 * @return float|string 1839 */ 1840 public static function IMCOS($complexNumber) 1841 { 1842 $complexNumber = Functions::flattenSingleValue($complexNumber); 1843 1844 return (string) (new Complex($complexNumber))->cos(); 1845 } 1846 1847 /** 1848 * IMCOSH. 1849 * 1850 * Returns the hyperbolic cosine of a complex number in x + yi or x + yj text format. 1851 * 1852 * Excel Function: 1853 * IMCOSH(complexNumber) 1854 * 1855 * @param string $complexNumber the complex number for which you want the hyperbolic cosine 1856 * 1857 * @return float|string 1858 */ 1859 public static function IMCOSH($complexNumber) 1860 { 1861 $complexNumber = Functions::flattenSingleValue($complexNumber); 1862 1863 return (string) (new Complex($complexNumber))->cosh(); 1864 } 1865 1866 /** 1867 * IMCOT. 1868 * 1869 * Returns the cotangent of a complex number in x + yi or x + yj text format. 1870 * 1871 * Excel Function: 1872 * IMCOT(complexNumber) 1873 * 1874 * @param string $complexNumber the complex number for which you want the cotangent 1875 * 1876 * @return float|string 1877 */ 1878 public static function IMCOT($complexNumber) 1879 { 1880 $complexNumber = Functions::flattenSingleValue($complexNumber); 1881 1882 return (string) (new Complex($complexNumber))->cot(); 1883 } 1884 1885 /** 1886 * IMCSC. 1887 * 1888 * Returns the cosecant of a complex number in x + yi or x + yj text format. 1889 * 1890 * Excel Function: 1891 * IMCSC(complexNumber) 1892 * 1893 * @param string $complexNumber the complex number for which you want the cosecant 1894 * 1895 * @return float|string 1896 */ 1897 public static function IMCSC($complexNumber) 1898 { 1899 $complexNumber = Functions::flattenSingleValue($complexNumber); 1900 1901 return (string) (new Complex($complexNumber))->csc(); 1902 } 1903 1904 /** 1905 * IMCSCH. 1906 * 1907 * Returns the hyperbolic cosecant of a complex number in x + yi or x + yj text format. 1908 * 1909 * Excel Function: 1910 * IMCSCH(complexNumber) 1911 * 1912 * @param string $complexNumber the complex number for which you want the hyperbolic cosecant 1913 * 1914 * @return float|string 1915 */ 1916 public static function IMCSCH($complexNumber) 1917 { 1918 $complexNumber = Functions::flattenSingleValue($complexNumber); 1919 1920 return (string) (new Complex($complexNumber))->csch(); 1921 } 1922 1923 /** 1924 * IMSIN. 1925 * 1926 * Returns the sine of a complex number in x + yi or x + yj text format. 1927 * 1928 * Excel Function: 1929 * IMSIN(complexNumber) 1930 * 1931 * @param string $complexNumber the complex number for which you want the sine 1932 * 1933 * @return float|string 1934 */ 1935 public static function IMSIN($complexNumber) 1936 { 1937 $complexNumber = Functions::flattenSingleValue($complexNumber); 1938 1939 return (string) (new Complex($complexNumber))->sin(); 1940 } 1941 1942 /** 1943 * IMSINH. 1944 * 1945 * Returns the hyperbolic sine of a complex number in x + yi or x + yj text format. 1946 * 1947 * Excel Function: 1948 * IMSINH(complexNumber) 1949 * 1950 * @param string $complexNumber the complex number for which you want the hyperbolic sine 1951 * 1952 * @return float|string 1953 */ 1954 public static function IMSINH($complexNumber) 1955 { 1956 $complexNumber = Functions::flattenSingleValue($complexNumber); 1957 1958 return (string) (new Complex($complexNumber))->sinh(); 1959 } 1960 1961 /** 1962 * IMSEC. 1963 * 1964 * Returns the secant of a complex number in x + yi or x + yj text format. 1965 * 1966 * Excel Function: 1967 * IMSEC(complexNumber) 1968 * 1969 * @param string $complexNumber the complex number for which you want the secant 1970 * 1971 * @return float|string 1972 */ 1973 public static function IMSEC($complexNumber) 1974 { 1975 $complexNumber = Functions::flattenSingleValue($complexNumber); 1976 1977 return (string) (new Complex($complexNumber))->sec(); 1978 } 1979 1980 /** 1981 * IMSECH. 1982 * 1983 * Returns the hyperbolic secant of a complex number in x + yi or x + yj text format. 1984 * 1985 * Excel Function: 1986 * IMSECH(complexNumber) 1987 * 1988 * @param string $complexNumber the complex number for which you want the hyperbolic secant 1989 * 1990 * @return float|string 1991 */ 1992 public static function IMSECH($complexNumber) 1993 { 1994 $complexNumber = Functions::flattenSingleValue($complexNumber); 1995 1996 return (string) (new Complex($complexNumber))->sech(); 1997 } 1998 1999 /** 2000 * IMTAN. 2001 * 2002 * Returns the tangent of a complex number in x + yi or x + yj text format. 2003 * 2004 * Excel Function: 2005 * IMTAN(complexNumber) 2006 * 2007 * @param string $complexNumber the complex number for which you want the tangent 2008 * 2009 * @return float|string 2010 */ 2011 public static function IMTAN($complexNumber) 2012 { 2013 $complexNumber = Functions::flattenSingleValue($complexNumber); 2014 2015 return (string) (new Complex($complexNumber))->tan(); 2016 } 2017 2018 /** 2019 * IMSQRT. 2020 * 2021 * Returns the square root of a complex number in x + yi or x + yj text format. 2022 * 2023 * Excel Function: 2024 * IMSQRT(complexNumber) 2025 * 2026 * @param string $complexNumber the complex number for which you want the square root 2027 * 2028 * @return string 2029 */ 2030 public static function IMSQRT($complexNumber) 2031 { 2032 $complexNumber = Functions::flattenSingleValue($complexNumber); 2033 2034 $theta = self::IMARGUMENT($complexNumber); 2035 if ($theta === Functions::DIV0()) { 2036 return '0'; 2037 } 2038 2039 return (string) (new Complex($complexNumber))->sqrt(); 2040 } 2041 2042 /** 2043 * IMLN. 2044 * 2045 * Returns the natural logarithm of a complex number in x + yi or x + yj text format. 2046 * 2047 * Excel Function: 2048 * IMLN(complexNumber) 2049 * 2050 * @param string $complexNumber the complex number for which you want the natural logarithm 2051 * 2052 * @return string 2053 */ 2054 public static function IMLN($complexNumber) 2055 { 2056 $complexNumber = Functions::flattenSingleValue($complexNumber); 2057 2058 $complex = new Complex($complexNumber); 2059 if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) { 2060 return Functions::NAN(); 2061 } 2062 2063 return (string) (new Complex($complexNumber))->ln(); 2064 } 2065 2066 /** 2067 * IMLOG10. 2068 * 2069 * Returns the common logarithm (base 10) of a complex number in x + yi or x + yj text format. 2070 * 2071 * Excel Function: 2072 * IMLOG10(complexNumber) 2073 * 2074 * @param string $complexNumber the complex number for which you want the common logarithm 2075 * 2076 * @return string 2077 */ 2078 public static function IMLOG10($complexNumber) 2079 { 2080 $complexNumber = Functions::flattenSingleValue($complexNumber); 2081 2082 $complex = new Complex($complexNumber); 2083 if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) { 2084 return Functions::NAN(); 2085 } 2086 2087 return (string) (new Complex($complexNumber))->log10(); 2088 } 2089 2090 /** 2091 * IMLOG2. 2092 * 2093 * Returns the base-2 logarithm of a complex number in x + yi or x + yj text format. 2094 * 2095 * Excel Function: 2096 * IMLOG2(complexNumber) 2097 * 2098 * @param string $complexNumber the complex number for which you want the base-2 logarithm 2099 * 2100 * @return string 2101 */ 2102 public static function IMLOG2($complexNumber) 2103 { 2104 $complexNumber = Functions::flattenSingleValue($complexNumber); 2105 2106 $complex = new Complex($complexNumber); 2107 if ($complex->getReal() == 0.0 && $complex->getImaginary() == 0.0) { 2108 return Functions::NAN(); 2109 } 2110 2111 return (string) (new Complex($complexNumber))->log2(); 2112 } 2113 2114 /** 2115 * IMEXP. 2116 * 2117 * Returns the exponential of a complex number in x + yi or x + yj text format. 2118 * 2119 * Excel Function: 2120 * IMEXP(complexNumber) 2121 * 2122 * @param string $complexNumber the complex number for which you want the exponential 2123 * 2124 * @return string 2125 */ 2126 public static function IMEXP($complexNumber) 2127 { 2128 $complexNumber = Functions::flattenSingleValue($complexNumber); 2129 2130 return (string) (new Complex($complexNumber))->exp(); 2131 } 2132 2133 /** 2134 * IMPOWER. 2135 * 2136 * Returns a complex number in x + yi or x + yj text format raised to a power. 2137 * 2138 * Excel Function: 2139 * IMPOWER(complexNumber,realNumber) 2140 * 2141 * @param string $complexNumber the complex number you want to raise to a power 2142 * @param float $realNumber the power to which you want to raise the complex number 2143 * 2144 * @return string 2145 */ 2146 public static function IMPOWER($complexNumber, $realNumber) 2147 { 2148 $complexNumber = Functions::flattenSingleValue($complexNumber); 2149 $realNumber = Functions::flattenSingleValue($realNumber); 2150 2151 if (!is_numeric($realNumber)) { 2152 return Functions::VALUE(); 2153 } 2154 2155 return (string) (new Complex($complexNumber))->pow($realNumber); 2156 } 2157 2158 /** 2159 * IMDIV. 2160 * 2161 * Returns the quotient of two complex numbers in x + yi or x + yj text format. 2162 * 2163 * Excel Function: 2164 * IMDIV(complexDividend,complexDivisor) 2165 * 2166 * @param string $complexDividend the complex numerator or dividend 2167 * @param string $complexDivisor the complex denominator or divisor 2168 * 2169 * @return string 2170 */ 2171 public static function IMDIV($complexDividend, $complexDivisor) 2172 { 2173 $complexDividend = Functions::flattenSingleValue($complexDividend); 2174 $complexDivisor = Functions::flattenSingleValue($complexDivisor); 2175 2176 try { 2177 return (string) (new Complex($complexDividend))->divideby(new Complex($complexDivisor)); 2178 } catch (ComplexException $e) { 2179 return Functions::NAN(); 2180 } 2181 } 2182 2183 /** 2184 * IMSUB. 2185 * 2186 * Returns the difference of two complex numbers in x + yi or x + yj text format. 2187 * 2188 * Excel Function: 2189 * IMSUB(complexNumber1,complexNumber2) 2190 * 2191 * @param string $complexNumber1 the complex number from which to subtract complexNumber2 2192 * @param string $complexNumber2 the complex number to subtract from complexNumber1 2193 * 2194 * @return string 2195 */ 2196 public static function IMSUB($complexNumber1, $complexNumber2) 2197 { 2198 $complexNumber1 = Functions::flattenSingleValue($complexNumber1); 2199 $complexNumber2 = Functions::flattenSingleValue($complexNumber2); 2200 2201 try { 2202 return (string) (new Complex($complexNumber1))->subtract(new Complex($complexNumber2)); 2203 } catch (ComplexException $e) { 2204 return Functions::NAN(); 2205 } 2206 } 2207 2208 /** 2209 * IMSUM. 2210 * 2211 * Returns the sum of two or more complex numbers in x + yi or x + yj text format. 2212 * 2213 * Excel Function: 2214 * IMSUM(complexNumber[,complexNumber[,...]]) 2215 * 2216 * @param string ...$complexNumbers Series of complex numbers to add 2217 * 2218 * @return string 2219 */ 2220 public static function IMSUM(...$complexNumbers) 2221 { 2222 // Return value 2223 $returnValue = new Complex(0.0); 2224 $aArgs = Functions::flattenArray($complexNumbers); 2225 2226 try { 2227 // Loop through the arguments 2228 foreach ($aArgs as $complex) { 2229 $returnValue = $returnValue->add(new Complex($complex)); 2230 } 2231 } catch (ComplexException $e) { 2232 return Functions::NAN(); 2233 } 2234 2235 return (string) $returnValue; 2236 } 2237 2238 /** 2239 * IMPRODUCT. 2240 * 2241 * Returns the product of two or more complex numbers in x + yi or x + yj text format. 2242 * 2243 * Excel Function: 2244 * IMPRODUCT(complexNumber[,complexNumber[,...]]) 2245 * 2246 * @param string ...$complexNumbers Series of complex numbers to multiply 2247 * 2248 * @return string 2249 */ 2250 public static function IMPRODUCT(...$complexNumbers) 2251 { 2252 // Return value 2253 $returnValue = new Complex(1.0); 2254 $aArgs = Functions::flattenArray($complexNumbers); 2255 2256 try { 2257 // Loop through the arguments 2258 foreach ($aArgs as $complex) { 2259 $returnValue = $returnValue->multiply(new Complex($complex)); 2260 } 2261 } catch (ComplexException $e) { 2262 return Functions::NAN(); 2263 } 2264 2265 return (string) $returnValue; 2266 } 2267 2268 /** 2269 * DELTA. 2270 * 2271 * Tests whether two values are equal. Returns 1 if number1 = number2; returns 0 otherwise. 2272 * Use this function to filter a set of values. For example, by summing several DELTA 2273 * functions you calculate the count of equal pairs. This function is also known as the 2274 * Kronecker Delta function. 2275 * 2276 * Excel Function: 2277 * DELTA(a[,b]) 2278 * 2279 * @param float $a the first number 2280 * @param float $b The second number. If omitted, b is assumed to be zero. 2281 * 2282 * @return int 2283 */ 2284 public static function DELTA($a, $b = 0) 2285 { 2286 $a = Functions::flattenSingleValue($a); 2287 $b = Functions::flattenSingleValue($b); 2288 2289 return (int) ($a == $b); 2290 } 2291 2292 /** 2293 * GESTEP. 2294 * 2295 * Excel Function: 2296 * GESTEP(number[,step]) 2297 * 2298 * Returns 1 if number >= step; returns 0 (zero) otherwise 2299 * Use this function to filter a set of values. For example, by summing several GESTEP 2300 * functions you calculate the count of values that exceed a threshold. 2301 * 2302 * @param float $number the value to test against step 2303 * @param float $step The threshold value. 2304 * If you omit a value for step, GESTEP uses zero. 2305 * 2306 * @return int 2307 */ 2308 public static function GESTEP($number, $step = 0) 2309 { 2310 $number = Functions::flattenSingleValue($number); 2311 $step = Functions::flattenSingleValue($step); 2312 2313 return (int) ($number >= $step); 2314 } 2315 2316 // 2317 // Private method to calculate the erf value 2318 // 2319 private static $twoSqrtPi = 1.128379167095512574; 2320 2321 public static function erfVal($x) 2322 { 2323 if (abs($x) > 2.2) { 2324 return 1 - self::erfcVal($x); 2325 } 2326 $sum = $term = $x; 2327 $xsqr = ($x * $x); 2328 $j = 1; 2329 do { 2330 $term *= $xsqr / $j; 2331 $sum -= $term / (2 * $j + 1); 2332 ++$j; 2333 $term *= $xsqr / $j; 2334 $sum += $term / (2 * $j + 1); 2335 ++$j; 2336 if ($sum == 0.0) { 2337 break; 2338 } 2339 } while (abs($term / $sum) > Functions::PRECISION); 2340 2341 return self::$twoSqrtPi * $sum; 2342 } 2343 2344 /** 2345 * Validate arguments passed to the bitwise functions. 2346 * 2347 * @param mixed $value 2348 * 2349 * @throws Exception 2350 * 2351 * @return int 2352 */ 2353 private static function validateBitwiseArgument($value) 2354 { 2355 $value = Functions::flattenSingleValue($value); 2356 2357 if (is_int($value)) { 2358 return $value; 2359 } elseif (is_numeric($value)) { 2360 if ($value == (int) ($value)) { 2361 $value = (int) ($value); 2362 if (($value > pow(2, 48) - 1) || ($value < 0)) { 2363 throw new Exception(Functions::NAN()); 2364 } 2365 2366 return $value; 2367 } 2368 2369 throw new Exception(Functions::NAN()); 2370 } 2371 2372 throw new Exception(Functions::VALUE()); 2373 } 2374 2375 /** 2376 * BITAND. 2377 * 2378 * Returns the bitwise AND of two integer values. 2379 * 2380 * Excel Function: 2381 * BITAND(number1, number2) 2382 * 2383 * @category Engineering Functions 2384 * 2385 * @param int $number1 2386 * @param int $number2 2387 * 2388 * @return int|string 2389 */ 2390 public static function BITAND($number1, $number2) 2391 { 2392 try { 2393 $number1 = self::validateBitwiseArgument($number1); 2394 $number2 = self::validateBitwiseArgument($number2); 2395 } catch (Exception $e) { 2396 return $e->getMessage(); 2397 } 2398 2399 return $number1 & $number2; 2400 } 2401 2402 /** 2403 * BITOR. 2404 * 2405 * Returns the bitwise OR of two integer values. 2406 * 2407 * Excel Function: 2408 * BITOR(number1, number2) 2409 * 2410 * @category Engineering Functions 2411 * 2412 * @param int $number1 2413 * @param int $number2 2414 * 2415 * @return int|string 2416 */ 2417 public static function BITOR($number1, $number2) 2418 { 2419 try { 2420 $number1 = self::validateBitwiseArgument($number1); 2421 $number2 = self::validateBitwiseArgument($number2); 2422 } catch (Exception $e) { 2423 return $e->getMessage(); 2424 } 2425 2426 return $number1 | $number2; 2427 } 2428 2429 /** 2430 * BITXOR. 2431 * 2432 * Returns the bitwise XOR of two integer values. 2433 * 2434 * Excel Function: 2435 * BITXOR(number1, number2) 2436 * 2437 * @category Engineering Functions 2438 * 2439 * @param int $number1 2440 * @param int $number2 2441 * 2442 * @return int|string 2443 */ 2444 public static function BITXOR($number1, $number2) 2445 { 2446 try { 2447 $number1 = self::validateBitwiseArgument($number1); 2448 $number2 = self::validateBitwiseArgument($number2); 2449 } catch (Exception $e) { 2450 return $e->getMessage(); 2451 } 2452 2453 return $number1 ^ $number2; 2454 } 2455 2456 /** 2457 * BITLSHIFT. 2458 * 2459 * Returns the number value shifted left by shift_amount bits. 2460 * 2461 * Excel Function: 2462 * BITLSHIFT(number, shift_amount) 2463 * 2464 * @category Engineering Functions 2465 * 2466 * @param int $number 2467 * @param int $shiftAmount 2468 * 2469 * @return int|string 2470 */ 2471 public static function BITLSHIFT($number, $shiftAmount) 2472 { 2473 try { 2474 $number = self::validateBitwiseArgument($number); 2475 } catch (Exception $e) { 2476 return $e->getMessage(); 2477 } 2478 2479 $shiftAmount = Functions::flattenSingleValue($shiftAmount); 2480 2481 $result = $number << $shiftAmount; 2482 if ($result > pow(2, 48) - 1) { 2483 return Functions::NAN(); 2484 } 2485 2486 return $result; 2487 } 2488 2489 /** 2490 * BITRSHIFT. 2491 * 2492 * Returns the number value shifted right by shift_amount bits. 2493 * 2494 * Excel Function: 2495 * BITRSHIFT(number, shift_amount) 2496 * 2497 * @category Engineering Functions 2498 * 2499 * @param int $number 2500 * @param int $shiftAmount 2501 * 2502 * @return int|string 2503 */ 2504 public static function BITRSHIFT($number, $shiftAmount) 2505 { 2506 try { 2507 $number = self::validateBitwiseArgument($number); 2508 } catch (Exception $e) { 2509 return $e->getMessage(); 2510 } 2511 2512 $shiftAmount = Functions::flattenSingleValue($shiftAmount); 2513 2514 return $number >> $shiftAmount; 2515 } 2516 2517 /** 2518 * ERF. 2519 * 2520 * Returns the error function integrated between the lower and upper bound arguments. 2521 * 2522 * Note: In Excel 2007 or earlier, if you input a negative value for the upper or lower bound arguments, 2523 * the function would return a #NUM! error. However, in Excel 2010, the function algorithm was 2524 * improved, so that it can now calculate the function for both positive and negative ranges. 2525 * PhpSpreadsheet follows Excel 2010 behaviour, and accepts negative arguments. 2526 * 2527 * Excel Function: 2528 * ERF(lower[,upper]) 2529 * 2530 * @param float $lower lower bound for integrating ERF 2531 * @param float $upper upper bound for integrating ERF. 2532 * If omitted, ERF integrates between zero and lower_limit 2533 * 2534 * @return float|string 2535 */ 2536 public static function ERF($lower, $upper = null) 2537 { 2538 $lower = Functions::flattenSingleValue($lower); 2539 $upper = Functions::flattenSingleValue($upper); 2540 2541 if (is_numeric($lower)) { 2542 if ($upper === null) { 2543 return self::erfVal($lower); 2544 } 2545 if (is_numeric($upper)) { 2546 return self::erfVal($upper) - self::erfVal($lower); 2547 } 2548 } 2549 2550 return Functions::VALUE(); 2551 } 2552 2553 /** 2554 * ERFPRECISE. 2555 * 2556 * Returns the error function integrated between the lower and upper bound arguments. 2557 * 2558 * Excel Function: 2559 * ERF.PRECISE(limit) 2560 * 2561 * @param float $limit bound for integrating ERF 2562 * 2563 * @return float|string 2564 */ 2565 public static function ERFPRECISE($limit) 2566 { 2567 $limit = Functions::flattenSingleValue($limit); 2568 2569 return self::ERF($limit); 2570 } 2571 2572 // 2573 // Private method to calculate the erfc value 2574 // 2575 private static $oneSqrtPi = 0.564189583547756287; 2576 2577 private static function erfcVal($x) 2578 { 2579 if (abs($x) < 2.2) { 2580 return 1 - self::erfVal($x); 2581 } 2582 if ($x < 0) { 2583 return 2 - self::ERFC(-$x); 2584 } 2585 $a = $n = 1; 2586 $b = $c = $x; 2587 $d = ($x * $x) + 0.5; 2588 $q1 = $q2 = $b / $d; 2589 $t = 0; 2590 do { 2591 $t = $a * $n + $b * $x; 2592 $a = $b; 2593 $b = $t; 2594 $t = $c * $n + $d * $x; 2595 $c = $d; 2596 $d = $t; 2597 $n += 0.5; 2598 $q1 = $q2; 2599 $q2 = $b / $d; 2600 } while ((abs($q1 - $q2) / $q2) > Functions::PRECISION); 2601 2602 return self::$oneSqrtPi * exp(-$x * $x) * $q2; 2603 } 2604 2605 /** 2606 * ERFC. 2607 * 2608 * Returns the complementary ERF function integrated between x and infinity 2609 * 2610 * Note: In Excel 2007 or earlier, if you input a negative value for the lower bound argument, 2611 * the function would return a #NUM! error. However, in Excel 2010, the function algorithm was 2612 * improved, so that it can now calculate the function for both positive and negative x values. 2613 * PhpSpreadsheet follows Excel 2010 behaviour, and accepts nagative arguments. 2614 * 2615 * Excel Function: 2616 * ERFC(x) 2617 * 2618 * @param float $x The lower bound for integrating ERFC 2619 * 2620 * @return float|string 2621 */ 2622 public static function ERFC($x) 2623 { 2624 $x = Functions::flattenSingleValue($x); 2625 2626 if (is_numeric($x)) { 2627 return self::erfcVal($x); 2628 } 2629 2630 return Functions::VALUE(); 2631 } 2632 2633 /** 2634 * getConversionGroups 2635 * Returns a list of the different conversion groups for UOM conversions. 2636 * 2637 * @return array 2638 */ 2639 public static function getConversionGroups() 2640 { 2641 $conversionGroups = []; 2642 foreach (self::$conversionUnits as $conversionUnit) { 2643 $conversionGroups[] = $conversionUnit['Group']; 2644 } 2645 2646 return array_merge(array_unique($conversionGroups)); 2647 } 2648 2649 /** 2650 * getConversionGroupUnits 2651 * Returns an array of units of measure, for a specified conversion group, or for all groups. 2652 * 2653 * @param string $group The group whose units of measure you want to retrieve 2654 * 2655 * @return array 2656 */ 2657 public static function getConversionGroupUnits($group = null) 2658 { 2659 $conversionGroups = []; 2660 foreach (self::$conversionUnits as $conversionUnit => $conversionGroup) { 2661 if (($group === null) || ($conversionGroup['Group'] == $group)) { 2662 $conversionGroups[$conversionGroup['Group']][] = $conversionUnit; 2663 } 2664 } 2665 2666 return $conversionGroups; 2667 } 2668 2669 /** 2670 * getConversionGroupUnitDetails. 2671 * 2672 * @param string $group The group whose units of measure you want to retrieve 2673 * 2674 * @return array 2675 */ 2676 public static function getConversionGroupUnitDetails($group = null) 2677 { 2678 $conversionGroups = []; 2679 foreach (self::$conversionUnits as $conversionUnit => $conversionGroup) { 2680 if (($group === null) || ($conversionGroup['Group'] == $group)) { 2681 $conversionGroups[$conversionGroup['Group']][] = [ 2682 'unit' => $conversionUnit, 2683 'description' => $conversionGroup['Unit Name'], 2684 ]; 2685 } 2686 } 2687 2688 return $conversionGroups; 2689 } 2690 2691 /** 2692 * getConversionMultipliers 2693 * Returns an array of the Multiplier prefixes that can be used with Units of Measure in CONVERTUOM(). 2694 * 2695 * @return array of mixed 2696 */ 2697 public static function getConversionMultipliers() 2698 { 2699 return self::$conversionMultipliers; 2700 } 2701 2702 /** 2703 * CONVERTUOM. 2704 * 2705 * Converts a number from one measurement system to another. 2706 * For example, CONVERT can translate a table of distances in miles to a table of distances 2707 * in kilometers. 2708 * 2709 * Excel Function: 2710 * CONVERT(value,fromUOM,toUOM) 2711 * 2712 * @param float $value the value in fromUOM to convert 2713 * @param string $fromUOM the units for value 2714 * @param string $toUOM the units for the result 2715 * 2716 * @return float|string 2717 */ 2718 public static function CONVERTUOM($value, $fromUOM, $toUOM) 2719 { 2720 $value = Functions::flattenSingleValue($value); 2721 $fromUOM = Functions::flattenSingleValue($fromUOM); 2722 $toUOM = Functions::flattenSingleValue($toUOM); 2723 2724 if (!is_numeric($value)) { 2725 return Functions::VALUE(); 2726 } 2727 $fromMultiplier = 1.0; 2728 if (isset(self::$conversionUnits[$fromUOM])) { 2729 $unitGroup1 = self::$conversionUnits[$fromUOM]['Group']; 2730 } else { 2731 $fromMultiplier = substr($fromUOM, 0, 1); 2732 $fromUOM = substr($fromUOM, 1); 2733 if (isset(self::$conversionMultipliers[$fromMultiplier])) { 2734 $fromMultiplier = self::$conversionMultipliers[$fromMultiplier]['multiplier']; 2735 } else { 2736 return Functions::NA(); 2737 } 2738 if ((isset(self::$conversionUnits[$fromUOM])) && (self::$conversionUnits[$fromUOM]['AllowPrefix'])) { 2739 $unitGroup1 = self::$conversionUnits[$fromUOM]['Group']; 2740 } else { 2741 return Functions::NA(); 2742 } 2743 } 2744 $value *= $fromMultiplier; 2745 2746 $toMultiplier = 1.0; 2747 if (isset(self::$conversionUnits[$toUOM])) { 2748 $unitGroup2 = self::$conversionUnits[$toUOM]['Group']; 2749 } else { 2750 $toMultiplier = substr($toUOM, 0, 1); 2751 $toUOM = substr($toUOM, 1); 2752 if (isset(self::$conversionMultipliers[$toMultiplier])) { 2753 $toMultiplier = self::$conversionMultipliers[$toMultiplier]['multiplier']; 2754 } else { 2755 return Functions::NA(); 2756 } 2757 if ((isset(self::$conversionUnits[$toUOM])) && (self::$conversionUnits[$toUOM]['AllowPrefix'])) { 2758 $unitGroup2 = self::$conversionUnits[$toUOM]['Group']; 2759 } else { 2760 return Functions::NA(); 2761 } 2762 } 2763 if ($unitGroup1 != $unitGroup2) { 2764 return Functions::NA(); 2765 } 2766 2767 if (($fromUOM == $toUOM) && ($fromMultiplier == $toMultiplier)) { 2768 // We've already factored $fromMultiplier into the value, so we need 2769 // to reverse it again 2770 return $value / $fromMultiplier; 2771 } elseif ($unitGroup1 == 'Temperature') { 2772 if (($fromUOM == 'F') || ($fromUOM == 'fah')) { 2773 if (($toUOM == 'F') || ($toUOM == 'fah')) { 2774 return $value; 2775 } 2776 $value = (($value - 32) / 1.8); 2777 if (($toUOM == 'K') || ($toUOM == 'kel')) { 2778 $value += 273.15; 2779 } 2780 2781 return $value; 2782 } elseif ((($fromUOM == 'K') || ($fromUOM == 'kel')) && 2783 (($toUOM == 'K') || ($toUOM == 'kel')) 2784 ) { 2785 return $value; 2786 } elseif ((($fromUOM == 'C') || ($fromUOM == 'cel')) && 2787 (($toUOM == 'C') || ($toUOM == 'cel')) 2788 ) { 2789 return $value; 2790 } 2791 if (($toUOM == 'F') || ($toUOM == 'fah')) { 2792 if (($fromUOM == 'K') || ($fromUOM == 'kel')) { 2793 $value -= 273.15; 2794 } 2795 2796 return ($value * 1.8) + 32; 2797 } 2798 if (($toUOM == 'C') || ($toUOM == 'cel')) { 2799 return $value - 273.15; 2800 } 2801 2802 return $value + 273.15; 2803 } 2804 2805 return ($value * self::$unitConversions[$unitGroup1][$fromUOM][$toUOM]) / $toMultiplier; 2806 } 2807 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body