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