PHPExcel_Calculation_Engineering::IMABS()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 7
rs 9.4285
1
<?php
2
/**
3
 * PHPExcel
4
 *
5
 * Copyright (c) 2006 - 2012 PHPExcel
6
 *
7
 * This library is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * This library is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with this library; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 *
21
 * @category	PHPExcel
22
 * @package		PHPExcel_Calculation
23
 * @copyright	Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
24
 * @license		http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt	LGPL
25
 * @version		1.7.7, 2012-05-19
26
 */
27
28
29
/** PHPExcel root directory */
30 View Code Duplication
if (!defined('PHPEXCEL_ROOT')) {
31
	/**
32
	 * @ignore
33
	 */
34
	define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../');
35
	require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
36
}
37
38
39
/** EULER */
40
define('EULER', 2.71828182845904523536);
41
42
43
/**
44
 * PHPExcel_Calculation_Engineering
45
 *
46
 * @category	PHPExcel
47
 * @package		PHPExcel_Calculation
48
 * @copyright	Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
49
 */
50
class PHPExcel_Calculation_Engineering {
51
52
	/**
53
	 * Details of the Units of measure that can be used in CONVERTUOM()
54
	 *
55
	 * @var mixed[]
56
	 */
57
	private static $_conversionUnits = array( 'g'		=> array(	'Group'	=> 'Mass',			'Unit Name'	=> 'Gram',						'AllowPrefix'	=> True		),
58
											  'sg'		=> array(	'Group'	=> 'Mass',			'Unit Name'	=> 'Slug',						'AllowPrefix'	=> False	),
59
											  'lbm'		=> array(	'Group'	=> 'Mass',			'Unit Name'	=> 'Pound mass (avoirdupois)',	'AllowPrefix'	=> False	),
60
											  'u'		=> array(	'Group'	=> 'Mass',			'Unit Name'	=> 'U (atomic mass unit)',		'AllowPrefix'	=> True		),
61
											  'ozm'		=> array(	'Group'	=> 'Mass',			'Unit Name'	=> 'Ounce mass (avoirdupois)',	'AllowPrefix'	=> False	),
62
											  'm'		=> array(	'Group'	=> 'Distance',		'Unit Name'	=> 'Meter',						'AllowPrefix'	=> True		),
63
											  'mi'		=> array(	'Group'	=> 'Distance',		'Unit Name'	=> 'Statute mile',				'AllowPrefix'	=> False	),
64
											  'Nmi'		=> array(	'Group'	=> 'Distance',		'Unit Name'	=> 'Nautical mile',				'AllowPrefix'	=> False	),
65
											  'in'		=> array(	'Group'	=> 'Distance',		'Unit Name'	=> 'Inch',						'AllowPrefix'	=> False	),
66
											  'ft'		=> array(	'Group'	=> 'Distance',		'Unit Name'	=> 'Foot',						'AllowPrefix'	=> False	),
67
											  'yd'		=> array(	'Group'	=> 'Distance',		'Unit Name'	=> 'Yard',						'AllowPrefix'	=> False	),
68
											  'ang'		=> array(	'Group'	=> 'Distance',		'Unit Name'	=> 'Angstrom',					'AllowPrefix'	=> True		),
69
											  'Pica'	=> array(	'Group'	=> 'Distance',		'Unit Name'	=> 'Pica (1/72 in)',			'AllowPrefix'	=> False	),
70
											  'yr'		=> array(	'Group'	=> 'Time',			'Unit Name'	=> 'Year',						'AllowPrefix'	=> False	),
71
											  'day'		=> array(	'Group'	=> 'Time',			'Unit Name'	=> 'Day',						'AllowPrefix'	=> False	),
72
											  'hr'		=> array(	'Group'	=> 'Time',			'Unit Name'	=> 'Hour',						'AllowPrefix'	=> False	),
73
											  'mn'		=> array(	'Group'	=> 'Time',			'Unit Name'	=> 'Minute',					'AllowPrefix'	=> False	),
74
											  'sec'		=> array(	'Group'	=> 'Time',			'Unit Name'	=> 'Second',					'AllowPrefix'	=> True		),
75
											  'Pa'		=> array(	'Group'	=> 'Pressure',		'Unit Name'	=> 'Pascal',					'AllowPrefix'	=> True		),
76
											  'p'		=> array(	'Group'	=> 'Pressure',		'Unit Name'	=> 'Pascal',					'AllowPrefix'	=> True		),
77
											  'atm'		=> array(	'Group'	=> 'Pressure',		'Unit Name'	=> 'Atmosphere',				'AllowPrefix'	=> True		),
78
											  'at'		=> array(	'Group'	=> 'Pressure',		'Unit Name'	=> 'Atmosphere',				'AllowPrefix'	=> True		),
79
											  'mmHg'	=> array(	'Group'	=> 'Pressure',		'Unit Name'	=> 'mm of Mercury',				'AllowPrefix'	=> True		),
80
											  'N'		=> array(	'Group'	=> 'Force',			'Unit Name'	=> 'Newton',					'AllowPrefix'	=> True		),
81
											  'dyn'		=> array(	'Group'	=> 'Force',			'Unit Name'	=> 'Dyne',						'AllowPrefix'	=> True		),
82
											  'dy'		=> array(	'Group'	=> 'Force',			'Unit Name'	=> 'Dyne',						'AllowPrefix'	=> True		),
83
											  'lbf'		=> array(	'Group'	=> 'Force',			'Unit Name'	=> 'Pound force',				'AllowPrefix'	=> False	),
84
											  'J'		=> array(	'Group'	=> 'Energy',		'Unit Name'	=> 'Joule',						'AllowPrefix'	=> True		),
85
											  'e'		=> array(	'Group'	=> 'Energy',		'Unit Name'	=> 'Erg',						'AllowPrefix'	=> True		),
86
											  'c'		=> array(	'Group'	=> 'Energy',		'Unit Name'	=> 'Thermodynamic calorie',		'AllowPrefix'	=> True		),
87
											  'cal'		=> array(	'Group'	=> 'Energy',		'Unit Name'	=> 'IT calorie',				'AllowPrefix'	=> True		),
88
											  'eV'		=> array(	'Group'	=> 'Energy',		'Unit Name'	=> 'Electron volt',				'AllowPrefix'	=> True		),
89
											  'ev'		=> array(	'Group'	=> 'Energy',		'Unit Name'	=> 'Electron volt',				'AllowPrefix'	=> True		),
90
											  'HPh'		=> array(	'Group'	=> 'Energy',		'Unit Name'	=> 'Horsepower-hour',			'AllowPrefix'	=> False	),
91
											  'hh'		=> array(	'Group'	=> 'Energy',		'Unit Name'	=> 'Horsepower-hour',			'AllowPrefix'	=> False	),
92
											  'Wh'		=> array(	'Group'	=> 'Energy',		'Unit Name'	=> 'Watt-hour',					'AllowPrefix'	=> True		),
93
											  'wh'		=> array(	'Group'	=> 'Energy',		'Unit Name'	=> 'Watt-hour',					'AllowPrefix'	=> True		),
94
											  'flb'		=> array(	'Group'	=> 'Energy',		'Unit Name'	=> 'Foot-pound',				'AllowPrefix'	=> False	),
95
											  'BTU'		=> array(	'Group'	=> 'Energy',		'Unit Name'	=> 'BTU',						'AllowPrefix'	=> False	),
96
											  'btu'		=> array(	'Group'	=> 'Energy',		'Unit Name'	=> 'BTU',						'AllowPrefix'	=> False	),
97
											  'HP'		=> array(	'Group'	=> 'Power',			'Unit Name'	=> 'Horsepower',				'AllowPrefix'	=> False	),
98
											  'h'		=> array(	'Group'	=> 'Power',			'Unit Name'	=> 'Horsepower',				'AllowPrefix'	=> False	),
99
											  'W'		=> array(	'Group'	=> 'Power',			'Unit Name'	=> 'Watt',						'AllowPrefix'	=> True		),
100
											  'w'		=> array(	'Group'	=> 'Power',			'Unit Name'	=> 'Watt',						'AllowPrefix'	=> True		),
101
											  'T'		=> array(	'Group'	=> 'Magnetism',		'Unit Name'	=> 'Tesla',						'AllowPrefix'	=> True		),
102
											  'ga'		=> array(	'Group'	=> 'Magnetism',		'Unit Name'	=> 'Gauss',						'AllowPrefix'	=> True		),
103
											  'C'		=> array(	'Group'	=> 'Temperature',	'Unit Name'	=> 'Celsius',					'AllowPrefix'	=> False	),
104
											  'cel'		=> array(	'Group'	=> 'Temperature',	'Unit Name'	=> 'Celsius',					'AllowPrefix'	=> False	),
105
											  'F'		=> array(	'Group'	=> 'Temperature',	'Unit Name'	=> 'Fahrenheit',				'AllowPrefix'	=> False	),
106
											  'fah'		=> array(	'Group'	=> 'Temperature',	'Unit Name'	=> 'Fahrenheit',				'AllowPrefix'	=> False	),
107
											  'K'		=> array(	'Group'	=> 'Temperature',	'Unit Name'	=> 'Kelvin',					'AllowPrefix'	=> False	),
108
											  'kel'		=> array(	'Group'	=> 'Temperature',	'Unit Name'	=> 'Kelvin',					'AllowPrefix'	=> False	),
109
											  'tsp'		=> array(	'Group'	=> 'Liquid',		'Unit Name'	=> 'Teaspoon',					'AllowPrefix'	=> False	),
110
											  'tbs'		=> array(	'Group'	=> 'Liquid',		'Unit Name'	=> 'Tablespoon',				'AllowPrefix'	=> False	),
111
											  'oz'		=> array(	'Group'	=> 'Liquid',		'Unit Name'	=> 'Fluid Ounce',				'AllowPrefix'	=> False	),
112
											  'cup'		=> array(	'Group'	=> 'Liquid',		'Unit Name'	=> 'Cup',						'AllowPrefix'	=> False	),
113
											  'pt'		=> array(	'Group'	=> 'Liquid',		'Unit Name'	=> 'U.S. Pint',					'AllowPrefix'	=> False	),
114
											  'us_pt'	=> array(	'Group'	=> 'Liquid',		'Unit Name'	=> 'U.S. Pint',					'AllowPrefix'	=> False	),
115
											  'uk_pt'	=> array(	'Group'	=> 'Liquid',		'Unit Name'	=> 'U.K. Pint',					'AllowPrefix'	=> False	),
116
											  'qt'		=> array(	'Group'	=> 'Liquid',		'Unit Name'	=> 'Quart',						'AllowPrefix'	=> False	),
117
											  'gal'		=> array(	'Group'	=> 'Liquid',		'Unit Name'	=> 'Gallon',					'AllowPrefix'	=> False	),
118
											  'l'		=> array(	'Group'	=> 'Liquid',		'Unit Name'	=> 'Litre',						'AllowPrefix'	=> True		),
119
											  'lt'		=> array(	'Group'	=> 'Liquid',		'Unit Name'	=> 'Litre',						'AllowPrefix'	=> True		)
120
											);
121
122
	/**
123
	 * Details of the Multiplier prefixes that can be used with Units of Measure in CONVERTUOM()
124
	 *
125
	 * @var mixed[]
126
	 */
127
	private static $_conversionMultipliers = array(	'Y'	=> array(	'multiplier'	=> 1E24,	'name'	=> 'yotta'	),
128
													'Z'	=> array(	'multiplier'	=> 1E21,	'name'	=> 'zetta'	),
129
													'E'	=> array(	'multiplier'	=> 1E18,	'name'	=> 'exa'	),
130
													'P'	=> array(	'multiplier'	=> 1E15,	'name'	=> 'peta'	),
131
													'T'	=> array(	'multiplier'	=> 1E12,	'name'	=> 'tera'	),
132
													'G'	=> array(	'multiplier'	=> 1E9,		'name'	=> 'giga'	),
133
													'M'	=> array(	'multiplier'	=> 1E6,		'name'	=> 'mega'	),
134
													'k'	=> array(	'multiplier'	=> 1E3,		'name'	=> 'kilo'	),
135
													'h'	=> array(	'multiplier'	=> 1E2,		'name'	=> 'hecto'	),
136
													'e'	=> array(	'multiplier'	=> 1E1,		'name'	=> 'deka'	),
137
													'd'	=> array(	'multiplier'	=> 1E-1,	'name'	=> 'deci'	),
138
													'c'	=> array(	'multiplier'	=> 1E-2,	'name'	=> 'centi'	),
139
													'm'	=> array(	'multiplier'	=> 1E-3,	'name'	=> 'milli'	),
140
													'u'	=> array(	'multiplier'	=> 1E-6,	'name'	=> 'micro'	),
141
													'n'	=> array(	'multiplier'	=> 1E-9,	'name'	=> 'nano'	),
142
													'p'	=> array(	'multiplier'	=> 1E-12,	'name'	=> 'pico'	),
143
													'f'	=> array(	'multiplier'	=> 1E-15,	'name'	=> 'femto'	),
144
													'a'	=> array(	'multiplier'	=> 1E-18,	'name'	=> 'atto'	),
145
													'z'	=> array(	'multiplier'	=> 1E-21,	'name'	=> 'zepto'	),
146
													'y'	=> array(	'multiplier'	=> 1E-24,	'name'	=> 'yocto'	)
147
												 );
148
149
	/**
150
	 * Details of the Units of measure conversion factors, organised by group
151
	 *
152
	 * @var mixed[]
153
	 */
154
	private static $_unitConversions = array(	'Mass'		=> array(	'g'		=> array(	'g'		=> 1.0,
155
																							'sg'	=> 6.85220500053478E-05,
156
																							'lbm'	=> 2.20462291469134E-03,
157
																							'u'		=> 6.02217000000000E+23,
158
																							'ozm'	=> 3.52739718003627E-02
159
																						),
160
																		'sg'	=> array(	'g'		=> 1.45938424189287E+04,
161
																							'sg'	=> 1.0,
162
																							'lbm'	=> 3.21739194101647E+01,
163
																							'u'		=> 8.78866000000000E+27,
164
																							'ozm'	=> 5.14782785944229E+02
165
																						),
166
																		'lbm'	=> array(	'g'		=> 4.5359230974881148E+02,
167
																							'sg'	=> 3.10810749306493E-02,
168
																							'lbm'	=> 1.0,
169
																							'u'		=> 2.73161000000000E+26,
170
																							'ozm'	=> 1.60000023429410E+01
171
																						),
172
																		'u'		=> array(	'g'		=> 1.66053100460465E-24,
173
																							'sg'	=> 1.13782988532950E-28,
174
																							'lbm'	=> 3.66084470330684E-27,
175
																							'u'		=> 1.0,
176
																							'ozm'	=> 5.85735238300524E-26
177
																						),
178
																		'ozm'	=> array(	'g'		=> 2.83495152079732E+01,
179
																							'sg'	=> 1.94256689870811E-03,
180
																							'lbm'	=> 6.24999908478882E-02,
181
																							'u'		=> 1.70725600000000E+25,
182
																							'ozm'	=> 1.0
183
																						)
184
																	),
185
												'Distance'	=> array(	'm'		=> array(	'm'		=> 1.0,
186
																							'mi'	=> 6.21371192237334E-04,
187
																							'Nmi'	=> 5.39956803455724E-04,
188
																							'in'	=> 3.93700787401575E+01,
189
																							'ft'	=> 3.28083989501312E+00,
190
																							'yd'	=> 1.09361329797891E+00,
191
																							'ang'	=> 1.00000000000000E+10,
192
																							'Pica'	=> 2.83464566929116E+03
193
																						),
194
																		'mi'	=> array(	'm'		=> 1.60934400000000E+03,
195
																							'mi'	=> 1.0,
196
																							'Nmi'	=> 8.68976241900648E-01,
197
																							'in'	=> 6.33600000000000E+04,
198
																							'ft'	=> 5.28000000000000E+03,
199
																							'yd'	=> 1.76000000000000E+03,
200
																							'ang'	=> 1.60934400000000E+13,
201
																							'Pica'	=> 4.56191999999971E+06
202
																						),
203
																		'Nmi'	=> array(	'm'		=> 1.85200000000000E+03,
204
																							'mi'	=> 1.15077944802354E+00,
205
																							'Nmi'	=> 1.0,
206
																							'in'	=> 7.29133858267717E+04,
207
																							'ft'	=> 6.07611548556430E+03,
208
																							'yd'	=> 2.02537182785694E+03,
209
																							'ang'	=> 1.85200000000000E+13,
210
																							'Pica'	=> 5.24976377952723E+06
211
																						),
212
																		'in'	=> array(	'm'		=> 2.54000000000000E-02,
213
																							'mi'	=> 1.57828282828283E-05,
214
																							'Nmi'	=> 1.37149028077754E-05,
215
																							'in'	=> 1.0,
216
																							'ft'	=> 8.33333333333333E-02,
217
																							'yd'	=> 2.77777777686643E-02,
218
																							'ang'	=> 2.54000000000000E+08,
219
																							'Pica'	=> 7.19999999999955E+01
220
																						),
221
																		'ft'	=> array(	'm'		=> 3.04800000000000E-01,
222
																							'mi'	=> 1.89393939393939E-04,
223
																							'Nmi'	=> 1.64578833693305E-04,
224
																							'in'	=> 1.20000000000000E+01,
225
																							'ft'	=> 1.0,
226
																							'yd'	=> 3.33333333223972E-01,
227
																							'ang'	=> 3.04800000000000E+09,
228
																							'Pica'	=> 8.63999999999946E+02
229
																						),
230
																		'yd'	=> array(	'm'		=> 9.14400000300000E-01,
231
																							'mi'	=> 5.68181818368230E-04,
232
																							'Nmi'	=> 4.93736501241901E-04,
233
																							'in'	=> 3.60000000118110E+01,
234
																							'ft'	=> 3.00000000000000E+00,
235
																							'yd'	=> 1.0,
236
																							'ang'	=> 9.14400000300000E+09,
237
																							'Pica'	=> 2.59200000085023E+03
238
																						),
239
																		'ang'	=> array(	'm'		=> 1.00000000000000E-10,
240
																							'mi'	=> 6.21371192237334E-14,
241
																							'Nmi'	=> 5.39956803455724E-14,
242
																							'in'	=> 3.93700787401575E-09,
243
																							'ft'	=> 3.28083989501312E-10,
244
																							'yd'	=> 1.09361329797891E-10,
245
																							'ang'	=> 1.0,
246
																							'Pica'	=> 2.83464566929116E-07
247
																						),
248
																		'Pica'	=> array(	'm'		=> 3.52777777777800E-04,
249
																							'mi'	=> 2.19205948372629E-07,
250
																							'Nmi'	=> 1.90484761219114E-07,
251
																							'in'	=> 1.38888888888898E-02,
252
																							'ft'	=> 1.15740740740748E-03,
253
																							'yd'	=> 3.85802469009251E-04,
254
																							'ang'	=> 3.52777777777800E+06,
255
																							'Pica'	=> 1.0
256
																						)
257
																	),
258
												'Time'		=> array(	'yr'	=> array(	'yr'		=> 1.0,
259
																							'day'		=> 365.25,
260
																							'hr'		=> 8766.0,
261
																							'mn'		=> 525960.0,
262
																							'sec'		=> 31557600.0
263
																						),
264
																		'day'	=> array(	'yr'		=> 2.73785078713210E-03,
265
																							'day'		=> 1.0,
266
																							'hr'		=> 24.0,
267
																							'mn'		=> 1440.0,
268
																							'sec'		=> 86400.0
269
																						),
270
																		'hr'	=> array(	'yr'		=> 1.14077116130504E-04,
271
																							'day'		=> 4.16666666666667E-02,
272
																							'hr'		=> 1.0,
273
																							'mn'		=> 60.0,
274
																							'sec'		=> 3600.0
275
																						),
276
																		'mn'	=> array(	'yr'		=> 1.90128526884174E-06,
277
																							'day'		=> 6.94444444444444E-04,
278
																							'hr'		=> 1.66666666666667E-02,
279
																							'mn'		=> 1.0,
280
																							'sec'		=> 60.0
281
																						),
282
																		'sec'	=> array(	'yr'		=> 3.16880878140289E-08,
283
																							'day'		=> 1.15740740740741E-05,
284
																							'hr'		=> 2.77777777777778E-04,
285
																							'mn'		=> 1.66666666666667E-02,
286
																							'sec'		=> 1.0
287
																						)
288
																	),
289
												'Pressure'	=> array(	'Pa'	=> array(	'Pa'		=> 1.0,
290
																							'p'			=> 1.0,
291
																							'atm'		=> 9.86923299998193E-06,
292
																							'at'		=> 9.86923299998193E-06,
293
																							'mmHg'		=> 7.50061707998627E-03
294
																						),
295
																		'p'		=> array(	'Pa'		=> 1.0,
296
																							'p'			=> 1.0,
297
																							'atm'		=> 9.86923299998193E-06,
298
																							'at'		=> 9.86923299998193E-06,
299
																							'mmHg'		=> 7.50061707998627E-03
300
																						),
301
																		'atm'	=> array(	'Pa'		=> 1.01324996583000E+05,
302
																							'p'			=> 1.01324996583000E+05,
303
																							'atm'		=> 1.0,
304
																							'at'		=> 1.0,
305
																							'mmHg'		=> 760.0
306
																						),
307
																		'at'	=> array(	'Pa'		=> 1.01324996583000E+05,
308
																							'p'			=> 1.01324996583000E+05,
309
																							'atm'		=> 1.0,
310
																							'at'		=> 1.0,
311
																							'mmHg'		=> 760.0
312
																						),
313
																		'mmHg'	=> array(	'Pa'		=> 1.33322363925000E+02,
314
																							'p'			=> 1.33322363925000E+02,
315
																							'atm'		=> 1.31578947368421E-03,
316
																							'at'		=> 1.31578947368421E-03,
317
																							'mmHg'		=> 1.0
318
																						)
319
																	),
320
												'Force'		=> array(	'N'		=> array(	'N'			=> 1.0,
321
																							'dyn'		=> 1.0E+5,
322
																							'dy'		=> 1.0E+5,
323
																							'lbf'		=> 2.24808923655339E-01
324
																						),
325
																		'dyn'	=> array(	'N'			=> 1.0E-5,
326
																							'dyn'		=> 1.0,
327
																							'dy'		=> 1.0,
328
																							'lbf'		=> 2.24808923655339E-06
329
																						),
330
																		'dy'	=> array(	'N'			=> 1.0E-5,
331
																							'dyn'		=> 1.0,
332
																							'dy'		=> 1.0,
333
																							'lbf'		=> 2.24808923655339E-06
334
																						),
335
																		'lbf'	=> array(	'N'			=> 4.448222,
336
																							'dyn'		=> 4.448222E+5,
337
																							'dy'		=> 4.448222E+5,
338
																							'lbf'		=> 1.0
339
																						)
340
																	),
341
												'Energy'	=> array(	'J'		=> array(	'J'			=> 1.0,
342
																							'e'			=> 9.99999519343231E+06,
343
																							'c'			=> 2.39006249473467E-01,
344
																							'cal'		=> 2.38846190642017E-01,
345
																							'eV'		=> 6.24145700000000E+18,
346
																							'ev'		=> 6.24145700000000E+18,
347
																							'HPh'		=> 3.72506430801000E-07,
348
																							'hh'		=> 3.72506430801000E-07,
349
																							'Wh'		=> 2.77777916238711E-04,
350
																							'wh'		=> 2.77777916238711E-04,
351
																							'flb'		=> 2.37304222192651E+01,
352
																							'BTU'		=> 9.47815067349015E-04,
353
																							'btu'		=> 9.47815067349015E-04
354
																						),
355
																		'e'		=> array(	'J'			=> 1.00000048065700E-07,
356
																							'e'			=> 1.0,
357
																							'c'			=> 2.39006364353494E-08,
358
																							'cal'		=> 2.38846305445111E-08,
359
																							'eV'		=> 6.24146000000000E+11,
360
																							'ev'		=> 6.24146000000000E+11,
361
																							'HPh'		=> 3.72506609848824E-14,
362
																							'hh'		=> 3.72506609848824E-14,
363
																							'Wh'		=> 2.77778049754611E-11,
364
																							'wh'		=> 2.77778049754611E-11,
365
																							'flb'		=> 2.37304336254586E-06,
366
																							'BTU'		=> 9.47815522922962E-11,
367
																							'btu'		=> 9.47815522922962E-11
368
																						),
369
																		'c'		=> array(	'J'			=> 4.18399101363672E+00,
370
																							'e'			=> 4.18398900257312E+07,
371
																							'c'			=> 1.0,
372
																							'cal'		=> 9.99330315287563E-01,
373
																							'eV'		=> 2.61142000000000E+19,
374
																							'ev'		=> 2.61142000000000E+19,
375
																							'HPh'		=> 1.55856355899327E-06,
376
																							'hh'		=> 1.55856355899327E-06,
377
																							'Wh'		=> 1.16222030532950E-03,
378
																							'wh'		=> 1.16222030532950E-03,
379
																							'flb'		=> 9.92878733152102E+01,
380
																							'BTU'		=> 3.96564972437776E-03,
381
																							'btu'		=> 3.96564972437776E-03
382
																						),
383
																		'cal'	=> array(	'J'			=> 4.18679484613929E+00,
384
																							'e'			=> 4.18679283372801E+07,
385
																							'c'			=> 1.00067013349059E+00,
386
																							'cal'		=> 1.0,
387
																							'eV'		=> 2.61317000000000E+19,
388
																							'ev'		=> 2.61317000000000E+19,
389
																							'HPh'		=> 1.55960800463137E-06,
390
																							'hh'		=> 1.55960800463137E-06,
391
																							'Wh'		=> 1.16299914807955E-03,
392
																							'wh'		=> 1.16299914807955E-03,
393
																							'flb'		=> 9.93544094443283E+01,
394
																							'BTU'		=> 3.96830723907002E-03,
395
																							'btu'		=> 3.96830723907002E-03
396
																						),
397
																		'eV'	=> array(	'J'			=> 1.60219000146921E-19,
398
																							'e'			=> 1.60218923136574E-12,
399
																							'c'			=> 3.82933423195043E-20,
400
																							'cal'		=> 3.82676978535648E-20,
401
																							'eV'		=> 1.0,
402
																							'ev'		=> 1.0,
403
																							'HPh'		=> 5.96826078912344E-26,
404
																							'hh'		=> 5.96826078912344E-26,
405
																							'Wh'		=> 4.45053000026614E-23,
406
																							'wh'		=> 4.45053000026614E-23,
407
																							'flb'		=> 3.80206452103492E-18,
408
																							'BTU'		=> 1.51857982414846E-22,
409
																							'btu'		=> 1.51857982414846E-22
410
																						),
411
																		'ev'	=> array(	'J'			=> 1.60219000146921E-19,
412
																							'e'			=> 1.60218923136574E-12,
413
																							'c'			=> 3.82933423195043E-20,
414
																							'cal'		=> 3.82676978535648E-20,
415
																							'eV'		=> 1.0,
416
																							'ev'		=> 1.0,
417
																							'HPh'		=> 5.96826078912344E-26,
418
																							'hh'		=> 5.96826078912344E-26,
419
																							'Wh'		=> 4.45053000026614E-23,
420
																							'wh'		=> 4.45053000026614E-23,
421
																							'flb'		=> 3.80206452103492E-18,
422
																							'BTU'		=> 1.51857982414846E-22,
423
																							'btu'		=> 1.51857982414846E-22
424
																						),
425
																		'HPh'	=> array(	'J'			=> 2.68451741316170E+06,
426
																							'e'			=> 2.68451612283024E+13,
427
																							'c'			=> 6.41616438565991E+05,
428
																							'cal'		=> 6.41186757845835E+05,
429
																							'eV'		=> 1.67553000000000E+25,
430
																							'ev'		=> 1.67553000000000E+25,
431
																							'HPh'		=> 1.0,
432
																							'hh'		=> 1.0,
433
																							'Wh'		=> 7.45699653134593E+02,
434
																							'wh'		=> 7.45699653134593E+02,
435
																							'flb'		=> 6.37047316692964E+07,
436
																							'BTU'		=> 2.54442605275546E+03,
437
																							'btu'		=> 2.54442605275546E+03
438
																						),
439
																		'hh'	=> array(	'J'			=> 2.68451741316170E+06,
440
																							'e'			=> 2.68451612283024E+13,
441
																							'c'			=> 6.41616438565991E+05,
442
																							'cal'		=> 6.41186757845835E+05,
443
																							'eV'		=> 1.67553000000000E+25,
444
																							'ev'		=> 1.67553000000000E+25,
445
																							'HPh'		=> 1.0,
446
																							'hh'		=> 1.0,
447
																							'Wh'		=> 7.45699653134593E+02,
448
																							'wh'		=> 7.45699653134593E+02,
449
																							'flb'		=> 6.37047316692964E+07,
450
																							'BTU'		=> 2.54442605275546E+03,
451
																							'btu'		=> 2.54442605275546E+03
452
																						),
453
																		'Wh'	=> array(	'J'			=> 3.59999820554720E+03,
454
																							'e'			=> 3.59999647518369E+10,
455
																							'c'			=> 8.60422069219046E+02,
456
																							'cal'		=> 8.59845857713046E+02,
457
																							'eV'		=> 2.24692340000000E+22,
458
																							'ev'		=> 2.24692340000000E+22,
459
																							'HPh'		=> 1.34102248243839E-03,
460
																							'hh'		=> 1.34102248243839E-03,
461
																							'Wh'		=> 1.0,
462
																							'wh'		=> 1.0,
463
																							'flb'		=> 8.54294774062316E+04,
464
																							'BTU'		=> 3.41213254164705E+00,
465
																							'btu'		=> 3.41213254164705E+00
466
																						),
467
																		'wh'	=> array(	'J'			=> 3.59999820554720E+03,
468
																							'e'			=> 3.59999647518369E+10,
469
																							'c'			=> 8.60422069219046E+02,
470
																							'cal'		=> 8.59845857713046E+02,
471
																							'eV'		=> 2.24692340000000E+22,
472
																							'ev'		=> 2.24692340000000E+22,
473
																							'HPh'		=> 1.34102248243839E-03,
474
																							'hh'		=> 1.34102248243839E-03,
475
																							'Wh'		=> 1.0,
476
																							'wh'		=> 1.0,
477
																							'flb'		=> 8.54294774062316E+04,
478
																							'BTU'		=> 3.41213254164705E+00,
479
																							'btu'		=> 3.41213254164705E+00
480
																						),
481
																		'flb'	=> array(	'J'			=> 4.21400003236424E-02,
482
																							'e'			=> 4.21399800687660E+05,
483
																							'c'			=> 1.00717234301644E-02,
484
																							'cal'		=> 1.00649785509554E-02,
485
																							'eV'		=> 2.63015000000000E+17,
486
																							'ev'		=> 2.63015000000000E+17,
487
																							'HPh'		=> 1.56974211145130E-08,
488
																							'hh'		=> 1.56974211145130E-08,
489
																							'Wh'		=> 1.17055614802000E-05,
490
																							'wh'		=> 1.17055614802000E-05,
491
																							'flb'		=> 1.0,
492
																							'BTU'		=> 3.99409272448406E-05,
493
																							'btu'		=> 3.99409272448406E-05
494
																						),
495
																		'BTU'	=> array(	'J'			=> 1.05505813786749E+03,
496
																							'e'			=> 1.05505763074665E+10,
497
																							'c'			=> 2.52165488508168E+02,
498
																							'cal'		=> 2.51996617135510E+02,
499
																							'eV'		=> 6.58510000000000E+21,
500
																							'ev'		=> 6.58510000000000E+21,
501
																							'HPh'		=> 3.93015941224568E-04,
502
																							'hh'		=> 3.93015941224568E-04,
503
																							'Wh'		=> 2.93071851047526E-01,
504
																							'wh'		=> 2.93071851047526E-01,
505
																							'flb'		=> 2.50369750774671E+04,
506
																							'BTU'		=> 1.0,
507
																							'btu'		=> 1.0,
508
																						),
509
																		'btu'	=> array(	'J'			=> 1.05505813786749E+03,
510
																							'e'			=> 1.05505763074665E+10,
511
																							'c'			=> 2.52165488508168E+02,
512
																							'cal'		=> 2.51996617135510E+02,
513
																							'eV'		=> 6.58510000000000E+21,
514
																							'ev'		=> 6.58510000000000E+21,
515
																							'HPh'		=> 3.93015941224568E-04,
516
																							'hh'		=> 3.93015941224568E-04,
517
																							'Wh'		=> 2.93071851047526E-01,
518
																							'wh'		=> 2.93071851047526E-01,
519
																							'flb'		=> 2.50369750774671E+04,
520
																							'BTU'		=> 1.0,
521
																							'btu'		=> 1.0,
522
																						)
523
																	),
524
												'Power'		=> array(	'HP'	=> array(	'HP'		=> 1.0,
525
																							'h'			=> 1.0,
526
																							'W'			=> 7.45701000000000E+02,
527
																							'w'			=> 7.45701000000000E+02
528
																						),
529
																		'h'		=> array(	'HP'		=> 1.0,
530
																							'h'			=> 1.0,
531
																							'W'			=> 7.45701000000000E+02,
532
																							'w'			=> 7.45701000000000E+02
533
																						),
534
																		'W'		=> array(	'HP'		=> 1.34102006031908E-03,
535
																							'h'			=> 1.34102006031908E-03,
536
																							'W'			=> 1.0,
537
																							'w'			=> 1.0
538
																						),
539
																		'w'		=> array(	'HP'		=> 1.34102006031908E-03,
540
																							'h'			=> 1.34102006031908E-03,
541
																							'W'			=> 1.0,
542
																							'w'			=> 1.0
543
																						)
544
																	),
545
												'Magnetism'	=> array(	'T'		=> array(	'T'			=> 1.0,
546
																							'ga'		=> 10000.0
547
																						),
548
																		'ga'	=> array(	'T'			=> 0.0001,
549
																							'ga'		=> 1.0
550
																						)
551
																	),
552
												'Liquid'	=> array(	'tsp'	=> array(	'tsp'		=> 1.0,
553
																							'tbs'		=> 3.33333333333333E-01,
554
																							'oz'		=> 1.66666666666667E-01,
555
																							'cup'		=> 2.08333333333333E-02,
556
																							'pt'		=> 1.04166666666667E-02,
557
																							'us_pt'		=> 1.04166666666667E-02,
558
																							'uk_pt'		=> 8.67558516821960E-03,
559
																							'qt'		=> 5.20833333333333E-03,
560
																							'gal'		=> 1.30208333333333E-03,
561
																							'l'			=> 4.92999408400710E-03,
562
																							'lt'		=> 4.92999408400710E-03
563
																						),
564
																		'tbs'	=> array(	'tsp'		=> 3.00000000000000E+00,
565
																							'tbs'		=> 1.0,
566
																							'oz'		=> 5.00000000000000E-01,
567
																							'cup'		=> 6.25000000000000E-02,
568
																							'pt'		=> 3.12500000000000E-02,
569
																							'us_pt'		=> 3.12500000000000E-02,
570
																							'uk_pt'		=> 2.60267555046588E-02,
571
																							'qt'		=> 1.56250000000000E-02,
572
																							'gal'		=> 3.90625000000000E-03,
573
																							'l'			=> 1.47899822520213E-02,
574
																							'lt'		=> 1.47899822520213E-02
575
																						),
576
																		'oz'	=> array(	'tsp'		=> 6.00000000000000E+00,
577
																							'tbs'		=> 2.00000000000000E+00,
578
																							'oz'		=> 1.0,
579
																							'cup'		=> 1.25000000000000E-01,
580
																							'pt'		=> 6.25000000000000E-02,
581
																							'us_pt'		=> 6.25000000000000E-02,
582
																							'uk_pt'		=> 5.20535110093176E-02,
583
																							'qt'		=> 3.12500000000000E-02,
584
																							'gal'		=> 7.81250000000000E-03,
585
																							'l'			=> 2.95799645040426E-02,
586
																							'lt'		=> 2.95799645040426E-02
587
																						),
588
																		'cup'	=> array(	'tsp'		=> 4.80000000000000E+01,
589
																							'tbs'		=> 1.60000000000000E+01,
590
																							'oz'		=> 8.00000000000000E+00,
591
																							'cup'		=> 1.0,
592
																							'pt'		=> 5.00000000000000E-01,
593
																							'us_pt'		=> 5.00000000000000E-01,
594
																							'uk_pt'		=> 4.16428088074541E-01,
595
																							'qt'		=> 2.50000000000000E-01,
596
																							'gal'		=> 6.25000000000000E-02,
597
																							'l'			=> 2.36639716032341E-01,
598
																							'lt'		=> 2.36639716032341E-01
599
																						),
600
																		'pt'	=> array(	'tsp'		=> 9.60000000000000E+01,
601
																							'tbs'		=> 3.20000000000000E+01,
602
																							'oz'		=> 1.60000000000000E+01,
603
																							'cup'		=> 2.00000000000000E+00,
604
																							'pt'		=> 1.0,
605
																							'us_pt'		=> 1.0,
606
																							'uk_pt'		=> 8.32856176149081E-01,
607
																							'qt'		=> 5.00000000000000E-01,
608
																							'gal'		=> 1.25000000000000E-01,
609
																							'l'			=> 4.73279432064682E-01,
610
																							'lt'		=> 4.73279432064682E-01
611
																						),
612
																		'us_pt'	=> array(	'tsp'		=> 9.60000000000000E+01,
613
																							'tbs'		=> 3.20000000000000E+01,
614
																							'oz'		=> 1.60000000000000E+01,
615
																							'cup'		=> 2.00000000000000E+00,
616
																							'pt'		=> 1.0,
617
																							'us_pt'		=> 1.0,
618
																							'uk_pt'		=> 8.32856176149081E-01,
619
																							'qt'		=> 5.00000000000000E-01,
620
																							'gal'		=> 1.25000000000000E-01,
621
																							'l'			=> 4.73279432064682E-01,
622
																							'lt'		=> 4.73279432064682E-01
623
																						),
624
																		'uk_pt'	=> array(	'tsp'		=> 1.15266000000000E+02,
625
																							'tbs'		=> 3.84220000000000E+01,
626
																							'oz'		=> 1.92110000000000E+01,
627
																							'cup'		=> 2.40137500000000E+00,
628
																							'pt'		=> 1.20068750000000E+00,
629
																							'us_pt'		=> 1.20068750000000E+00,
630
																							'uk_pt'		=> 1.0,
631
																							'qt'		=> 6.00343750000000E-01,
632
																							'gal'		=> 1.50085937500000E-01,
633
																							'l'			=> 5.68260698087162E-01,
634
																							'lt'		=> 5.68260698087162E-01
635
																						),
636
																		'qt'	=> array(	'tsp'		=> 1.92000000000000E+02,
637
																							'tbs'		=> 6.40000000000000E+01,
638
																							'oz'		=> 3.20000000000000E+01,
639
																							'cup'		=> 4.00000000000000E+00,
640
																							'pt'		=> 2.00000000000000E+00,
641
																							'us_pt'		=> 2.00000000000000E+00,
642
																							'uk_pt'		=> 1.66571235229816E+00,
643
																							'qt'		=> 1.0,
644
																							'gal'		=> 2.50000000000000E-01,
645
																							'l'			=> 9.46558864129363E-01,
646
																							'lt'		=> 9.46558864129363E-01
647
																						),
648
																		'gal'	=> array(	'tsp'		=> 7.68000000000000E+02,
649
																							'tbs'		=> 2.56000000000000E+02,
650
																							'oz'		=> 1.28000000000000E+02,
651
																							'cup'		=> 1.60000000000000E+01,
652
																							'pt'		=> 8.00000000000000E+00,
653
																							'us_pt'		=> 8.00000000000000E+00,
654
																							'uk_pt'		=> 6.66284940919265E+00,
655
																							'qt'		=> 4.00000000000000E+00,
656
																							'gal'		=> 1.0,
657
																							'l'			=> 3.78623545651745E+00,
658
																							'lt'		=> 3.78623545651745E+00
659
																						),
660
																		'l'		=> array(	'tsp'		=> 2.02840000000000E+02,
661
																							'tbs'		=> 6.76133333333333E+01,
662
																							'oz'		=> 3.38066666666667E+01,
663
																							'cup'		=> 4.22583333333333E+00,
664
																							'pt'		=> 2.11291666666667E+00,
665
																							'us_pt'		=> 2.11291666666667E+00,
666
																							'uk_pt'		=> 1.75975569552166E+00,
667
																							'qt'		=> 1.05645833333333E+00,
668
																							'gal'		=> 2.64114583333333E-01,
669
																							'l'			=> 1.0,
670
																							'lt'		=> 1.0
671
																						),
672
																		'lt'	=> array(	'tsp'		=> 2.02840000000000E+02,
673
																							'tbs'		=> 6.76133333333333E+01,
674
																							'oz'		=> 3.38066666666667E+01,
675
																							'cup'		=> 4.22583333333333E+00,
676
																							'pt'		=> 2.11291666666667E+00,
677
																							'us_pt'		=> 2.11291666666667E+00,
678
																							'uk_pt'		=> 1.75975569552166E+00,
679
																							'qt'		=> 1.05645833333333E+00,
680
																							'gal'		=> 2.64114583333333E-01,
681
																							'l'			=> 1.0,
682
																							'lt'		=> 1.0
683
																						)
684
																	)
685
											);
686
687
688
	/**
689
	 * _parseComplex
690
	 *
691
	 * Parses a complex number into its real and imaginary parts, and an I or J suffix
692
	 *
693
	 * @param	string		$complexNumber	The complex number
694
	 * @return	string[]	Indexed on "real", "imaginary" and "suffix"
695
	 */
696
	public static function _parseComplex($complexNumber) {
697
		$workString = (string) $complexNumber;
698
699
		$realNumber = $imaginary = 0;
700
		//	Extract the suffix, if there is one
701
		$suffix = substr($workString,-1);
702
		if (!is_numeric($suffix)) {
703
			$workString = substr($workString,0,-1);
704
		} else {
705
			$suffix = '';
706
		}
707
708
		//	Split the input into its Real and Imaginary components
709
		$leadingSign = 0;
710
		if (strlen($workString) > 0) {
711
			$leadingSign = (($workString{0} == '+') || ($workString{0} == '-')) ? 1 : 0;
712
		}
713
		$power = '';
714
		$realNumber = strtok($workString, '+-');
715
		if (strtoupper(substr($realNumber,-1)) == 'E') {
716
			$power = strtok('+-');
717
			++$leadingSign;
718
		}
719
720
		$realNumber = substr($workString,0,strlen($realNumber)+strlen($power)+$leadingSign);
721
722
		if ($suffix != '') {
723
			$imaginary = substr($workString,strlen($realNumber));
724
725
			if (($imaginary == '') && (($realNumber == '') || ($realNumber == '+') || ($realNumber == '-'))) {
726
				$imaginary = $realNumber.'1';
727
				$realNumber = '0';
728
			} else if ($imaginary == '') {
729
				$imaginary = $realNumber;
730
				$realNumber = '0';
731
			} elseif (($imaginary == '+') || ($imaginary == '-')) {
732
				$imaginary .= '1';
733
			}
734
		}
735
736
		return array( 'real'		=> $realNumber,
737
					  'imaginary'	=> $imaginary,
738
					  'suffix'		=> $suffix
739
					);
740
	}	//	function _parseComplex()
741
742
743
	/**
744
	 * _cleanComplex
745
	 *
746
	 * Cleans the leading characters in a complex number string
747
	 *
748
	 * @param	string		$complexNumber	The complex number to clean
749
	 * @return	string		The "cleaned" complex number
750
	 */
751
	private static function _cleanComplex($complexNumber) {
752
		if ($complexNumber{0} == '+') $complexNumber = substr($complexNumber,1);
753
		if ($complexNumber{0} == '0') $complexNumber = substr($complexNumber,1);
754
		if ($complexNumber{0} == '.') $complexNumber = '0'.$complexNumber;
755
		if ($complexNumber{0} == '+') $complexNumber = substr($complexNumber,1);
756
		return $complexNumber;
757
	}
758
759
760
	private static function _nbrConversionFormat($xVal,$places) {
761
		if (!is_null($places)) {
762
			if (strlen($xVal) <= $places) {
763
				return substr(str_pad($xVal,$places,'0',STR_PAD_LEFT),-10);
764
			} else {
765
				return PHPExcel_Calculation_Functions::NaN();
766
			}
767
		}
768
769
		return substr($xVal,-10);
770
	}	//	function _nbrConversionFormat()
771
772
773
	/**
774
	 * BESSELI
775
	 *
776
	 * Returns the modified Bessel function, which is equivalent to the Bessel function evaluated for
777
	 * purely imaginary arguments
778
	 *
779
	 * Excel Function:
780
	 *		BESSELI(x,ord)
781
	 *
782
	 * @access	public
783
	 * @category Engineering Functions
784
	 * @param	float		$x		The value at which to evaluate the function.
785
	 *								If x is nonnumeric, BESSELI returns the #VALUE! error value.
786
	 * @param	integer		$ord	The order of the Bessel function. If n is not an integer, it is truncated.
787
	 *								If $ord is nonnumeric, BESSELI returns the #VALUE! error value.
788
	 *								If $ord < 0, BESSELI returns the #NUM! error value.
789
	 * @return	float
790
	 *
791
	 * @TODO Better handling of the approximation method to support the differences between Excel/Gnumeric and Open/Libre Office
792
	 *
793
	 */
794
	public static function BESSELI($x, $ord) {
795
		$x	= (is_null($x))	? 0.0 :	PHPExcel_Calculation_Functions::flattenSingleValue($x);
796
		$ord	= (is_null($ord))	? 0.0 :	PHPExcel_Calculation_Functions::flattenSingleValue($ord);
797
798
		if ((is_numeric($x)) && (is_numeric($ord))) {
799
			$ord	= floor($ord);
800
			if ($ord < 0) {
801
				return PHPExcel_Calculation_Functions::NaN();
802
			}
803
804
			if (abs($x) <= 30) {
805
				$fResult = $fTerm = pow($x / 2, $ord) / PHPExcel_Calculation_MathTrig::FACT($ord);
806
				$ordK = 1;
807
				$fSqrX = ($x * $x) / 4;
808 View Code Duplication
				do {
809
					$fTerm *= $fSqrX;
810
					$fTerm /= ($ordK * ($ordK + $ord));
811
					$fResult += $fTerm;
812
				} while ((abs($fTerm) > 1e-12) && (++$ordK < 100));
813
			} else {
814
				$f_2_PI = 2 * M_PI;
815
816
				$fXAbs = abs($x);
817
				$fResult = exp($fXAbs) / sqrt($f_2_PI * $fXAbs);
818
				if (($ord & 1) && ($x < 0)) {
819
					$fResult = -$fResult;
820
				}
821
			}
822
			return (is_nan($fResult)) ? PHPExcel_Calculation_Functions::NaN() : $fResult;
823
		}
824
		return PHPExcel_Calculation_Functions::VALUE();
825
	}	//	function BESSELI()
826
827
828
	/**
829
	 * BESSELJ
830
	 *
831
	 * Returns the Bessel function
832
	 *
833
	 * Excel Function:
834
	 *		BESSELJ(x,ord)
835
	 *
836
	 * @access	public
837
	 * @category Engineering Functions
838
	 * @param	float		$x		The value at which to evaluate the function.
839
	 *								If x is nonnumeric, BESSELJ returns the #VALUE! error value.
840
	 * @param	integer		$ord	The order of the Bessel function. If n is not an integer, it is truncated.
841
	 *								If $ord is nonnumeric, BESSELJ returns the #VALUE! error value.
842
	 *								If $ord < 0, BESSELJ returns the #NUM! error value.
843
	 * @return	float
844
	 *
845
	 * @TODO Better handling of the approximation method to support the differences between Excel/Gnumeric and Open/Libre Office
846
	 *
847
	 */
848
	public static function BESSELJ($x, $ord) {
849
		$x	= (is_null($x))	? 0.0 :	PHPExcel_Calculation_Functions::flattenSingleValue($x);
850
		$ord	= (is_null($ord))	? 0.0 :	PHPExcel_Calculation_Functions::flattenSingleValue($ord);
851
852
		if ((is_numeric($x)) && (is_numeric($ord))) {
853
			$ord	= floor($ord);
854
			if ($ord < 0) {
855
				return PHPExcel_Calculation_Functions::NaN();
856
			}
857
858
			$fResult = 0;
859
			if (abs($x) <= 30) {
860
				$fResult = $fTerm = pow($x / 2, $ord) / PHPExcel_Calculation_MathTrig::FACT($ord);
861
				$ordK = 1;
862
				$fSqrX = ($x * $x) / -4;
863 View Code Duplication
				do {
864
					$fTerm *= $fSqrX;
865
					$fTerm /= ($ordK * ($ordK + $ord));
866
					$fResult += $fTerm;
867
				} while ((abs($fTerm) > 1e-12) && (++$ordK < 100));
868
			} else {
869
				$f_PI_DIV_2 = M_PI / 2;
870
				$f_PI_DIV_4 = M_PI / 4;
871
872
				$fXAbs = abs($x);
873
				$fResult = sqrt(M_2DIVPI / $fXAbs) * cos($fXAbs - $ord * $f_PI_DIV_2 - $f_PI_DIV_4);
874
				if (($ord & 1) && ($x < 0)) {
875
					$fResult = -$fResult;
876
				}
877
			}
878
			return (is_nan($fResult)) ? PHPExcel_Calculation_Functions::NaN() : $fResult;
879
		}
880
		return PHPExcel_Calculation_Functions::VALUE();
881
	}	//	function BESSELJ()
882
883
884
	private static function _Besselk0($fNum) {
885
		if ($fNum <= 2) {
886
			$fNum2 = $fNum * 0.5;
887
			$y = ($fNum2 * $fNum2);
888
			$fRet = -log($fNum2) * self::BESSELI($fNum, 0) +
889
					(-0.57721566 + $y * (0.42278420 + $y * (0.23069756 + $y * (0.3488590e-1 + $y * (0.262698e-2 + $y *
890
					(0.10750e-3 + $y * 0.74e-5))))));
891 View Code Duplication
		} else {
892
			$y = 2 / $fNum;
893
			$fRet = exp(-$fNum) / sqrt($fNum) *
894
					(1.25331414 + $y * (-0.7832358e-1 + $y * (0.2189568e-1 + $y * (-0.1062446e-1 + $y *
895
					(0.587872e-2 + $y * (-0.251540e-2 + $y * 0.53208e-3))))));
896
		}
897
		return $fRet;
898
	}	//	function _Besselk0()
899
900
901
	private static function _Besselk1($fNum) {
902
		if ($fNum <= 2) {
903
			$fNum2 = $fNum * 0.5;
904
			$y = ($fNum2 * $fNum2);
905
			$fRet = log($fNum2) * self::BESSELI($fNum, 1) +
906
					(1 + $y * (0.15443144 + $y * (-0.67278579 + $y * (-0.18156897 + $y * (-0.1919402e-1 + $y *
907
					(-0.110404e-2 + $y * (-0.4686e-4))))))) / $fNum;
908 View Code Duplication
		} else {
909
			$y = 2 / $fNum;
910
			$fRet = exp(-$fNum) / sqrt($fNum) *
911
					(1.25331414 + $y * (0.23498619 + $y * (-0.3655620e-1 + $y * (0.1504268e-1 + $y * (-0.780353e-2 + $y *
912
					(0.325614e-2 + $y * (-0.68245e-3)))))));
913
		}
914
		return $fRet;
915
	}	//	function _Besselk1()
916
917
918
	/**
919
	 * BESSELK
920
	 *
921
	 * Returns the modified Bessel function, which is equivalent to the Bessel functions evaluated
922
	 * for purely imaginary arguments.
923
	 *
924
	 * Excel Function:
925
	 *		BESSELK(x,ord)
926
	 *
927
	 * @access	public
928
	 * @category Engineering Functions
929
	 * @param	float		$x		The value at which to evaluate the function.
930
	 *								If x is nonnumeric, BESSELK returns the #VALUE! error value.
931
	 * @param	integer		$ord	The order of the Bessel function. If n is not an integer, it is truncated.
932
	 *								If $ord is nonnumeric, BESSELK returns the #VALUE! error value.
933
	 *								If $ord < 0, BESSELK returns the #NUM! error value.
934
	 * @return	float
935
	 *
936
	 * @TODO Better handling of the approximation method to support the differences between Excel/Gnumeric and Open/Libre Office
937
	 *
938
	 */
939 View Code Duplication
	public static function BESSELK($x, $ord) {
940
		$x		= (is_null($x))		? 0.0 :	PHPExcel_Calculation_Functions::flattenSingleValue($x);
941
		$ord	= (is_null($ord))	? 0.0 :	PHPExcel_Calculation_Functions::flattenSingleValue($ord);
942
943
		if ((is_numeric($x)) && (is_numeric($ord))) {
944
			if (($ord < 0) || ($x == 0.0)) {
945
				return PHPExcel_Calculation_Functions::NaN();
946
			}
947
948
			switch(floor($ord)) {
949
				case 0 :	return self::_Besselk0($x);
950
							break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
951
				case 1 :	return self::_Besselk1($x);
952
							break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
953
				default :	$fTox	= 2 / $x;
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a DEFAULT statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in the default statement.

switch ($expr) {
    default : //wrong
        doSomething();
        break;
}

switch ($expr) {
    default: //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Coding Style introduced by
The default body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a default statement must start on the line immediately following the statement.

switch ($expr) {
    default:
        doSomething(); //right
        break;
}


switch ($expr) {
    default:

        doSomething(); //wrong
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
954
							$fBkm	= self::_Besselk0($x);
955
							$fBk	= self::_Besselk1($x);
956
							for ($n = 1; $n < $ord; ++$n) {
957
								$fBkp	= $fBkm + $n * $fTox * $fBk;
958
								$fBkm	= $fBk;
959
								$fBk	= $fBkp;
960
							}
961
			}
962
			return (is_nan($fBk)) ? PHPExcel_Calculation_Functions::NaN() : $fBk;
963
		}
964
		return PHPExcel_Calculation_Functions::VALUE();
965
	}	//	function BESSELK()
966
967
968
	private static function _Bessely0($fNum) {
969
		if ($fNum < 8.0) {
970
			$y = ($fNum * $fNum);
971
			$f1 = -2957821389.0 + $y * (7062834065.0 + $y * (-512359803.6 + $y * (10879881.29 + $y * (-86327.92757 + $y * 228.4622733))));
972
			$f2 = 40076544269.0 + $y * (745249964.8 + $y * (7189466.438 + $y * (47447.26470 + $y * (226.1030244 + $y))));
973
			$fRet = $f1 / $f2 + 0.636619772 * self::BESSELJ($fNum, 0) * log($fNum);
974
		} else {
975
			$z = 8.0 / $fNum;
976
			$y = ($z * $z);
977
			$xx = $fNum - 0.785398164;
978
			$f1 = 1 + $y * (-0.1098628627e-2 + $y * (0.2734510407e-4 + $y * (-0.2073370639e-5 + $y * 0.2093887211e-6)));
979
			$f2 = -0.1562499995e-1 + $y * (0.1430488765e-3 + $y * (-0.6911147651e-5 + $y * (0.7621095161e-6 + $y * (-0.934945152e-7))));
980
			$fRet = sqrt(0.636619772 / $fNum) * (sin($xx) * $f1 + $z * cos($xx) * $f2);
981
		}
982
		return $fRet;
983
	}	//	function _Bessely0()
984
985
986
	private static function _Bessely1($fNum) {
987
		if ($fNum < 8.0) {
988
			$y = ($fNum * $fNum);
989
			$f1 = $fNum * (-0.4900604943e13 + $y * (0.1275274390e13 + $y * (-0.5153438139e11 + $y * (0.7349264551e9 + $y *
990
				(-0.4237922726e7 + $y * 0.8511937935e4)))));
991
			$f2 = 0.2499580570e14 + $y * (0.4244419664e12 + $y * (0.3733650367e10 + $y * (0.2245904002e8 + $y *
992
				(0.1020426050e6 + $y * (0.3549632885e3 + $y)))));
993
			$fRet = $f1 / $f2 + 0.636619772 * ( self::BESSELJ($fNum, 1) * log($fNum) - 1 / $fNum);
994
		} else {
995
//			$z = 8.0 / $fNum;
996
//			$y = ($z * $z);
997
//			$xx = $fNum - 2.356194491;
998
//			$f1 = 1 + $y * (0.183105e-2 + $y * (-0.3516396496e-4 + $y * (0.2457520174e-5 + $y * (-0.240337019e6))));
999
//			$f2 = 0.04687499995 + $y * (-0.2002690873e-3 + $y * (0.8449199096e-5 + $y * (-0.88228987e-6 + $y * 0.105787412e-6)));
1000
//			$fRet = sqrt(0.636619772 / $fNum) * (sin($xx) * $f1 + $z * cos($xx) * $f2);
1001
			#i12430# ...but this seems to work much better.
1002
			$fRet = sqrt(0.636619772 / $fNum) * sin($fNum - 2.356194491);
1003
		}
1004
		return $fRet;
1005
	}	//	function _Bessely1()
1006
1007
1008
	/**
1009
	 * BESSELY
1010
	 *
1011
	 * Returns the Bessel function, which is also called the Weber function or the Neumann function.
1012
	 *
1013
	 * Excel Function:
1014
	 *		BESSELY(x,ord)
1015
	 *
1016
	 * @access	public
1017
	 * @category Engineering Functions
1018
	 * @param	float		$x		The value at which to evaluate the function.
1019
	 *								If x is nonnumeric, BESSELK returns the #VALUE! error value.
1020
	 * @param	integer		$ord	The order of the Bessel function. If n is not an integer, it is truncated.
1021
	 *								If $ord is nonnumeric, BESSELK returns the #VALUE! error value.
1022
	 *								If $ord < 0, BESSELK returns the #NUM! error value.
1023
	 *
1024
	 * @TODO Better handling of the approximation method to support the differences between Excel/Gnumeric and Open/Libre Office
1025
	 *
1026
	 * @return	float
1027
	 */
1028 View Code Duplication
	public static function BESSELY($x, $ord) {
1029
		$x		= (is_null($x))		? 0.0 :	PHPExcel_Calculation_Functions::flattenSingleValue($x);
1030
		$ord	= (is_null($ord))	? 0.0 :	PHPExcel_Calculation_Functions::flattenSingleValue($ord);
1031
1032
		if ((is_numeric($x)) && (is_numeric($ord))) {
1033
			if (($ord < 0) || ($x == 0.0)) {
1034
				return PHPExcel_Calculation_Functions::NaN();
1035
			}
1036
1037
			switch(floor($ord)) {
1038
				case 0 :	return self::_Bessely0($x);
1039
							break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
1040
				case 1 :	return self::_Bessely1($x);
1041
							break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
1042
				default:	$fTox	= 2 / $x;
0 ignored issues
show
Coding Style introduced by
The default body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a default statement must start on the line immediately following the statement.

switch ($expr) {
    default:
        doSomething(); //right
        break;
}


switch ($expr) {
    default:

        doSomething(); //wrong
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
1043
							$fBym	= self::_Bessely0($x);
1044
							$fBy	= self::_Bessely1($x);
1045
							for ($n = 1; $n < $ord; ++$n) {
1046
								$fByp	= $n * $fTox * $fBy - $fBym;
1047
								$fBym	= $fBy;
1048
								$fBy	= $fByp;
1049
							}
1050
			}
1051
			return (is_nan($fBy)) ? PHPExcel_Calculation_Functions::NaN() : $fBy;
1052
		}
1053
		return PHPExcel_Calculation_Functions::VALUE();
1054
	}	//	function BESSELY()
1055
1056
1057
	/**
1058
	 * BINTODEC
1059
	 *
1060
	 * Return a binary value as decimal.
1061
	 *
1062
	 * Excel Function:
1063
	 *		BIN2DEC(x)
1064
	 *
1065
	 * @access	public
1066
	 * @category Engineering Functions
1067
	 * @param	string		$x		The binary number (as a string) that you want to convert. The number
1068
	 *								cannot contain more than 10 characters (10 bits). The most significant
1069
	 *								bit of number is the sign bit. The remaining 9 bits are magnitude bits.
1070
	 *								Negative numbers are represented using two's-complement notation.
1071
	 *								If number is not a valid binary number, or if number contains more than
1072
	 *								10 characters (10 bits), BIN2DEC returns the #NUM! error value.
1073
	 * @return	string
1074
	 */
1075
	public static function BINTODEC($x) {
1076
		$x	= PHPExcel_Calculation_Functions::flattenSingleValue($x);
1077
1078
		if (is_bool($x)) {
1079
			if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE) {
1080
				$x = (int) $x;
1081
			} else {
1082
				return PHPExcel_Calculation_Functions::VALUE();
1083
			}
1084
		}
1085
		if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC) {
1086
			$x = floor($x);
1087
		}
1088
		$x = (string) $x;
1089
		if (strlen($x) > preg_match_all('/[01]/',$x,$out)) {
1090
			return PHPExcel_Calculation_Functions::NaN();
1091
		}
1092
		if (strlen($x) > 10) {
1093
			return PHPExcel_Calculation_Functions::NaN();
1094
		} elseif (strlen($x) == 10) {
1095
			//	Two's Complement
1096
			$x = substr($x,-9);
1097
			return '-'.(512-bindec($x));
1098
		}
1099
		return bindec($x);
1100
	}	//	function BINTODEC()
1101
1102
1103
	/**
1104
	 * BINTOHEX
1105
	 *
1106
	 * Return a binary value as hex.
1107
	 *
1108
	 * Excel Function:
1109
	 *		BIN2HEX(x[,places])
1110
	 *
1111
	 * @access	public
1112
	 * @category Engineering Functions
1113
	 * @param	string		$x		The binary number (as a string) that you want to convert. The number
1114
	 *								cannot contain more than 10 characters (10 bits). The most significant
1115
	 *								bit of number is the sign bit. The remaining 9 bits are magnitude bits.
1116
	 *								Negative numbers are represented using two's-complement notation.
1117
	 *								If number is not a valid binary number, or if number contains more than
1118
	 *								10 characters (10 bits), BIN2HEX returns the #NUM! error value.
1119
	 * @param	integer		$places	The number of characters to use. If places is omitted, BIN2HEX uses the
1120
	 *								minimum number of characters necessary. Places is useful for padding the
1121
	 *								return value with leading 0s (zeros).
1122
	 *								If places is not an integer, it is truncated.
1123
	 *								If places is nonnumeric, BIN2HEX returns the #VALUE! error value.
1124
	 *								If places is negative, BIN2HEX returns the #NUM! error value.
1125
	 * @return	string
1126
	 */
1127 View Code Duplication
	public static function BINTOHEX($x, $places=NULL) {
1128
		$x	= PHPExcel_Calculation_Functions::flattenSingleValue($x);
1129
		$places	= PHPExcel_Calculation_Functions::flattenSingleValue($places);
1130
1131
		if (is_bool($x)) {
1132
			if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE) {
1133
				$x = (int) $x;
1134
			} else {
1135
				return PHPExcel_Calculation_Functions::VALUE();
1136
			}
1137
		}
1138
		if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC) {
1139
			$x = floor($x);
1140
		}
1141
		$x = (string) $x;
1142
		if (strlen($x) > preg_match_all('/[01]/',$x,$out)) {
1143
			return PHPExcel_Calculation_Functions::NaN();
1144
		}
1145
		if (strlen($x) > 10) {
1146
			return PHPExcel_Calculation_Functions::NaN();
1147
		} elseif (strlen($x) == 10) {
1148
			//	Two's Complement
1149
			return str_repeat('F',8).substr(strtoupper(dechex(bindec(substr($x,-9)))),-2);
1150
		}
1151
		$hexVal = (string) strtoupper(dechex(bindec($x)));
1152
1153
		return self::_nbrConversionFormat($hexVal,$places);
1154
	}	//	function BINTOHEX()
