[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/phpexcel/PHPExcel/Calculation/ -> Engineering.php (source)

   1  <?php
   2  
   3  /** PHPExcel root directory */
   4  if (!defined('PHPEXCEL_ROOT')) {
   5      /**
   6       * @ignore
   7       */
   8      define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../');
   9      require (PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
  10  }
  11  
  12  /** EULER */
  13  define('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   */
  40  class 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  }


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1