1 |
<?php
|
2 |
//********************************************************************************
|
3 |
//Copyright (C) 2007 David T. Ashley
|
4 |
//********************************************************************************
|
5 |
//This program or source file is free software; you can redistribute it and/or
|
6 |
//modify it under the terms of the GNU Lesser General Public License as published
|
7 |
//by the Free Software Foundation; either version 2 of the License, or (at your
|
8 |
//option) any later version.
|
9 |
//
|
10 |
//This program or source file is distributed in the hope that it will
|
11 |
//be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
//GNU General Public License for more details.
|
14 |
//
|
15 |
//You may have received a copy of the GNU Lesser General Public License
|
16 |
//along with this program; if not, write to the Free Software
|
17 |
//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
18 |
//********************************************************************************
|
19 |
//This file implements arithmetic functions on integers (typically large
|
20 |
//integers) represented as string. These functions are used as a layer above
|
21 |
//the bcmath functions, in case this set of web pages must be implemented on
|
22 |
//a version of PHP without bcmath compiled in. In this event, the functions
|
23 |
//in this file can be replaced with (slower) PHP functions that perform
|
24 |
//the arithmetic on strings directly in PHP. As most of the algorithms on this
|
25 |
//set of web pages are O(log N) this _should_ work, but it hasn't been
|
26 |
//evaluated for speed.
|
27 |
//--------------------------------------------------------------------------------
|
28 |
//Notes on canonical form: for use with the numerical functions in this
|
29 |
//library, the following conventions apply:
|
30 |
// a)Zero has one representation, "0".
|
31 |
// b)On non-zero numbers, no leading 0's are allowed.
|
32 |
// c)Positive numbers have no leading "+", but negative numbers have a
|
33 |
// leading "-".
|
34 |
// d)No commas, spaces, or extraneous characters are allowed.
|
35 |
// e)The string "INAN" is allowed to indicate that the integer is not a
|
36 |
// number. Combining "INAN" with any other number in any other
|
37 |
// operation results in "INAN".
|
38 |
//
|
39 |
//The notes above apply only to the form used for calculation. For presentation
|
40 |
//in human-readable form, commas are allowed, and functions are provided to
|
41 |
//convert back and forth.
|
42 |
//--------------------------------------------------------------------------------
|
43 |
//Notes on the "scale" parameter to the bcmath functions ... this is provided on
|
44 |
//all calls that accept it in order to override the default value set via
|
45 |
//the bcscale() function. Although it should have no effect with natural numbers,
|
46 |
//it is provided to provide a more consistent environment and to head off
|
47 |
//bugs.
|
48 |
//--------------------------------------------------------------------------------
|
49 |
require_once("strfunc.inc");
|
50 |
//
|
51 |
//--------------------------------------------------------------------------------
|
52 |
//Result codes that may be returned from functions. These are integers designed
|
53 |
//to be masked. Since all known PHP implementations use 32-bit or larger
|
54 |
//integers, at least 31 bits are available.
|
55 |
define("ISARITH_RC_UPERROR", 0x00000001);
|
56 |
//An unidentified parse error occurred.
|
57 |
define("ISARITH_RC_EMPTY_STRING", 0x00000002);
|
58 |
//A request was made to parse the empty string.
|
59 |
define("ISARITH_RC_ICHAR", 0x00000004);
|
60 |
//Illegal character(s) other than space or tab were encountered as part of
|
61 |
//the parse.
|
62 |
define("ISARITH_RC_GAP", 0x00000008);
|
63 |
//The string to be parsed contained space or tab gaps.
|
64 |
define("ISARITH_RC_BADLIMIT", 0x00000010);
|
65 |
//The limits (min, max) passed in were bad or not parseable.
|
66 |
define("ISARITH_RC_NOTWHOLENUM", 0x00000020);
|
67 |
//The number supplied is not an integer (the mantissa and exponent
|
68 |
//create a number with a fractional part).
|
69 |
define("ISARITH_RC_IINAN", 0x00000040);
|
70 |
//INAN was encountered during the parse, while the parse parameters
|
71 |
//indicated that INAN is not allowed.
|
72 |
define("ISARITH_RC_2SMALL", 0x00000080);
|
73 |
//The value as parsed was smaller than allowed.
|
74 |
define("ISARITH_RC_2LARGE", 0x00000100);
|
75 |
//The value as parsed was larger than allowed.
|
76 |
define("ISARITH_RC_SIGNPARSE", 0x00000200);
|
77 |
//Multiple or conflicting mantissa signs were allowed.
|
78 |
define("ISARITH_RC_DPPARSE", 0x00000400);
|
79 |
//Multiple decimal points were found.
|
80 |
define("ISARITH_RC_EXPMPARSE", 0x00000800);
|
81 |
//Multiple exponent markers (e or E) were found.
|
82 |
define("ISARITH_RC_EMSGN", 0x00001000);
|
83 |
//Multiple or conflicting exponent signs were found
|
84 |
//--------------------------------------------------------------------------------
|
85 |
//Codes to specify behavior when non-integers are encountered.
|
86 |
define("ISARITH_NIB_INTEGERSONLY", 0);
|
87 |
//Numbers with fractional parts simply aren't allowed. Refuse to do the
|
88 |
//conversion and return ISARITH_RC_NOTWHOLENUM.
|
89 |
define("ISARITH_NIB_ROUNDNEAREST", 1);
|
90 |
//Round to the nearest integer with no exceptions. Values that are halfway
|
91 |
//are rounded to the integer of larger magnitude.
|
92 |
// 3.1 --> 3
|
93 |
// -3.1 --> -3
|
94 |
// 2.9 --> 3
|
95 |
// -2.9 --> -3
|
96 |
// 3.5 --> 4
|
97 |
// -3.5 --> -4
|
98 |
define("ISARITH_NIB_ROUNDLESSER", 2);
|
99 |
//Round to the lesser integer, with "lesser" being strictly defined as
|
100 |
//more to the left on the number line.
|
101 |
// 3.1 --> 3
|
102 |
// -3.1 --> -4
|
103 |
// 2.9 --> 2
|
104 |
// -2.9 --> -3
|
105 |
// 3.5 --> 3
|
106 |
// -3.5 --> -4
|
107 |
define("ISARITH_NIB_ROUNDGREATER", 3);
|
108 |
//Round to the greater integer, with "greater" being strictly defined as
|
109 |
//more to the right on the number line.
|
110 |
// 3.1 --> 4
|
111 |
// -3.1 --> -3
|
112 |
// 2.9 --> 3
|
113 |
// -2.9 --> -2
|
114 |
// 3.5 --> 4
|
115 |
// -3.5 --> -3
|
116 |
define("ISARITH_NIB_ROUNDLESSERMAG", 4);
|
117 |
//Round to the integer of lesser magnitude.
|
118 |
// 3.1 --> 3
|
119 |
// -3.1 --> -3
|
120 |
// 2.9 --> 2
|
121 |
// -2.9 --> -2
|
122 |
// 3.5 --> 3
|
123 |
// -3.5 --> -3
|
124 |
define("ISARITH_NIB_ROUNDGREATERMAG", 5);
|
125 |
//Round to the integer of greater magnitude.
|
126 |
// 3.1 --> 4
|
127 |
// -3.1 --> -4
|
128 |
// 2.9 --> 3
|
129 |
// -2.9 --> -3
|
130 |
// 3.5 --> 4
|
131 |
// -3.5 --> -4
|
132 |
//--------------------------------------------------------------------------------
|
133 |
//--------------------------------------------------------------------------------
|
134 |
//---- S T A T I C -------------------------------------------------------------
|
135 |
//--------------------------------------------------------------------------------
|
136 |
//--------------------------------------------------------------------------------
|
137 |
//Trims the leading 0's from a string representing a signed or unsigned
|
138 |
//integer. The string may have a sign, but may have no spaces or commas.
|
139 |
//
|
140 |
//If final result is "-0", changed to "0".
|
141 |
//
|
142 |
function ISARITH_trim_leading_zeros($arg)
|
143 |
{
|
144 |
//Be sure the argument is a string.
|
145 |
$arg = (string)$arg;
|
146 |
|
147 |
if (strlen($arg) != 0)
|
148 |
{
|
149 |
if (SubStr($arg, 0, 1) == "-")
|
150 |
{
|
151 |
//Argument has a minus sign.
|
152 |
while(
|
153 |
(strlen($arg) >= 3)
|
154 |
&&
|
155 |
(SubStr($arg, 1, 1) == "0")
|
156 |
)
|
157 |
{
|
158 |
$arg = "-" . SubStr($arg, 2);
|
159 |
}
|
160 |
|
161 |
if (strcmp("-0", $arg) == 0)
|
162 |
{
|
163 |
$arg = "0";
|
164 |
}
|
165 |
}
|
166 |
else
|
167 |
{
|
168 |
//Argument has no minus sign.
|
169 |
while(
|
170 |
(strlen($arg) >= 2)
|
171 |
&&
|
172 |
(SubStr($arg, 0, 1) == "0")
|
173 |
)
|
174 |
{
|
175 |
$arg = SubStr($arg, 1);
|
176 |
}
|
177 |
}
|
178 |
|
179 |
return($arg);
|
180 |
}
|
181 |
else
|
182 |
{
|
183 |
//Empty string?
|
184 |
return($arg);
|
185 |
}
|
186 |
}
|
187 |
//
|
188 |
//--------------------------------------------------------------------------------
|
189 |
//Passed an integer representing the bit mask of error codes from a function
|
190 |
//in this module, returns an array of symbolic tags indicating the
|
191 |
//codes. If no tags, FALSE is returned.
|
192 |
//
|
193 |
function ISARITH_integer_to_result_code_array($i_in)
|
194 |
{
|
195 |
if (!is_int($i_in))
|
196 |
return(FALSE);
|
197 |
else if ($i_in == 0)
|
198 |
return(FALSE);
|
199 |
else
|
200 |
{
|
201 |
if ($i_in & ISARITH_RC_UPERROR)
|
202 |
$rv[] = "ISARITH_RC_UPERROR";
|
203 |
if ($i_in & ISARITH_RC_EMPTY_STRING)
|
204 |
$rv[] = "ISARITH_RC_EMPTY_STRING";
|
205 |
if ($i_in & ISARITH_RC_ICHAR)
|
206 |
$rv[] = "ISARITH_RC_ICHAR";
|
207 |
if ($i_in & ISARITH_RC_GAP)
|
208 |
$rv[] = "ISARITH_RC_GAP";
|
209 |
if ($i_in & ISARITH_RC_BADLIMIT)
|
210 |
$rv[] = "ISARITH_RC_BADLIMIT";
|
211 |
if ($i_in & ISARITH_RC_NOTWHOLENUM)
|
212 |
$rv[] = "ISARITH_RC_NOTWHOLENUM";
|
213 |
if ($i_in & ISARITH_RC_IINAN)
|
214 |
$rv[] = "ISARITH_RC_IINAN";
|
215 |
if ($i_in & ISARITH_RC_2SMALL)
|
216 |
$rv[] = "ISARITH_RC_2SMALL";
|
217 |
if ($i_in & ISARITH_RC_2LARGE)
|
218 |
$rv[] = "ISARITH_RC_2LARGE";
|
219 |
if ($i_in & ISARITH_RC_SIGNPARSE)
|
220 |
$rv[] = "ISARITH_RC_SIGNPARSE";
|
221 |
if ($i_in & ISARITH_RC_DPPARSE)
|
222 |
$rv[] = "ISARITH_RC_DPPARSE";
|
223 |
if ($i_in & ISARITH_RC_EXPMPARSE)
|
224 |
$rv[] = "ISARITH_RC_EXPMPARSE";
|
225 |
if ($i_in & ISARITH_RC_EMSGN)
|
226 |
$rv[] = "ISARITH_RC_EMSGN";
|
227 |
|
228 |
if (!isset($rv))
|
229 |
$rv = FALSE;
|
230 |
|
231 |
return($rv);
|
232 |
}
|
233 |
}
|
234 |
//
|
235 |
//--------------------------------------------------------------------------------
|
236 |
//Forms a decimal number based on the predecimal and postdecimal parts, which
|
237 |
//may have had leading and trailing zeros (respectively) removed.
|
238 |
//
|
239 |
function ISARITH_form_decimal_number($pre_d, $post_d)
|
240 |
{
|
241 |
if (! strlen($pre_d) && ! strlen($post_d))
|
242 |
{
|
243 |
//Both strings evaluated to 0's that could be trimmed, 0.0
|
244 |
//is the right replacement.
|
245 |
$rv = "0.0";
|
246 |
}
|
247 |
else if (! strlen($pre_d) && strlen($post_d))
|
248 |
{
|
249 |
//The pre-decimal point value is the empty string, but the
|
250 |
//post isn't. 0.Y is the right answer.
|
251 |
$rv = "0." . $post_d;
|
252 |
}
|
253 |
else if (strlen($pre_d) && ! strlen($post_d))
|
254 |
{
|
255 |
//The post-decimal point value is the empty string, but the
|
256 |
//pre isn't. X is the right answer.
|
257 |
$rv = $pre_d;
|
258 |
}
|
259 |
else
|
260 |
{
|
261 |
//Both are non-empty.
|
262 |
$rv = $pre_d . "." . $post_d;
|
263 |
}
|
264 |
|
265 |
return($rv);
|
266 |
|
267 |
}
|
268 |
//
|
269 |
//--------------------------------------------------------------------------------
|
270 |
//Assigns an arbitrarily long integer from a string. The string is converted
|
271 |
//to a simple integer, if possible.
|
272 |
//
|
273 |
//There are no limits on this function, so it would be possible to cause an
|
274 |
//out of memory or other condition by passing in an argument with an exponent
|
275 |
//of large absolute value. This function should be reserved for contexts
|
276 |
//where user input isn't the source or where it has already been sanitized.
|
277 |
//
|
278 |
//This function will accept strings to parse in a more relaxed format
|
279 |
//than canonical form (it parses things into canonical form). The
|
280 |
//specific relaxations are:
|
281 |
// a)A unary "+" is allowed, even on "0".
|
282 |
// b)Unary "-" is allowed even on "0".
|
283 |
// c)Commas are allowed, and need not be properly placed. Commas may occur
|
284 |
// even in exponents.
|
285 |
//
|
286 |
//The input string must be sanitized of spaces and tabs, even leading and trailing
|
287 |
//ones. The responsibility of removing these was deliberately pushed off onto the
|
288 |
//caller.
|
289 |
//
|
290 |
//Allowable formats are:
|
291 |
// a)Integer format (i.e. "25", "-2,352", "+325", etc.).
|
292 |
// b)Scientific notation, i.e. "3.12451234e+23".
|
293 |
// c)Optionally, "INAN".
|
294 |
//
|
295 |
function ISARITH_int_parse_and_separate
|
296 |
(
|
297 |
$in_i2parse,
|
298 |
//The string to parse. As mentioned above, all characters not to be
|
299 |
//considered, including leading and trailing blanks and tabs. The design
|
300 |
//decision to push this off on the caller was deliberate, as it gives the
|
301 |
//caller more latitude to decide what is allowed and not.
|
302 |
$in_inan_allowed,
|
303 |
//TRUE if INAN is allowed as an input string, or FALSE otherwise.
|
304 |
$in_debug,
|
305 |
//Flag, per the rules for PHP Boolean interpretation, that indicates whether to
|
306 |
//provide debug information per the $debug_out variable.
|
307 |
&$out_parse_errs,
|
308 |
//An integer reflecting a bitmask of errors (or lack thereof) encountered during
|
309 |
//the parse. Zero is the only value which will result in the output values being
|
310 |
//all usable. The output values should not be used (values are undefined) if
|
311 |
//parse errors were encountered.
|
312 |
&$out_is_inan,
|
313 |
//TRUE if the value was parsed as INAN, FALSE otherwise.
|
314 |
&$out_mant_sign,
|
315 |
//The sign character of the mantissa. This will be either "" (no sign specified),
|
316 |
//"-" (minus sign specified), or "+" (plus sign specified).
|
317 |
&$out_mant_pre_dec,
|
318 |
//The mantissa, with commas removed, before the decimal point. If no decimal
|
319 |
//point is specified, this would contain the only digits. If no digits
|
320 |
//appear before the decimal point, this may be "". All leading 0's are
|
321 |
//removed, so if a number such as "0.9" or "0.0" is specified, this may be "".
|
322 |
&$out_mant_post_dec,
|
323 |
//The mantissa, with commas removed, after the decimal point. All trailing
|
324 |
//0's are removed, possibly resulting in "".
|
325 |
&$out_exp_sign,
|
326 |
//The sign of the exponent, "", "-", or "+".
|
327 |
&$out_exp_digits,
|
328 |
//The digits of the exponent, with leading 0's removed. No exponent specified
|
329 |
//or a number such as "3.14e+00" will result in an empty string here.
|
330 |
&$out_display_value_scimatch,
|
331 |
//If the integer to parse contained errors, the suggested display value to allow the user
|
332 |
//to correct them. If the integer to parse contained no errors, the suggested display
|
333 |
//value. With this string, the user's choice of scientific notation or not is matched in the
|
334 |
//output. Unlike other fields, if there were errors encountered, this will not be
|
335 |
//FALSE (it will always be a string).
|
336 |
&$out_debug
|
337 |
//If $debug_in is TRUE, this will be populated with an array of strings containing
|
338 |
//debug information, otherwise this variable will be FALSE.
|
339 |
)
|
340 |
{
|
341 |
//Assign initial values. This sets the type as well.
|
342 |
$out_parse_errors = 0;
|
343 |
$out_is_inan = FALSE;
|
344 |
$out_mant_sign = "";
|
345 |
$out_mant_pre_dec = "";
|
346 |
$out_mant_post_dec = "";
|
347 |
$out_exp_sign = "";
|
348 |
$out_exp_digits = "";
|
349 |
$out_display_value_scimatch = "";
|
350 |
|
351 |
//Set up for debug information.
|
352 |
if ($in_debug)
|
353 |
{
|
354 |
$debug_separator = "- - - - - - - - - - - - - - - - - - - - - - - - - - -";
|
355 |
$out_debug[] = $debug_separator;
|
356 |
$out_debug[] = "ISARITH_assign_from_string_nolimit() Debug Information";
|
357 |
$out_debug[] = $debug_separator;
|
358 |
}
|
359 |
else
|
360 |
{
|
361 |
$out_debug = FALSE;
|
362 |
}
|
363 |
|
364 |
//Guard against empty string.
|
365 |
$in_i2parse = (string)$in_i2parse;
|
366 |
if (strlen($in_i2parse) == 0)
|
367 |
{
|
368 |
if ($in_debug)
|
369 |
{
|
370 |
$out_debug[] = "(Line " . __LINE__ . ") Empty string. Returning.";
|
371 |
$out_debug[] = $debug_separator;
|
372 |
}
|
373 |
|
374 |
$out_display_value_scimatch = "";
|
375 |
$out_parse_errs = ISARITH_RC_EMPTY_STRING;
|
376 |
return;
|
377 |
}
|
378 |
|
379 |
//Handle the "INAN" case.
|
380 |
if (strcmp($in_i2parse, "INAN") == 0)
|
381 |
{
|
382 |
if ($in_inan_allowed)
|
383 |
{
|
384 |
//INAN is allowed, and we have it. Return INAN.
|
385 |
if ($in_debug)
|
386 |
{
|
387 |
$out_debug[] = "(Line " . __LINE__ . ") INAN found and allowed. Returning.";
|
388 |
$out_debug[] = $debug_separator;
|
389 |
}
|
390 |
|
391 |
$out_is_inan = TRUE;
|
392 |
return;
|
393 |
}
|
394 |
else
|
395 |
{
|
396 |
//INAN is not allowed, but we have it. This is an error.
|
397 |
if ($in_debug)
|
398 |
{
|
399 |
$out_debug[] = "(Line " . __LINE__ . ") INAN found and not allowed. Returning.";
|
400 |
$out_debug[] = $debug_separator;
|
401 |
}
|
402 |
|
403 |
$out_parse_errs = ISARITH_RC_IINAN;
|
404 |
return;
|
405 |
}
|
406 |
}
|
407 |
|
408 |
//Guard against invalid characters that are strongly disallowed
|
409 |
//(characters even more illegal than spaces or tabs).
|
410 |
if (! STRFUNC_is_char_subset($in_i2parse, " \t+-.,eE0123456789"))
|
411 |
{
|
412 |
if ($in_debug)
|
413 |
{
|
414 |
$out_debug[] = "(Line " . __LINE__ . ") Illegal character (more extreme than space or tab) found. Returning.";
|
415 |
$out_debug[] = $debug_separator;
|
416 |
}
|
417 |
|
418 |
$out_display_value_scimatch = STRFUNC_force_into_subset($in_i2parse, " \t+-.,eE0123456789");
|
419 |
$out_parse_errs = ISARITH_RC_ICHAR;
|
420 |
return;
|
421 |
}
|
422 |
|
423 |
//Guard against space/tab gaps, which are not allowed.
|
424 |
if (! STRFUNC_is_char_subset($in_i2parse, "+-.,eE0123456789"))
|
425 |
{
|
426 |
if ($in_debug)
|
427 |
{
|
428 |
$out_debug[] = "(Line " . __LINE__ . ") Space or tab gaps found. Returning.";
|
429 |
$out_debug[] = $debug_separator;
|
430 |
}
|
431 |
|
432 |
$out_display_value_scimatch = STRFUNC_force_into_subset($in_i2parse, "+-.,eE0123456789");
|
433 |
$out_parse_errs = ISARITH_RC_GAP;
|
434 |
return;
|
435 |
}
|
436 |
|
437 |
//Trim any commas from the string. These are by and large ignored.
|
438 |
$in_i2parse = STRFUNC_force_into_subset($in_i2parse, "+-.eE0123456789");
|
439 |
|
440 |
//If we created an empty string, this is a gross
|
441 |
//parse error.
|
442 |
if (strlen($in_i2parse) == 0)
|
443 |
{
|
444 |
if ($in_debug)
|
445 |
{
|
446 |
$out_debug[] = "(Line " . __LINE__ . ") Gross parsing error (empty string as intermediate result). Returning.";
|
447 |
$out_debug[] = $debug_separator;
|
448 |
}
|
449 |
|
450 |
$out_display_value_scimatch = "";
|
451 |
$out_parse_errs = ISARITH_RC_UPERROR;
|
452 |
return;
|
453 |
}
|
454 |
|
455 |
//Strip off any leading "-" and "+" signs of the mantissa.
|
456 |
$out_mant_sign = "";
|
457 |
while
|
458 |
(
|
459 |
(strlen($in_i2parse) != 0)
|
460 |
&&
|
461 |
(
|
462 |
(SubStr($in_i2parse, 0, 1) == "-")
|
463 |
||
|
464 |
(SubStr($in_i2parse, 0, 1) == "+")
|
465 |
)
|
466 |
)
|
467 |
{
|
468 |
if (SubStr($in_i2parse, 0, 1) == "-")
|
469 |
{
|
470 |
if (strlen($out_mant_sign))
|
471 |
{
|
472 |
//We are finding a second sign character. Not allowed.
|
473 |
if ($in_debug)
|
474 |
{
|
475 |
$out_debug[] = "(Line " . __LINE__ . ") Second sign character found (illegal). Returning.";
|
476 |
$out_debug[] = $debug_separator;
|
477 |
}
|
478 |
|
479 |
$out_display_value_scimatch = $in_i2parse;
|
480 |
$out_parse_errs = ISARITH_RC_SIGNPARSE;
|
481 |
return;
|
482 |
}
|
483 |
else
|
484 |
{
|
485 |
//Found a first minus sign. Record it.
|
486 |
if ($in_debug)
|
487 |
{
|
488 |
$out_debug[] = "(Line " . __LINE__ . ") Found a single minus sign (legal).";
|
489 |
}
|
490 |
|
491 |
$out_mant_sign = "-";
|
492 |
}
|
493 |
}
|
494 |
else if (SubStr($in_i2parse, 0, 1) == "+")
|
495 |
{
|
496 |
if (strlen($out_mant_sign))
|
497 |
{
|
498 |
//We are finding a second sign character. Not allowed.
|
499 |
if ($in_debug)
|
500 |
{
|
501 |
$out_debug[] = "(Line " . __LINE__ . ") Second sign character found (illegal). Returning.";
|
502 |
$out_debug[] = $debug_separator;
|
503 |
}
|
504 |
|
505 |
$out_display_value_scimatch = $in_i2parse;
|
506 |
$out_parse_errs = ISARITH_RC_SIGNPARSE;
|
507 |
return;
|
508 |
}
|
509 |
else
|
510 |
{
|
511 |
//Found a plus sign. Record it.
|
512 |
if ($in_debug)
|
513 |
{
|
514 |
$out_debug[] = "(Line " . __LINE__ . ") Plus sign found (legal).";
|
515 |
}
|
516 |
|
517 |
$out_mant_sign = "+";
|
518 |
}
|
519 |
}
|
520 |
|
521 |
//Strip the character.
|
522 |
$in_i2parse = SubStr($in_i2parse, 1);
|
523 |
} //End while()
|
524 |
|
525 |
//If we created an empty string, this is a gross
|
526 |
//parse error.
|
527 |
if (strlen($in_i2parse) == 0)
|
528 |
{
|
529 |
if ($in_debug)
|
530 |
{
|
531 |
$out_debug[] = "(Line " . __LINE__ . ") Gross parsing error (empty string as intermediate result). Returning.";
|
532 |
$out_debug[] = $debug_separator;
|
533 |
}
|
534 |
|
535 |
$out_display_value_scimatch = "";
|
536 |
$out_parse_errs = ISARITH_RC_UPERROR;
|
537 |
return;
|
538 |
}
|
539 |
|
540 |
//Debug info.
|
541 |
if ($in_debug)
|
542 |
{
|
543 |
$out_debug[] = "(Line " . __LINE__ . ") String created after removal of mantissa sign is \"" .
|
544 |
$in_i2parse . "\".";
|
545 |
}
|
546 |
|
547 |
//The next item has to be a decimal point or a digit, otherwise
|
548 |
//the mantissa is effectively missing.
|
549 |
if (! STRFUNC_is_char_subset(SubStr($in_i2parse, 0, 1), ".0123456789"))
|
550 |
{
|
551 |
if ($in_debug)
|
552 |
{
|
553 |
$debug_out[] = "(Line " . __LINE__ . ") Decimal point or digit not found when starting to parse mantissa. Returning.";
|
554 |
}
|
555 |
|
556 |
$out_display_value_scimatch = $out_mant_sign . $in_i2parse;
|
557 |
$out_parse_errs = ISARITH_RC_UPERROR;
|
558 |
return;
|
559 |
}
|
560 |
|
561 |
//Remove the digits, if any before the decimal point, if any.
|
562 |
while (
|
563 |
(strlen($in_i2parse))
|
564 |
&&
|
565 |
(STRFUNC_is_char_subset(SubStr($in_i2parse, 0, 1), "0123456789"))
|
566 |
)
|
567 |
{
|
568 |
$out_mant_pre_dec .= SubStr($in_i2parse, 0, 1);
|
569 |
$in_i2parse = SubStr($in_i2parse, 1);
|
570 |
}
|
571 |
|
572 |
//Debug info.
|
573 |
if ($in_debug)
|
574 |
{
|
575 |
$out_debug[] = "(Line " . __LINE__ . ") String created after removal of mantissa pre-decimal digits is \"" .
|
576 |
$in_i2parse . "\".";
|
577 |
}
|
578 |
|
579 |
//Remove any leading 0's from the string. This may result in "".
|
580 |
while
|
581 |
(
|
582 |
(strlen($out_mant_pre_dec))
|
583 |
&&
|
584 |
(SubStr($out_mant_pre_dec, 0, 1) == "0")
|
585 |
)
|
586 |
{
|
587 |
$out_mant_pre_dec = SubStr($out_mant_pre_dec, 1);
|
588 |
}
|
589 |
|
590 |
//Debug info.
|
591 |
if ($in_debug)
|
592 |
{
|
593 |
$out_debug[] = "(Line " . __LINE__ . ") out_mant_pre_dec after removal of leading 0's is \"" .
|
594 |
$out_mant_pre_dec . "\".";
|
595 |
}
|
596 |
|
597 |
//If we have an empty string, this is a permissible exit point. This would be an integer with
|
598 |
//no frills.
|
599 |
if (strlen($in_i2parse) == 0)
|
600 |
{
|
601 |
if ($in_debug)
|
602 |
{
|
603 |
$out_debug[] = "(Line " . __LINE__ . ") Plain integer detected.";
|
604 |
$out_debug[] = $debug_separator;
|
605 |
}
|
606 |
|
607 |
$out_display_value_scimatch = $out_mant_sign . $out_mant_pre_dec;
|
608 |
return;
|
609 |
}
|
610 |
|
611 |
//Remove the decimal point, if any.
|
612 |
if (STRFUNC_is_char_subset(SubStr($in_i2parse, 0, 1), "."))
|
613 |
{
|
614 |
$in_i2parse = SubStr($in_i2parse, 1);
|
615 |
}
|
616 |
|
617 |
//Debug info.
|
618 |
if ($in_debug)
|
619 |
{
|
620 |
$out_debug[] = "(Line " . __LINE__ . ") String created after removal of decimal point is \"" .
|
621 |
$in_i2parse . "\".";
|
622 |
}
|
623 |
|
624 |
//Remove the digits, if any, after the decimal point.
|
625 |
while (
|
626 |
(strlen($in_i2parse))
|
627 |
&&
|
628 |
(STRFUNC_is_char_subset(SubStr($in_i2parse, 0, 1), "0123456789"))
|
629 |
)
|
630 |
{
|
631 |
$out_mant_post_dec .= SubStr($in_i2parse, 0, 1);
|
632 |
$in_i2parse = SubStr($in_i2parse, 1);
|
633 |
}
|
634 |
|
635 |
//Debug info.
|
636 |
if ($in_debug)
|
637 |
{
|
638 |
$out_debug[] = "(Line " . __LINE__ . ") String created after removal of mantissa post-decimal digits is \"" .
|
639 |
$in_i2parse . "\".";
|
640 |
}
|
641 |
|
642 |
//Remove any trailing 0's from the string. This may result in "".
|
643 |
while
|
644 |
(
|
645 |
(strlen($out_mant_post_dec))
|
646 |
&&
|
647 |
(SubStr($out_mant_post_dec, strlen($out_mant_post_dec) - 1, 1) == "0")
|
648 |
)
|
649 |
{
|
650 |
$out_mant_post_dec = SubStr($out_mant_post_dec, 0, strlen($out_mant_post_dec) - 1);
|
651 |
}
|
652 |
|
653 |
//Debug info.
|
654 |
if ($in_debug)
|
655 |
{
|
656 |
$out_debug[] = "(Line " . __LINE__ . ") out_mant_post_dec after removal of trailing 0's is \"" .
|
657 |
$out_mant_post_dec . "\".";
|
658 |
}
|
659 |
|
660 |
//If we're here and have an empty string, this is an allowed parsing exit.
|
661 |
//It corresponds to entering a decimal number without an exponent where an
|
662 |
//integer is required. This is probably a misunderstanding of some sort, but
|
663 |
//the caller should deal with it (not this function).
|
664 |
if (strlen($in_i2parse) == 0)
|
665 |
{
|
666 |
if ($in_debug)
|
667 |
{
|
668 |
$out_debug[] = "(Line " . __LINE__ . ") Plain decimal number detected.";
|
669 |
$out_debug[] = $debug_separator;
|
670 |
}
|
671 |
|
672 |
$out_display_value_scimatch = $out_mant_sign . ISARITH_form_decimal_number($out_mant_pre_dec, $out_mant_post_dec);
|
673 |
return;
|
674 |
}
|
675 |
|
676 |
//The next character has to be an "E" or "e". If it isn't, this is a gross
|
677 |
//parsing error.
|
678 |
if (StrToUpper(SubStr($in_i2parse, 0, 1)) != "E")
|
679 |
{
|
680 |
//The character is not an "E" or "e". Gross parsing error.
|
681 |
|
682 |
if ($in_debug)
|
683 |
{
|
684 |
$out_debug[] = "(Line " . __LINE__ . ") Gross parsing error, E/e not in place.";
|
685 |
$out_debug[] = $debug_separator;
|
686 |
}
|
687 |
|
688 |
$out_display_value_scimatch = $out_mant_sign . ISARITH_form_decimal_number($out_mant_pre_dec, $out_mant_post_dec);
|
689 |
//Should ignore the stuff we can't parse. Just form the mantissa.
|
690 |
$out_parse_errs = ISARITH_RC_UPERROR;
|
691 |
return;
|
692 |
}
|
693 |
|
694 |
//Remove the "E" or "e" character.
|
695 |
$in_i2parse = SubStr($in_i2parse, 1);
|
696 |
|
697 |
//If we created an empty string, this is a gross
|
698 |
//parse error.
|
699 |
if (strlen($in_i2parse) == 0)
|
700 |
{
|
701 |
if ($in_debug)
|
702 |
{
|
703 |
$out_debug[] = "(Line " . __LINE__ . ") Gross parsing error (empty string as intermediate result). Returning.";
|
704 |
$out_debug[] = $debug_separator;
|
705 |
}
|
706 |
|
707 |
$out_display_value_scimatch = $out_mant_sign . ISARITH_form_decimal_number($out_mant_pre_dec, $out_mant_post_dec);
|
708 |
//Should ignore the stuff we can't parse. Just form the mantissa.
|
709 |
$out_parse_errs = ISARITH_RC_UPERROR;
|
710 |
return;
|
711 |
}
|
712 |
|
713 |
//Debug info.
|
714 |
if ($in_debug)
|
715 |
{
|
716 |
$out_debug[] = "(Line " . __LINE__ . ") String created after removal of E/e is \"" .
|
717 |
$in_i2parse . "\".";
|
718 |
}
|
719 |
|
720 |
//The next character has to be a sign character or a digit. If not, gross parsing error.
|
721 |
if (! STRFUNC_is_char_subset(SubStr($in_i2parse, 0, 1), "+-0123456789"))
|
722 |
{
|
723 |
if ($in_debug)
|
724 |
{
|
725 |
$out_debug[] = "(Line " . __LINE__ . ") Gross parsing error, char after E/e invalid.";
|
726 |
$out_debug[] = $debug_separator;
|
727 |
}
|
728 |
|
729 |
$out_display_value_scimatch = $out_mant_sign . ISARITH_form_decimal_number($out_mant_pre_dec, $out_mant_post_dec);
|
730 |
//Should ignore the stuff we can't parse. Just form the mantissa.
|
731 |
$out_parse_errs = ISARITH_RC_UPERROR;
|
732 |
return;
|
733 |
}
|
734 |
|
735 |
//Strip off and record the exponent sign, if any. There can be only one.
|
736 |
$out_exp_sign = "";
|
737 |
while
|
738 |
(
|
739 |
(strlen($in_i2parse) != 0)
|
740 |
&&
|
741 |
(
|
742 |
(SubStr($in_i2parse, 0, 1) == "-")
|
743 |
||
|
744 |
(SubStr($in_i2parse, 0, 1) == "+")
|
745 |
)
|
746 |
)
|
747 |
{
|
748 |
if (SubStr($in_i2parse, 0, 1) == "-")
|
749 |
{
|
750 |
if (strlen($out_exp_sign))
|
751 |
{
|
752 |
//We are finding a second sign character. Not allowed.
|
753 |
if ($in_debug)
|
754 |
{
|
755 |
$out_debug[] = "(Line " . __LINE__ . ") Second exponent sign character found (illegal). Returning.";
|
756 |
$out_debug[] = $debug_separator;
|
757 |
}
|
758 |
|
759 |
$out_display_value_scimatch
|
760 |
= $out_mant_sign . ISARITH_form_decimal_number($out_mant_pre_dec, $out_mant_post_dec);
|
761 |
$out_parse_errs = ISARITH_RC_EMSGN;
|
762 |
return;
|
763 |
}
|
764 |
else
|
765 |
{
|
766 |
//Found a first minus sign. Record it.
|
767 |
if ($in_debug)
|
768 |
{
|
769 |
$out_debug[] = "(Line " . __LINE__ . ") Found a single exponent minus sign (legal).";
|
770 |
}
|
771 |
|
772 |
$out_exp_sign = "-";
|
773 |
}
|
774 |
}
|
775 |
else if (SubStr($in_i2parse, 0, 1) == "+")
|
776 |
{
|
777 |
if (strlen($out_exp_sign))
|
778 |
{
|
779 |
//We are finding a second exponent sign character. Not allowed.
|
780 |
if ($in_debug)
|
781 |
{
|
782 |
$out_debug[] = "(Line " . __LINE__ . ") Second exponent sign character found (illegal). Returning.";
|
783 |
$out_debug[] = $debug_separator;
|
784 |
}
|
785 |
|
786 |
$out_display_value_scimatch
|
787 |
= $out_mant_sign . ISARITH_form_decimal_number($out_mant_pre_dec, $out_mant_post_dec);
|
788 |
$out_parse_errs = ISARITH_RC_EMSGN;
|
789 |
return;
|
790 |
}
|
791 |
else
|
792 |
{
|
793 |
//Found a plus sign. Record it.
|
794 |
if ($in_debug)
|
795 |
{
|
796 |
$out_debug[] = "(Line " . __LINE__ . ") Exponent plus sign found (legal).";
|
797 |
}
|
798 |
|
799 |
$out_exp_sign = "+";
|
800 |
}
|
801 |
}
|
802 |
|
803 |
//Strip the character.
|
804 |
$in_i2parse = SubStr($in_i2parse, 1);
|
805 |
} //End while()
|
806 |
|
807 |
//If we created an empty string, this is a gross
|
808 |
//parse error.
|
809 |
if (strlen($in_i2parse) == 0)
|
810 |
{
|
811 |
if ($in_debug)
|
812 |
{
|
813 |
$out_debug[] = "(Line " . __LINE__ . ") Gross parsing error (empty string as intermediate result). Returning.";
|
814 |
$out_debug[] = $debug_separator;
|
815 |
}
|
816 |
|
817 |
$out_display_value_scimatch = "";
|
818 |
$out_parse_errs = ISARITH_RC_UPERROR;
|
819 |
return;
|
820 |
}
|
821 |
|
822 |
//Debug info.
|
823 |
if ($in_debug)
|
824 |
{
|
825 |
$out_debug[] = "(Line " . __LINE__ . ") String created after removal of exponent sign is \"" .
|
826 |
$in_i2parse . "\".";
|
827 |
}
|
828 |
|
829 |
//The next character has to be a digit. If not, gross parsing error.
|
830 |
if (! STRFUNC_is_char_subset(SubStr($in_i2parse, 0, 1), "0123456789"))
|
831 |
{
|
832 |
if ($in_debug)
|
833 |
{
|
834 |
$out_debug[] = "(Line " . __LINE__ . ") Gross parsing error, exponent digits not as expected.";
|
835 |
$out_debug[] = $debug_separator;
|
836 |
}
|
837 |
|
838 |
$out_display_value_scimatch = $out_mant_sign . ISARITH_form_decimal_number($out_mant_pre_dec, $out_mant_post_dec);
|
839 |
//Should ignore the stuff we can't parse. Just form the mantissa.
|
840 |
$out_parse_errs = ISARITH_RC_UPERROR;
|
841 |
return;
|
842 |
}
|
843 |
|
844 |
//Remove the exponent digits.
|
845 |
while (
|
846 |
(strlen($in_i2parse))
|
847 |
&&
|
848 |
(STRFUNC_is_char_subset(SubStr($in_i2parse, 0, 1), "0123456789"))
|
849 |
)
|
850 |
{
|
851 |
$out_mant_exp_digits .= SubStr($in_i2parse, 0, 1);
|
852 |
$in_i2parse = SubStr($in_i2parse, 1);
|
853 |
}
|
854 |
|
855 |
//Debug info.
|
856 |
if ($in_debug)
|
857 |
{
|
858 |
$out_debug[] = "(Line " . __LINE__ . ") String created after removal of exponent digits is \"" .
|
859 |
$in_i2parse . "\".";
|
860 |
}
|
861 |
|
862 |
//Remove any leading 0's from the exponent. This may result in "".
|
863 |
while
|
864 |
(
|
865 |
(strlen($out_exp_digits))
|
866 |
&&
|
867 |
(SubStr($out_exp_digits, 0, 1) == "0")
|
868 |
)
|
869 |
{
|
870 |
$out_exp_digits = SubStr($out_exp_digits, 1);
|
871 |
}
|
872 |
|
873 |
//At this point, the string must be empty, otherwise there was stuff at the
|
874 |
//end of the number that is not digits.
|
875 |
if (strlen($in_i2parse) != 0)
|
876 |
{
|
877 |
if ($in_debug)
|
878 |
{
|
879 |
$out_debug[] = "(Line " . __LINE__ . ") Gross parsing error (non-digits at end of string). Returning.";
|
880 |
$out_debug[] = $debug_separator;
|
881 |
}
|
882 |
|
883 |
$out_display_value_scimatch = "";
|
884 |
$out_parse_errs = ISARITH_RC_UPERROR;
|
885 |
return;
|
886 |
}
|
887 |
|
888 |
//Debug info.
|
889 |
if ($in_debug)
|
890 |
{
|
891 |
$out_debug[] = "(Line " . __LINE__ . ") Setting up for normal non-error return.";
|
892 |
}
|
893 |
|
894 |
$out_display_value_scimatch = $out_mant_sign
|
895 |
. ISARITH_form_decimal_number($out_mant_pre_dec, $out_mant_post_dec);
|
896 |
if (strlen($out_exp_digits))
|
897 |
{
|
898 |
$out_display_value_scimatch = $out_display_value_scimatch
|
899 |
. "e"
|
900 |
. $out_exp_sign
|
901 |
. $out_exp_digits;
|
902 |
}
|
903 |
|
904 |
//Return fallthrough end of function.
|
905 |
}
|
906 |
//--------------------------------------------------------------------------------
|
907 |
//Assigns an arbitrarily long integer from a string. The string is converted
|
908 |
//to a simple integer, if possible.
|
909 |
//
|
910 |
//There are no limits on this function, so it would be possible to cause an
|
911 |
//out of memory or other condition by passing in an argument with an exponent
|
912 |
//of large absolute value. This function should be reserved for contexts
|
913 |
//where user input isn't the source or where it has already been sanitized.
|
914 |
//
|
915 |
//This function will accept strings to parse in a more relaxed format
|
916 |
//than canonical form (it parses things into canonical form). The
|
917 |
//specific relaxations are:
|
918 |
// a)A unary "+" is allowed, even on "0".
|
919 |
// b)Unary "-" is allowed even on "0".
|
920 |
// c)Commas are allowed, and need not be properly placed. Commas may occur
|
921 |
// even in exponents.
|
922 |
//
|
923 |
//The input string must be sanitized of spaces and tabs, even leading and trailing
|
924 |
//ones. The responsibility of removing these was deliberately pushed off onto the
|
925 |
//caller.
|
926 |
//
|
927 |
//Allowable formats are:
|
928 |
// a)Integer format (i.e. "25", "-2,352", "+325", etc.).
|
929 |
// b)Scientific notation, i.e. "3.12451234e+23".
|
930 |
// c)Optionally, "INAN".
|
931 |
//
|
932 |
function ISARITH_assign_from_string_nolimit
|
933 |
(
|
934 |
$in_i2parse,
|
935 |
//The string to parse. As mentioned above, all characters not to be
|
936 |
//considered, including leading and trailing blanks and tabs. The design
|
937 |
//decision to push this off on the caller was deliberate, as it gives the
|
938 |
//caller more latitude to decide what is allowed and not.
|
939 |
$in_inan_allowed,
|
940 |
//TRUE if INAN is allowed as an input string, or FALSE otherwise.
|
941 |
/* $in_nonint_behavior, */
|
942 |
//Behavior when non-integers are encountered (this may occur when a number is specified
|
943 |
//in scientific notation).
|
944 |
&$out_val,
|
945 |
//The output value parsed, as a simple integer string. This value will be
|
946 |
//FALSE iff there are errors.
|
947 |
&$out_errs,
|
948 |
//An integer reflecting a bitmask of errors (or lack thereof) encountered during
|
949 |
//the parse.
|
950 |
$debug_in,
|
951 |
//Flag, per the rules for PHP Boolean interpretation, that indicates whether to
|
952 |
//provide debug information per the $debug_out variable.
|
953 |
&$debug_out
|
954 |
//If $debug_in is TRUE, this will be populated with an array of strings containing
|
955 |
//debug information, otherwise this variable will be FALSE.
|
956 |
)
|
957 |
{
|
958 |
|
959 |
//Parse any digits before the decimal point, if there are any.
|
960 |
$parse_digits_pre_dec = "";
|
961 |
while (
|
962 |
(strlen($in_i2parse) != 0)
|
963 |
&&
|
964 |
(STRFUNC_is_char_subset(SubStr($in_i2parse, 0, 1), "0123456789"))
|
965 |
)
|
966 |
{
|
967 |
$parse_digits_pre_dec = $parse_digits_pre_dec . SubStr($in_i2parse, 0, 1);
|
968 |
$in_i2parse = SubStr($in_i2parse, 1);
|
969 |
}
|
970 |
|
971 |
//Parse the decimal point, if any. It is OK if we have an empty string
|
972 |
//at this point. There can be only one decimal point.
|
973 |
$parse_decimal_point_found = FALSE;
|
974 |
while
|
975 |
(
|
976 |
(strlen($in_i2parse) != 0)
|
977 |
&&
|
978 |
(SubStr($in_i2parse, 0, 1) == ".")
|
979 |
)
|
980 |
{
|
981 |
if ($parse_decimal_point_found)
|
982 |
{
|
983 |
//Illegal. Two decimal points.
|
984 |
$out_errs = ISARITH_RC_DPARSE;
|
985 |
return;
|
986 |
}
|
987 |
else
|
988 |
{
|
989 |
//Found a decimal point. This is fine, so long as it is the first one.
|
990 |
$parse_decimal_point_found = TRUE;
|
991 |
}
|
992 |
|
993 |
//Strip the character.
|
994 |
$in_i2parse = SubStr($in_i2parse, 1);
|
995 |
}
|
996 |
|
997 |
//Consume any digits that may occur after the decimal point.
|
998 |
$parse_digits_post_dec = "";
|
999 |
while (
|
1000 |
(strlen($in_i2parse) != 0)
|
1001 |
&&
|
1002 |
(STRFUNC_is_char_subset(SubStr($in_i2parse, 0, 1), "0123456789"))
|
1003 |
)
|
1004 |
{
|
1005 |
$parse_digits_post_dec = $parse_digits_post_dec . SubStr($in_i2parse, 0, 1);
|
1006 |
$in_i2parse = SubStr($in_i2parse, 1);
|
1007 |
}
|
1008 |
|
1009 |
//If the string remaining isn't empty, the only allowable character
|
1010 |
//is an "e" or "E". Once we have the "e" or "E", we must have an optional
|
1011 |
//sign and the digits.
|
1012 |
$parse_exp_marker_found = FALSE;
|
1013 |
$parse_exp_m_found = FALSE;
|
1014 |
$parse_exp_p_found = FALSE;
|
1015 |
$parse_exp_digits = "";
|
1016 |
|
1017 |
if (strlen($in_i2parse) != 0)
|
1018 |
{
|
1019 |
//Parse the exponent marker, if any.
|
1020 |
if (
|
1021 |
(SubStr($in_i2parse, 0, 1) == "e")
|
1022 |
||
|
1023 |
(SubStr($in_i2parse, 0, 1) == "E")
|
1024 |
)
|
1025 |
{
|
1026 |
$parse_exp_marker_found = TRUE;
|
1027 |
|
1028 |
//Strip the character.
|
1029 |
$in_i2parse = SubStr($in_i2parse, 1);
|
1030 |
}
|
1031 |
|
1032 |
//If we created an empty string, this is a gross
|
1033 |
//parse error.
|
1034 |
if (strlen($in_i2parse) == 0)
|
1035 |
{
|
1036 |
$out_errs = ISARITH_RC_UPERROR;
|
1037 |
return;
|
1038 |
}
|
1039 |
|
1040 |
//If there is a second exponent marker, this is a parse failure.
|
1041 |
if (
|
1042 |
(SubStr($in_i2parse, 0, 1) == "e")
|
1043 |
||
|
1044 |
(SubStr($in_i2parse, 0, 1) == "E")
|
1045 |
)
|
1046 |
{
|
1047 |
$out_errs = ISARITH_RC_EXPMPARSE;
|
1048 |
return;
|
1049 |
}
|
1050 |
|
1051 |
//Remove the optional sign from the exponent. There can be only one.
|
1052 |
while
|
1053 |
(
|
1054 |
(strlen($in_i2parse) != 0)
|
1055 |
&&
|
1056 |
(
|
1057 |
(SubStr($in_i2parse, 0, 1) == "-")
|
1058 |
||
|
1059 |
(SubStr($in_i2parse, 0, 1) == "+")
|
1060 |
)
|
1061 |
)
|
1062 |
{
|
1063 |
if (SubStr($in_i2parse, 0, 1) == "-")
|
1064 |
{
|
1065 |
if ($parse_exp_m_found || $parse_exp_p_found)
|
1066 |
{
|
1067 |
//We are finding a second sign character. Not allowed.
|
1068 |
$out_errs = ISARITH_RC_EMSGN;
|
1069 |
return;
|
1070 |
}
|
1071 |
else
|
1072 |
{
|
1073 |
//Found a minus sign. Record it.
|
1074 |
$parse_exp_m_found = TRUE;
|
1075 |
}
|
1076 |
}
|
1077 |
else if (SubStr($in_i2parse, 0, 1) == "+")
|
1078 |
{
|
1079 |
if ($parse_exp_m_found || $parse_exp_p_found)
|
1080 |
{
|
1081 |
//We are finding a second sign character. Not allowed.
|
1082 |
$out_errs = ISARITH_RC_EMSGN;
|
1083 |
return;
|
1084 |
}
|
1085 |
else
|
1086 |
{
|
1087 |
//Found a plus sign. Record it.
|
1088 |
$parse_exp_p_found = TRUE;
|
1089 |
}
|
1090 |
}
|
1091 |
|
1092 |
//Strip the character.
|
1093 |
$in_i2parse = SubStr($in_i2parse, 1);
|
1094 |
}
|
1095 |
|
1096 |
//If we created an empty string, this is a gross
|
1097 |
//parse error.
|
1098 |
if (strlen($in_i2parse) == 0)
|
1099 |
{
|
1100 |
$out_errs = ISARITH_RC_UPERROR;
|
1101 |
return;
|
1102 |
}
|
1103 |
|
1104 |
//There have to be some digits now, after the "e"/"E" and the optional sign.
|
1105 |
if (!STRFUNC_is_char_subset($in_i2parse, "0123456789"))
|
1106 |
{
|
1107 |
$out_errs = ISARITH_RC_UPERROR;
|
1108 |
return;
|
1109 |
}
|
1110 |
else
|
1111 |
{
|
1112 |
//We have all digits left. Just assign them and rip off the leading 0's
|
1113 |
//if any.
|
1114 |
$parse_exp_digits = $in_i2_parse;
|
1115 |
|
1116 |
//TODO: Rip off the 0's. Will need to add a function to STRFUNCS.
|
1117 |
}
|
1118 |
|
1119 |
} //End if characters remaining.
|
1120 |
else
|
1121 |
{
|
1122 |
//No exponent field.
|
1123 |
}
|
1124 |
|
1125 |
|
1126 |
//At this point, the following variables are assigned.
|
1127 |
//
|
1128 |
//
|
1129 |
//
|
1130 |
//
|
1131 |
//
|
1132 |
//
|
1133 |
//
|
1134 |
//
|
1135 |
//
|
1136 |
//
|
1137 |
//
|
1138 |
//
|
1139 |
//
|
1140 |
//
|
1141 |
//
|
1142 |
//
|
1143 |
//
|
1144 |
//
|
1145 |
//
|
1146 |
//
|
1147 |
//
|
1148 |
//
|
1149 |
//
|
1150 |
//
|
1151 |
//
|
1152 |
//
|
1153 |
//
|
1154 |
//
|
1155 |
//
|
1156 |
//
|
1157 |
|
1158 |
}
|
1159 |
|
1160 |
//--------------------------------------------------------------------------------
|
1161 |
//--------------------------------------------------------------------------------
|
1162 |
//---- A S S I G N M E N T -----------------------------------------------------
|
1163 |
//--------------------------------------------------------------------------------
|
1164 |
//--------------------------------------------------------------------------------
|
1165 |
//Assigns an arbitrarily long integer from a string. The formats accepted are:
|
1166 |
// a)Integer format (i.e. "25", "-2,352", etc.).
|
1167 |
// b)Scientific notation, i.e. "3.12451234e+23".
|
1168 |
// c)Optionally, "INAN".
|
1169 |
//
|
1170 |
//It is the caller's responsibility to sanitize the string, including removing
|
1171 |
//leading and trailing blanks or tabs. This function by design requires a
|
1172 |
//string strictly as described above.
|
1173 |
//
|
1174 |
//The limits supplied should be chosen sanely to head off trouble with memory
|
1175 |
//blowups. The min and max limits will place limits on how exponents on the
|
1176 |
//value to parsed are expanded.
|
1177 |
//
|
1178 |
function ISARITH_assign_from_string
|
1179 |
(
|
1180 |
$in_i2parse,
|
1181 |
//The string to parse. As mentioned above, all characters not to be
|
1182 |
//considered, including leading and trailing blanks and tabs. The design
|
1183 |
//decision to push this off on the caller was deliberate, as it gives the
|
1184 |
//caller more latitude to decide what is allowed and not.
|
1185 |
$in_inan_allowed,
|
1186 |
//TRUE if INAN is allowed as an input string, or FALSE otherwise.
|
1187 |
$in_pval_min,
|
1188 |
$in_pval_max,
|
1189 |
//The minimum and maximum values that the parsed input may attain.
|
1190 |
//If the parsed value goes outside this range, an error is returned.
|
1191 |
&$out_val,
|
1192 |
//The output value parsed, as a simple integer string. This value will be
|
1193 |
//FALSE iff there are errors.
|
1194 |
&$out_errs
|
1195 |
//An integer reflecting the errors (or lack thereof) encountered during
|
1196 |
//the parse.
|
1197 |
)
|
1198 |
{
|
1199 |
//Assign default outputs.
|
1200 |
$out_val = FALSE;
|
1201 |
$out_errs = 0;
|
1202 |
|
1203 |
//Try to parse and assign the lower limit. If this can't be parsed,
|
1204 |
//can't continue.
|
1205 |
ISARITH_assign_from_string_nolimit(
|
1206 |
$in_pval_min,
|
1207 |
FALSE, //INAN is invalid as a limit, lower or upper.
|
1208 |
$pval_min_expanded,
|
1209 |
$local_conversion_errs
|
1210 |
);
|
1211 |
|
1212 |
if ($local_conversion_errs != 0)
|
1213 |
{
|
1214 |
//The minimum wouldn't parse successfully. Repackage this error for the
|
1215 |
//caller and return.
|
1216 |
$out_errs = ISARITH_RC_BADLIMIT;
|
1217 |
return;
|
1218 |
}
|
1219 |
|
1220 |
//Try to parse and assign the upper limit. If this can't be parsed,
|
1221 |
//can't continue.
|
1222 |
ISARITH_assign_from_string_nolimit(
|
1223 |
$in_pval_max,
|
1224 |
FALSE, //INAN is invalid as a limit, lower or upper.
|
1225 |
$pval_max_expanded,
|
1226 |
$local_conversion_errs
|
1227 |
);
|
1228 |
|
1229 |
if ($local_conversion_errs != 0)
|
1230 |
{
|
1231 |
//The maximum wouldn't parse successfully. Repackage this error for the
|
1232 |
//caller and return.
|
1233 |
$out_errs = ISARITH_RC_BADLIMIT;
|
1234 |
return;
|
1235 |
}
|
1236 |
|
1237 |
|
1238 |
|
1239 |
//Guts here.
|
1240 |
}
|
1241 |
|
1242 |
//--------------------------------------------------------------------------------
|
1243 |
//--------------------------------------------------------------------------------
|
1244 |
//--------------------------------------------------------------------------------
|
1245 |
//--------------------------------------------------------------------------------
|
1246 |
//--------------------------------------------------------------------------------
|
1247 |
function ISARITH_cmp($in_n1, $in_n2)
|
1248 |
{
|
1249 |
$rv = bccomp($in_n1, $in_n2);
|
1250 |
|
1251 |
return($rv);
|
1252 |
}
|
1253 |
|
1254 |
function ISARITH_add($in_n1, $in_n2)
|
1255 |
{
|
1256 |
$rv = bcadd($in_n1, $in_n2, 0);
|
1257 |
|
1258 |
return($rv);
|
1259 |
}
|
1260 |
|
1261 |
function ISARITH_sub($in_n1, $in_n2)
|
1262 |
{
|
1263 |
$rv = bcsub($in_n1, $in_n2, 0);
|
1264 |
|
1265 |
return($rv);
|
1266 |
}
|
1267 |
|
1268 |
function ISARITH_mul($in_n1, $in_n2)
|
1269 |
{
|
1270 |
$rv = bcmul($in_n1, $in_n2, 0);
|
1271 |
|
1272 |
return($rv);
|
1273 |
}
|
1274 |
|
1275 |
function ISARITH_div($in_n1, $in_n2)
|
1276 |
{
|
1277 |
$rv = bcdiv($in_n1, $in_n2, 0);
|
1278 |
|
1279 |
return($rv);
|
1280 |
}
|
1281 |
|
1282 |
function ISARITH_mod($in_n1, $in_n2)
|
1283 |
{
|
1284 |
$rv = bcmod($in_n1, $in_n2);
|
1285 |
|
1286 |
return($rv);
|
1287 |
}
|
1288 |
|
1289 |
function ISARITH_pow($in_base, $in_exponent)
|
1290 |
{
|
1291 |
$rv = bcpow($in_base, $in_exponent, 0);
|
1292 |
|
1293 |
return($rv);
|
1294 |
}
|
1295 |
|
1296 |
function ISARITH_powmod($in_base, $in_exponent, $in_modulus)
|
1297 |
{
|
1298 |
$rv = bcpowmod($in_base, $in_exponent, $in_modulus, 0);
|
1299 |
|
1300 |
return($rv);
|
1301 |
}
|
1302 |
|
1303 |
function ISARITH_sqrt($in_arg)
|
1304 |
{
|
1305 |
$rv = bcsqrt($in_arg, 0);
|
1306 |
|
1307 |
//Untested ... will need to sure above does not round.
|
1308 |
|
1309 |
return($rv);
|
1310 |
}
|
1311 |
|
1312 |
//Commanates.
|
1313 |
//
|
1314 |
function ISARITH_commanate($in_arg)
|
1315 |
{
|
1316 |
$prefix = "";
|
1317 |
if (SubStr($in_arg, 0, 1) == "-")
|
1318 |
{
|
1319 |
$prefix = "-";
|
1320 |
$in_arg = SubStr($in_arg, 1);
|
1321 |
}
|
1322 |
|
1323 |
$rv = "";
|
1324 |
while (strlen($in_arg) > 3)
|
1325 |
{
|
1326 |
$rv = "," . SubStr($in_arg, strlen($in_arg)-3) . $rv;
|
1327 |
$in_arg = SubStr($in_arg, 0, strlen($in_arg)-3);
|
1328 |
}
|
1329 |
|
1330 |
$rv = $prefix . $in_arg . $rv;
|
1331 |
|
1332 |
return($rv);
|
1333 |
}
|
1334 |
|
1335 |
//Commanates, but adds a string passed at the end of every
|
1336 |
//groupcount of groups of 3 digits, as a separator.
|
1337 |
//
|
1338 |
function ISARITH_commanate_wtext($in_arg, $in_groupcount, $in_groupsuffix)
|
1339 |
{
|
1340 |
$prefix = "";
|
1341 |
if (SubStr($in_arg, 0, 1) == "-")
|
1342 |
{
|
1343 |
$prefix = "-";
|
1344 |
$in_arg = SubStr($in_arg, 1);
|
1345 |
}
|
1346 |
|
1347 |
$rv = "";
|
1348 |
$groupnum = 0;
|
1349 |
|
1350 |
while (strlen($in_arg) > 3)
|
1351 |
{
|
1352 |
$groupnum++;
|
1353 |
if (($groupnum % $in_groupcount) == 0)
|
1354 |
$rv = "," . $in_groupsuffix . SubStr($in_arg, strlen($in_arg)-3) . $rv;
|
1355 |
else
|
1356 |
$rv = "," . SubStr($in_arg, strlen($in_arg)-3) . $rv;
|
1357 |
|
1358 |
$in_arg = SubStr($in_arg, 0, strlen($in_arg)-3);
|
1359 |
}
|
1360 |
|
1361 |
$rv = $prefix . $in_arg . $rv;
|
1362 |
|
1363 |
return($rv);
|
1364 |
}
|
1365 |
|
1366 |
function ISARITH_decommanate($in_arg)
|
1367 |
{
|
1368 |
$rv = STRFUNC_force_into_subset($in_arg, "-0123456789");
|
1369 |
|
1370 |
return($rv);
|
1371 |
}
|
1372 |
?>
|