1155
1156
1157
	/**
1158
	 * BINTOOCT
1159
	 *
1160
	 * Return a binary value as octal.
1161
	 *
1162
	 * Excel Function:
1163
	 *		BIN2OCT(x[,places])
1164
	 *
1165
	 * @access	public
1166
	 * @category Engineering Functions
1167
	 * @param	string		$x		The binary number (as a string) that you want to convert. The number
1168
	 *								cannot contain more than 10 characters (10 bits). The most significant
1169
	 *								bit of number is the sign bit. The remaining 9 bits are magnitude bits.
1170
	 *								Negative numbers are represented using two's-complement notation.
1171
	 *								If number is not a valid binary number, or if number contains more than
1172
	 *								10 characters (10 bits), BIN2OCT returns the #NUM! error value.
1173
	 * @param	integer		$places	The number of characters to use. If places is omitted, BIN2OCT uses the
1174
	 *								minimum number of characters necessary. Places is useful for padding the
1175
	 *								return value with leading 0s (zeros).
1176
	 *								If places is not an integer, it is truncated.
1177
	 *								If places is nonnumeric, BIN2OCT returns the #VALUE! error value.
1178
	 *								If places is negative, BIN2OCT returns the #NUM! error value.
1179
	 * @return	string
1180
	 */
