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