1181 View Code Duplication
	public static function BINTOOCT($x, $places=NULL) {
1182
		$x	= PHPExcel_Calculation_Functions::flattenSingleValue($x);
1183
		$places	= PHPExcel_Calculation_Functions::flattenSingleValue($places);
1184
1185
		if (is_bool($x)) {
1186
			if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE) {
1187
				$x = (int) $x;
1188
			} else {
1189
				return PHPExcel_Calculation_Functions::VALUE();
1190
			}
1191
		}
1192
		if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC) {
1193
			$x = floor($x);
1194
		}
1195
		$x = (string) $x;
1196
		if (strlen($x) > preg_match_all('/[01]/',$x,$out)) {
1197
			return PHPExcel_Calculation_Functions::NaN();
1198
		}
1199
		if (strlen($x) > 10) {
1200
			return PHPExcel_Calculation_Functions::NaN();
1201
		} elseif (strlen($x) == 10) {
1202
			//	Two's Complement
1203
			return str_repeat('7',7).substr(strtoupper(decoct(bindec(substr($x,-9)))),-3);
1204
		}
1205
		$octVal = (string) decoct(bindec($x));
1206
1207
		return self::_nbrConversionFormat($octVal,$places);
1208
	}	//	function BINTOOCT()
1209
1210
1211
	/**
1212
	 * DECTOBIN
1213
	 *
1214
	 * Return a decimal value as binary.
1215
	 *
1216
	 * Excel Function:
1217
	 *		DEC2BIN(x[,places])
1218
	 *
1219
	 * @access	public
1220
	 * @category Engineering Functions
1221
	 * @param	string		$x		The decimal integer you want to convert. If number is negative,
1222
	 *								valid place values are ignored and DEC2BIN returns a 10-character
1223
	 *								(10-bit) binary number in which the most significant bit is the sign
1224
	 *								bit. The remaining 9 bits are magnitude bits. Negative numbers are
1225
	 *								represented using two's-complement notation.
1226
	 *								If number < -512 or if number > 511, DEC2BIN returns the #NUM! error
1227
	 *								value.
1228
	 *								If number is nonnumeric, DEC2BIN returns the #VALUE! error value.
1229
	 *								If DEC2BIN requires more than places characters, it returns the #NUM!
1230
	 *								error value.
1231
	 * @param	integer		$places	The number of characters to use. If places is omitted, DEC2BIN uses
1232
	 *								the minimum number of characters necessary. Places is useful for
1233
	 *								padding the return value with leading 0s (zeros).
1234
	 *								If places is not an integer, it is truncated.
1235
	 *								If places is nonnumeric, DEC2BIN returns the #VALUE! error value.
1236
	 *								If places is zero or negative, DEC2BIN returns the #NUM! error value.
1237
	 * @return	string
1238
	 */
1239
	public static function DECTOBIN($x, $places=NULL) {
1240
		$x	= PHPExcel_Calculation_Functions::flattenSingleValue($x);
1241
		$places	= PHPExcel_Calculation_Functions::flattenSingleValue($places);
1242
1243
		if (is_bool($x)) {
1244
			if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE) {
1245
				$x = (int) $x;
1246
			} else {
1247
				return PHPExcel_Calculation_Functions::VALUE();
1248
			}
1249
		}
1250
		$x = (string) $x;
1251
		if (strlen($x) > preg_match_all('/[-0123456789.]/',$x,$out)) {
1252
			return PHPExcel_Calculation_Functions::VALUE();
1253
		}
1254
		$x = (string) floor($x);
1255
		$r = decbin($x);
1256
		if (strlen($r) == 32) {
1257
			//	Two's Complement
1258
			$r = substr($r,-10);
1259
		} elseif (strlen($r) > 11) {
1260
			return PHPExcel_Calculation_Functions::NaN();
1261
		}
1262
1263
		return self::_nbrConversionFormat($r,$places);
1264
	}	//	function DECTOBIN()
1265
1266
1267
	/**
1268
	 * DECTOHEX
1269
	 *
1270
	 * Return a decimal value as hex.
1271
	 *
1272
	 * Excel Function:
1273
	 *		DEC2HEX(x[,places])
1274
	 *
1275
	 * @access	public
1276
	 * @category Engineering Functions
1277
	 * @param	string		$x		The decimal integer you want to convert. If number is negative,
1278
	 *								places is ignored and DEC2HEX returns a 10-character (40-bit)
1279
	 *								hexadecimal number in which the most significant bit is the sign
1280
	 *								bit. The remaining 39 bits are magnitude bits. Negative numbers
1281
	 *								are represented using two's-complement notation.
1282
	 *								If number < -549,755,813,888 or if number > 549,755,813,887,
1283
	 *								DEC2HEX returns the #NUM! error value.
1284
	 *								If number is nonnumeric, DEC2HEX returns the #VALUE! error value.
1285
	 *								If DEC2HEX requires more than places characters, it returns the
1286
	 *								#NUM! error value.
1287
	 * @param	integer		$places	The number of characters to use. If places is omitted, DEC2HEX uses
1288
	 *								the minimum number of characters necessary. Places is useful for
1289
	 *								padding the return value with leading 0s (zeros).
1290
	 *								If places is not an integer, it is truncated.
1291
	 *								If places is nonnumeric, DEC2HEX returns the #VALUE! error value.
1292
	 *								If places is zero or negative, DEC2HEX returns the #NUM! error value.
1293
	 * @return	string
1294
	 */
1295 View Code Duplication
	public static function DECTOHEX($x, $places=null) {
1296
		$x	= PHPExcel_Calculation_Functions::flattenSingleValue($x);
1297
		$places	= PHPExcel_Calculation_Functions::flattenSingleValue($places);
1298
1299
		if (is_bool($x)) {
1300
			if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE) {
1301
				$x = (int) $x;
1302
			} else {
1303
				return PHPExcel_Calculation_Functions::VALUE();
1304
			}
1305
		}
1306
		$x = (string) $x;
1307
		if (strlen($x) > preg_match_all('/[-0123456789.]/',$x,$out)) {
1308
			return PHPExcel_Calculation_Functions::VALUE();
1309
		}
1310
		$x = (string) floor($x);
1311
		$r = strtoupper(dechex($x));
1312
		if (strlen($r) == 8) {
1313
			//	Two's Complement
1314
			$r = 'FF'.$r;
1315
		}
1316
1317
		return self::_nbrConversionFormat($r,$places);
1318
	}	//	function DECTOHEX()
1319
1320
1321
	/**
1322
	 * DECTOOCT
1323
	 *
1324
	 * Return an decimal value as octal.
1325
	 *
1326
	 * Excel Function:
1327
	 *		DEC2OCT(x[,places])
1328
	 *
1329
	 * @access	public
1330
	 * @category Engineering Functions
1331
	 * @param	string		$x		The decimal integer you want to convert. If number is negative,
1332
	 *								places is ignored and DEC2OCT returns a 10-character (30-bit)
1333
	 *								octal number in which the most significant bit is the sign bit.
1334
	 *								The remaining 29 bits are magnitude bits. Negative numbers are
1335
	 *								represented using two's-complement notation.
1336
	 *								If number < -536,870,912 or if number > 536,870,911, DEC2OCT
1337
	 *								returns the #NUM! error value.
1338
	 *								If number is nonnumeric, DEC2OCT returns the #VALUE! error value.
1339
	 *								If DEC2OCT requires more than places characters, it returns the
1340
	 *								#NUM! error value.
1341
	 * @param	integer		$places	The number of characters to use. If places is omitted, DEC2OCT uses
1342
	 *								the minimum number of characters necessary. Places is useful for
1343
	 *								padding the return value with leading 0s (zeros).
1344
	 *								If places is not an integer, it is truncated.
1345
	 *								If places is nonnumeric, DEC2OCT returns the #VALUE! error value.
1346
	 *								If places is zero or negative, DEC2OCT returns the #NUM! error value.
1347
	 * @return	string
1348
	 */
1349 View Code Duplication
	public static function DECTOOCT($x, $places=null) {
1350
		$x	= PHPExcel_Calculation_Functions::flattenSingleValue($x);
1351
		$places	= PHPExcel_Calculation_Functions::flattenSingleValue($places);
1352
1353
		if (is_bool($x)) {
1354
			if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE) {
1355
				$x = (int) $x;
1356
			} else {
1357
				return PHPExcel_Calculation_Functions::VALUE();
1358
			}
1359
		}
1360
		$x = (string) $x;
1361
		if (strlen($x) > preg_match_all('/[-0123456789.]/',$x,$out)) {
1362
			return PHPExcel_Calculation_Functions::VALUE();
1363
		}
1364
		$x = (string) floor($x);
1365
		$r = decoct($x);
1366
		if (strlen($r) == 11) {
1367
			//	Two's Complement
1368
			$r = substr($r,-10);
1369
		}
1370
1371
		return self::_nbrConversionFormat($r,$places);
1372
	}	//	function DECTOOCT()
1373
1374
1375
	/**
1376
	 * HEXTOBIN
1377
	 *
1378
	 * Return a hex value as binary.
1379
	 *
1380
	 * Excel Function:
1381
	 *		HEX2BIN(x[,places])
1382
	 *
1383
	 * @access	public
1384
	 * @category Engineering Functions
1385
	 * @param	string		$x			the hexadecimal number you want to convert. Number cannot
1386
	 *									contain more than 10 characters. The most significant bit of
1387
	 *									number is the sign bit (40th bit from the right). The remaining
1388
	 *									9 bits are magnitude bits. Negative numbers are represented
1389
	 *									using two's-complement notation.
1390
	 *									If number is negative, HEX2BIN ignores places and returns a
1391
	 *									10-character binary number.
1392
	 *									If number is negative, it cannot be less than FFFFFFFE00, and
1393
	 *									if number is positive, it cannot be greater than 1FF.
1394
	 *									If number is not a valid hexadecimal number, HEX2BIN returns
1395
	 *									the #NUM! error value.
1396
	 *									If HEX2BIN requires more than places characters, it returns
1397
	 *									the #NUM! error value.
1398
	 * @param	integer		$places		The number of characters to use. If places is omitted,
1399
	 *									HEX2BIN uses the minimum number of characters necessary. Places
1400
	 *									is useful for padding the return value with leading 0s (zeros).
1401
	 *									If places is not an integer, it is truncated.
1402
	 *									If places is nonnumeric, HEX2BIN returns the #VALUE! error value.
1403
	 *									If places is negative, HEX2BIN returns the #NUM! error value.
1404
	 * @return	string
1405
	 */
1406
	public static function HEXTOBIN($x, $places=null) {
1407
		$x	= PHPExcel_Calculation_Functions::flattenSingleValue($x);
1408
		$places	= PHPExcel_Calculation_Functions::flattenSingleValue($places);
1409
1410
		if (is_bool($x)) {
1411
			return PHPExcel_Calculation_Functions::VALUE();
1412
		}
1413
		$x = (string) $x;
1414
		if (strlen($x) > preg_match_all('/[0123456789ABCDEF]/',strtoupper($x),$out)) {
1415
			return PHPExcel_Calculation_Functions::NaN();
1416
		}
1417
		$binVal = decbin(hexdec($x));
1418
1419
		return substr(self::_nbrConversionFormat($binVal,$places),-10);
1420
	}	//	function HEXTOBIN()
1421
1422
1423
	/**
1424
	 * HEXTODEC
1425
	 *
1426
	 * Return a hex value as decimal.
1427
	 *
1428
	 * Excel Function:
1429
	 *		HEX2DEC(x)
1430
	 *
1431
	 * @access	public
1432
	 * @category Engineering Functions
1433
	 * @param	string		$x		The hexadecimal number you want to convert. This number cannot
1434
	 *								contain more than 10 characters (40 bits). The most significant
1435
	 *								bit of number is the sign bit. The remaining 39 bits are magnitude
1436
	 *								bits. Negative numbers are represented using two's-complement
1437
	 *								notation.
1438
	 *								If number is not a valid hexadecimal number, HEX2DEC returns the
1439
	 *								#NUM! error value.
1440
	 * @return	string
1441
	 */
1442 View Code Duplication
	public static function HEXTODEC($x) {
1443
		$x	= PHPExcel_Calculation_Functions::flattenSingleValue($x);
1444
1445
		if (is_bool($x)) {
1446
			return PHPExcel_Calculation_Functions::VALUE();
1447
		}
1448
		$x = (string) $x;
1449
		if (strlen($x) > preg_match_all('/[0123456789ABCDEF]/',strtoupper($x),$out)) {
1450
			return PHPExcel_Calculation_Functions::NaN();
1451
		}
1452
		return hexdec($x);
1453
	}	//	function HEXTODEC()
1454
1455
1456
	/**
1457
	 * HEXTOOCT
1458
	 *
1459
	 * Return a hex value as octal.
1460
	 *
1461
	 * Excel Function:
1462
	 *		HEX2OCT(x[,places])
1463
	 *
1464
	 * @access	public
1465
	 * @category Engineering Functions
1466
	 * @param	string		$x			The hexadecimal number you want to convert. Number cannot
1467
	 *									contain more than 10 characters. The most significant bit of
1468
	 *									number is the sign bit. The remaining 39 bits are magnitude
1469
	 *									bits. Negative numbers are represented using two's-complement
1470
	 *									notation.
1471
	 *									If number is negative, HEX2OCT ignores places and returns a
1472
	 *									10-character octal number.
1473
	 *									If number is negative, it cannot be less than FFE0000000, and
1474
	 *									if number is positive, it cannot be greater than 1FFFFFFF.
1475
	 *									If number is not a valid hexadecimal number, HEX2OCT returns
1476
	 *									the #NUM! error value.
1477
	 *									If HEX2OCT requires more than places characters, it returns
1478
	 *									the #NUM! error value.
1479
	 * @param	integer		$places		The number of characters to use. If places is omitted, HEX2OCT
1480
	 *									uses the minimum number of characters necessary. Places is
1481
	 *									useful for padding the return value with leading 0s (zeros).
1482
	 *									If places is not an integer, it is truncated.
1483
	 *									If places is nonnumeric, HEX2OCT returns the #VALUE! error
1484
	 *									value.
1485
	 *									If places is negative, HEX2OCT returns the #NUM! error value.
1486
	 * @return	string
1487
	 */
1488 View Code Duplication
	public static function HEXTOOCT($x, $places=null) {
1489
		$x	= PHPExcel_Calculation_Functions::flattenSingleValue($x);
1490
		$places	= PHPExcel_Calculation_Functions::flattenSingleValue($places);
1491
1492
		if (is_bool($x)) {
1493
			return PHPExcel_Calculation_Functions::VALUE();
1494
		}
1495
		$x = (string) $x;
1496
		if (strlen($x) > preg_match_all('/[0123456789ABCDEF]/',strtoupper($x),$out)) {
1497
			return PHPExcel_Calculation_Functions::NaN();
1498
		}
1499
		$octVal = decoct(hexdec($x));
1500
1501
		return self::_nbrConversionFormat($octVal,$places);
1502
	}	//	function HEXTOOCT()
1503
1504
1505
	/**
1506
	 * OCTTOBIN
1507
	 *
1508
	 * Return an octal value as binary.
1509
	 *
1510
	 * Excel Function:
1511
	 *		OCT2BIN(x[,places])
1512
	 *
1513
	 * @access	public
1514
	 * @category Engineering Functions
1515
	 * @param	string		$x			The octal number you want to convert. Number may not
1516
	 *									contain more than 10 characters. The most significant
1517
	 *									bit of number is the sign bit. The remaining 29 bits
1518
	 *									are magnitude bits. Negative numbers are represented
1519
	 *									using two's-complement notation.
1520
	 *									If number is negative, OCT2BIN ignores places and returns
1521
	 *									a 10-character binary number.
1522
	 *									If number is negative, it cannot be less than 7777777000,
1523
	 *									and if number is positive, it cannot be greater than 777.
1524
	 *									If number is not a valid octal number, OCT2BIN returns
1525
	 *									the #NUM! error value.
1526
	 *									If OCT2BIN requires more than places characters, it
1527
	 *									returns the #NUM! error value.
1528
	 * @param	integer		$places		The number of characters to use. If places is omitted,
1529
	 *									OCT2BIN uses the minimum number of characters necessary.
1530
	 *									Places is useful for padding the return value with
1531
	 *									leading 0s (zeros).
1532
	 *									If places is not an integer, it is truncated.
1533
	 *									If places is nonnumeric, OCT2BIN returns the #VALUE!
1534
	 *									error value.
1535
	 *									If places is negative, OCT2BIN returns the #NUM! error
1536
	 *									value.
1537
	 * @return	string
1538
	 */
1539 View Code Duplication
	public static function OCTTOBIN($x, $places=null) {
1540
		$x	= PHPExcel_Calculation_Functions::flattenSingleValue($x);
1541
		$places	= PHPExcel_Calculation_Functions::flattenSingleValue($places);
1542
1543
		if (is_bool($x)) {
1544
			return PHPExcel_Calculation_Functions::VALUE();
1545
		}
1546
		$x = (string) $x;
1547
		if (preg_match_all('/[01234567]/',$x,$out) != strlen($x)) {
1548
			return PHPExcel_Calculation_Functions::NaN();
1549
		}
1550
		$r = decbin(octdec($x));
1551
1552
		return self::_nbrConversionFormat($r,$places);
1553
	}	//	function OCTTOBIN()
1554
1555
1556
	/**
1557
	 * OCTTODEC
1558
	 *
1559
	 * Return an octal value as decimal.
1560
	 *
1561
	 * Excel Function:
1562
	 *		OCT2DEC(x)
1563
	 *
1564
	 * @access	public
1565
	 * @category Engineering Functions
1566
	 * @param	string		$x		The octal number you want to convert. Number may not contain
1567
	 *								more than 10 octal characters (30 bits). The most significant
1568
	 *								bit of number is the sign bit. The remaining 29 bits are
1569
	 *								magnitude bits. Negative numbers are represented using
1570
	 *								two's-complement notation.
1571
	 *								If number is not a valid octal number, OCT2DEC returns the
1572
	 *								#NUM! error value.
1573
	 * @return	string
1574
	 */
1575 View Code Duplication
	public static function OCTTODEC($x) {
1576
		$x	= PHPExcel_Calculation_Functions::flattenSingleValue($x);
1577
1578
		if (is_bool($x)) {
1579
			return PHPExcel_Calculation_Functions::VALUE();
1580
		}
1581
		$x = (string) $x;
1582
		if (preg_match_all('/[01234567]/',$x,$out) != strlen($x)) {
1583
			return PHPExcel_Calculation_Functions::NaN();
1584
		}
1585
		return octdec($x);
1586
	}	//	function OCTTODEC()
1587
1588
1589
	/**
1590
	 * OCTTOHEX
1591
	 *
1592
	 * Return an octal value as hex.
1593
	 *
1594
	 * Excel Function:
1595
	 *		OCT2HEX(x[,places])
1596
	 *
1597
	 * @access	public
1598
	 * @category Engineering Functions
1599
	 * @param	string		$x			The octal number you want to convert. Number may not contain
1600
	 *									more than 10 octal characters (30 bits). The most significant
1601
	 *									bit of number is the sign bit. The remaining 29 bits are
1602
	 *									magnitude bits. Negative numbers are represented using
1603
	 *									two's-complement notation.
1604
	 *									If number is negative, OCT2HEX ignores places and returns a
1605
	 *									10-character hexadecimal number.
1606
	 *									If number is not a valid octal number, OCT2HEX returns the
1607
	 *									#NUM! error value.
1608
	 *									If OCT2HEX requires more than places characters, it returns
1609
	 *									the #NUM! error value.
1610
	 * @param	integer		$places		The number of characters to use. If places is omitted, OCT2HEX
1611
	 *									uses the minimum number of characters necessary. Places is useful
1612
	 *									for padding the return value with leading 0s (zeros).
1613
	 *									If places is not an integer, it is truncated.
1614
	 *									If places is nonnumeric, OCT2HEX returns the #VALUE! error value.
1615
	 *									If places is negative, OCT2HEX returns the #NUM! error value.
1616
	 * @return	string
1617
	 */
1618 View Code Duplication
	public static function OCTTOHEX($x, $places=null) {
1619
		$x	= PHPExcel_Calculation_Functions::flattenSingleValue($x);
1620
		$places	= PHPExcel_Calculation_Functions::flattenSingleValue($places);
1621
1622
		if (is_bool($x)) {
1623
			return PHPExcel_Calculation_Functions::VALUE();
1624
		}
1625
		$x = (string) $x;
1626
		if (preg_match_all('/[01234567]/',$x,$out) != strlen($x)) {
1627
			return PHPExcel_Calculation_Functions::NaN();
1628
		}
1629
		$hexVal = strtoupper(dechex(octdec($x)));
1630
1631
		return self::_nbrConversionFormat($hexVal,$places);
1632
	}	//	function OCTTOHEX()
1633
1634
1635
	/**
1636
	 * COMPLEX
1637
	 *
1638
	 * Converts real and imaginary coefficients into a complex number of the form x + yi or x + yj.
1639
	 *
1640
	 * Excel Function:
1641
	 *		COMPLEX(realNumber,imaginary[,places])
1642
	 *
1643
	 * @access	public
1644
	 * @category Engineering Functions
1645
	 * @param	float		$realNumber		The real coefficient of the complex number.
1646
	 * @param	float		$imaginary		The imaginary coefficient of the complex number.
1647
	 * @param	string		$suffix			The suffix for the imaginary component of the complex number.
1648
	 *										If omitted, the suffix is assumed to be "i".
1649
	 * @return	string
1650
	 */
1651
	public static function COMPLEX($realNumber=0.0, $imaginary=0.0, $suffix='i') {
1652
		$realNumber	= (is_null($realNumber))	? 0.0 :	PHPExcel_Calculation_Functions::flattenSingleValue($realNumber);
1653
		$imaginary	= (is_null($imaginary))		? 0.0 :	PHPExcel_Calculation_Functions::flattenSingleValue($imaginary);
1654
		$suffix		= (is_null($suffix))		? 'i' :	PHPExcel_Calculation_Functions::flattenSingleValue($suffix);
1655
1656
		if (((is_numeric($realNumber)) && (is_numeric($imaginary))) &&
1657
			(($suffix == 'i') || ($suffix == 'j') || ($suffix == ''))) {
1658
			$realNumber	= (float) $realNumber;
1659
			$imaginary	= (float) $imaginary;
1660
1661
			if ($suffix == '') $suffix = 'i';
1662
			if ($realNumber == 0.0) {
1663
				if ($imaginary == 0.0) {
1664
					return (string) '0';
1665
				} elseif ($imaginary == 1.0) {
1666
					return (string) $suffix;
1667
				} elseif ($imaginary == -1.0) {
1668
					return (string) '-'.$suffix;
1669
				}
1670
				return (string) $imaginary.$suffix;
1671
			} elseif ($imaginary == 0.0) {
1672
				return (string) $realNumber;
1673
			} elseif ($imaginary == 1.0) {
1674
				return (string) $realNumber.'+'.$suffix;
1675
			} elseif ($imaginary == -1.0) {
1676
				return (string) $realNumber.'-'.$suffix;
1677
			}
1678
			if ($imaginary > 0) { $imaginary = (string) '+'.$imaginary; }
1679
			return (string) $realNumber.$imaginary.$suffix;
1680
		}
1681
1682
		return PHPExcel_Calculation_Functions::VALUE();
1683
	}	//	function COMPLEX()
1684
1685
1686
	/**
1687
	 * IMAGINARY
1688
	 *
1689
	 * Returns the imaginary coefficient of a complex number in x + yi or x + yj text format.
1690
	 *
1691
	 * Excel Function:
1692
	 *		IMAGINARY(complexNumber)
1693
	 *
1694
	 * @access	public
1695
	 * @category Engineering Functions
1696
	 * @param	string		$complexNumber	The complex number for which you want the imaginary
1697
	 * 										coefficient.
1698
	 * @return	float
1699
	 */
1700
	public static function IMAGINARY($complexNumber) {
1701
		$complexNumber	= PHPExcel_Calculation_Functions::flattenSingleValue($complexNumber);
1702
1703
		$parsedComplex = self::_parseComplex($complexNumber);
1704
		return $parsedComplex['imaginary'];
1705
	}	//	function IMAGINARY()
1706
1707
1708
	/**
1709
	 * IMREAL
1710
	 *
1711
	 * Returns the real coefficient of a complex number in x + yi or x + yj text format.
1712
	 *
1713
	 * Excel Function:
1714
	 *		IMREAL(complexNumber)
1715
	 *
1716
	 * @access	public
1717
	 * @category Engineering Functions
1718
	 * @param	string		$complexNumber	The complex number for which you want the real coefficient.
1719
	 * @return	float
1720
	 */
1721
	public static function IMREAL($complexNumber) {
1722
		$complexNumber	= PHPExcel_Calculation_Functions::flattenSingleValue($complexNumber);
1723
1724
		$parsedComplex = self::_parseComplex($complexNumber);
1725
		return $parsedComplex['real'];
1726
	}	//	function IMREAL()
1727
1728
1729
	/**
1730
	 * IMABS
1731
	 *
1732
	 * Returns the absolute value (modulus) of a complex number in x + yi or x + yj text format.
1733
	 *
1734
	 * Excel Function:
1735
	 *		IMABS(complexNumber)
1736
	 *
1737
	 * @param	string		$complexNumber	The complex number for which you want the absolute value.
1738
	 * @return	float
1739
	 */
1740
	public static function IMABS($complexNumber) {
1741
		$complexNumber	= PHPExcel_Calculation_Functions::flattenSingleValue($complexNumber);
1742
1743
		$parsedComplex = self::_parseComplex($complexNumber);
1744
1745
		return sqrt(($parsedComplex['real'] * $parsedComplex['real']) + ($parsedComplex['imaginary'] * $parsedComplex['imaginary']));
1746
	}	//	function IMABS()
1747
1748
1749
	/**
1750
	 * IMARGUMENT
1751
	 *
1752
	 * Returns the argument theta of a complex number, i.e. the angle in radians from the real
1753
	 * axis to the representation of the number in polar coordinates.
1754
	 *
1755
	 * Excel Function:
1756
	 *		IMARGUMENT(complexNumber)
1757
	 *
1758
	 * @param	string		$complexNumber	The complex number for which you want the argument theta.
1759
	 * @return	float
1760
	 */
1761
	public static function IMARGUMENT($complexNumber) {
1762
		$complexNumber	= PHPExcel_Calculation_Functions::flattenSingleValue($complexNumber);
1763
1764
		$parsedComplex = self::_parseComplex($complexNumber);
1765
1766
		if ($parsedComplex['real'] == 0.0) {
1767
			if ($parsedComplex['imaginary'] == 0.0) {
1768
				return 0.0;
1769
			} elseif($parsedComplex['imaginary'] < 0.0) {
1770
				return M_PI / -2;
1771
			} else {
1772
				return M_PI / 2;
1773
			}
1774
		} elseif ($parsedComplex['real'] > 0.0) {
1775
			return atan($parsedComplex['imaginary'] / $parsedComplex['real']);
1776
		} elseif ($parsedComplex['imaginary'] < 0.0) {
1777
			return 0 - (M_PI - atan(abs($parsedComplex['imaginary']) / abs($parsedComplex['real'])));
1778
		} else {
1779
			return M_PI - atan($parsedComplex['imaginary'] / abs($parsedComplex['real']));
1780
		}
1781
	}	//	function IMARGUMENT()
1782
1783
1784
	/**
1785
	 * IMCONJUGATE
1786
	 *
1787
	 * Returns the complex conjugate of a complex number in x + yi or x + yj text format.
1788
	 *
1789
	 * Excel Function:
1790
	 *		IMCONJUGATE(complexNumber)
1791
	 *
1792
	 * @param	string		$complexNumber	The complex number for which you want the conjugate.
1793
	 * @return	string
1794
	 */
1795
	public static function IMCONJUGATE($complexNumber) {
1796
		$complexNumber	= PHPExcel_Calculation_Functions::flattenSingleValue($complexNumber);
1797
1798
		$parsedComplex = self::_parseComplex($complexNumber);
1799
1800
		if ($parsedComplex['imaginary'] == 0.0) {
1801
			return $parsedComplex['real'];
1802
		} else {
1803
			return self::_cleanComplex( self::COMPLEX( $parsedComplex['real'],
1804
													   0 - $parsedComplex['imaginary'],
1805
													   $parsedComplex['suffix']
1806
													 )
1807
									  );
1808
		}
1809
	}	//	function IMCONJUGATE()
1810
1811
1812
	/**
1813
	 * IMCOS
1814
	 *
1815
	 * Returns the cosine of a complex number in x + yi or x + yj text format.
1816
	 *
1817
	 * Excel Function:
1818
	 *		IMCOS(complexNumber)
1819
	 *
1820
	 * @param	string		$complexNumber	The complex number for which you want the cosine.
1821
	 * @return	string|float
1822
	 */
1823 View Code Duplication
	public static function IMCOS($complexNumber) {
1824
		$complexNumber	= PHPExcel_Calculation_Functions::flattenSingleValue($complexNumber);
1825
1826
		$parsedComplex = self::_parseComplex($complexNumber);
1827
1828
		if ($parsedComplex['imaginary'] == 0.0) {
1829
			return cos($parsedComplex['real']);
1830
		} else {
1831
			return self::IMCONJUGATE(self::COMPLEX(cos($parsedComplex['real']) * cosh($parsedComplex['imaginary']),sin($parsedComplex['real']) * sinh($parsedComplex['imaginary']),$parsedComplex['suffix']));
1832
		}
1833
	}	//	function IMCOS()
1834
1835
1836
	/**
1837
	 * IMSIN
1838
	 *
1839
	 * Returns the sine of a complex number in x + yi or x + yj text format.
1840
	 *
1841
	 * Excel Function:
1842
	 *		IMSIN(complexNumber)
1843
	 *
1844
	 * @param	string		$complexNumber	The complex number for which you want the sine.
1845
	 * @return	string|float
1846
	 */
1847 View Code Duplication
	public static function IMSIN($complexNumber) {
1848
		$complexNumber	= PHPExcel_Calculation_Functions::flattenSingleValue($complexNumber);
1849
1850
		$parsedComplex = self::_parseComplex($complexNumber);
1851
1852
		if ($parsedComplex['imaginary'] == 0.0) {
1853
			return sin($parsedComplex['real']);
1854
		} else {
1855
			return self::COMPLEX(sin($parsedComplex['real']) * cosh($parsedComplex['imaginary']),cos($parsedComplex['real']) * sinh($parsedComplex['imaginary']),$parsedComplex['suffix']);
1856
		}
1857
	}	//	function IMSIN()
1858
1859
1860
	/**
1861
	 * IMSQRT
1862
	 *
1863
	 * Returns the square root of a complex number in x + yi or x + yj text format.
1864
	 *
1865
	 * Excel Function:
1866
	 *		IMSQRT(complexNumber)
1867
	 *
1868
	 * @param	string		$complexNumber	The complex number for which you want the square root.
1869
	 * @return	string
1870
	 */
1871
	public static function IMSQRT($complexNumber) {
1872
		$complexNumber	= PHPExcel_Calculation_Functions::flattenSingleValue($complexNumber);
1873
1874
		$parsedComplex = self::_parseComplex($complexNumber);
1875
1876
		$theta = self::IMARGUMENT($complexNumber);
1877
		$d1 = cos($theta / 2);
1878
		$d2 = sin($theta / 2);
1879
		$r = sqrt(sqrt(($parsedComplex['real'] * $parsedComplex['real']) + ($parsedComplex['imaginary'] * $parsedComplex['imaginary'])));
1880
1881
		if ($parsedComplex['suffix'] == '') {
1882
			return self::COMPLEX($d1 * $r,$d2 * $r);
1883
		} else {
1884
			return self::COMPLEX($d1 * $r,$d2 * $r,$parsedComplex['suffix']);
1885
		}
1886
	}	//	function IMSQRT()
1887
1888
1889
	/**
1890
	 * IMLN
1891
	 *
1892
	 * Returns the natural logarithm of a complex number in x + yi or x + yj text format.
1893
	 *
1894
	 * Excel Function:
1895
	 *		IMLN(complexNumber)
1896
	 *
1897
	 * @param	string		$complexNumber	The complex number for which you want the natural logarithm.
1898
	 * @return	string
1899
	 */
1900
	public static function IMLN($complexNumber) {
1901
		$complexNumber	= PHPExcel_Calculation_Functions::flattenSingleValue($complexNumber);
1902
1903
		$parsedComplex = self::_parseComplex($complexNumber);
1904
1905
		if (($parsedComplex['real'] == 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
1906
			return PHPExcel_Calculation_Functions::NaN();
1907
		}
1908
1909
		$logR = log(sqrt(($parsedComplex['real'] * $parsedComplex['real']) + ($parsedComplex['imaginary'] * $parsedComplex['imaginary'])));
1910
		$t = self::IMARGUMENT($complexNumber);
1911
1912
		if ($parsedComplex['suffix'] == '') {
1913
			return self::COMPLEX($logR,$t);
1914
		} else {
1915
			return self::COMPLEX($logR,$t,$parsedComplex['suffix']);
1916
		}
1917
	}	//	function IMLN()
1918
1919
1920
	/**
1921
	 * IMLOG10
1922
	 *
1923
	 * Returns the common logarithm (base 10) of a complex number in x + yi or x + yj text format.
1924
	 *
1925
	 * Excel Function:
1926
	 *		IMLOG10(complexNumber)
1927
	 *
1928
	 * @param	string		$complexNumber	The complex number for which you want the common logarithm.
1929
	 * @return	string
1930
	 */
1931 View Code Duplication
	public static function IMLOG10($complexNumber) {
1932
		$complexNumber	= PHPExcel_Calculation_Functions::flattenSingleValue($complexNumber);
1933
1934
		$parsedComplex = self::_parseComplex($complexNumber);
1935
1936
		if (($parsedComplex['real'] == 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
1937
			return PHPExcel_Calculation_Functions::NaN();
1938
		} elseif (($parsedComplex['real'] > 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
1939
			return log10($parsedComplex['real']);
1940
		}
1941
1942
		return self::IMPRODUCT(log10(EULER),self::IMLN($complexNumber));
1943
	}	//	function IMLOG10()
1944
1945
1946
	/**
1947
	 * IMLOG2
1948
	 *
1949
	 * Returns the common logarithm (base 10) of a complex number in x + yi or x + yj text format.
1950
	 *
1951
	 * Excel Function:
1952
	 *		IMLOG2(complexNumber)
1953
	 *
1954
	 * @param	string		$complexNumber	The complex number for which you want the base-2 logarithm.
1955
	 * @return	string
1956
	 */
1957 View Code Duplication
	public static function IMLOG2($complexNumber) {
1958
		$complexNumber	= PHPExcel_Calculation_Functions::flattenSingleValue($complexNumber);
1959
1960
		$parsedComplex = self::_parseComplex($complexNumber);
1961
1962
		if (($parsedComplex['real'] == 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
1963
			return PHPExcel_Calculation_Functions::NaN();
1964
		} elseif (($parsedComplex['real'] > 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
1965
			return log($parsedComplex['real'],2);
1966
		}
1967
1968
		return self::IMPRODUCT(log(EULER,2),self::IMLN($complexNumber));
1969
	}	//	function IMLOG2()
1970
1971
1972
	/**
1973
	 * IMEXP
1974
	 *
1975
	 * Returns the exponential of a complex number in x + yi or x + yj text format.
1976
	 *
1977
	 * Excel Function:
1978
	 *		IMEXP(complexNumber)
1979
	 *
1980
	 * @param	string		$complexNumber	The complex number for which you want the exponential.
1981
	 * @return	string
1982
	 */
1983
	public static function IMEXP($complexNumber) {
1984
		$complexNumber	= PHPExcel_Calculation_Functions::flattenSingleValue($complexNumber);
1985
1986
		$parsedComplex = self::_parseComplex($complexNumber);
1987
1988
		if (($parsedComplex['real'] == 0.0) && ($parsedComplex['imaginary'] == 0.0)) {
1989
			return '1';
1990
		}
1991
1992
		$e = exp($parsedComplex['real']);
1993
		$eX = $e * cos($parsedComplex['imaginary']);
1994
		$eY = $e * sin($parsedComplex['imaginary']);
1995
1996
		if ($parsedComplex['suffix'] == '') {
1997
			return self::COMPLEX($eX,$eY);
1998
		} else {
1999
			return self::COMPLEX($eX,$eY,$parsedComplex['suffix']);
2000
		}
2001
	}	//	function IMEXP()
2002
2003
2004
	/**
2005
	 * IMPOWER
2006
	 *
2007
	 * Returns a complex number in x + yi or x + yj text format raised to a power.
2008
	 *
2009
	 * Excel Function:
2010
	 *		IMPOWER(complexNumber,realNumber)
2011
	 *
2012
	 * @param	string		$complexNumber	The complex number you want to raise to a power.
2013
	 * @param	float		$realNumber		The power to which you want to raise the complex number.
2014
	 * @return	string
2015
	 */
2016
	public static function IMPOWER($complexNumber,$realNumber) {
2017
		$complexNumber	= PHPExcel_Calculation_Functions::flattenSingleValue($complexNumber);
2018
		$realNumber		= PHPExcel_Calculation_Functions::flattenSingleValue($realNumber);
2019
2020
		if (!is_numeric($realNumber)) {
2021
			return PHPExcel_Calculation_Functions::VALUE();
2022
		}
2023
2024
		$parsedComplex = self::_parseComplex($complexNumber);
2025
2026
		$r = sqrt(($parsedComplex['real'] * $parsedComplex['real']) + ($parsedComplex['imaginary'] * $parsedComplex['imaginary']));
2027
		$rPower = pow($r,$realNumber);
2028
		$theta = self::IMARGUMENT($complexNumber) * $realNumber;
2029
		if ($theta == 0) {
2030
			return 1;
2031
		} elseif ($parsedComplex['imaginary'] == 0.0) {
2032
			return self::COMPLEX($rPower * cos($theta),$rPower * sin($theta),$parsedComplex['suffix']);
2033
		} else {
2034
			return self::COMPLEX($rPower * cos($theta),$rPower * sin($theta),$parsedComplex['suffix']);
2035
		}
2036
	}	//	function IMPOWER()
2037
2038
2039
	/**
2040
	 * IMDIV
2041
	 *
2042
	 * Returns the quotient of two complex numbers in x + yi or x + yj text format.
2043
	 *
2044
	 * Excel Function:
2045
	 *		IMDIV(complexDividend,complexDivisor)
2046
	 *
2047
	 * @param	string		$complexDividend	The complex numerator or dividend.
2048
	 * @param	string		$complexDivisor		The complex denominator or divisor.
2049
	 * @return	string
2050
	 */
2051
	public static function IMDIV($complexDividend,$complexDivisor) {
2052
		$complexDividend	= PHPExcel_Calculation_Functions::flattenSingleValue($complexDividend);
2053
		$complexDivisor	= PHPExcel_Calculation_Functions::flattenSingleValue($complexDivisor);
2054
2055
		$parsedComplexDividend = self::_parseComplex($complexDividend);
2056
		$parsedComplexDivisor = self::_parseComplex($complexDivisor);
2057
2058
		if (($parsedComplexDividend['suffix'] != '') && ($parsedComplexDivisor['suffix'] != '') &&
2059
			($parsedComplexDividend['suffix'] != $parsedComplexDivisor['suffix'])) {
2060
			return PHPExcel_Calculation_Functions::NaN();
2061
		}
2062
		if (($parsedComplexDividend['suffix'] != '') && ($parsedComplexDivisor['suffix'] == '')) {
2063
			$parsedComplexDivisor['suffix'] = $parsedComplexDividend['suffix'];
2064
		}
2065
2066
		$d1 = ($parsedComplexDividend['real'] * $parsedComplexDivisor['real']) + ($parsedComplexDividend['imaginary'] * $parsedComplexDivisor['imaginary']);
2067
		$d2 = ($parsedComplexDividend['imaginary'] * $parsedComplexDivisor['real']) - ($parsedComplexDividend['real'] * $parsedComplexDivisor['imaginary']);
2068
		$d3 = ($parsedComplexDivisor['real'] * $parsedComplexDivisor['real']) + ($parsedComplexDivisor['imaginary'] * $parsedComplexDivisor['imaginary']);
2069
2070
		$r = $d1/$d3;
2071
		$i = $d2/$d3;
2072
2073
		if ($i > 0.0) {
2074
			return self::_cleanComplex($r.'+'.$i.$parsedComplexDivisor['suffix']);
2075
		} elseif ($i < 0.0) {
2076
			return self::_cleanComplex($r.$i.$parsedComplexDivisor['suffix']);
2077
		} else {
2078
			return $r;
2079
		}
2080
	}	//	function IMDIV()
2081
2082
2083
	/**
2084
	 * IMSUB
2085
	 *
2086
	 * Returns the difference of two complex numbers in x + yi or x + yj text format.
2087
	 *
2088
	 * Excel Function:
2089
	 *		IMSUB(complexNumber1,complexNumber2)
2090
	 *
2091
	 * @param	string		$complexNumber1		The complex number from which to subtract complexNumber2.
2092
	 * @param	string		$complexNumber2		The complex number to subtract from complexNumber1.
2093
	 * @return	string
2094
	 */
2095
	public static function IMSUB($complexNumber1,$complexNumber2) {
2096
		$complexNumber1	= PHPExcel_Calculation_Functions::flattenSingleValue($complexNumber1);
2097
		$complexNumber2	= PHPExcel_Calculation_Functions::flattenSingleValue($complexNumber2);
2098
2099
		$parsedComplex1 = self::_parseComplex($complexNumber1);
2100
		$parsedComplex2 = self::_parseComplex($complexNumber2);
2101
2102
		if ((($parsedComplex1['suffix'] != '') && ($parsedComplex2['suffix'] != '')) &&
2103
			($parsedComplex1['suffix'] != $parsedComplex2['suffix'])) {
2104
			return PHPExcel_Calculation_Functions::NaN();
2105
		} elseif (($parsedComplex1['suffix'] == '') && ($parsedComplex2['suffix'] != '')) {
2106
			$parsedComplex1['suffix'] = $parsedComplex2['suffix'];
2107
		}
2108
2109
		$d1 = $parsedComplex1['real'] - $parsedComplex2['real'];
2110
		$d2 = $parsedComplex1['imaginary'] - $parsedComplex2['imaginary'];
2111
2112
		return self::COMPLEX($d1,$d2,$parsedComplex1['suffix']);
2113
	}	//	function IMSUB()
2114
2115
2116
	/**
2117
	 * IMSUM
2118
	 *
2119
	 * Returns the sum of two or more complex numbers in x + yi or x + yj text format.
2120
	 *
2121
	 * Excel Function:
2122
	 *		IMSUM(complexNumber[,complexNumber[,...]])
2123
	 *
2124
	 * @param	string		$complexNumber,...	Series of complex numbers to add
0 ignored issues
show
Bug introduced by
There is no parameter named $complexNumber,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
2125
	 * @return	string
2126
	 */
2127
	public static function IMSUM() {
2128
		// Return value
2129
		$returnValue = self::_parseComplex('0');
2130
		$activeSuffix = '';
2131
2132
		// Loop through the arguments
2133
		$aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
2134
		foreach ($aArgs as $arg) {
2135
			$parsedComplex = self::_parseComplex($arg);
2136
2137 View Code Duplication
			if ($activeSuffix == '') {
2138
				$activeSuffix = $parsedComplex['suffix'];
2139
			} elseif (($parsedComplex['suffix'] != '') && ($activeSuffix != $parsedComplex['suffix'])) {
2140
				return PHPExcel_Calculation_Functions::VALUE();
2141
			}
2142
2143
			$returnValue['real'] += $parsedComplex['real'];
2144
			$returnValue['imaginary'] += $parsedComplex['imaginary'];
2145
		}
2146
2147
		if ($returnValue['imaginary'] == 0.0) { $activeSuffix = ''; }
2148
		return self::COMPLEX($returnValue['real'],$returnValue['imaginary'],$activeSuffix);
2149
	}	//	function IMSUM()
2150
2151
2152
	/**
2153
	 * IMPRODUCT
2154
	 *
2155
	 * Returns the product of two or more complex numbers in x + yi or x + yj text format.
2156
	 *
2157
	 * Excel Function:
2158
	 *		IMPRODUCT(complexNumber[,complexNumber[,...]])
2159
	 *
2160
	 * @param	string		$complexNumber,...	Series of complex numbers to multiply
0 ignored issues
show
Bug introduced by
There is no parameter named $complexNumber,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
2161
	 * @return	string
2162
	 */
2163
	public static function IMPRODUCT() {
2164
		// Return value
2165
		$returnValue = self::_parseComplex('1');
2166
		$activeSuffix = '';
2167
2168
		// Loop through the arguments
2169
		$aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
2170
		foreach ($aArgs as $arg) {
2171
			$parsedComplex = self::_parseComplex($arg);
2172
2173
			$workValue = $returnValue;
2174 View Code Duplication
			if (($parsedComplex['suffix'] != '') && ($activeSuffix == '')) {
2175
				$activeSuffix = $parsedComplex['suffix'];
2176
			} elseif (($parsedComplex['suffix'] != '') && ($activeSuffix != $parsedComplex['suffix'])) {
2177
				return PHPExcel_Calculation_Functions::NaN();
2178
			}
2179
			$returnValue['real'] = ($workValue['real'] * $parsedComplex['real']) - ($workValue['imaginary'] * $parsedComplex['imaginary']);
2180
			$returnValue['imaginary'] = ($workValue['real'] * $parsedComplex['imaginary']) + ($workValue['imaginary'] * $parsedComplex['real']);
2181
		}
2182
2183
		if ($returnValue['imaginary'] == 0.0) { $activeSuffix = ''; }
2184
		return self::COMPLEX($returnValue['real'],$returnValue['imaginary'],$activeSuffix);
2185
	}	//	function IMPRODUCT()
2186
2187
2188
	/**
2189
	 * DELTA
2190
	 *
2191
	 * Tests whether two values are equal. Returns 1 if number1 = number2; returns 0 otherwise.
2192
	 * Use this function to filter a set of values. For example, by summing several DELTA
2193
	 * functions you calculate the count of equal pairs. This function is also known as the
2194
	 * Kronecker Delta function.
2195
	 *
2196
	 * Excel Function:
2197
	 *		DELTA(a[,b])
2198
	 *
2199
	 * @param	float		$a	The first number.
2200
	 * @param	float		$b	The second number. If omitted, b is assumed to be zero.
2201
	 * @return	int
2202
	 */
2203
	public static function DELTA($a, $b=0) {
2204
		$a	= PHPExcel_Calculation_Functions::flattenSingleValue($a);
2205
		$b	= PHPExcel_Calculation_Functions::flattenSingleValue($b);
2206
2207
		return (int) ($a == $b);
2208
	}	//	function DELTA()
2209
2210
2211
	/**
2212
	 * GESTEP
2213
	 *
2214
	 * Excel Function:
2215
	 *		GESTEP(number[,step])
2216
	 *
2217
	 * Returns 1 if number >= step; returns 0 (zero) otherwise
2218
	 * Use this function to filter a set of values. For example, by summing several GESTEP
2219
	 * functions you calculate the count of values that exceed a threshold.
2220
	 *
2221
	 * @param	float		$number		The value to test against step.
2222
	 * @param	float		$step		The threshold value.
2223
	 *									If you omit a value for step, GESTEP uses zero.
2224
	 * @return	int
2225
	 */
2226
	public static function GESTEP($number, $step=0) {
2227
		$number	= PHPExcel_Calculation_Functions::flattenSingleValue($number);
2228
		$step	= PHPExcel_Calculation_Functions::flattenSingleValue($step);
2229
2230
		return (int) ($number >= $step);
2231
	}	//	function GESTEP()
2232
2233
2234
	//
2235
	//	Private method to calculate the erf value
2236
	//
2237
	private static $_two_sqrtpi = 1.128379167095512574;
2238
2239
	public static function _erfVal($x) {
2240
		if (abs($x) > 2.2) {
2241
			return 1 - self::_erfcVal($x);
2242
		}
2243
		$sum = $term = $x;
2244
		$xsqr = ($x * $x);
2245
		$j = 1;
2246
		do {
2247
			$term *= $xsqr / $j;
2248
			$sum -= $term / (2 * $j + 1);
2249
			++$j;
2250
			$term *= $xsqr / $j;
2251
			$sum += $term / (2 * $j + 1);
2252
			++$j;
2253
			if ($sum == 0.0) {
2254
				break;
2255
			}
2256
		} while (abs($term / $sum) > PRECISION);
2257
		return self::$_two_sqrtpi * $sum;
2258
	}	//	function _erfVal()
2259
2260
2261
	/**
2262
	 * ERF
2263
	 *
2264
	 * Returns the error function integrated between lower_limit and upper_limit
2265
	 *
2266
	 * Excel Function:
2267
	 *		ERF(lower[,upper])
2268
	 *
2269
	 * @param	float		$lower	lower bound for integrating ERF
2270
	 * @param	float		$upper	upper bound for integrating ERF.
2271
	 *								If omitted, ERF integrates between zero and lower_limit
2272
	 * @return	int
2273
	 */
2274
	public static function ERF($lower, $upper = null) {
2275
		$lower	= PHPExcel_Calculation_Functions::flattenSingleValue($lower);
2276
		$upper	= PHPExcel_Calculation_Functions::flattenSingleValue($upper);
2277
2278
		if (is_numeric($lower)) {
2279
			if ($lower < 0) {
2280
				return PHPExcel_Calculation_Functions::NaN();
2281
			}
2282
			if (is_null($upper)) {
2283
				return self::_erfVal($lower);
2284
			}
2285
			if (is_numeric($upper)) {
2286
				if ($upper < 0) {
2287
					return PHPExcel_Calculation_Functions::NaN();
2288
				}
2289
				return self::_erfVal($upper) - self::_erfVal($lower);
2290
			}
2291
		}
2292
		return PHPExcel_Calculation_Functions::VALUE();
2293
	}	//	function ERF()
2294
2295
2296
	//
2297
	//	Private method to calculate the erfc value
2298
	//
2299
	private static $_one_sqrtpi = 0.564189583547756287;
2300
2301
	private static function _erfcVal($x) {
2302
		if (abs($x) < 2.2) {
2303
			return 1 - self::_erfVal($x);
2304
		}
2305
		if ($x < 0) {
2306
			return 2 - self::ERFC(-$x);
2307
		}
2308
		$a = $n = 1;
2309
		$b = $c = $x;
2310
		$d = ($x * $x) + 0.5;
2311
		$q1 = $q2 = $b / $d;
2312
		$t = 0;
2313
		do {
2314
			$t = $a * $n + $b * $x;
2315
			$a = $b;
2316
			$b = $t;
2317
			$t = $c * $n + $d * $x;
2318
			$c = $d;
2319
			$d = $t;
2320
			$n += 0.5;
2321
			$q1 = $q2;
2322
			$q2 = $b / $d;
2323
		} while ((abs($q1 - $q2) / $q2) > PRECISION);
2324
		return self::$_one_sqrtpi * exp(-$x * $x) * $q2;
2325
	}	//	function _erfcVal()
2326
2327
2328
	/**
2329
	 * ERFC
2330
	 *
2331
	 * Returns the complementary ERF function integrated between x and infinity
2332
	 *
2333
	 * Excel Function:
2334
	 *		ERF(x)
2335
	 *
2336
	 * @param	float		$x		The lower bound for integrating ERF
2337
	 * @return	int
2338
	 */
2339 View Code Duplication
	public static function ERFC($x) {
2340
		$x	= PHPExcel_Calculation_Functions::flattenSingleValue($x);
2341
2342
		if (is_numeric($x)) {
2343
			if ($x < 0) {
2344
				return PHPExcel_Calculation_Functions::NaN();
2345
			}
2346
			return self::_erfcVal($x);
2347
		}
2348
		return PHPExcel_Calculation_Functions::VALUE();
2349
	}	//	function ERFC()
2350
2351
2352
	/**
2353
	 * getConversionGroups
2354
	 *
2355
	 * @return	array
2356
	 */
2357
	public static function getConversionGroups() {
2358
		$conversionGroups = array();
2359
		foreach(self::$_conversionUnits as $conversionUnit) {
2360
			$conversionGroups[] = $conversionUnit['Group'];
2361
		}
2362
		return array_merge(array_unique($conversionGroups));
2363
	}	//	function getConversionGroups()
2364
2365
2366
	/**
2367
	 * getConversionGroupUnits
2368
	 *
2369
	 * @return	array
2370
	 */
2371
	public static function getConversionGroupUnits($group = NULL) {
2372
		$conversionGroups = array();
2373
		foreach(self::$_conversionUnits as $conversionUnit => $conversionGroup) {
2374
			if ((is_null($group)) || ($conversionGroup['Group'] == $group)) {
2375
				$conversionGroups[$conversionGroup['Group']][] = $conversionUnit;
2376
			}
2377
		}
2378
		return $conversionGroups;
2379
	}	//	function getConversionGroupUnits()
2380
2381
2382
	/**
2383
	 * getConversionGroupUnitDetails
2384
	 *
2385
	 * @return	array
2386
	 */
2387
	public static function getConversionGroupUnitDetails($group = NULL) {
2388
		$conversionGroups = array();
2389
		foreach(self::$_conversionUnits as $conversionUnit => $conversionGroup) {
2390
			if ((is_null($group)) || ($conversionGroup['Group'] == $group)) {
2391
				$conversionGroups[$conversionGroup['Group']][] = array(	'unit'			=> $conversionUnit,
2392
																		'description'	=> $conversionGroup['Unit Name']
2393
																	  );
2394
			}
2395
		}
2396
		return $conversionGroups;
2397
	}	//	function getConversionGroupUnitDetails()
2398
2399
2400
	/**
2401
	 * getConversionGroups
2402
	 *
2403
	 * @return	array
2404
	 */
2405
	public static function getConversionMultipliers() {
2406
		return self::$_conversionMultipliers;
2407
	}	//	function getConversionGroups()
2408
2409
2410
	/**
2411
	 * CONVERTUOM
2412
	 *
2413
	 * Converts a number from one measurement system to another.
2414
	 * For example, CONVERT can translate a table of distances in miles to a table of distances
2415
	 * in kilometers.
2416
	 *
2417
	 * Excel Function:
2418
	 *		CONVERT(value,fromUOM,toUOM)
2419
	 *
2420
	 * @param	float		$value		The value in fromUOM to convert.
2421
	 * @param	string		$fromUOM	The units for value.
2422
	 * @param	string		$toUOM		The units for the result.
2423
	 * @return	float
2424
	 */
2425
	public static function CONVERTUOM($value, $fromUOM, $toUOM) {
2426
		$value		= PHPExcel_Calculation_Functions::flattenSingleValue($value);
2427
		$fromUOM	= PHPExcel_Calculation_Functions::flattenSingleValue($fromUOM);
2428
		$toUOM		= PHPExcel_Calculation_Functions::flattenSingleValue($toUOM);
2429
2430
		if (!is_numeric($value)) {
2431
			return PHPExcel_Calculation_Functions::VALUE();
2432
		}
2433
		$fromMultiplier = 1.0;
2434 View Code Duplication
		if (isset(self::$_conversionUnits[$fromUOM])) {
2435
			$unitGroup1 = self::$_conversionUnits[$fromUOM]['Group'];
2436
		} else {
2437
			$fromMultiplier = substr($fromUOM,0,1);
2438
			$fromUOM = substr($fromUOM,1);
2439
			if (isset(self::$_conversionMultipliers[$fromMultiplier])) {
2440
				$fromMultiplier = self::$_conversionMultipliers[$fromMultiplier]['multiplier'];
2441
			} else {
2442
				return PHPExcel_Calculation_Functions::NA();
2443
			}
2444
			if ((isset(self::$_conversionUnits[$fromUOM])) && (self::$_conversionUnits[$fromUOM]['AllowPrefix'])) {
2445
				$unitGroup1 = self::$_conversionUnits[$fromUOM]['Group'];
2446
			} else {
2447
				return PHPExcel_Calculation_Functions::NA();
2448
			}
2449
		}
2450
		$value *= $fromMultiplier;
2451
2452
		$toMultiplier = 1.0;
2453 View Code Duplication
		if (isset(self::$_conversionUnits[$toUOM])) {
2454
			$unitGroup2 = self::$_conversionUnits[$toUOM]['Group'];
2455
		} else {
2456
			$toMultiplier = substr($toUOM,0,1);
2457
			$toUOM = substr($toUOM,1);
2458
			if (isset(self::$_conversionMultipliers[$toMultiplier])) {
2459
				$toMultiplier = self::$_conversionMultipliers[$toMultiplier]['multiplier'];
2460
			} else {
2461
				return PHPExcel_Calculation_Functions::NA();
2462
			}
2463
			if ((isset(self::$_conversionUnits[$toUOM])) && (self::$_conversionUnits[$toUOM]['AllowPrefix'])) {
2464
				$unitGroup2 = self::$_conversionUnits[$toUOM]['Group'];
2465
			} else {
2466
				return PHPExcel_Calculation_Functions::NA();
2467
			}
2468
		}
2469
		if ($unitGroup1 != $unitGroup2) {
2470
			return PHPExcel_Calculation_Functions::NA();
2471
		}
2472
2473
		if (($fromUOM == $toUOM) && ($fromMultiplier == $toMultiplier)) {
2474
			//	We've already factored $fromMultiplier into the value, so we need
2475
			//		to reverse it again
2476
			return $value / $fromMultiplier;
2477
		} elseif ($unitGroup1 == 'Temperature') {
2478
			if (($fromUOM == 'F') || ($fromUOM == 'fah')) {
2479
				if (($toUOM == 'F') || ($toUOM == 'fah')) {
2480
					return $value;
2481
				} else {
2482
					$value = (($value - 32) / 1.8);
2483
					if (($toUOM == 'K') || ($toUOM == 'kel')) {
2484
						$value += 273.15;
2485
					}
2486
					return $value;
2487
				}
2488
			} elseif ((($fromUOM == 'K') || ($fromUOM == 'kel')) &&
2489
					  (($toUOM == 'K') || ($toUOM == 'kel'))) {
2490
						return $value;
2491
			} elseif ((($fromUOM == 'C') || ($fromUOM == 'cel')) &&
2492
					  (($toUOM == 'C') || ($toUOM == 'cel'))) {
2493
					return $value;
2494
			}
2495
			if (($toUOM == 'F') || ($toUOM == 'fah')) {
2496
				if (($fromUOM == 'K') || ($fromUOM == 'kel')) {
2497
					$value -= 273.15;
2498
				}
2499
				return ($value * 1.8) + 32;
2500
			}
2501
			if (($toUOM == 'C') || ($toUOM == 'cel')) {
2502
				return $value - 273.15;
2503
			}
2504
			return $value + 273.15;
2505
		}
2506
		return ($value * self::$_unitConversions[$unitGroup1][$fromUOM][$toUOM]) / $toMultiplier;
2507
	}	//	function CONVERTUOM()
2508
2509
}	//	class PHPExcel_Calculation_Engineering
2510