NumberStringClass.cpp
Go to the documentation of this file.
1 /*----------------------------------------------------------------------------*/
2 /* */
3 /* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved. */
4 /* Copyright (c) 2005-2009 Rexx Language Association. All rights reserved. */
5 /* */
6 /* This program and the accompanying materials are made available under */
7 /* the terms of the Common Public License v1.0 which accompanies this */
8 /* distribution. A copy is also available at the following address: */
9 /* http://www.oorexx.org/license.html */
10 /* */
11 /* Redistribution and use in source and binary forms, with or */
12 /* without modification, are permitted provided that the following */
13 /* conditions are met: */
14 /* */
15 /* Redistributions of source code must retain the above copyright */
16 /* notice, this list of conditions and the following disclaimer. */
17 /* Redistributions in binary form must reproduce the above copyright */
18 /* notice, this list of conditions and the following disclaimer in */
19 /* the documentation and/or other materials provided with the distribution. */
20 /* */
21 /* Neither the name of Rexx Language Association nor the names */
22 /* of its contributors may be used to endorse or promote products */
23 /* derived from this software without specific prior written permission. */
24 /* */
25 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
26 /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
27 /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
28 /* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
29 /* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
30 /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */
31 /* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */
32 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY */
33 /* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
34 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
35 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
36 /* */
37 /*----------------------------------------------------------------------------*/
38 /******************************************************************************/
39 /* REXX Kernel */
40 /* */
41 /* Primitive NumberString Class */
42 /* */
43 /******************************************************************************/
44 #include <ctype.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <math.h>
48 #include <float.h>
49 #include "RexxCore.h"
50 #include "StringClass.hpp"
51 #include "BufferClass.hpp"
52 #include "RexxActivation.hpp"
53 #include "NumberStringMath.hpp"
54 #include "Numerics.hpp"
55 #include "StringUtil.hpp"
56 #include "DirectoryClass.hpp"
57 
58 
59 
60 // singleton class instance
62 
63 
64 /**
65  * Create initial class object at bootstrap time.
66  */
68 {
69  CLASS_CREATE(NumberString, "String", RexxClass);
70 }
71 
72 
73 /* MHES 20050108 deprecated */
74 #define string_forwarder(method)\
75 RexxObject *RexxNumberString::##method(RexxObject *operand)\
76  {\
77  return (RexxObject *)this->stringValue()->##method(operand);\
78  }
79 
80 
81 /**
82  * Constructor for a new number string value.
83  *
84  * @param len The length we require for the value.
85  */
87 {
88  this->NumDigits = number_digits();
89  this->sign = 1;
90  this->length = len;
92  {
93  this->NumFlags |= NumFormScientific;
94  }
95 }
96 
97 
98 /**
99  * Create a number string for a given digits precision
100  *
101  * @param len The length of value we need to accomodate
102  * @param precision The precision to be used for formatting.
103  */
104 RexxNumberString::RexxNumberString(size_t len, size_t precision)
105 {
106  this->NumDigits = precision;
107  this->sign = 1;
108  this->length = len;
110  {
111  this->NumFlags |= NumFormScientific;
112  }
113 }
114 
116 /******************************************************************************/
117 /* Function: low level copy of a number string object */
118 /******************************************************************************/
119 {
120  /* first clone ourselves */
122  /* don't keep the original string */
123  OrefSet(newObj, newObj->stringObject, OREF_NULL);
124  /* or the OVD fields */
125  OrefSet(newObj, newObj->objectVariables, OREF_NULL);
126  return newObj; /* return this */
127 }
128 
129 
130 /**
131  * Get the primitive hash value of this String object.
132  *
133  * @return The calculated string hash for the string.
134  */
136 {
137  return stringValue()->getHashValue();
138 }
139 
140 void RexxNumberString::live(size_t liveMark)
141 /******************************************************************************/
142 /* Function: Normal garbage collection live marking */
143 /******************************************************************************/
144 {
145  memory_mark(this->objectVariables);
146  memory_mark(this->stringObject);
147 }
148 
150 /******************************************************************************/
151 /* Function: Generalized object marking */
152 /******************************************************************************/
153 {
154  memory_mark_general(this->objectVariables);
156 }
157 
159 /******************************************************************************/
160 /* Function: Flatten an object */
161 /******************************************************************************/
162 {
164 
165  flatten_reference(newThis->objectVariables, envelope);
166  flatten_reference(newThis->stringObject, envelope);
167 
169 }
170 
172  RexxString *stringObj ) /* new string value */
173 /******************************************************************************/
174 /* Function: Set the number string's string value */
175 /******************************************************************************/
176 {
177  /* set the new string value */
178  OrefSet(this, this->stringObject, stringObj);
179  this->setHasReferences(); /* we now have to garbage collect */
180 }
181 
183 /******************************************************************************/
184 /* Function: Handle a REQUEST('STRING') request for a REXX numberstring */
185 /******************************************************************************/
186 {
187  return this->stringValue(); /* return the string value */
188 }
189 
190 
191 /**
192  * Override for the default object makearray method.
193  *
194  * @return The results of our string representation's makearray.
195  */
197 {
198  return this->stringValue()->makeArray(); // have the string value handle this
199 }
200 
202 /******************************************************************************/
203 /* Function: Handle a HASMETHOD request for an integer */
204 /******************************************************************************/
205 {
206  /* return the string value's answer */
207  return this->stringValue()->hasMethod(methodName);
208 }
209 
211 /******************************************************************************/
212 /* Function: Handle a REQUEST('STRING') request for a REXX numberstring */
213 /******************************************************************************/
214 {
215  if (this->stringObject != OREF_NULL) /* already converted? */
216  {
217  return this->stringObject; /* all finished */
218  }
219  return this->stringValue(); /* return the string value */
220 }
221 
223 /******************************************************************************/
224 /* Function: Convert a number string to a string object */
225 /******************************************************************************/
226 {
227  char expstring[17], num;
228  int carry;
229  size_t createdDigits;
230  size_t MaxNumSize, LenValue;
231  wholenumber_t numindex;
232  wholenumber_t temp, ExpValue, ExpFactor;
233  size_t charpos;
234  RexxString *StringObj;
235 
236  if (this->stringObject != OREF_NULL) /* already converted? */
237  {
238  return this->stringObject; /* all finished */
239  }
240  /* Start converting the number. */
241 
242  if (this->sign == 0 )
243  { /* is the number zero? */
244  /* Yes, return a 0 string. */
245  OrefSet(this, this->stringObject, OREF_ZERO_STRING);
246  this->setHasReferences(); /* we now have to garbage collect */
247  return this->stringObject; /* and return now */
248  }
249  else
250  { /* No, convert the number. */
251  /* convert the exponent numeber into */
252  /* string. */
253 
254  createdDigits = this->NumDigits; /* Get Digits settings at creation */
255 
256  ExpValue = this->exp; /* Working copy of exponent */
257  LenValue = this->length; /* Working copy of the length. */
258 
259  /* If no exponent */
260  if (ExpValue == 0)
261  {
262  /* Yes, we can fast path conversion */
263  MaxNumSize = LenValue; /* Size of result is length of number*/
264  if (this->sign <0) /* if number is negative. */
265  {
266  MaxNumSize++; /* result one bigger for - sign. */
267  }
268  /* Get new string, of exact length, */
269  StringObj = (RexxString *)raw_string(MaxNumSize);
270  charpos = 0; /* data in string to start. */
271  if (this->sign < 0)
272  { /* If number is neagative */
273  /* add negative sign and bump index */
274  StringObj->putChar(charpos++, ch_MINUS);
275  }
276  /* For each number digits in number */
277  for (numindex=0; (size_t)numindex < LenValue; numindex++)
278  {
279  /* place char rep in NumString */
280  num = this->number[numindex] + ch_ZERO;
281  StringObj->putChar(charpos++, num);
282  } /* Done with Fast Path.... */
283  }
284  else
285  { /* We need to do this the long way */
286  carry = 0; /* assume rounding-up NOT necessary */
287 
288  /*is number just flat out too big? */
289  if ((( ExpValue + (wholenumber_t)LenValue - 1) > Numerics::MAX_EXPONENT) ||
290  (ExpValue < (Numerics::MIN_EXPONENT)) ) /* Yes, report Overflow error. */
291  {
293  }
294 
295 
296  ExpFactor = 0; /* number not eponential yet.. */
297  temp = ExpValue + (wholenumber_t)LenValue - 1; /* get size of this number */
298  expstring[0] = '\0'; /* string vlaue of exp factor, Null */
299  /* is left of decimal > NumDigits or */
300  if ((temp >= (wholenumber_t)createdDigits) || /* exponent twice numDigits */
301  ((size_t)Numerics::abs(ExpValue) > (createdDigits*2)) )
302  {
303  /* Yes, we need to go exponential. */
304  /* we need Engineering format? */
305  if (!(this->NumFlags & NumFormScientific))
306  {
307  if (temp < 0) /* Yes, is number a whole number? */
308  {
309  temp -= 2; /* force 2 char adjustment to left */
310  }
311  temp = (temp/3) * 3; /* get count to the right of Decimal */
312  }
314  { /* is adjusted number too big? */
315  if (temp > Numerics::MAX_EXPONENT) /* did it overflow? */
316  {
317  /* Yes, report overflow error. */
319  }
320  else
321  {
322  /* Actually an underflow error. */
324  }
325  }
326  ExpValue -= temp; /* adjust the exponent */
327  if ( temp != 0 )
328  { /* do we still have exponent ? */
329  ExpFactor = true; /* Save the factor */
330  }
331  else
332  {
333  ExpFactor = false; /* no need to save the factor */
334  }
335 
336  if (temp < 0)
337  {
338  *expstring = 'E';
339  /* convert exponent value into string*/
340  Numerics::formatWholeNumber(temp, expstring + 1);
341  }
342  else if (temp > 0)
343  {
344  strcpy(expstring, "E+");
345  /* convert exponent value into string*/
346  Numerics::formatWholeNumber(temp, expstring + 2);
347  }
348  temp = Numerics::abs(temp); /* get positive exponent factor */
349 
350  }
351  /* Now compute size of result string */
352  if (ExpValue >= 0 ) /* if the Exponent is positive */
353  {
354  /* Size is length of number plus exp.*/
355  MaxNumSize = (size_t)ExpValue + LenValue;
356  }
357  /*is exponent larger than length, */
358  else if ((size_t)Numerics::abs(ExpValue) >= LenValue)
359  {
360  /* Yes, we will need to add zeros to */
361  /* the front plus a 0. */
362  MaxNumSize = Numerics::abs(ExpValue) + 2;
363  }
364 
365  else /*Won't be adding any digits, just */
366  {
367  MaxNumSize = LenValue + 1; /* length of number + 1 for decimal */
368  }
369 
370  if (ExpFactor) /* Are we using Exponential notation?*/
371  {
372  /* Yes, need to add in size of the */
373  MaxNumSize += strlen(expstring); /* exponent stuff. */
374  }
375 
376  if (this->sign <0) /* is number negative? */
377  {
378  MaxNumSize++; /* yes, add one to size for - sign */
379  }
380  /* get new string of appropriate size*/
381  StringObj = (RexxString *)raw_string(MaxNumSize);
382 
383  charpos = 0; /* set starting position */
384  if (this->sign < 0)
385  { /* Is the number negative? */
386  /* Yes, add in the negative sign. */
387  StringObj->putChar(charpos, ch_MINUS);
388  }
389  temp = ExpValue + (wholenumber_t)LenValue; /* get the adjusted length. */
390 
391  /* Since we may have carry from round*/
392  /* we'll fill in the number from the */
393  /* back and make our way forward. */
394 
395  /* Strindex points to exponent start */
396  /* part of string. */
397  charpos = MaxNumSize - strlen(expstring);
398 
399  if (ExpFactor) /* will result have Exponent? */
400  {
401  /* Yes, put the data into the string.*/
402  StringObj->put(charpos, expstring, strlen(expstring));
403  }
404 
405  /* Next series of If's will determine*/
406  /* if we need to add zeros to end */
407  /* of the number and where to place */
408  /* decimal, fill in string as we */
409  /* go, also need to check for a carry*/
410  /* if we rounded the number early on.*/
411 
412  if (temp <= 0)
413  { /* Is ther an Integer portion? */
414  /* 0.000000xxxx result. */
415  /* ^^^^^^^^ filler */
416 
417  /* Start filling in digits */
418  /* from the back.... */
419  for (numindex = (wholenumber_t)(LenValue-1);numindex >= 0 ;numindex-- )
420  {
421  /* are we carry from round? */
422  num = this->number[numindex]; /* working copy of this Digit. */
423  num = num + ch_ZERO; /* now put the number as a character */
424  StringObj->putChar(--charpos, num);
425  }
426  temp = -temp; /* make the number positive... */
427 
428  if (temp)
429  {
430  charpos -= temp; /* yes, point to starting pos to fill*/
431  /* now fill in the leading Zeros. */
432  StringObj->set(charpos, ch_ZERO, temp);
433  }
434  StringObj->putChar(--charpos, ch_PERIOD);
435  if (carry) /* now put in the leading 1. is carry*/
436  {
437  StringObj->putChar(--charpos, ch_ONE);
438  }
439  else /* or 0. if no carry. */
440  {
441  StringObj->putChar(--charpos, ch_ZERO);
442  }
443  }
444  /* do we need to add zeros at end? */
445  else if ((size_t)temp >= LenValue)
446  {
447  /* xxxxxx000000 result */
448  /* ^^^^^^ filler */
449 
450  /* Yes, add zeros first. */
451  temp -= LenValue; /* see how many zeros we need to add.*/
452  charpos -= temp; /* point to starting pos to fill */
453  /* now fill in the leading Zeros. */
454  StringObj->set(charpos, ch_ZERO, temp);
455  /* done w/ trailing zeros start */
456  /* adding digits (from back) */
457 
458 
459  /* start filling in digits */
460  for (numindex = (wholenumber_t)LenValue-1;numindex >= 0 ;numindex-- )
461  {
462  num = this->number[numindex]; /* working copy of this Digit. */
463  num = num + ch_ZERO; /* now put the number as a character */
464  StringObj->putChar(--charpos, num);
465  }
466  } /* done with this case.... */
467 
468  else
469  { /* we have a partial Decimal number */
470  /* add in the first digit a 1. */
471  /* Start filling in digits */
472  for (numindex = (wholenumber_t)LenValue - 1; numindex > temp - 1 ;numindex-- )
473  {
474  num = this->number[numindex]; /* working copy of this Digit. */
475  /* now put the number as a character */
476  num += ch_ZERO;
477  StringObj->putChar(--charpos, num);
478  }
479  /* add in the decimal point. */
480  StringObj->putChar(--charpos, ch_PERIOD);
481 
482  /* Start filling in digits */
483  /* add numbers before decimal point */
484  for (numindex = temp - 1; numindex >= 0; numindex-- )
485  {
486  num = this->number[numindex]; /* working copy of this Digit. */
487  num += ch_ZERO;
488  StringObj->putChar(--charpos, num);
489  }
490  /* end of final case, conversion done*/
491  }
492  } /* end of non-fast path conversion. */
493  } /* End of conversion of number */
494  /* since string is created from */
495  /* number string, we can set the */
496  StringObj->setNumberString(this); /* lookaside right away */
497  /* and also save this string */
498  OrefSet(this, this->stringObject, StringObj);
499  this->setHasReferences(); /* we now have to garbage collect */
500  return StringObj; /* all done, return new string */
501 }
502 
503 
505 /******************************************************************************/
506 /* Function: Convert a number string to a wholenumber value */
507 /******************************************************************************/
508 {
509  // convert using the default digits version
510  return this->numberValue(result, Numerics::DEFAULT_DIGITS);
511 }
512 
514 /******************************************************************************/
515 /* Function: Convert a number string to a unsigned whole number value */
516 /******************************************************************************/
517 {
518  // convert using the default digits version
519  return this->unsignedNumberValue(result, Numerics::DEFAULT_DIGITS);
520 }
521 
522 bool RexxNumberString::numberValue(wholenumber_t &result, size_t numDigits)
523 /******************************************************************************/
524 /* Function: Convert a number string to a number value */
525 /******************************************************************************/
526 {
527  // set up the default values
528 
529  bool carry = false;
530  wholenumber_t numberExp = this->exp;
531  stringsize_t numberLength = this->length;
532  size_t intnum;
533 
534  // if the number is exactly zero, then this is easy
535  if (this->sign == 0)
536  {
537  result = 0;
538  return true;
539  }
540  // is this easily within limits (very common)?
541  if (length <= numDigits && numberExp >= 0)
542  {
543  if (!createUnsignedValue(number, length, false, numberExp, Numerics::maxValueForDigits(numDigits), intnum))
544  {
545  return false; // too big to handle
546  }
547  // adjust for the sign
548  result = ((wholenumber_t)intnum) * sign;
549  return true;
550  }
551 
552  // this number either has decimals, or needs to be truncated/rounded because of
553  // the conversion digits value. We need to make adjustments.
554 
555  if (!checkIntegerDigits(numDigits, numberLength, numberExp, carry))
556  {
557  return false;
558  }
559 
560  // if because of this adjustment, the decimal point lies to the left
561  // of our first digit, then this value truncates to 0 (or 1, if a carry condition
562  // resulted).
563  if (-numberExp>= (wholenumber_t)numberLength)
564  {
565  // since we know a) this number is all decimals, and b) the
566  // remaining decimals are either all 0 or all 9s with a carry,
567  // this result is either 0 or 1.
568  result = carry ? 1 : 0;
569  return true;
570  }
571 
572  // we process different bits depending on whether this is a negative or positive
573  // exponent
574  if (numberExp < 0)
575  {
576  // now convert this into an unsigned value
577  if (!createUnsignedValue(number, numberLength + numberExp, carry, 0, Numerics::maxValueForDigits(numDigits), intnum))
578  {
579  return false; // to big to handle
580  }
581  }
582  else
583  { /* straight out number. just compute.*/
584  if (!createUnsignedValue(number, numberLength, carry, numberExp, Numerics::maxValueForDigits(numDigits), intnum))
585  {
586  return false; // to big to handle
587  }
588  }
589 
590  // adjust for the sign
591  result = ((wholenumber_t)intnum) * sign;
592  return true;
593 }
594 
596 /******************************************************************************/
597 /* Function: Convert a number string to an unsigned number value */
598 /******************************************************************************/
599 {
600  // set up the default values
601 
602  bool carry = false;
603  wholenumber_t numberExp = this->exp;
604  stringsize_t numberLength = this->length;
605  size_t intnum;
606 
607  // if the number is exactly zero, then this is easy
608  if (this->sign == 0)
609  {
610  result = 0;
611  return true;
612  }
613  // we can't convert negative values into an unsigned one
614  if (sign < 0)
615  {
616  return false;
617  }
618 
619  // is this easily within limits (very common)?
620  if (length <= numDigits && numberExp >= 0)
621  {
622  if (!createUnsignedValue(number, length, false, numberExp, Numerics::maxValueForDigits(numDigits), intnum))
623  {
624  return false; // too big to handle
625  }
626  // we can just return this directly.
627  result = intnum;
628  return true;
629  }
630 
631  // this number either has decimals, or needs to be truncated/rounded because of
632  // the conversion digits value. We need to make adjustments.
633  if (!checkIntegerDigits(numDigits, numberLength, numberExp, carry))
634  {
635  return false;
636  }
637 
638  // if because of this adjustment, the decimal point lies to the left
639  // of our first digit, then this value truncates to 0 (or 1, if a carry condition
640  // resulted).
641  if (-numberExp>= (wholenumber_t)numberLength)
642  {
643  // since we know a) this number is all decimals, and b) the
644  // remaining decimals are either all 0 or all 9s with a carry,
645  // this result is either 0 or 1.
646  result = carry ? 1 : 0;
647  return true;
648  }
649 
650  // we process different bits depending on whether this is a negative or positive
651  // exponent
652  if (numberExp < 0)
653  {
654  // now convert this into an unsigned value
655  if (!createUnsignedValue(number, numberLength + numberExp, carry, 0, Numerics::maxValueForDigits(numDigits), intnum))
656  {
657  return false; // to big to handle
658  }
659  }
660  else
661  { /* straight out number. just compute.*/
662  if (!createUnsignedValue(number, numberLength, carry, numberExp, Numerics::maxValueForDigits(numDigits), intnum))
663  {
664  return false; // to big to handle
665  }
666  }
667 
668  // adjust for the sign
669  result = intnum;
670  return true;
671 }
672 
673 bool RexxNumberString::doubleValue(double &result)
674 /******************************************************************************/
675 /* Function: Convert a number string to a double */
676 /******************************************************************************/
677 {
678  RexxString *string; /* string version of the number */
679 
680  string = this->stringValue(); /* get the string value */
681  /* convert the number */
682  result = strtod(string->getStringData(), NULL);
683  // and let pass all of the special cases
684  return true;
685 }
686 
688  size_t digits ) /* required precision */
689 /******************************************************************************/
690 /* Function: convert a number string to an integer object */
691 /******************************************************************************/
692 {
693 
694  wholenumber_t integerNumber; /* converted value */
695 
696  if (!numberValue(integerNumber, number_digits()))
697  {
698  return (RexxInteger *)TheNilObject;/* just return .nil */
699  }
700 
701  return new_integer(integerNumber);
702 }
703 
704 
705 /*********************************************************************/
706 /* Function: Convert the numberstring to unsigned value */
707 /*********************************************************************/
708 bool RexxNumberString::createUnsignedValue(const char *thisnum, stringsize_t intlength, int carry, wholenumber_t exponent, uwholenumber_t maxValue, uwholenumber_t &result)
709 {
710  // if the exponent multiplier would cause an overflow, there's no point in doing
711  // anything here
713  {
714  return false;
715  }
716 
717  // our converted value
718  uwholenumber_t intNumber = 0;
719 
720  for (stringsize_t numpos = 1; numpos <= intlength; numpos++ )
721  {
722  // add in the next digit value
723  uwholenumber_t newNumber = (intNumber * 10) + (size_t)*thisnum++;
724  // if an overflow occurs, then the new number will wrap around and be
725  // smaller that the starting value.
726  if (newNumber < intNumber)
727  {
728  return false;
729  }
730  // make this the current value and continue
731  intNumber = newNumber;
732  }
733 
734  // do we need to add in a carry value because of a rounding situation?
735  if (carry)
736  {
737  // add in the carry bit and check for an overflow, again
738  uwholenumber_t newNumber = intNumber + 1;
739  if (newNumber < intNumber)
740  {
741  return false;
742  }
743  intNumber = newNumber;
744  }
745 
746  // have an exponent to process?
747  if (exponent > 0)
748  {
749  // get this as a multipler value
750  uwholenumber_t exponentMultiplier = 1;
751  while (exponent > 0)
752  {
753  exponentMultiplier *= 10;
754  exponent--;
755  }
756  // get this as a multipler value
757  uwholenumber_t newNumber = intNumber * exponentMultiplier;
758 
759  // did this wrap? This is a safe test, since we capped
760  // the maximum exponent size we can multiply by.
761  if (newNumber < intNumber)
762  {
763  return false;
764  }
765  intNumber = newNumber;
766  }
767 
768  // was ths out of range for this conversion?
769  if (intNumber >= maxValue)
770  {
771  return false;
772  }
773 
774  result = intNumber; /* Assign return value. */
775  return true; /* Indicate sucessfule converison. */
776 }
777 
778 
779 /*********************************************************************/
780 /* Function: Convert the numberstring to unsigned value */
781 /*********************************************************************/
782 bool RexxNumberString::createUnsignedInt64Value(const char *thisnum, stringsize_t intlength, int carry, wholenumber_t exponent, uint64_t maxValue, uint64_t &result)
783 {
784  // if the exponent multiplier would cause an overflow, there's no point in doing
785  // anything here
786  if (exponent > (wholenumber_t)Numerics::DIGITS64)
787  {
788  return false;
789  }
790 
791  // our converted value
792  uint64_t intNumber = 0;
793 
794  for (stringsize_t numpos = 1; numpos <= intlength; numpos++ )
795  {
796  // add in the next digit value
797  uint64_t newNumber = (intNumber * 10) + (uint64_t)*thisnum++;
798  // if an overflow occurs, then the new number will wrap around and be
799  // smaller that the starting value.
800  if (newNumber < intNumber)
801  {
802  return false;
803  }
804  // make this the current value and continue
805  intNumber = newNumber;
806  }
807 
808  // do we need to add in a carry value because of a rounding situation?
809  if (carry)
810  {
811  // add in the carry bit and check for an overflow, again
812  uint64_t newNumber = intNumber + 1;
813  if (newNumber < intNumber)
814  {
815  return false;
816  }
817  intNumber = newNumber;
818  }
819 
820  // have an exponent to process?
821  if (exponent > 0)
822  {
823  // get this as a multipler value
824  uint64_t exponentMultiplier = 1;
825  while (exponent > 0)
826  {
827  exponentMultiplier *= 10;
828  exponent--;
829  }
830 
831 
832  uint64_t newNumber = intNumber * exponentMultiplier;
833 
834  // did this wrap? This is a safe test, since we capped
835  // the maximum exponent size we can multiply by.
836  if (newNumber < intNumber)
837  {
838  return false;
839  }
840  intNumber = newNumber;
841  }
842 
843  // was ths out of range for this conversion?
844  if (intNumber > maxValue)
845  {
846  return false;
847  }
848 
849  result = intNumber; /* Assign return value. */
850  return true; /* Indicate sucessfule converison. */
851 }
852 
853 
855  wholenumber_t &numberExponent, bool &carry)
856 /******************************************************************************/
857 /* Function: Check that a numberstring is convertable into an integer value */
858 /******************************************************************************/
859 {
860  carry = false;
861  numberExponent = this->exp;
862  numberLength = this->length;
863 
864  // is this number longer than the digits value?
865  // this is going to be truncated or rounded, so we
866  // need to see if a carry is required, and also
867  // adjust the exponent value.
868  if (this->length > numDigits)
869  {
870  // adjust the effective exponent up by the difference
871  numberExponent += (this->length - numDigits);
872  // and override the converted length to be just the digits length
873  numberLength = numDigits;
874 
875  // now check to see if the first excluded digit will cause rounding
876  // if it does, we need to worry about a carry value when converting
877  if (*(this->number + numberLength) >= 5)
878  {
879  carry = true;
880  }
881  }
882  // if we have a negative exponent, then we need to look at
883  // the values below the decimal point
884  if (numberExponent < 0)
885  {
886  // the position of the decimal is the negation of the exponent
887  stringsize_t decimalPos = (stringsize_t)(-numberExponent);
888  // everything to the right of the decimal must be a zero.
889  char compareChar = 0;
890  // if we had a previous carry condition, this changes things a
891  // bit. Since the carry will add 1 to the right-most digit,
892  // in order for all of the decimals to end up zero, then all of
893  // the digits there must actually be '9's.
894  if (carry)
895  {
896  // if the decimal position will result in at least one padding
897  // zero, then the carry makes it impossible for all of the decimals
898  // to reduce to zero. This cannot be a whole number.
899  if (decimalPos > numberLength)
900  {
901  return false;
902  }
903  // switch the checking value
904  compareChar = 9;
905  }
906 
907  const char *numberData;
908  if (decimalPos >= numberLength )
909  {
910  // decimal is somewhere to the left of everything...
911  // all of these digits must be checked
912  decimalPos = numberLength;
913  numberData = this->number;
914  }
915  else
916  {
917  // get the exponent adjusted position
918  numberData = this->number + numberLength + numberExponent;
919  }
920 
921  for ( ; decimalPos > 0 ; decimalPos--)
922  {
923  // a bad digits data means a conversion failure
924  if ( *numberData++ != compareChar)
925  {
926  return false;
927  }
928  }
929  }
930  return true;
931 }
932 
933 
935 /******************************************************************************/
936 /* Function: Convert a number string to a int64 value */
937 /******************************************************************************/
938 {
939  // set up the default values
940 
941  bool carry = false;
942  wholenumber_t numberExp = this->exp;
943  stringsize_t numberLength = this->length;
944  uint64_t intnum;
945 
946  // if the number is exactly zero, then this is easy
947  if (this->sign == 0)
948  {
949  *result = 0;
950  return true;
951  }
952  // is this easily within limits (very common)?
953  if (length <= numDigits && numberExp >= 0)
954  {
955  // the minimum negative value requires one more than the max positive
956  if (!createUnsignedInt64Value(number, length, false, numberExp, ((uint64_t)INT64_MAX) + 1, intnum))
957  {
958  return false; // too big to handle
959  }
960  // this edge case can be a problem, so check for it specifically
961  if (intnum == ((uint64_t)INT64_MAX) + 1)
962  {
963  // if at the limit, this must be a negative number
964  if (sign != -1)
965  {
966  return false;
967  }
968  *result = INT64_MIN;
969  }
970  else
971  {
972  // adjust for the sign
973  *result = ((int64_t)intnum) * sign;
974  }
975  return true;
976  }
977 
978  // this number either has decimals, or needs to be truncated/rounded because of
979  // the conversion digits value. We need to make adjustments.
980 
981  if (!checkIntegerDigits(numDigits, numberLength, numberExp, carry))
982  {
983  return false;
984  }
985 
986  // if because of this adjustment, the decimal point lies to the left
987  // of our first digit, then this value truncates to 0 (or 1, if a carry condition
988  // resulted).
989  if (-numberExp>= (wholenumber_t)numberLength)
990  {
991  // since we know a) this number is all decimals, and b) the
992  // remaining decimals are either all 0 or all 9s with a carry,
993  // this result is either 0 or 1.
994  *result = carry ? 1 : 0;
995  return true;
996  }
997 
998  // we process different bits depending on whether this is a negative or positive
999  // exponent
1000  if (numberExp < 0)
1001  {
1002  // now convert this into an unsigned value
1003  if (!createUnsignedInt64Value(number, numberLength + numberExp, carry, 0, ((uint64_t)INT64_MAX) + 1, intnum))
1004  {
1005  return false; // to big to handle
1006  }
1007  }
1008  else
1009  { /* straight out number. just compute.*/
1010  if (!createUnsignedInt64Value(number, numberLength, carry, numberExp, ((uint64_t)INT64_MAX) + 1, intnum))
1011  {
1012  return false; // to big to handle
1013  }
1014  }
1015  // the edge case is a problem, so handle it directly
1016  if (intnum == ((uint64_t)INT64_MAX) + 1)
1017  {
1018  // if at the limit, this must be a negative number
1019  if (sign != -1)
1020  {
1021  return false;
1022  }
1023  *result = INT64_MAX;
1024  }
1025  else
1026  {
1027  // adjust for the sign
1028  *result = ((int64_t)intnum) * sign;
1029  }
1030  return true;
1031 }
1032 
1033 
1035 /******************************************************************************/
1036 /* Function: Convert a number string to a int64 value */
1037 /******************************************************************************/
1038 {
1039  // set up the default values
1040 
1041  bool carry = false;
1042  wholenumber_t numberExp = this->exp;
1043  stringsize_t numberLength = this->length;
1044 
1045  // if the number is exactly zero, then this is easy
1046  if (this->sign == 0)
1047  {
1048  *result = 0;
1049  return true;
1050  }
1051 
1052  // no signed values allowed
1053  if (sign == -1)
1054  {
1055  return false;
1056  }
1057 
1058  // is this easily within limits (very common)?
1059  if (length <= numDigits && numberExp >= 0)
1060  {
1061  if (!createUnsignedInt64Value(number, length, false, numberExp, UINT64_MAX, *result))
1062  {
1063  return false; // too big to handle
1064  }
1065  return true;
1066  }
1067 
1068  // this number either has decimals, or needs to be truncated/rounded because of
1069  // the conversion digits value. We need to make adjustments.
1070 
1071  if (!checkIntegerDigits(numDigits, numberLength, numberExp, carry))
1072  {
1073  return false;
1074  }
1075 
1076  // if because of this adjustment, the decimal point lies to the left
1077  // of our first digit, then this value truncates to 0 (or 1, if a carry condition
1078  // resulted).
1079  if (-numberExp>= (wholenumber_t)numberLength)
1080  {
1081  // since we know a) this number is all decimals, and b) the
1082  // remaining decimals are either all 0 or all 9s with a carry,
1083  // this result is either 0 or 1.
1084  *result = carry ? 1 : 0;
1085  return true;
1086  }
1087 
1088  // we process different bits depending on whether this is a negative or positive
1089  // exponent
1090  if (numberExp < 0)
1091  {
1092  // now convert this into an unsigned value
1093  return createUnsignedInt64Value(number, numberLength + numberExp, carry, 0, UINT64_MAX, *result);
1094  }
1095  else
1096  { /* straight out number. just compute.*/
1097  return createUnsignedInt64Value(number, numberLength, carry, numberExp, UINT64_MAX, *result);
1098  }
1099 }
1100 
1101 
1103  int errorcode ) /* error to raise if not good */
1104 /******************************************************************************/
1105 /* Function: Return a truth value boolean for a number string */
1106 /******************************************************************************/
1107 {
1108  if (this->sign == 0 ) /* exactly zero? */
1109  {
1110  return false; /* done quickly */
1111  }
1112  /* not exactly 1? */
1113  else if (!(this->sign == 1 && this->exp == 0 && this->length == 1L && *(this->number) == 1))
1114  {
1115  reportException(errorcode, this);/* report the error */
1116  }
1117  return true; /* this is true */
1118 }
1119 
1120 
1121 /**
1122  * Convert an object to a logical value without raising an
1123  * error.
1124  *
1125  * @param result The converted value.
1126  *
1127  * @return true if this converted ok, false for an invalid logical.
1128  */
1130 {
1131  if (this->sign == 0 ) /* exactly zero? */
1132  {
1133  result = false; // this is false and the conversion worked
1134  return true;
1135  }
1136  /* exactly 1? */
1137  else if (this->sign == 1 && this->exp == 0 && this->length == 1 && *(this->number) == 1)
1138  {
1139  result = true; // this is true and the conversion worked
1140  return true;
1141  }
1142  else
1143  {
1144  return false; // bad conversion
1145  }
1146 }
1147 
1148 bool numberStringScan(const char *number, size_t length)
1149 /******************************************************************************/
1150 /* Arguments: Number data, number length */
1151 /* Function :Scan the string to determine if its a valid number */
1152 /* Returned : 0 if input was valid number */
1153 /* 1 if input was invalid number */
1154 /******************************************************************************/
1155 {
1156  char ch; /* current character */
1157  const char *InPtr; /* Input Data Pointer */
1158  const char *EndData; /* Scan end position */
1159  bool hadPeriod; /* had a decimal point already */
1160 
1161  /* for efficiency, this code takes */
1162  /* advantage of the fact that REXX */
1163  /* string object's all have a guard */
1164  /* null character on the end */
1165 
1166  if (!length)
1167  { /* Length zero not a number? */
1168  return true; /* a null string is not a number */
1169  }
1170 
1171  hadPeriod = false; /* period yet */
1172  InPtr = number; /*Point to start of input string. */
1173  EndData = InPtr + length; /*Point to end of Data + 1. */
1174 
1175  while (*InPtr == ch_BLANK || *InPtr == ch_TAB) /* Skip all leading blanks. */
1176  {
1177  InPtr++; /* Skip it, and go on to next char */
1178  }
1179  /* Is this a sign Character? */
1180  if ((ch = *InPtr) == ch_MINUS || ch == ch_PLUS)
1181  {
1182  InPtr++; /* Yes, skip it. */
1183  while (*InPtr == ch_BLANK || *InPtr == ch_TAB) /* Ship all leading blanks. */
1184  {
1185  InPtr++; /* Skip it, and go on to next char */
1186  }
1187  }
1188 
1189  if (*InPtr == ch_PERIOD)
1190  { /* got a leading period? */
1191  InPtr++; /* step over it */
1192  hadPeriod = true; /* got the decimal point already */
1193  }
1194 
1195  ch = *InPtr; /* Get 1st Digit. */
1196  if (ch < ch_ZERO || ch > ch_NINE) /* Is this a valid digit? */
1197  {
1198  return true; /* Nope, bad number */
1199  }
1200  else
1201  {
1202  /*Skip all leading Zero's */
1203  while (*InPtr == ch_ZERO) /* While 1st Digit is a 0 */
1204  {
1205  InPtr++; /* Go to next character. */
1206  }
1207  /* Have we reach end of number,num */
1208  /*zero? */
1209  if (InPtr >= EndData)
1210  {
1211  return false; /* valid number... all Zeros */
1212  }
1213  }
1214  /* While the character is a Digit. */
1215  while (*InPtr >= ch_ZERO && *InPtr <= ch_NINE)
1216  {
1217  InPtr++; /* Go to next digit */
1218  }
1219  if (InPtr >= EndData) /* Did we reach end of data? */
1220  {
1221  return false; /* all done, just return valid number*/
1222  }
1223 
1224  if (*InPtr == ch_PERIOD)
1225  { /*Decimal point??? */
1226  if (hadPeriod) /* already had one? */
1227  {
1228  return true; /* yep, this is a bad number */
1229  }
1230  InPtr++; /* yes, skip it. */
1231  /* While the character is a Digit. */
1232  while (*InPtr >= ch_ZERO && *InPtr <= ch_NINE)
1233  {
1234  InPtr++; /* Go to next digit */
1235  }
1236  if (InPtr >= EndData) /* Did we reach end of data */
1237  {
1238  return false; /* this was fine */
1239  }
1240  }
1241 
1242  if (toupper(*InPtr) == 'E')
1243  { /* See if this char is an exponent? */
1244  if (++InPtr >= EndData) /* Yes, but did we reach end of input*/
1245  {
1246  /* Yes, invalid number. */
1247  return true;
1248  }
1249  /* If this a plus/minus sign? */
1250  if ((*InPtr == ch_MINUS) || (*InPtr == ch_PLUS))
1251  {
1252  InPtr++; /* go on to next char. */
1253  }
1254  if (InPtr >= EndData) /* reach end of Input ? */
1255  {
1256  return true; /* Yes, invalid number. */
1257  }
1258  /* If this char a valid digit? */
1259  if (*InPtr < ch_ZERO || *InPtr > ch_NINE)
1260  {
1261  return true; /* No, invalid number. */
1262  }
1263  /* Do while we have a valid digit */
1264  while (*InPtr >= ch_ZERO && *InPtr <= ch_NINE)
1265  {
1266  InPtr++; /* Yup, go to next one and check */
1267  }
1268  }
1269  /* At this point all that should be */
1270  /* left Are trailing blanks. */
1271  while (*InPtr == ch_BLANK || *InPtr == ch_TAB) /* Skip all trailing blanks */
1272  {
1273  InPtr++; /* Skip it, and go on to next char */
1274  }
1275  if (InPtr >= EndData) /* Did we reach end of data */
1276  {
1277  return false; /* this was fine */
1278  }
1279  return true; /* wasn't a valid number */
1280 }
1281 
1282 void fill_digits( /* create a string of digits */
1283  char *outPtr, /* output location */
1284  const char *number, /* start of string of digits */
1285  size_t count ) /* size of resulting string */
1286 /******************************************************************************/
1287 /* Function : Copy "count" digits of a number to the desired location, */
1288 /* converting them back to character digits */
1289 /******************************************************************************/
1290 {
1291  while (count--) /* while still have characters */
1292  {
1293  *outPtr++ = *number++ + '0'; /* convert back to character */
1294  }
1295 }
1296 
1298  RexxObject *decimal_digits) /* number of decimal digits */
1299 /******************************************************************************/
1300 /* Function: Truncate a number to given decimal digit count */
1301 /******************************************************************************/
1302 {
1303  /* get the decimal count */
1304  size_t needed_digits = optionalNonNegative(decimal_digits, 0, OREF_positional, ARG_ONE);
1305  /* round to current digits setting */
1306  return this->prepareNumber(number_digits(), ROUND)->truncInternal(needed_digits);
1307 }
1308 
1310  size_t needed_digits) /* number of decimal digits */
1311 /******************************************************************************/
1312 /* Function: Truncate a number to given decimal digit count */
1313 /******************************************************************************/
1314 {
1315  RexxString *result; /* returned result */
1316  wholenumber_t temp; /* temporary string value */
1317  wholenumber_t integer_digits; /* leading integer digits */
1318  size_t size; /* total size of the result */
1319  int signValue; /* current sign indicator */
1320  char *resultPtr; /* result pointer */
1321 
1322  if (this->sign == 0)
1323  { /* is the number zero? */
1324  if (needed_digits == 0) /* no decimals requested? */
1325  {
1326  /* just return a zero */
1327  return IntegerZero;
1328  }
1329  else
1330  { /* need to pad */
1331  /* get an empty string */
1332  result = (RexxString *)raw_string(needed_digits + 2);
1333  /* get a data pointer */
1334  resultPtr = result->getWritableData();
1335  strcpy(resultPtr, "0."); /* copy the leading part */
1336  /* fill in the trailing zeros */
1337  memset(resultPtr + 2, '0', needed_digits);
1338  return result; /* return the result */
1339  }
1340  }
1341  else
1342  { /* have to do real formatting */
1343  size = 0; /* start with nothing */
1344  signValue = this->sign; /* copy the sign */
1345  /* calculate the leading part */
1346  /* number have a decimal part? */
1347  if (this->exp > 0)
1348  {
1349  /* add in both length and exponent */
1350  size += this->length + this->exp;
1351  if (needed_digits != 0) /* have digits required? */
1352  {
1353  size += needed_digits + 1; /* add in the digits and the decimal */
1354  }
1355  }
1356  else
1357  { /* number has a decimal part. */
1358  /* get the leading part */
1359  integer_digits = (wholenumber_t)this->length + this->exp;
1360  if (integer_digits > 0)
1361  { /* something on the left hand side? */
1362  size += integer_digits; /* add in these digits */
1363  if (needed_digits != 0) /* decimals requested? */
1364  {
1365  size += needed_digits + 1; /* add in the digits and the decimal */
1366  }
1367  }
1368  else
1369  { /* no leading part */
1370  if (needed_digits == 0) /* nothing wanted after decimal? */
1371  {
1372  return IntegerZero; /* this is just zero then */
1373  }
1374  /* do we need to pad more zeros than */
1375  /* number we want after the decimal?*/
1376  if ((wholenumber_t)needed_digits <= -integer_digits)
1377  {
1378  size = needed_digits + 2; /* result is formatted zero...no sign*/
1379  signValue = 0; /* force the sign out */
1380  }
1381  else
1382  {
1383  size += needed_digits + 2; /* calculate the decimal size */
1384  }
1385  }
1386  }
1387  if (signValue < 0) /* negative number? */
1388  {
1389  size++; /* start with a sign */
1390  }
1391  /* get an empty pointer */
1392  result = (RexxString *)raw_string(size);
1393  /* point to the data part */
1394  resultPtr = result->getWritableData();
1395  if (signValue < 0) /* negative number? */
1396  {
1397  *resultPtr++ = '-'; /* start with a sign */
1398  }
1399  /* calculate the leading part */
1400  /* number have a decimal part? */
1401  if (this->exp > 0)
1402  {
1403  /* fill in the digits */
1404  fill_digits(resultPtr, this->number, this->length);
1405  resultPtr += this->length; /* step over the length */
1406  /* now fill in the extra zeros */
1407  memset(resultPtr, '0', this->exp);
1408  resultPtr += this->exp; /* and the exponent */
1409  if (needed_digits != 0)
1410  { /* decimals requested? */
1411  *resultPtr++ = '.'; /* add a trailing decimal point */
1412  /* copy on the trailers */
1413  memset(resultPtr, '0', needed_digits);
1414  }
1415  }
1416  else
1417  { /* number has a decimal part. */
1418  integer_digits = this->length + this->exp;
1419  if (integer_digits > 0)
1420  { /* something on the left hand side? */
1421  /* add the integer digits */
1422  fill_digits(resultPtr, this->number, integer_digits);
1423  resultPtr += integer_digits; /* step over the digits */
1424  if (needed_digits != 0)
1425  { /* decimals requested? */
1426  *resultPtr++ = '.'; /* add a trailing decimal point */
1427  /* get count to add */
1428  temp = Numerics::minVal(needed_digits, this->length - integer_digits);
1429  /* fill in the digits */
1430  fill_digits(resultPtr, this->number + integer_digits, temp);
1431  resultPtr += temp; /* step over the digits */
1432  needed_digits -= temp; /* adjust the length */
1433  if (needed_digits != 0) /* still need more? */
1434  {
1435  /* copy on the trailers */
1436  memset(resultPtr, '0', needed_digits);
1437  }
1438  }
1439  }
1440  else
1441  { /* no leading part */
1442  /* do we need to pad more zeros than */
1443  /* number we want after the decimal?*/
1444  if ((wholenumber_t)needed_digits <= -integer_digits)
1445  {
1446  strcpy(resultPtr, "0."); /* copy a leading zero part */
1447  resultPtr += 2; /* step over */
1448  /* copy on the trailers */
1449  memset(resultPtr, '0', needed_digits);
1450  }
1451  else
1452  {
1453  strcpy(resultPtr, "0."); /* copy a leading zero part */
1454  resultPtr += 2; /* step over */
1455  /* copy on the trailers */
1456  memset(resultPtr, '0', -integer_digits);
1457  resultPtr += -integer_digits;/* step over the digits */
1458  needed_digits += integer_digits; /* reduce needed_digits */
1459  /* get count to add */
1460  temp = Numerics::minVal(needed_digits, this->length);
1461  /* fill in the digits */
1462  fill_digits(resultPtr, this->number, temp);
1463  resultPtr += temp; /* step over the digits */
1464  needed_digits -= temp; /* adjust the length */
1465  if (needed_digits != 0) /* still need more? */
1466  {
1467  /* copy on the trailers */
1468  memset(resultPtr, '0', needed_digits);
1469  }
1470  }
1471  }
1472  }
1473  }
1474  return result; /* return the formatted number */
1475 }
1476 
1477 
1478 /**
1479  * Return the floor value for a decimal numeric value. The floor
1480  * is the first full number value less that the current
1481  * value. If the number has no significant decimal positions,
1482  * this returns the same value (minus any trailing decimal zeros).
1483  * NOTE: If the number is negative, the value goes toward the
1484  * lower number (e.g., the floor of -3.5 is -4, not -3).
1485  *
1486  * @return The numeric floor of this value.
1487  */
1489 {
1490  /* round to current digits setting */
1491  return this->prepareNumber(number_digits(), ROUND)->floorInternal();
1492 }
1493 
1494 /**
1495  * Calculate the floor value for a number.
1496  *
1497  * @return A string value of the floor, with appropriate
1498  * formatting for the function.
1499  */
1501 {
1502  // if this is exactly zero, then the floor is always zero
1503  if (this->sign == 0)
1504  {
1505  return IntegerZero;
1506  }
1507  // if this is a positive number, then this is the same as trunc
1508  else if (this->sign > 0)
1509  {
1510  return this->truncInternal(0);
1511  }
1512  else
1513  {
1514  // since we have to go lower, first check to see if there are
1515  // any non-zero decimals. If not, then we can call trunc
1516  // directly to format. If there are non-zero decimals, we add one
1517  // to the value and then let trunc do the heavy lifting.
1518 
1519  // not have a decimal part? If no decimal part, just pass to trunc
1520  if (this->exp >= 0)
1521  {
1522  return this->truncInternal(0);
1523  }
1524  else
1525  {
1526  // number has a decimal part, so we need to see if there are
1527  // any non-zero decimals
1528 
1529  // get the number of decimals we need to scan
1530  stringsize_t decimals = Numerics::minVal(this->length, (stringsize_t)(-this->exp));
1531  // get the position to start the scan
1532  stringsize_t lastDecimal = this->length - 1;
1533  bool foundNonZero = false;
1534  for (stringsize_t i = decimals; i > 0; i--)
1535  {
1536  // if we found a non-zero, we have to do this the hard way
1537  if (this->number[lastDecimal--] != 0)
1538  {
1539  foundNonZero = true;
1540  break;
1541  }
1542  }
1543 
1544  // no-nonzero values, we can allow trunc to handle it from here
1545  if (!foundNonZero)
1546  {
1547  return this->truncInternal(0);
1548  }
1549 
1550  // ok, we need to add 1 to this value, and then allow trunc to finish the
1551  // job. Unfortunately, this might require us to round out of the top of
1552  // the number, so we need to account for this
1553 
1554  // get the leading digits of the value
1555  wholenumber_t integer_digits = (wholenumber_t)this->length + this->exp;
1556  // if there are no integer digits, then this number is between 0 and -1.
1557  // we can just punt here and return -1.
1558  if (integer_digits <= 0)
1559  {
1560  return IntegerMinusOne;
1561  }
1562  else
1563  {
1564  // ok, we have integer digits. Let's make like easy at this
1565  // point by chopping this down to just the integer digits and
1566  // throwing away the exponent
1567  this->length = integer_digits;
1568  this->exp = 0;
1569 
1570  // point to the first digit, and start adding until
1571  // we no longer round
1572  char *current = this->number + integer_digits - 1;
1573 
1574  while (current >= this->number)
1575  {
1576  int ch = *current + 1;
1577  // did this round?
1578  if (ch > 9)
1579  {
1580  // overwrite with a zero and keep looping
1581  *current-- = 0;
1582  }
1583  else
1584  {
1585  // overwrite this value and have the trunc function
1586  // format the value
1587  *current = ch;
1588  return this->truncInternal(0);
1589  }
1590  }
1591 
1592  // ok, we rounded all the way out. At this point, every digit in
1593  // the buffer is a zero. Doing the rounding is easy here, just
1594  // stuff a 1 in the first digit and bump the exponent by 1
1595  *this->number = 1;
1596  this->exp += 1;
1597  // and again, the trunc code can handle all of the formatting
1598  return this->truncInternal(0);
1599  }
1600  }
1601  }
1602 }
1603 
1604 
1605 /**
1606  * Return the ceiling value for a decimal numeric value. The
1607  * ceiling is the first full number value greater that the
1608  * current value. If the number has no significant decimal
1609  * positions, this returns the same value (minus any trailing
1610  * decimal zeros). NOTE: If the number is negative, the value
1611  * goes toward the higher number (e.g., the ceiling of -3.5 is
1612  * -3, not
1613  * -4).
1614  *
1615  * @return The numeric ceiling of this value.
1616  */
1618 {
1619  /* round to current digits setting */
1620  return this->prepareNumber(number_digits(), ROUND)->ceilingInternal();
1621 }
1622 
1623 /**
1624  * Calculate the ceiling value for a number.
1625  *
1626  * @return A string value of the ceiling, with appropriate
1627  * formatting for the function.
1628  */
1630 {
1631  // if this is exactly zero, then the ceiling is always zero
1632  if (this->sign == 0)
1633  {
1634  return IntegerZero;
1635  }
1636  // if this is a negative number, then this is the same as trunc
1637  else if (this->sign < 0)
1638  {
1639  return this->truncInternal(0);
1640  }
1641  else
1642  {
1643  // since we have to go higher, first check to see if there are
1644  // any non-zero decimals. If not, then we can call trunc
1645  // directly to format. If there are non-zero decimals, we add one
1646  // to the value and then let trunc do the heavy lifting.
1647 
1648  // not have a decimal part? If no decimal part, just pass to trunc
1649  if (this->exp >= 0)
1650  {
1651  return this->truncInternal(0);
1652  }
1653  else
1654  {
1655  // number has a decimal part, so we need to see if there are
1656  // any non-zero decimals
1657 
1658  // get the number of decimals we need to scan
1659  stringsize_t decimals = Numerics::minVal((stringsize_t)this->length, (stringsize_t)(-this->exp));
1660  // get the position to start the scan
1661  stringsize_t lastDecimal = this->length - 1;
1662  bool foundNonZero = false;
1663  for (stringsize_t i = decimals; i > 0; i--)
1664  {
1665  // if we found a non-zero, we have to do this the hard way
1666  if (this->number[lastDecimal--] != 0)
1667  {
1668  foundNonZero = true;
1669  break;
1670  }
1671  }
1672 
1673  // no-nonzero values, we can allow trunc to handle it from here
1674  if (!foundNonZero)
1675  {
1676  return this->truncInternal(0);
1677  }
1678 
1679  // ok, we need to add 1 to this value, and then allow trunc to finish the
1680  // job. Unfortunately, this might require us to round out of the top of
1681  // the number, so we need to account for this
1682 
1683  // get the leading digits of the value
1684  wholenumber_t integer_digits = (wholenumber_t)this->length + this->exp;
1685  // if there are no integer digits, then this number is between 0 and 1.
1686  // we can just punt here and return 1.
1687  if (integer_digits <= 0)
1688  {
1689  return IntegerOne;
1690  }
1691  else
1692  {
1693  // ok, we have integer digits. Let's make like easy at this
1694  // point by chopping this down to just the integer digits and
1695  // throwing away the exponent
1696  this->length = integer_digits;
1697  this->exp = 0;
1698 
1699  // point to the first digit, and start adding until
1700  // we no longer round
1701  char *current = this->number + integer_digits - 1;
1702 
1703  while (current >= this->number)
1704  {
1705  int ch = *current + 1;
1706  // did this round?
1707  if (ch > 9)
1708  {
1709  // overwrite with a zero and keep looping
1710  *current-- = 0;
1711  }
1712  else
1713  {
1714  // overwrite this value and have the trunc function
1715  // format the value
1716  *current = ch;
1717  return this->truncInternal(0);
1718  }
1719  }
1720 
1721  // ok, we rounded all the way out. At this point, every digit in
1722  // the buffer is a zero. Doing the rounding is easy here, just
1723  // stuff a 1 in the first digit and bump the exponent by 1
1724  *this->number = 1;
1725  this->exp += 1;
1726  // and again, the trunc code can handle all of the formatting
1727  return this->truncInternal(0);
1728  }
1729  }
1730  }
1731 }
1732 
1733 
1734 /**
1735  * Round the number value depending on the value of the first
1736  * decimal position using standard rounding rules.
1737  * NOTE: this uses the same rules for floor and ceiling when
1738  * determining how things are rounded. This is really defined
1739  * as floor(number + .5). Thus 3.4 and -3.4 round to 3 and -3,
1740  * since they end up calculating floor(3.9) and floor(-2.9),
1741  * repectively.
1742  *
1743  * @return The rounded value
1744  */
1746 {
1747  /* round to current digits setting */
1748  return this->prepareNumber(number_digits(), ROUND)->roundInternal();
1749 }
1750 
1751 /**
1752  * Calculate the rounded number value.
1753  *
1754  * @return A string value of the rounded number.
1755  */
1757 {
1758  // if this is exactly zero, then the rounded value is always zero
1759  if (this->sign == 0)
1760  {
1761  return IntegerZero;
1762  }
1763  // ok, regardless of the sign, we first decide based on the first
1764  // decimal which way we are rounding.
1765  else
1766  {
1767  // since we might have to go higher, first check to see if there are
1768  // any non-zero decimals. If not, then we can call trunc
1769  // directly to format. Otherwise, we need to look at the first
1770  // decimal position and see which way we go.
1771 
1772  // not have a decimal part? If no decimal part, just pass to trunc
1773  if (this->exp >= 0)
1774  {
1775  return this->truncInternal(0);
1776  }
1777  else
1778  {
1779  // number has a decimal part, so we need to look at the first
1780  // decimal position
1781 
1782  // get the leading digits of the value
1783  wholenumber_t integer_digits = (wholenumber_t)this->length + this->exp;
1784  // if the exponent is larger than the number of significant digits, then
1785  // the first digit to the right of the decimal is zero, so this will always
1786  // round to zero
1787  if (integer_digits < 0)
1788  {
1789  return IntegerZero;
1790  }
1791  else
1792  {
1793  // ok, we have integer digits and decimals. The returned value will
1794  // be an integer, so we can just set the exponent to zero now and
1795  // throw away the decimal part
1796  this->length = integer_digits;
1797  this->exp = 0;
1798 
1799  // Now we need to look at the first decimal and see if
1800  // we're rounding up
1801  char *current = this->number + integer_digits;
1802  // no rounding needed, go do the formatting
1803  if (*current < 5)
1804  {
1805  return this->truncInternal(0);
1806  }
1807 
1808  // we need to add one to the integer part...which of course
1809  // might round all the way out.
1810  current--;
1811 
1812  while (current >= this->number)
1813  {
1814  int ch = *current + 1;
1815  // did this round?
1816  if (ch > 9)
1817  {
1818  // overwrite with a zero and keep looping
1819  *current-- = 0;
1820  }
1821  else
1822  {
1823  // overwrite this value and have the trunc function
1824  // format the value
1825  *current = ch;
1826  return this->truncInternal(0);
1827  }
1828  }
1829 
1830  // ok, we rounded all the way out. At this point, every digit in
1831  // the buffer is a zero. Doing the rounding is easy here, just
1832  // stuff a 1 in the first digit and bump the exponent by 1
1833  *this->number = 1;
1834  this->exp += 1;
1835  // and again, the trunc code can handle all of the formatting
1836  return this->truncInternal(0);
1837  }
1838  }
1839  }
1840 }
1841 
1842 
1844  RexxObject *Integers, /* space for integer part */
1845  RexxObject *Decimals, /* number of decimals required */
1846  RexxObject *MathExp, /* the exponent size */
1847  RexxObject *ExpTrigger ) /* the exponent trigger */
1848 /******************************************************************************/
1849 /* Function : Format the numberstring data according to the format */
1850 /* function controls. */
1851 /******************************************************************************/
1852 {
1853  size_t integers; /* integer space requested */
1854  size_t decimals; /* decimal space requested */
1855  size_t mathexp; /* exponent space requested */
1856  size_t exptrigger; /* exponential notation trigger */
1857  size_t digits; /* current numeric digits */
1858  bool form; /* current numeric form */
1859 
1860  digits = number_digits(); /* get the current digits value */
1861  form = number_form(); /* and the exponential form */
1862  /* get the space for integer part */
1863  integers = optionalNonNegative(Integers, -1, OREF_positional, ARG_ONE);
1864  /* and the decimal part */
1865  decimals = optionalNonNegative(Decimals, -1, OREF_positional, ARG_TWO);
1866  /* also the exponent size */
1867  mathexp = optionalNonNegative(MathExp, -1, OREF_positional, ARG_THREE);
1868  /* and the trigger */
1869  exptrigger = optionalNonNegative(ExpTrigger, digits, OREF_positional, ARG_FOUR);
1870  /* round to current digits setting */
1871  return this->prepareNumber(digits, ROUND)->formatInternal(integers, decimals, mathexp, exptrigger, this, digits, form);
1872 }
1873 
1875  size_t integers, /* space for integer part */
1876  size_t decimals, /* number of decimals required */
1877  size_t mathexp, /* the exponent size */
1878  size_t exptrigger, /* the exponent trigger */
1879  RexxNumberString *original, /* oringial NumStr */
1880  size_t digits, /* digits to format to */
1881  bool form) /* form to format to */
1882 /******************************************************************************/
1883 /* Function : Format the numberstring data according to the format */
1884 /* function controls. */
1885 /******************************************************************************/
1886 {
1887  wholenumber_t expfactor; /* actual used exponent */
1888  wholenumber_t temp; /* temporary calculation holder */
1889  size_t exponentsize = 0; /* size of the exponent */
1890  char exponent[15]; /* character exponent value */
1891  wholenumber_t adjust; /* exponent adjustment factor */
1892  size_t size; /* total size of the result */
1893  size_t leadingSpaces; /* number of leading spaces */
1894  size_t leadingZeros = 0; /* number of leading zeros */
1895  size_t leadingExpZeros = 0; /* number of leading zeros in exp */
1896  size_t trailingZeros; /* number of trailing zeros */
1897  size_t reqIntegers; /* requested integers */
1898  RexxString *result; /* final formatted number */
1899  char *resultPtr; /* pointer within the result */
1900  bool defaultexpsize = false; /* default exponent size */
1901 
1902  expfactor = 0; /* not exponential yet */
1903 
1904  if (mathexp != 0)
1905  { /* Is exponential allowed? */
1906  /* calculate the exponent factor */
1907  temp = this->exp + this->length - 1;
1908  /* is left of dec>digits */
1909  /* or twice digits on right */
1910  if (temp >= (wholenumber_t)exptrigger || Numerics::abs(this->exp) > (wholenumber_t)(exptrigger * 2))
1911  {
1912  if (form == Numerics::FORM_ENGINEERING)
1913  { /* request for Engineering notation? */
1914  if (temp < 0) /* yes, is it a whole number? */
1915  {
1916  temp = temp - 2; /* no, force two char left adjustment -2 instead of -1 */
1917  }
1918  temp = (temp / 3) * 3; /* get count right of decimal point */
1919  }
1920  this->exp = this->exp - temp; /* adjust the exponent */
1921  expfactor = temp; /* save the factor */
1922  temp = Numerics::abs(temp); /* get positive exponent value */
1923  /* format exponent to a string */
1924  Numerics::formatWholeNumber(temp, exponent);
1925  /* get the number of digits needed */
1926  exponentsize = strlen(exponent);
1927  if (mathexp == (size_t)-1)
1928  { /* default exponent size? */
1929  mathexp = exponentsize; /* use actual length */
1930  defaultexpsize = true; /* default exponent size on */
1931  }
1932  if (exponentsize > mathexp) /* not enough room? */
1933  {
1935  }
1936  }
1937  }
1938 
1939  if (decimals == (size_t)-1)
1940  { /* default decimal processing? */
1941  if (this->exp < 0) /* negative exponent? */
1942  {
1943  decimals = -this->exp; /* get number of decimals */
1944  }
1945  }
1946  else
1947  {
1948  if (this->exp < 0)
1949  { /* have actual decimals? */
1950  adjust = -this->exp; /* get absolute value */
1951  if ((size_t)adjust > decimals)
1952  { /* need to round or truncate? */
1953  adjust = adjust - decimals; /* get the difference */
1954  /* adjust exponent */
1955  this->exp = this->exp + adjust;
1956  if (adjust >= (wholenumber_t)this->length)
1957  { /* Losing all digits? need rounding */
1958  /* is rounding needed? */
1959  if (adjust == (wholenumber_t)this->length && this->number[0] >= 5)
1960  {
1961  this->number[0] = 1; /* round up */
1962  }
1963  else
1964  {
1965  this->number[0] = 0; /* round down */
1966  this->exp = 0; /* nothing left at all */
1967  this->sign = 1; /* suppress a negative sign */
1968  }
1969  this->length = 1; /* just one digit left */
1970  }
1971  /* Need to round? */
1972  else
1973  { /* truncating, need to check rounding*/
1974  temp = decimals - adjust; /* get the difference */
1975  /* adjust the length */
1976  this->length = this->length - adjust;
1977  /* go round this number */
1978  this->mathRound(this->number);
1979  /* calculate new adjusted value */
1980  /* undo the previous exponent calculation */
1981  /* needed for format(.999999,,4,2,2) */
1982  if (mathexp != 0 && expfactor != 0)
1983  {
1984  this->exp += expfactor;
1985  expfactor = 0;
1986  strcpy(exponent, "0");
1987  exponentsize = strlen(exponent);
1988  }
1989 
1990  temp = this->exp + this->length - 1;
1991 
1992  /* did rounding trigger the */
1993  /* exponential form? */
1994  if (mathexp != 0 && (temp >= (wholenumber_t)exptrigger || (size_t)Numerics::abs(this->exp) > exptrigger * 2))
1995  {
1996  /* yes, request for */
1997  if (form == Numerics::FORM_ENGINEERING)
1998  {
1999  /* Engineering notation fmt? */
2000  if (temp < 0) /* yes, is it a whole number? */
2001  temp = temp - 2; /* no, force two char adjust to left */
2002  temp = (temp / 3) * 3; /* get count right of decimal point */
2003  }
2004  /* adjust the exponent */
2005  this->exp = this->exp - temp;
2006  /* adjust the exponent factor */
2007  expfactor = expfactor + temp;
2008  /* format exponent to a string */
2009  Numerics::formatWholeNumber(Numerics::abs(expfactor), exponent);
2010  /* get the number of digits needed */
2011  exponentsize = strlen(exponent);
2012 
2013  if (mathexp == (size_t)-1) /* default exponent size? */
2014  {
2015  mathexp = exponentsize; /* use actual length */
2016  }
2017  if (exponentsize > mathexp)/* not enough room? */
2018  {
2020  }
2021  }
2022  }
2023  }
2024  }
2025  }
2026 
2027  if (integers == (size_t)-1)
2028  { /* default integers requested */
2029  if (this->exp >= 0) /* non-negative exponent? */
2030  {
2031  /* use all of number */
2032  integers = this->length + this->exp;
2033  }
2034  else
2035  {
2036  /* no integer part? */
2037  if ((size_t)Numerics::abs(this->exp) > this->length)
2038  {
2039  integers = 1; /* just the leading zero */
2040  }
2041  else /* get the integer part */
2042  {
2043  integers = this->length + this->exp;
2044  }
2045  }
2046  }
2047  else
2048  { /* user requested size */
2049  reqIntegers = integers; /* save integers */
2050  if (this->sign == -1) /* negative number? */
2051  {
2052  integers = integers - 1; /* the sign takes up one spot */
2053  }
2054  if (this->exp >= 0) /* non-negative exponent? */
2055  {
2056  temp = this->length + this->exp; /* use all of number */
2057  }
2058  else
2059  {
2060  /* no integer part? */
2061  if ((size_t)Numerics::abs(this->exp) > this->length)
2062  {
2063  temp = 1; /* just the leading zero */
2064  }
2065  else
2066  {
2067  /* get the integer part */
2068  temp = this->length + this->exp;
2069  }
2070  }
2071  if ((wholenumber_t)integers < temp) /* not enough room? */
2072  {
2073  /* this is an error */
2075  }
2076  }
2077 
2078  size = 0; /* start with a null string */
2079  leadingSpaces = 0; /* no leading spaces yet */
2080  temp = this->exp + this->length; /* get adjusted length */
2081  if (temp != (wholenumber_t)integers)
2082  { /* need leading spaces? */
2083  if (temp > 0) /* have leading part? */
2084  {
2085  leadingSpaces = integers - temp; /* get leading length */
2086  }
2087  else
2088  {
2089  leadingSpaces = integers - 1; /* leave space for leading 0 */
2090  }
2091  size += leadingSpaces; /* fill in the spaces */
2092  }
2093  if (this->sign == -1) /* negative number? */
2094  {
2095  size++; /* space for the sign */
2096  }
2097 
2098  if (temp <= 0)
2099  { /* no integer portion? */
2100  size += 2; /* add room for zero and decimal */
2101  leadingZeros = -temp; /* get positive of zeros */
2102  size += leadingZeros; /* add in the zeros size */
2103  if (this->length > 0) /* have a length? */
2104  {
2105  size += this->length; /* add on the actual data */
2106  }
2107  /* need more zeros? */
2108  if (leadingZeros + this->length < decimals)
2109  {
2110  /* get the trailing count */
2111  trailingZeros = decimals - (leadingZeros + this->length);
2112  size += trailingZeros; /* add them on */
2113  }
2114  else
2115  {
2116  trailingZeros = 0; /* no trailing zeros */
2117  }
2118  }
2119  else if (temp >= (wholenumber_t)this->length)
2120  { /* all integer data? */
2121  size += this->length; /* add on the digits */
2122  /* reduce total length */
2123  trailingZeros = temp - this->length;
2124  size += trailingZeros; /* add this to the total size */
2125  if (decimals > 0) /* decimals needed? */
2126  {
2127  size += decimals + 1; /* add decimal point and trailers */
2128  }
2129  }
2130  else
2131  { /* partial decimal number */
2132  size += this->length + 1; /* need the length plus a decimal */
2133  /* get needed extra zeroes */
2134  trailingZeros = decimals - (this->length - temp);
2135  size += trailingZeros; /* add that to the size */
2136  if ((wholenumber_t)trailingZeros < 0)
2137  {
2138  this->length += trailingZeros;
2139  this->exp -= trailingZeros;
2140  trailingZeros = 0;
2141  }
2142  }
2143 
2144  if (expfactor != 0)
2145  { /* exponential value? */
2146  size += 2; /* add on the E and the sign */
2147  /* get extra size needed */
2148  leadingExpZeros = mathexp - exponentsize;
2149  size += mathexp; /* add on the total exponent size */
2150  }
2151  /* spaces needed for exp.? */
2152  else if (mathexp > 0 && !defaultexpsize && temp > (wholenumber_t)exptrigger)
2153  {
2154  size += mathexp + 2; /* add on the spaces needed */
2155  }
2156  result = raw_string(size); /* get an empty string to start */
2157 
2158  resultPtr = result->getWritableData();
2159  temp = this->exp + this->length; /* get adjusted length */
2160  if (leadingSpaces != 0)
2161  { /* need leading spaces? */
2162  /* fill them in */
2163  memset(resultPtr, ' ', leadingSpaces);
2164  resultPtr += leadingSpaces; /* and step past them */
2165  }
2166  if (this->sign == -1) /* negative number? */
2167  {
2168  *resultPtr++ = '-'; /* add the sign */
2169  }
2170 
2171  if (temp <= 0)
2172  { /* no integer portion? */
2173  strcpy(resultPtr, "0."); /* add the leading zero and decimal */
2174  resultPtr += 2; /* and step past them */
2175  if (leadingZeros != 0)
2176  { /* zeroes needed? */
2177  /* fill them in */
2178  memset(resultPtr, '0', leadingZeros);
2179  resultPtr += leadingZeros; /* and step past them */
2180  }
2181  if (this->length > 0)
2182  { /* have a length? */
2183  /* fill in the remaining part */
2184  fill_digits(resultPtr, this->number, this->length);
2185  resultPtr += this->length; /* step over the digits */
2186  }
2187  if (trailingZeros != 0)
2188  { /* need more zeros? */
2189  /* fill them in */
2190  memset(resultPtr, '0', trailingZeros);
2191  resultPtr += trailingZeros; /* and step past them */
2192  }
2193  }
2194  else if (temp >= (wholenumber_t)this->length)
2195  {/* all integer data? */
2196  /* fill in the remaining part */
2197  fill_digits(resultPtr, this->number, this->length);
2198  resultPtr += this->length; /* step over the digits */
2199  if (trailingZeros != 0)
2200  { /* need more zeros? */
2201  /* fill them in */
2202  memset(resultPtr, '0', trailingZeros);
2203  resultPtr += trailingZeros; /* and step past them */
2204  }
2205  if ((wholenumber_t)decimals > 0)
2206  { /* decimals needed? */
2207  *resultPtr++ = '.'; /* add the period */
2208  memset(resultPtr, '0', decimals);/* fill them in */
2209  resultPtr += decimals; /* and step past them */
2210  }
2211  }
2212  else
2213  { /* partial decimal number */
2214  /* fill in the leading part */
2215  fill_digits(resultPtr, this->number, temp);
2216  resultPtr += temp; /* step over the digits */
2217  *resultPtr++ = '.'; /* add the period */
2218  /* fill in the trailing part */
2219  fill_digits(resultPtr, this->number + temp, this->length - temp);
2220  resultPtr += this->length - temp; /* step over the extra part */
2221  if ((wholenumber_t)trailingZeros > 0)
2222  { /* extra decimals needed? */
2223  /* fill them in */
2224  memset(resultPtr, '0', trailingZeros);
2225  resultPtr += trailingZeros; /* and step past them */
2226  }
2227  }
2228 
2229  if (expfactor != 0)
2230  { /* exponential value? */
2231  *resultPtr++ = 'E'; /* fill in the notation character */
2232  if (expfactor > 0) /* positive exponent? */
2233  {
2234  *resultPtr++ = '+'; /* add the plus sign */
2235  }
2236  else
2237  {
2238  *resultPtr++ = '-'; /* a minus sign is required */
2239  }
2240  if (leadingExpZeros > 0)
2241  { /* need extras? */
2242  /* fill them in */
2243  memset(resultPtr, '0', leadingExpZeros);
2244  resultPtr += leadingExpZeros; /* and step past them */
2245  }
2246  /* now add on the exponent */
2247  memcpy(resultPtr, exponent, exponentsize);
2248  }
2249  /* blanks needed instead? */
2250  else if (mathexp > 0 && !defaultexpsize && temp > (wholenumber_t)exptrigger)
2251  {
2252  /* fill them in */
2253  memset(resultPtr, ' ', mathexp + 2);
2254  resultPtr += mathexp; /* and step past them */
2255  /* add on the spaces */
2256  }
2257  return result; /* return the result */
2258 }
2259 
2260 int RexxNumberString::format(const char *_number, size_t _length)
2261 /******************************************************************************/
2262 /* Function : Format the string data into a numberstring. */
2263 /* NOTE: now that a scan is done first the is some cleanup that can*/
2264 /* be done, since we can make some assumptions about certain */
2265 /* data/chars being valid. */
2266 /* */
2267 /* Returned: 0 if input was valid number */
2268 /* 1 if input was invalid number */
2269 /******************************************************************************/
2270 {
2271 
2272  int ExpSign; /* Exponent Sign */
2273  wholenumber_t ExpValue; /* Exponent Value */
2274  size_t MaxDigits; /* Maximum number size */
2275  char ch; /* current character */
2276  char MSDigit = 0; /* Most Significant digit truncated */
2277  const char *InPtr; /* Input Data Pointer */
2278  char *OutPtr; /* Output Data Pointer */
2279  const char *EndData; /* Scan end position */
2280  bool isZero; /* Number is zero if true */
2281  size_t resultDigits; /* Number of digits in result */
2282 
2283 
2284  ExpValue = 0; /* Initial Exponent. */
2285  ExpSign = 0; /* set exponent sign */
2286  isZero = true; /* Assume number will be zero. */
2287 
2288  InPtr = _number; /*Point to start of input string. */
2289  EndData = InPtr + _length; /*Point to end of Data + 1. */
2290 
2291  while (*InPtr == ch_BLANK || *InPtr == ch_TAB) /* Ship all leading blanks. */
2292  {
2293  InPtr++; /* Skip it, and go on to next char */
2294  }
2295  /* Is this a sign Character? */
2296  if ((ch = *InPtr) == ch_MINUS || ch == ch_PLUS)
2297  {
2298  InPtr++; /* Yes, skip it. */
2299  if (ch == ch_MINUS) /* is it a Minus sign? */
2300  {
2301  this->sign = -1; /* Yup, indicate a negative number. */
2302  }
2303  }
2304  while (*InPtr == ch_BLANK || *InPtr == ch_TAB) /* Ship all leading blanks. */
2305  {
2306  InPtr++; /* Skip it, and go on to next char */
2307  }
2308  ch = *InPtr; /* Get 1st Digit. */
2309  MaxDigits = resultDigits = _length; /* Set our max digits counter. */
2310  OutPtr = this->number; /* Point to Output area. */
2311 
2312  /*Skip all leading Zero's */
2313  while (*InPtr == ch_ZERO) /* While 1st Digit is a 0 */
2314  {
2315  InPtr++; /* Go to next character. */
2316  }
2317 
2318  /* Have we reach end of number,num */
2319  /*zero? */
2320  if (InPtr >= EndData)
2321  {
2322  SetNumberStringZero(); /* Make value a zero. */
2323  return 0;
2324  }
2325  /* Now process real digits. */
2326  ExpValue = 0; /* Start accumulating exponent */
2327 
2328  if (*InPtr > ch_ZERO && *InPtr <= ch_NINE)
2329  {
2330  isZero = false; /* found the first non-zero digit */
2331  }
2332  /* While the character is a Digit. */
2333  while (*InPtr >= ch_ZERO && *InPtr <= ch_NINE)
2334  {
2335  if (MaxDigits)
2336  { /* Still room to add digits */
2337  /* Move digit into output. */
2338  *OutPtr++ = (char)(*InPtr++ - '0');
2339  MaxDigits--; /* Now room for one less. */
2340  }
2341  else
2342  {
2343  /* Have we found our most Sig Digit */
2344  /* and have we not run out of data? */
2345  if ((!MSDigit) && (InPtr < EndData))
2346  {
2347  MSDigit = *InPtr; /* Nope, now we have MSD. */
2348  }
2349  InPtr++; /* Point to next char */
2350  ExpValue++; /* Increment the exponent value. */
2351  }
2352  }
2353  if (InPtr >= EndData)
2354  { /* Did we reach end of data? */
2355  /* compute length. */
2356  this->length = (size_t) (resultDigits - MaxDigits);
2357  this->exp = ExpValue; /* set exponent value */
2358  this->roundUp(MSDigit);
2359  this->roundUp(MSDigit); /* Round up the number if necessary */
2360  return 0; /* all done, just return */
2361  }
2362  /* compute length. */
2363  this->length = (resultDigits - MaxDigits);
2364  this->exp = ExpValue; /* set exponent value */
2365 
2366  if (*InPtr == ch_PERIOD)
2367  { /*Decimal point??? */
2368  InPtr++; /* yes, skip it. */
2369  if (InPtr >= EndData)
2370  { /* Did we reach end of data */
2371  /* Yes, valid digits continue. */
2372  /*is it "0.", or number Zero */
2373  if (MaxDigits == resultDigits || isZero)
2374  {
2375  this->setZero(); /* make number just zero. */
2376  }
2377  else
2378  {
2379  /* Round up the number if necessary */
2380  this->roundUp(MSDigit);
2381  }
2382  return 0; /* All done, exit. */
2383  }
2384  if (MaxDigits == resultDigits)
2385  { /*Any significant digits? */
2386  /* No, Ship leading Zeros */
2387  while (*InPtr == ch_ZERO)
2388  { /* While 1st Digit is a 0 */
2389  ExpValue--; /* decrement exponent. */
2390  InPtr++; /* Go to next character. */
2391  /* Have we reach end of number,num */
2392  /*zero? */
2393  if (InPtr >= EndData)
2394  {
2395  SetNumberStringZero(); /* Make value a zero. */
2396  return 0;
2397  }
2398  }
2399  }
2400  /* in the range 1-9? */
2401  if (*InPtr > ch_ZERO && *InPtr <= ch_NINE)
2402  {
2403  isZero = false; /* found the first non-zero digit */
2404  }
2405  /*While there are still digits */
2406  while (*InPtr >= ch_ZERO && *InPtr <= ch_NINE)
2407  {
2408  if (MaxDigits)
2409  { /*if still room for digits */
2410  ExpValue--; /* Decrement Exponent */
2411  /* Move char to output */
2412  *OutPtr++ = (char)(*InPtr++ - '0');
2413  MaxDigits--; /* Room for one less digit. */
2414  }
2415  else
2416  {
2417  if (!MSDigit) /* not gotten a most sig digit yet? */
2418  {
2419  MSDigit = *InPtr; /* record this one */
2420  }
2421  InPtr++; /* No more room, go to next digit */
2422  }
2423  }
2424  if (InPtr >= EndData)
2425  { /*Are we at end of data? */
2426  /* Compute length of number. */
2427  this->length = (resultDigits - MaxDigits);
2428  this->exp = ExpValue; /* get exponent. */
2429  /* Round up the number if necessary */
2430  this->roundUp(MSDigit);
2431  return 0; /* All done, return */
2432  }
2433  } /* End is it a Decimal point. */
2434 
2435  /* At this point we are don copying */
2436  /* digits. We are just looking for */
2437  /* exponent value if any and any */
2438  /*trailing blanks */
2439 
2440  /* Get final length of number. */
2441  this->length = resultDigits - MaxDigits;
2442  if (!this->length)
2443  { /* No digits, number is Zero. */
2444  /* Have we reached the end of the */
2445  /*string */
2446  if (InPtr >= EndData)
2447  {
2448  /* Yes, all done. */
2449  this->setZero(); /* make number just zero. */
2450  return 0; /* All done, exit. */
2451  }
2452  }
2453  this->exp = ExpValue; /* get current exponent value. */
2454 
2455  if (toupper(*InPtr) == 'E')
2456  { /* See if this char is an exponent? */
2457  ExpSign = 1; /* Assume sign of exponent to '+' */
2458  InPtr++; /* step over the 'E' */
2459  if (*InPtr == ch_MINUS)
2460  { /* If this a minus sign? */
2461  ExpSign = -1; /* Yes, make sign of exp '-' */
2462  InPtr++; /* go on to next char. */
2463  }
2464  else if (*InPtr == ch_PLUS) /* If this a plus sign? */
2465  {
2466  InPtr++; /* Yes, skip it and go to next char. */
2467  }
2468  ExpValue = 0; /* Start of exponent clear work area.*/
2469  MaxDigits = 0; /* claer digit counter. */
2470 
2471  /* Do while we have a valid digit */
2472  while (*InPtr >= ch_ZERO && *InPtr <= ch_NINE)
2473  {
2474  /* Add this digit to Exponent value. */
2475  ExpValue = ExpValue * 10 + ((*InPtr++) - '0');
2476  if (ExpValue > Numerics::MAX_EXPONENT) /* Exponent can only be 9 digits long*/
2477  {
2478  return 1; /* if more than that, indicate error.*/
2479  }
2480  if (ExpValue) /* Any significance in the Exponent? */
2481  {
2482  MaxDigits++; /* Yes, bump up the digits counter. */
2483  }
2484  }
2485  this->exp += (ExpValue * ExpSign);/* Compute real exponent. */
2486  /* Is it bigger than allowed max */
2488  {
2489  return 1; /* yes, indicate error. */
2490  }
2491  }
2492 
2493  if (this->sign == 0 || isZero)
2494  { /* Was this really a zero number? */
2495  this->setZero(); /* make number just zero. */
2496  }
2497 
2498  this->roundUp(MSDigit); /* Round up the number if necessary */
2499  /*is number just flat out too big? */
2500  if ((this->exp + (wholenumber_t)this->length - 1) > Numerics::MAX_EXPONENT)
2501  {
2502  return 1; /* also bad */
2503  }
2504  return 0; /* All done !! */
2505 }
2506 
2508 /******************************************************************************/
2509 /* Function : Format the integer num into a numberstring. */
2510 /******************************************************************************/
2511 {
2512  if (integer == 0)
2513  { /* is integer 0? */
2514  /* indicate this. */
2515  this->setZero();
2516  }
2517  else
2518  { /* number is non-zero */
2519  /* Format the number */
2520  if (integer < 0 )
2521  { /* Negative integer number? */
2522  this->sign = -1;
2523  }
2524  /* convert value into string */
2525  this->length = Numerics::normalizeWholeNumber(integer, (char *)this->number);
2526  }
2527 }
2528 
2530 /******************************************************************************/
2531 /* Function : Format the integer num into a numberstring. */
2532 /******************************************************************************/
2533 {
2534  char *current; /* current position */
2535 
2536  if (integer == 0)
2537  { /* is integer 0? */
2538  /* indicate this. */
2539  this->setZero();
2540  }
2541  else
2542  { /* number is non-zero */
2543  /* Format the number */
2544  /* convert value into string */
2545  Numerics::formatStringSize(integer, (char *)this->number);
2546  current = this->number; /* point to the data start */
2547  while (*current != '\0')
2548  { /* while still have digits */
2549  *current -= '0'; /* make zero based */
2550  current++; /* step to the next one */
2551  }
2552  /* set the proper length */
2553  this->length = current - this->number;
2554  }
2555 }
2556 
2557 
2559 /******************************************************************************/
2560 /* Function : Format the integer num into a numberstring. */
2561 /******************************************************************************/
2562 {
2563  if (integer == 0)
2564  { /* is integer 0? */
2565  /* indicate this. */
2566  this->setZero();
2567  }
2568  else
2569  { /* number is non-zero */
2570  // we convert this directly because portable numeric-to-ascii routines
2571  // don't really exist for the various 32/64 bit values.
2572  char buffer[32];
2573  size_t index = sizeof(buffer);
2574 
2575  // negative number? copy a negative sign, and take the abs value
2576  if (integer < 0)
2577  {
2578  // work from an unsigned version that can hold all of the digits
2579  // we need to use a version we can negate first, then add the
2580  // digit back in
2581  uint64_t working = (uint64_t)(-(integer + 1));
2582  working++; // undoes the +1 above
2583  sign = -1; // negative number
2584 
2585  while (working > 0)
2586  {
2587  // get the digit and reduce the size of the integer
2588  int digit = (int)(working % 10);
2589  working = working / 10;
2590  // store the digit
2591  buffer[--index] = digit;
2592  }
2593  }
2594  else
2595  {
2596  sign = 1; // positive number
2597  while (integer > 0)
2598  {
2599  // get the digit and reduce the size of the integer
2600  int digit = (int)(integer % 10);
2601  integer = integer / 10;
2602  // store the digit
2603  buffer[--index] = digit;
2604  }
2605  }
2606 
2607  // copy into the buffer and set the length
2608  this->length = sizeof(buffer) - index;
2609  memcpy(this->number, &buffer[index], this->length);
2610  }
2611 }
2612 
2613 
2615 /******************************************************************************/
2616 /* Function : Format the integer num into a numberstring. */
2617 /******************************************************************************/
2618 {
2619  if (integer == 0)
2620  { /* is integer 0? */
2621  /* indicate this. */
2622  this->setZero();
2623  }
2624  else
2625  { /* number is non-zero */
2626  // we convert this directly because A) we need to post-process the numbers
2627  // to make them zero based, and B) portable numeric-to-ascii routines
2628  // don't really exist for the various 32/64 bit values.
2629  char buffer[32];
2630  size_t index = sizeof(buffer);
2631 
2632  while (integer > 0)
2633  {
2634  // get the digit and reduce the size of the integer
2635  int digit = (int)(integer % 10);
2636  integer = integer / 10;
2637  // store the digit
2638  buffer[--index] = digit;
2639  }
2640 
2641  // copy into the buffer and set the length
2642  this->length = sizeof(buffer) - index;
2643  memcpy(this->number, &buffer[index], this->length);
2644  }
2645 }
2646 
2647 
2649  RexxDirectory *named_arguments)
2650 /******************************************************************************/
2651 /* Function: Forward all unknown messages to the numberstring's string */
2652 /* representation */
2653 /******************************************************************************/
2654 {
2655  return this->stringValue()->sendMessage(msgname, arguments, named_arguments);
2656 }
2657 
2658 
2659 /**
2660  * Wrapper around the compareTo() method that does string sort
2661  * comparisons.
2662  *
2663  * @param other The other comparison object
2664  *
2665  * @return -1, 0, 1 depending on the comparison result.
2666  */
2668 {
2669  // just send this as a message directly to the string object.
2670  return stringValue()->compareTo(other);
2671 }
2672 
2673 
2674 /**
2675  * Override for the normal isinstanceof method. This version
2676  * allows the NumberStringClass to "lie" about being a string.
2677  *
2678  * @param other The comparison class
2679  *
2680  * @return True if the string value is an instance of the target class.
2681  */
2683 {
2684  return stringValue()->isInstanceOf(other);
2685 }
2686 
2687 
2688 /**
2689  * Retrieve the method instance for an object's defined method.
2690  *
2691  * @param method_name
2692  * The method name.
2693  *
2694  * @return The method object that implements the object method.
2695  */
2697 {
2698  return stringValue()->instanceMethod(method_name);
2699 }
2700 
2701 
2702 /**
2703  * Return a supplier containing the methods implemented by an
2704  * object. Depending on the argument, this is either A) all of
2705  * the methods, B) just the explicitly set instance methods, or
2706  * C) the methods provided by a given class.
2707  *
2708  * @param class_object
2709  * The target class object (optional).
2710  *
2711  * @return A supplier with the appropriate method set.
2712  */
2714 {
2715  return stringValue()->instanceMethods(class_object);
2716 }
2717 
2718 
2720 /******************************************************************************/
2721 /* Function: Blank concatenation operator */
2722 /******************************************************************************/
2723 {
2724  return this->stringValue()->concatBlank(other);
2725 }
2726 
2728 /******************************************************************************/
2729 /* Function: Normal concatentation operator */
2730 /******************************************************************************/
2731 {
2732  return this->stringValue()->concatRexx(other);
2733 }
2734  /* numberstring operator forwarders */
2735  /* to process string operators */
2736 
2738 {
2739  return (RexxObject *)this->stringValue()->orOp(operand);
2740 }
2741 
2743 {
2744  return (RexxObject *)this->stringValue()->andOp(operand);
2745 }
2746 
2748 {
2749  return (RexxObject *)this->stringValue()->xorOp(operand);
2750 }
2751 
2753  RexxObject *other) /* other comparison object */
2754 /******************************************************************************/
2755 /* Function: Primitive strict equal\not equal method. This determines */
2756 /* only strict equality, not greater or less than values. */
2757 /******************************************************************************/
2758 {
2759  if (this->isSubClassOrEnhanced()) /* not a primitive? */
2760  {
2761  /* do the full lookup compare */
2762  RexxObject *result = this->sendMessage(OREF_STRICT_EQUAL, other);
2763  if (result == OREF_NULL)
2764  {
2765  reportException(Error_No_result_object_message, OREF_STRICT_EQUAL);
2766  }
2767  return result->truthValue(Error_Logical_value_method);
2768  }
2769  /* go do a string compare */
2770  return this->stringValue()->isEqual(other);
2771 }
2772 
2774 /******************************************************************************/
2775 /* Function: Compare the two values. */
2776 /* */
2777 /* Returned: return <0 if other is greater than this */
2778 /* return 0 if this equals other */
2779 /* return >0 if this is greater than other */
2780 /******************************************************************************/
2781 {
2782  /* the strict compare is done against*/
2783  /* strings only, so convert to string*/
2784  /* and let string do this compare. */
2785  return this->stringValue()->strictComp(other);
2786 }
2787 
2789  RexxObject *right, RexxString *alternativeOperator, RexxInteger **alternativeOperatorResultPtr) /* right hand side of compare */
2790 /******************************************************************************/
2791 /* Function: Do a value comparison of two number strings for the non-strict */
2792 /* comparisons. This returns for the compares: */
2793 /* */
2794 /* a value < 0 when this is smaller than other */
2795 /* a value 0 when this is equal to other */
2796 /* a value > 0 when this is larger than other */
2797 /******************************************************************************/
2798 {
2799  RexxNumberString *rightNumber; /* converted right hand number */
2800  wholenumber_t aLexp; /* adjusted left exponent */
2801  wholenumber_t aRexp; /* adjusted right exponent */
2802  size_t aLlen; /* adjusted left length */
2803  size_t aRlen; /* adjusted right length */
2804  wholenumber_t MinExp; /* minimum exponent */
2805  size_t NumberDigits; /* current digits setting */
2806  char *scan; /* scan pointer */
2807  wholenumber_t rc; /* compare result */
2808 
2809  /* the compare is acually done by */
2810  /* subtracting the two numbers, the */
2811  /* sign of the result obj will be our*/
2812  /* return value. */
2813  requiredArgument(right, OREF_positional, ARG_ONE); /* make sure we have a real value */
2814  /* get a numberstring object from */
2815  /*right */
2816  rightNumber = right->numberString();
2817  if (rightNumber == OREF_NULL) /* didn't convert? */
2818  {
2819  if (alternativeOperator != OREF_NULL && alternativeOperatorResultPtr != NULL)
2820  {
2821  // Try an alternative operator
2822  // CAREFUL! Here, the operator returns a boolean result, not a value -1,0,1.
2823  // That's why a separated parameter is used to return this boolean result.
2824  ProtectedObject result;
2825  RexxObject *left = this;
2826  RexxObject *args[1];
2827  args[0] = left; // positional argument
2828  bool alternativeResult = right->messageSend(alternativeOperator, args, 1, 0, result, false);
2829  if (alternativeResult && (RexxObject *)result != OREF_NULL)
2830  {
2831  *alternativeOperatorResultPtr = (RexxInteger *)(RexxObject *)result;
2832  return 0; // You are not supposed to test this value, because *alternativeOperatorResultPtr is non NULL
2833  }
2834  }
2835 
2836  /* numbers couldn't be compared */
2837  /* numerically, do a string compare. */
2838  return this->stringValue()->comp(right);
2839  }
2840 
2841  // unfortunately, we need to perform any lostdigits checks before
2842  // handling any of the short cuts
2843  NumberDigits = number_digits();
2844 
2845  if (this->length > NumberDigits)
2846  {
2847  reportCondition(OREF_LOSTDIGITS, (RexxString *)this);
2848  }
2849  if (rightNumber->length > NumberDigits)
2850  {
2851  reportCondition(OREF_LOSTDIGITS, (RexxString *)rightNumber);
2852  }
2853 
2854  if (this->sign != rightNumber->sign) /* are numbers the same sign? */
2855  {
2856  /* no, this is easy */
2857  return(this->sign < rightNumber->sign) ? -1 : 1;
2858  }
2859  if (rightNumber->sign == 0) /* right one is zero? */
2860  {
2861  return this->sign; /* use this sign */
2862  }
2863  if (this->sign == 0) /* am I zero? */
2864  {
2865  return rightNumber->sign; /* return the right sign */
2866  }
2867  /* set smaller exponent */
2868  MinExp = (rightNumber->exp < this->exp)? rightNumber->exp : this->exp;
2869  aLexp = this->exp - MinExp; /* get adjusted left size */
2870  aRexp = rightNumber->exp - MinExp; /* get adjusted right size */
2871  aLlen = aLexp + this->length; /* get adjusted left size */
2872  aRlen = aRexp + rightNumber->length; /* get adjusted right size */
2873  NumberDigits = number_fuzzydigits(); /* get precision for comparisons. */
2874  /* can we do a fast exit? */
2875  if (aLlen <= NumberDigits && aRlen <= NumberDigits)
2876  {
2877  /* longer number is the winner */
2878  if (aLlen > aRlen) /* left longer? */
2879  {
2880  return this->sign; /* use left sign */
2881  }
2882  else if (aRlen > aLlen) /* right longer? */
2883  {
2884  return -this->sign; /* use inverse of the sign */
2885  }
2886  else
2887  {
2888  /* actual lengths the same? */
2889  if (this->length == rightNumber->length)
2890  {
2891  /* return the comparison result */
2892  /* adjusted by the sign value */
2893  return memcmp(this->number, rightNumber->number, this->length) * this->sign;
2894  }
2895  /* right one shorter? */
2896  else if (this->length > rightNumber->length)
2897  {
2898  /* compare for shorter length */
2899  rc = memcmp(this->number, rightNumber->number, rightNumber->length) * this->sign;
2900  if (rc == 0)
2901  { /* equal for that length? */
2902  /* point to the remainder part */
2903  scan = this->number + rightNumber->length;
2904  /* get the remainder length */
2905  aRlen = this->length - rightNumber->length;
2906  while (aRlen--)
2907  { /* scan the remainder */
2908  if (*scan++ != 0) /* found a non-zero one? */
2909  {
2910  return this->sign; /* left side is greater */
2911  }
2912  }
2913  return 0; /* these are equal */
2914  }
2915  return rc; /* return compare result */
2916  }
2917  else
2918  { /* left one is shorter */
2919  /* compare for shorter length */
2920  rc = memcmp(this->number, rightNumber->number, this->length) * this->sign;
2921  if (rc == 0)
2922  { /* equal for that length? */
2923  /* point to the remainder part */
2924  scan = rightNumber->number + this->length;
2925  /* get the remainder length */
2926  aRlen = rightNumber->length - this->length;
2927  while (aRlen--)
2928  { /* scan the remainder */
2929  if (*scan++ != 0) /* found a non-zero one? */
2930  {
2931  return -this->sign; /* right side is greater */
2932  }
2933  }
2934  return 0; /* these are equal */
2935  }
2936  return rc; /* return compare result */
2937  }
2938  }
2939  }
2940  else
2941  { /* need to subtract these */
2942  /* call addsub to do computation */
2943  rightNumber = this->addSub(rightNumber, OT_MINUS, number_fuzzydigits());
2944  return rightNumber->sign; /* compare result is subtract sign */
2945  }
2946 }
2947 
2949 /******************************************************************************/
2950 /* Function: non-strict "=" operator */
2951 /******************************************************************************/
2952 {
2953  if (other == TheNilObject) // all conditionals return .false when compared to .nil
2954  {
2955  return TheFalseObject;
2956  }
2957  // return (this->comp(other) == 0) ? TheTrueObject : TheFalseObject;
2958  RexxInteger *alternativeResult = OREF_NULL;
2959  wholenumber_t result = this->comp(other, OREF_EQUAL_RIGHT, &alternativeResult);
2960  if (alternativeResult != OREF_NULL) return alternativeResult;
2961  return (result == 0) ? TheTrueObject : TheFalseObject;
2962 }
2963 
2965 /******************************************************************************/
2966 /* Function: non-strict "\=" operator */
2967 /******************************************************************************/
2968 {
2969  if (other == TheNilObject) // all conditionals return .false when compared to .nil
2970  {
2971  return TheTrueObject;
2972  }
2973  // return (this->comp(other) != 0) ? TheTrueObject : TheFalseObject;
2974  RexxInteger *alternativeResult = OREF_NULL;
2975  wholenumber_t result = this->comp(other, OREF_BACKSLASH_EQUAL_RIGHT, &alternativeResult);
2976  if (alternativeResult != OREF_NULL) return alternativeResult;
2977  return (result != 0) ? TheTrueObject : TheFalseObject;
2978 }
2979 
2981 /******************************************************************************/
2982 /* Function: non-strict ">" operator */
2983 /******************************************************************************/
2984 {
2985  if (other == TheNilObject) // all conditionals return .false when compared to .nil
2986  {
2987  return TheFalseObject;
2988  }
2989  // return (this->comp(other) > 0) ? TheTrueObject : TheFalseObject;
2990  RexxInteger *alternativeResult = OREF_NULL;
2991  wholenumber_t result = this->comp(other, OREF_GREATERTHAN_RIGHT, &alternativeResult);
2992  if (alternativeResult != OREF_NULL) return alternativeResult;
2993  return (result > 0) ? TheTrueObject : TheFalseObject;
2994 }
2995 
2997 /******************************************************************************/
2998 /* Function: non-strict "<" operator */
2999 /******************************************************************************/
3000 {
3001  if (other == TheNilObject) // all conditionals return .false when compared to .nil
3002  {
3003  return TheFalseObject;
3004  }
3005  // return (this->comp(other) < 0) ? TheTrueObject : TheFalseObject;
3006  RexxInteger *alternativeResult = OREF_NULL;
3007  wholenumber_t result = this->comp(other, OREF_LESSTHAN_RIGHT, &alternativeResult);
3008  if (alternativeResult != OREF_NULL) return alternativeResult;
3009  return (result < 0) ? TheTrueObject : TheFalseObject;
3010 }
3011 
3013 /******************************************************************************/
3014 /* Function: non-strict ">=" operator */
3015 /******************************************************************************/
3016 {
3017  if (other == TheNilObject) // all conditionals return .false when compared to .nil
3018  {
3019  return TheFalseObject;
3020  }
3021  // return (this->comp(other) >= 0) ? TheTrueObject : TheFalseObject;
3022  RexxInteger *alternativeResult = OREF_NULL;
3023  wholenumber_t result = this->comp(other, OREF_GREATERTHAN_EQUAL_RIGHT, &alternativeResult);
3024  if (alternativeResult != OREF_NULL) return alternativeResult;
3025  return (result >= 0) ? TheTrueObject : TheFalseObject;
3026 }
3027 
3029 /******************************************************************************/
3030 /* Function: non-strict "<=" operator */
3031 /******************************************************************************/
3032 {
3033  if (other == TheNilObject) // all conditionals return .false when compared to .nil
3034  {
3035  return TheFalseObject;
3036  }
3037  // return (this->comp(other) <= 0) ? TheTrueObject : TheFalseObject;
3038  RexxInteger *alternativeResult = OREF_NULL;
3039  wholenumber_t result = this->comp(other, OREF_LESSTHAN_EQUAL_RIGHT, &alternativeResult);
3040  if (alternativeResult != OREF_NULL) return alternativeResult;
3041  return (result <= 0) ? TheTrueObject : TheFalseObject;
3042 }
3043 
3044 
3045 /**
3046  * Exported version of the HASHCODE method for retrieving the
3047  * object's hash.
3048  *
3049  * @return A string version of the hash (generally holds binary characters).
3050  */
3052 {
3053  // get the hash value, which is actually derived from the integer string value
3054  HashCode h = this->hash();
3055  return new_string((const char *)&h, sizeof(HashCode));
3056 }
3057 
3059 /******************************************************************************/
3060 /* Function: Perform the primitive level "==" compare, including the hash */
3061 /* value processing. */
3062 /******************************************************************************/
3063 {
3064  if (other == TheNilObject) // all conditionals return .false when compared to .nil
3065  {
3066  return TheFalseObject;
3067  }
3068  return (this->strictComp(other) == 0) ? TheTrueObject : TheFalseObject;
3069 }
3070 
3072 /******************************************************************************/
3073 /* Function: Strict inequality operation */
3074 /******************************************************************************/
3075 {
3076  if (other == TheNilObject) // all conditionals return .false when compared to .nil
3077  {
3078  return TheTrueObject;
3079  }
3080  return (this->strictComp(other) != 0) ? TheTrueObject : TheFalseObject;
3081 }
3082 
3083 
3085 /******************************************************************************/
3086 /* Function: strict ">>" operator */
3087 /******************************************************************************/
3088 {
3089  if (other == TheNilObject) // all conditionals return .false when compared to .nil
3090  {
3091  return TheFalseObject;
3092  }
3093  return (this->strictComp(other) > 0) ? TheTrueObject : TheFalseObject;
3094 }
3095 
3097 /******************************************************************************/
3098 /* Function: strict "<<" operator */
3099 /******************************************************************************/
3100 {
3101  if (other == TheNilObject) // all conditionals return .false when compared to .nil
3102  {
3103  return TheFalseObject;
3104  }
3105  return (this->strictComp(other) < 0) ? TheTrueObject : TheFalseObject;
3106 }
3107 
3109 /******************************************************************************/
3110 /* Function: strict ">>=" operator */
3111 /******************************************************************************/
3112 {
3113  if (other == TheNilObject) // all conditionals return .false when compared to .nil
3114  {
3115  return TheFalseObject;
3116  }
3117  return (this->strictComp(other) >= 0) ? TheTrueObject : TheFalseObject;
3118 }
3119 
3121 /******************************************************************************/
3122 /* Function: strict "<<=" operator */
3123 /******************************************************************************/
3124 {
3125  if (other == TheNilObject) // all conditionals return .false when compared to .nil
3126  {
3127  return TheFalseObject;
3128  }
3129  return (this->strictComp(other) <= 0) ? TheTrueObject : TheFalseObject;
3130 }
3131 
3133 /********************************************************************/
3134 /* Function: Add two number strings */
3135 /********************************************************************/
3136 {
3137  if (right != OREF_NULL)
3138  { /* Is this a dyadic operation? */
3139  /* get a numberstring object from */
3140  /*right */
3141  RexxNumberString *rightNumber = right->numberString();
3142  if (rightNumber == OREF_NULL) /* is the operand numeric? */
3143  {
3144  // Try an alternative operator
3145  ProtectedObject result;
3146  RexxObject *self = this;
3147  RexxObject *args[1];
3148  args[0] = self; // positional argument
3149  bool alternativeResult = right->messageSend(OREF_PLUS_RIGHT, args, 1, 0, result, false);
3150  if (alternativeResult && (RexxObject *)result != OREF_NULL) return (RexxNumberString *)(RexxObject *)result;
3151  /* nope, this is an error */
3153  }
3154  /* call addsub to do computation */
3155  return this->addSub(rightNumber, OT_PLUS, number_digits());
3156  }
3157  else
3158  {
3159  /* need to format under different */
3160  /* precision? */
3161  if (this->stringObject != OREF_NULL || this->NumDigits != number_digits() ||
3163  (number_form() == Numerics::FORM_ENGINEERING && this->NumFlags&NumFormScientific))
3164  {
3165  /* need to copy and reformat */
3167  }
3168  else
3169  {
3170  return this; /* just return the same value */
3171  }
3172  }
3173 }
3174 
3176 /********************************************************************/
3177 /* Function: Subtraction between two numbers */
3178 /********************************************************************/
3179 {
3180  if (right != OREF_NULL)
3181  { /* Is this a dyadic operation? */
3182  /* get a numberstring object from */
3183  /*right */
3184  RexxNumberString *rightNumber = right->numberString();
3185  if (rightNumber == OREF_NULL) /* is the operand numeric? */
3186  {
3187  // Try an alternative operator
3188  ProtectedObject result;
3189  RexxObject *self = this;
3190  RexxObject *args[1];
3191  args[0] = self; // positional argument
3192  bool alternativeResult = right->messageSend(OREF_SUBTRACT_RIGHT, args, 1, 0, result, false);
3193  if (alternativeResult && (RexxObject *)result != OREF_NULL) return (RexxNumberString *)(RexxObject *)result;
3194  /* nope, this is an error */
3196  }
3197  /* call addsub to do computation */
3198  return this->addSub(rightNumber, OT_MINUS, number_digits());
3199  }
3200  else
3201  {
3202  /* need to copy and reformat */
3204  /* invert the sign of our copy. */
3205  result->sign = -(result->sign);
3206  return result; /* return addition result */
3207  }
3208 }
3209 
3211 /********************************************************************/
3212 /* Function: Multiply two numbers */
3213 /********************************************************************/
3214 {
3215  requiredArgument(right, OREF_positional, ARG_ONE); /* must have an argument */
3216  /* get a numberstring object from */
3217  /*right */
3218  RexxNumberString *rightNumber = right->numberString();
3219  if (rightNumber == OREF_NULL) /* is the operand numeric? */
3220  {
3221  // Try an alternative operator
3222  ProtectedObject result;
3223  RexxObject *self = this;
3224  RexxObject *args[1];
3225  args[0] = self; // positional argument
3226  bool alternativeResult = right->messageSend(OREF_MULTIPLY_RIGHT, args, 1, 0, result, false);
3227  if (alternativeResult && (RexxObject *)result != OREF_NULL) return (RexxNumberString *)(RexxObject *)result;
3228  /* nope, this is an error */
3230  }
3231  return this->Multiply(rightNumber); /* go do the multiply */
3232 }
3233 
3235 /********************************************************************/
3236 /* Function: Divide two numbers */
3237 /********************************************************************/
3238 {
3239  requiredArgument(right, OREF_positional, ARG_ONE); /* must have an argument */
3240 
3241  /* get a numberstring object from */
3242  /*right */
3243  RexxNumberString *rightNumber = right->numberString();
3244  if (rightNumber == OREF_NULL) /* is the operand numeric? */
3245  {
3246  // Try an alternative operator
3247  ProtectedObject result;
3248  RexxObject *self = this;
3249  RexxObject *args[1];
3250  args[0] = self; // positional argument
3251  bool alternativeResult = right->messageSend(OREF_DIVIDE_RIGHT, args, 1, 0, result, false);
3252  if (alternativeResult && (RexxObject *)result != OREF_NULL) return (RexxNumberString *)(RexxObject *)result;
3253  /* nope, this is an error */
3255  }
3256  /* go do the division */
3257  return this->Division(rightNumber, OT_DIVIDE);
3258 }
3259 
3261 /********************************************************************/
3262 /* Function: Integer division between two numbers */
3263 /********************************************************************/
3264 {
3265  requiredArgument(right, OREF_positional, ARG_ONE); /* must have an argument */
3266  /* get a numberstring object from */
3267  /*right */
3268  RexxNumberString *rightNumber = right->numberString();
3269  if (rightNumber == OREF_NULL) /* is the operand numeric? */
3270  {
3271  // Try an alternative operator
3272  ProtectedObject result;
3273  RexxObject *self = this;
3274  RexxObject *args[1];
3275  args[0] = self; // positional argument
3276  bool alternativeResult = right->messageSend(OREF_INTDIV_RIGHT, args, 1, 0, result, false);
3277  if (alternativeResult && (RexxObject *)result != OREF_NULL) return (RexxNumberString *)(RexxObject *)result;
3278  /* nope, this is an error */
3280  }
3281  /* go do the division */
3282  return this->Division(rightNumber, OT_INT_DIVIDE);
3283 }
3284 
3286 /********************************************************************/
3287 /* Function: Remainder division between two numbers */
3288 /********************************************************************/
3289 {
3290  requiredArgument(right, OREF_positional, ARG_ONE); /* must have an argument */
3291 
3292  /* get a numberstring object from */
3293  /*right */
3294  RexxNumberString *rightNumber = right->numberString();
3295  if (rightNumber == OREF_NULL) /* is the operand numeric? */
3296  {
3297  // Try an alternative operator
3298  ProtectedObject result;
3299  RexxObject *self = this;
3300  RexxObject *args[1];
3301  args[0] = self; // positional argument
3302  bool alternativeResult = right->messageSend(OREF_REMAINDER_RIGHT, args, 1, 0, result, false);
3303  if (alternativeResult && (RexxObject *)result != OREF_NULL) return (RexxNumberString *)(RexxObject *)result;
3304  /* nope, this is an error */
3306  }
3307  /* go do the division */
3308  return this->Division(rightNumber, OT_REMAINDER);
3309 }
3310 
3312 /********************************************************************/
3313 /* Function: Return the absolute value of a number */
3314 /********************************************************************/
3315 {
3316  RexxNumberString *NewNumber = this->clone(); /* copy the number */
3317  /* inherit the current numeric settings and perform rounding, if */
3318  /* necessary */
3319  NewNumber->setupNumber();
3320  /* switch the sign */
3321  NewNumber->sign = (short)::abs(NewNumber->sign);
3322  return NewNumber; /* and return */
3323 }
3324 
3326 /********************************************************************/
3327 /* Function: Return the sign of a number */
3328 /********************************************************************/
3329 {
3330  RexxNumberString *NewNumber = this->clone(); /* copy the number */
3331  /* inherit the current numeric settings and perform rounding, if */
3332  /* necessary */
3333  NewNumber->setupNumber();
3334  return new_integer(NewNumber->sign); /* just return the sign value */
3335 }
3336 
3338 /********************************************************************/
3339 /* Function: Logical not of a number string value */
3340 /********************************************************************/
3341 {
3342  return this->stringValue()->notOp();
3343 }
3344 
3346 /********************************************************************/
3347 /* Function: Polymorphic NOT operator method */
3348 /********************************************************************/
3349 {
3350  return this->stringValue()->notOp();
3351 }
3352 
3354  RexxObject **args, /* array of comparison values */
3355  size_t argCount, /* count of arguments */
3356  size_t named_argCount)
3357 /********************************************************************/
3358 /* Function: Process MAX function */
3359 /********************************************************************/
3360 {
3361  return this->maxMin(args, argCount, named_argCount, OT_MAX);
3362 }
3363 
3365  RexxObject **args, /* array of comparison values */
3366  size_t argCount, /* count of arguments */
3367  size_t named_argCount)
3368 /********************************************************************/
3369 /* Function: Process the MIN function */
3370 /********************************************************************/
3371 {
3372  return this->maxMin(args, argCount, named_argCount, OT_MIN);
3373 }
3374 
3376 /******************************************************************************/
3377 /* This method determines if the formatted numberstring is s true integer */
3378 /* string. That is, its not of the form 1.00E3 but 10000 */
3379 /******************************************************************************/
3380 {
3381  /* first convert number to formatted */
3382  /* objetc, "make it a string" */
3383  /* now call string to check for */
3384  return this->stringValue()->isInteger();
3385 }
3386 
3387 /*********************************************************************/
3388 /* Function: Round up a number as a result of the chopping*/
3389 /* digits off of the number during init. */
3390 /*********************************************************************/
3391 void RexxNumberString::roundUp(int MSDigit)
3392 {
3393  int carry;
3394  char *InPtr;
3395  char ch;
3396  /* Did we chop off digits and is it */
3397  /* greater/equal to 5, rounding? */
3398  if (MSDigit >= ch_FIVE && MSDigit <= ch_NINE)
3399  {
3400  /* yes, we have to round up digits */
3401 
3402  carry = 1; /* indicate we have a carry. */
3403  /* point to last digit. */
3404  InPtr = this->number + this->length - 1;
3405 
3406  /* all digits and still have a carry */
3407  while ((InPtr >= this->number) && carry)
3408  {
3409  if (*InPtr == 9) /* Is this digit a 9? */
3410  {
3411  ch = 0; /* make digit 0, still have carry */
3412  }
3413  else
3414  {
3415  ch = *InPtr + 1; /* Not nine, just add one to digit. */
3416  carry = 0; /* No more carry. */
3417  }
3418  *InPtr-- = ch; /* replace digit with new value. */
3419  } /* All done rounding. */
3420 
3421  if (carry)
3422  { /* Do we still have a carry? */
3423  /* yes, carry rippled all the way */
3424  *this->number = 1; /* set 1st digit to a 1. */
3425  this->exp += 1; /* increment exponent by one. */
3426  }
3427  }
3428 }
3429 
3431  RexxObject *_length) /* result length */
3432 /******************************************************************************/
3433 /* Function: Convert a valid numberstring to a hex string. */
3434 /******************************************************************************/
3435 {
3436  /* forward to the formatting routine */
3437  return this->d2xD2c(_length, false);
3438 }
3439 
3441  RexxObject *_length) /* result length */
3442 /******************************************************************************/
3443 /* Function: Convert a valid numberstring to a character string. */
3444 /******************************************************************************/
3445 {
3446  /* forward to the formatting routine */
3447  return this->d2xD2c(_length, true);
3448 }
3449 
3450 
3452  RexxActivation *context, /* current activation context */
3453  RexxExpressionStack *stack ) /* evaluation stack */
3454 /******************************************************************************/
3455 /* Function: Polymorphic method that makes numberstring a polymorphic */
3456 /* expression term for literals */
3457 /******************************************************************************/
3458 {
3459  stack->push(this); /* place on the evaluation stack */
3460  /* trace if necessary */
3461  context->traceIntermediate(this, TRACE_PREFIX_LITERAL);
3462  return this; /* also return the result */
3463 }
3464 
3466  RexxObject *_length, /* result length */
3467  bool type ) /* D2C or D2X flag */
3468 /******************************************************************************/
3469 /* Function: Convert a valid numberstring to a hex or character string. */
3470 /******************************************************************************/
3471 
3472 {
3473  char PadChar; /* needed padding character */
3474  stringsize_t ResultSize; /* size of result string */
3475  size_t HexLength; /* length of hex characters */
3476  size_t BufferLength; /* length of the buffer */
3477  char * Scan; /* scan pointer */
3478  char * HighDigit; /* highest digit location */
3479  char * Accumulator; /* accumulator pointer */
3480  char * TempPtr; /* temporary pointer value */
3481  size_t PadSize; /* needed padding */
3482  size_t CurrentDigits; /* current digits setting */
3483  size_t TargetLength; /* length of current number */
3484  RexxBuffer *Target; /* formatted number */
3485  RexxString *Retval; /* returned result */
3486 
3487 
3488  /* get the target length */
3489  ResultSize = optionalLengthArgument(_length, SIZE_MAX, ARG_ONE);
3490  CurrentDigits = number_digits(); /* get the current digits setting */
3491  TargetLength = this->length; /* copy the length */
3492  /* too big to process? */
3493  if (this->exp + this->length > CurrentDigits)
3494  {
3495  if (type == true) /* d2c form? */
3496  {
3497  /* use that message */
3499  }
3500  else /* use d2x form */
3501  {
3503  }
3504  }
3505  else if (this->exp < 0)
3506  { /* may have trailing zeros */
3507  /* point to the decimal part */
3508  TempPtr = this->number + this->length + this->exp;
3509  HexLength = -this->exp; /* get the length to check */
3510  /* point to the rounding digit */
3511  HighDigit = this->number + CurrentDigits;
3512  /* while more decimals */
3513  while (HexLength -- && TempPtr <= HighDigit)
3514  {
3515  if (*TempPtr != 0)
3516  { /* non-zero decimal? */
3517  /* this may be non-significant */
3518  if (TargetLength > CurrentDigits)
3519  {
3520  /* this the "rounding" digit? */
3521  if (TempPtr == HighDigit && *TempPtr < 5)
3522  {
3523  break; /* insignificant digit found */
3524  }
3525  }
3526  if (type == true) /* d2c form? */
3527  {
3528  /* use that message */
3530  }
3531  else /* use d2x form */
3532  {
3534  }
3535  }
3536  TempPtr++; /* step the pointer */
3537  }
3538  /* adjust the length */
3539  TargetLength = this->length + this->exp;
3540  }
3541  /* negative without a size */
3542  if (this->sign < 0 && ResultSize == SIZE_MAX)
3543  {
3544  /* this is an error */
3546  }
3547  if (ResultSize == SIZE_MAX) /* using default size? */
3548  {
3549  /* allocate buffer based on digits */
3550  BufferLength = CurrentDigits + OVERFLOWSPACE;
3551  }
3552  else if (type == true)
3553  { /* X2C function? */
3554  if (ResultSize * 2 < CurrentDigits)/* smaller than digits setting? */
3555  {
3556  /* allocate buffer based on digits */
3557  BufferLength = CurrentDigits + OVERFLOWSPACE;
3558  }
3559  else /* allocate a large buffer */
3560  {
3561  BufferLength = (ResultSize * 2) + OVERFLOWSPACE;
3562  }
3563  }
3564  else
3565  { /* D2X function */
3566  if (ResultSize < CurrentDigits) /* smaller than digits setting? */
3567  {
3568  /* allocate buffer based on digits */
3569  BufferLength = CurrentDigits + OVERFLOWSPACE;
3570  }
3571  else /* allocate a large buffer */
3572  {
3573  BufferLength = ResultSize + OVERFLOWSPACE;
3574  }
3575  }
3576  Target = new_buffer(BufferLength); /* set up format buffer */
3577  Scan = this->number; /* point to first digit */
3578  /* set accumulator pointer */
3579  Accumulator = Target->getData() + BufferLength - 2;
3580  HighDigit = Accumulator - 1; /* set initial high position */
3581  /* clear the accumulator */
3582  memset(Target->getData(), '\0', BufferLength);
3583  while (TargetLength--)
3584  { /* while more digits */
3585  /* add next digit */
3586  HighDigit = addToBaseSixteen(*Scan++, Accumulator, HighDigit);
3587  if (TargetLength != 0) /* not last digit? */
3588  {
3589  /* do another multiply */
3590  HighDigit = multiplyBaseSixteen(Accumulator, HighDigit);
3591  }
3592  }
3593  if (this->exp > 0)
3594  { /* have extra digits to worry about? */
3595  /* do another multiply */
3596  HighDigit = multiplyBaseSixteen(Accumulator, HighDigit);
3597  TargetLength = this->exp; /* copy the exponent */
3598  while (TargetLength--)
3599  { /* while more digits */
3600  /* add next zero digit */
3601  HighDigit = addToBaseSixteen('\0', Accumulator, HighDigit);
3602  if (TargetLength != 0) /* not last digit? */
3603  {
3604  /* do the multiply */
3605  HighDigit = multiplyBaseSixteen(Accumulator, HighDigit);
3606  }
3607  }
3608  }
3609  HexLength = Accumulator - HighDigit; /* get accumulator length */
3610  if (this->sign < 0)
3611  { /* have a negative number? */
3612  /* take twos complement */
3613  PadChar = 'F'; /* pad negatives with foxes */
3614  Scan = Accumulator; /* point to last digit */
3615  while (!*Scan) /* handle any borrows */
3616  {
3617  *Scan-- = 0xf; /* make digit a 15 */
3618  }
3619  *Scan = *Scan - 1; /* subtract the 1 */
3620  Scan = Accumulator; /* start at first digit again */
3621  while (Scan > HighDigit)
3622  { /* invert all the bits */
3623  /* one digit at a time */
3624  *Scan = (char)(*Scan ^ (unsigned)0x0f);
3625  Scan--; /* step to next digit */
3626  }
3627  }
3628  else
3629  {
3630  PadChar = '0'; /* pad positives with zero */
3631  }
3632  /* now make number printable */
3633  Scan = Accumulator; /* start at first digit again */
3634  while (Scan > HighDigit)
3635  { /* convert all the nibbles */
3636  *Scan = IntToHexDigit(*Scan); /* one digit at a time */
3637  Scan--; /* step to next digit */
3638  }
3639  Scan = HighDigit + 1; /* point to first digit */
3640 
3641  if (type == false)
3642  { /* d2x function ? */
3643  if (ResultSize == SIZE_MAX) /* using default length? */
3644  {
3645  ResultSize = HexLength; /* use actual data length */
3646  }
3647  }
3648  else
3649  { /* d2c function */
3650  if (ResultSize == SIZE_MAX) /* using default length? */
3651  {
3652  ResultSize = HexLength; /* use actual data length */
3653  }
3654  else
3655  {
3656  ResultSize += ResultSize; /* double the size */
3657  }
3658  }
3659  if (ResultSize < HexLength)
3660  { /* need to truncate? */
3661  PadSize = 0; /* no Padding */
3662  Scan += HexLength - ResultSize; /* step the pointer */
3663  HexLength = ResultSize; /* adjust number of digits */
3664  }
3665  else /* possible padding */
3666  {
3667  PadSize = ResultSize - HexLength; /* calculate needed padding */
3668  }
3669  if (PadSize)
3670  { /* padding needed? */
3671  Scan -= PadSize; /* step back the pointer */
3672  memset(Scan, PadChar, PadSize); /* pad in front */
3673  }
3674  if (type == true) /* need to pack? */
3675  {
3676  Retval = StringUtil::packHex(Scan, ResultSize);/* yes, pack to character */
3677  }
3678  else
3679  {
3680  /* allocate result string */
3681  Retval = new_string(Scan, ResultSize);
3682  }
3683  return Retval; /* return proper result */
3684 }
3685 
3686 
3688  RexxActivation *context) /* current activation context */
3689 /******************************************************************************/
3690 /* Function: Polymorphic get_value function used with expression terms */
3691 /******************************************************************************/
3692 {
3693  return (RexxObject *)this; /* just return this value */
3694 }
3695 
3696 
3698  RexxVariableDictionary *context) /* current activation context */
3699 /******************************************************************************/
3700 /* Function: Polymorphic get_value function used with expression terms */
3701 /******************************************************************************/
3702 {
3703  return (RexxObject *)this; /* just return this value */
3704 }
3705 
3706 
3708  RexxActivation *context) /* current activation context */
3709 /******************************************************************************/
3710 /* Function: Polymorphic get_value function used with expression terms */
3711 /******************************************************************************/
3712 {
3713  return (RexxObject *)this; /* just return this value */
3714 }
3715 
3716 
3718  RexxVariableDictionary *context) /* current activation context */
3719 /******************************************************************************/
3720 /* Function: Polymorphic get_value function used with expression terms */
3721 /******************************************************************************/
3722 {
3723  return (RexxObject *)this; /* just return this value */
3724 }
3725 
3727 /******************************************************************************/
3728 /* Function: Return the String class object for numberstring instances */
3729 /******************************************************************************/
3730 {
3731  /* just return class from behaviour */
3732  return TheStringClass;
3733 }
3734 
3735 void *RexxNumberString::operator new(size_t size, size_t length)
3736 /******************************************************************************/
3737 /* Function: Create a new NumberString object */
3738 /******************************************************************************/
3739 {
3740  RexxNumberString *newNumber = (RexxNumberString *)new_object(size + length, T_NumberString);
3741  /* initialize the new object */
3742  newNumber->setHasNoReferences(); /* Let GC know no to bother with LIVE*/
3743  return newNumber; /* return the new numberstring */
3744 }
3745 
3747 /******************************************************************************/
3748 /* Function: Create a new number string object */
3749 /******************************************************************************/
3750 {
3751  RexxNumberString *newNumber;
3752 
3753  if (number == NULL)
3754  { /* asking for a dummy string? */
3755  /* allocate a new string */
3756  newNumber = new (len) RexxNumberString (len);
3757  /* make it a zero value */
3758  newNumber->setZero();
3759  return newNumber; /* return this now */
3760  }
3761  /* scan the string 1st to see if its */
3762  /*valid */
3763  if (numberStringScan(number, len))
3764  {
3765  newNumber = OREF_NULL; /* not a valid number, get out now. */
3766  }
3767  else
3768  {
3769  /* looks to be valid. get a new */
3770  /* format it */
3771  newNumber = new (len) RexxNumberString (len);
3772  /* now see if the data actually is */
3773  /* a number and fill in actual data */
3774  /* NOTE: even though a scan has been */
3775  /* we still may not have a thorough*/
3776  /* enough check. */
3777  if (newNumber->format(number, len))
3778  {
3779  /* number didn't convert, */
3780  newNumber = OREF_NULL;
3781  }
3782  }
3783  return newNumber;
3784 }
3785 
3787 /******************************************************************************/
3788 /* Function: Create a numberstring object from a floating point number */
3789 /******************************************************************************/
3790 {
3791  return newInstanceFromDouble((double)num, number_digits());
3792 }
3793 
3795 /******************************************************************************/
3796 /* Function: Create a NumberString from a double value */
3797 /******************************************************************************/
3798 {
3800 }
3801 
3802 
3803 /**
3804  * Create a numberstring from a double value using a given
3805  * formatting precision.
3806  *
3807  * @param number The double number to convert
3808  * @param precision The precision to apply to the result.
3809  *
3810  * @return The formatted number, as a numberstring value.
3811  */
3813 {
3814  // make a nan value a string value
3815  if (isnan(number))
3816  {
3817  return (RexxNumberString *)new_string("nan");
3818  }
3819  else if (number == +HUGE_VAL)
3820  {
3821  return (RexxNumberString *)new_string("+infinity");
3822  }
3823  else if (number == -HUGE_VAL)
3824  {
3825  return (RexxNumberString *)new_string("-infinity");
3826  }
3827 
3828  RexxNumberString *result;
3829  size_t resultLen;
3830  /* Max length of double str is */
3831  /* 22, make 30 just to be safe */
3832  char doubleStr[30];
3833  /* get double as a string value. */
3834  /* Use digits as precision. */
3835  snprintf(doubleStr, sizeof doubleStr, "%.*g", (int)(precision + 2), number);
3836  resultLen = strlen(doubleStr); /* Compute length of floatString */
3837  /* Create new NumberString */
3838  result = new (resultLen) RexxNumberString (resultLen, precision);
3839  /* now format as a numberstring */
3840  result->format(doubleStr, resultLen);
3841  return result->prepareNumber(precision, ROUND);
3842 }
3843 
3845 /******************************************************************************/
3846 /* Function: Create a NumberString object from a wholenumber_t value */
3847 /******************************************************************************/
3848 {
3849  // the size of the integer depends on the platform, 32-bit or 64-bit.
3850  // ARGUMENT_DIGITS ensures the correct value
3852  newNumber->formatNumber(integer); /* format the number */
3853  return newNumber;
3854 }
3855 
3857 /******************************************************************************/
3858 /* Function: Create a NumberString object from a size_t value */
3859 /******************************************************************************/
3860 {
3861  // the size of the integer depends on the platform, 32-bit or 64-bit.
3862  // ARGUMENT_DIGITS ensures the correct value
3864  newNumber->formatUnsignedNumber(integer); /* format the number */
3865  return newNumber;
3866 }
3867 
3868 
3870 /******************************************************************************/
3871 /* Function: Create a NumberString object from a signed 64 bit number */
3872 /******************************************************************************/
3873 {
3874  // this give us space for entire binary range of the int64_t number.
3876  newNumber->formatInt64(integer); /* format the number */
3877  return newNumber;
3878 }
3879 
3880 
3882 /******************************************************************************/
3883 /* Function: Create a NumberString object from an unsigned 64 bit number */
3884 /******************************************************************************/
3885 {
3886  // this give us space for entire binary range of the uint64_t number.
3888  newNumber->formatUnsignedInt64(integer); /* format the number */
3889  return newNumber;
3890 }
3891 
3892  /* numberstring operator methods */
3894 {
3895  NULL, /* first entry not used */
3896  (PCPPM)&RexxNumberString::plus, // "+"
3897  (PCPPM)&RexxNumberString::minus, // "-"
3902  (PCPPM)&RexxNumberString::power, // "**"
3903  (PCPPM)&RexxNumberString::concat, // "" should be ::abuttal
3904  (PCPPM)&RexxNumberString::concat, // "||"
3906  (PCPPM)&RexxNumberString::equal, // "="
3909  (PCPPM)&RexxNumberString::isLessOrEqual, // ">" should be ::isBackslashGreaterThan
3911  (PCPPM)&RexxNumberString::isGreaterOrEqual, // "<" should be ::isBackslashLessThan
3917  (PCPPM)&RexxNumberString::strictLessOrEqual, // ">>" should be ::strictBackslashGreaterThan
3919  (PCPPM)&RexxNumberString::strictGreaterOrEqual, // "<<" should be ::strictBackslashLessThan
3922  (PCPPM)&RexxNumberString::notEqual, // "<>" should be ::lessThanGreaterThan
3923  (PCPPM)&RexxNumberString::notEqual, // "><" should be ::greaterThanLessThan
3924  (PCPPM)&RexxNumberString::andOp, // "&"
3925  (PCPPM)&RexxNumberString::orOp, // "|"
3926  (PCPPM)&RexxNumberString::xorOp, // "&&"
3928 };
void reportCondition(RexxString *condition, RexxString *description)
void reportException(wholenumber_t error)
RexxBuffer * new_buffer(size_t s)
@ T_NumberString
@ ch_PERIOD
Definition: Encodings.hpp:44
RexxInteger * new_integer(wholenumber_t v)
bool numberStringScan(const char *number, size_t length)
void fill_digits(char *outPtr, const char *number, size_t count)
#define ch_ONE
#define ch_FIVE
#define SetNumberStringZero()
#define ch_ZERO
#define ch_TAB
#define ch_PLUS
#define ch_NINE
#define ch_BLANK
#define ch_MINUS
#define NumFormScientific
#define OVERFLOWSPACE
#define OT_PLUS
#define OT_REMAINDER
#define OT_MIN
#define OT_MINUS
#define OT_INT_DIVIDE
#define OT_MAX
#define OT_DIVIDE
#define ROUND
bool number_form()
Definition: Numerics.hpp:149
size_t number_digits()
Definition: Numerics.hpp:147
size_t number_fuzzydigits()
Definition: Numerics.hpp:150
RexxObject *(RexxObject::* PCPPM)()
size_t HashCode
Definition: ObjectClass.hpp:79
@ TRACE_PREFIX_LITERAL
#define OREF_NULL
Definition: RexxCore.h:61
const int ARG_FOUR
Definition: RexxCore.h:86
#define IntegerOne
Definition: RexxCore.h:200
#define TheStringClass
Definition: RexxCore.h:169
const int ARG_THREE
Definition: RexxCore.h:85
#define OrefSet(o, r, v)
Definition: RexxCore.h:101
#define TheTrueObject
Definition: RexxCore.h:196
const int ARG_TWO
Definition: RexxCore.h:84
size_t optionalNonNegative(RexxObject *o, size_t d, RexxString *kind, size_t p)
Definition: RexxCore.h:382
size_t optionalLengthArgument(RexxObject *o, size_t d, size_t p)
Definition: RexxCore.h:355
#define TheNilObject
Definition: RexxCore.h:191
#define TheFalseObject
Definition: RexxCore.h:195
const int ARG_ONE
Definition: RexxCore.h:83
#define IntegerZero
Definition: RexxCore.h:199
void requiredArgument(RexxObject *object, RexxString *kind, size_t position)
Definition: RexxCore.h:303
#define IntegerMinusOne
Definition: RexxCore.h:209
#define Error_Logical_value_method
#define Error_Incorrect_method_d2x
#define Error_No_result_object_message
#define Error_Incorrect_method_exponent_oversize
#define Error_Overflow_expoverflow
#define Error_Incorrect_method_d2c
#define Error_Incorrect_method_d2xd2c
#define Error_Overflow_expunderflow
#define Error_Conversion_operator
#define Error_Incorrect_method_before_oversize
#define memory_mark(oref)
Definition: RexxMemory.hpp:450
RexxObject * new_object(size_t s)
Definition: RexxMemory.hpp:436
#define flatten_reference(oref, envel)
Definition: RexxMemory.hpp:498
#define CLASS_CREATE(name, id, className)
Definition: RexxMemory.hpp:503
#define memory_mark_general(oref)
Definition: RexxMemory.hpp:451
#define cleanUpFlatten
Definition: RexxMemory.hpp:484
#define setUpFlatten(type)
Definition: RexxMemory.hpp:478
RexxString * raw_string(stringsize_t l)
RexxString * new_string(const char *s, stringsize_t l)
char IntToHexDigit(int n)
ssize_t integer(RexxObject *obj, const char *errorMessage)
Definition: TextClass.cpp:289
size_t RexxEntry BufferLength(RexxThreadContext *c, RexxBufferObject b)
static const wholenumber_t MIN_EXPONENT
Definition: Numerics.hpp:65
static size_t formatStringSize(stringsize_t integer, char *dest)
Definition: Numerics.cpp:698
static const size_t DIGITS64
Definition: Numerics.hpp:75
static wholenumber_t abs(wholenumber_t n)
Definition: Numerics.hpp:115
static const wholenumber_t MAX_EXPONENT
Definition: Numerics.hpp:64
static wholenumber_t maxValueForDigits(size_t d)
Definition: Numerics.hpp:120
static wholenumber_t minVal(wholenumber_t n1, wholenumber_t n2)
Definition: Numerics.hpp:116
static const bool FORM_SCIENTIFIC
Definition: Numerics.hpp:76
static const bool FORM_ENGINEERING
Definition: Numerics.hpp:77
static size_t normalizeWholeNumber(wholenumber_t integer, char *dest)
Definition: Numerics.cpp:637
static const size_t ARGUMENT_DIGITS
Definition: Numerics.hpp:68
static size_t formatWholeNumber(wholenumber_t integer, char *dest)
Definition: Numerics.cpp:572
static const size_t DEFAULT_DIGITS
Definition: Numerics.hpp:66
void traceIntermediate(RexxObject *v, int p)
virtual char * getData()
void push(RexxObject *value)
RexxObject * clone()
void formatUnsignedInt64(uint64_t integer)
RexxInteger * strictGreaterThan(RexxObject *)
wholenumber_t comp(RexxObject *, RexxString *alternativeOperator=OREF_NULL, RexxInteger **alternativeOperatorResultPtr=NULL)
static RexxNumberString * newInstanceFromFloat(float)
RexxObject * xorOp(RexxObject *)
RexxInteger * isLessThan(RexxObject *)
void formatUnsignedNumber(size_t)
RexxInteger * strictEqual(RexxObject *)
void flatten(RexxEnvelope *)
RexxObject * truncInternal(size_t)
static RexxNumberString * newInstance(const char *, stringsize_t)
RexxNumberString * prepareNumber(size_t, bool)
RexxInteger * strictLessThan(RexxObject *)
RexxInteger * isGreaterThan(RexxObject *)
bool createUnsignedInt64Value(const char *thisnum, stringsize_t intlength, int carry, wholenumber_t exponent, uint64_t maxValue, uint64_t &result)
static RexxNumberString * newInstanceFromDouble(double)
bool createUnsignedValue(const char *thisnum, stringsize_t intlength, int carry, wholenumber_t exponent, uwholenumber_t maxValue, uwholenumber_t &result)
RexxString * concatBlank(RexxObject *)
RexxString * makeString()
RexxNumberString * multiply(RexxObject *)
RexxObject * roundInternal()
RexxObject * getRealValue(RexxActivation *)
RexxNumberString * minus(RexxObject *)
RexxString * primitiveMakeString()
RexxNumberString * Max(RexxObject **, size_t, size_t)
void formatNumber(wholenumber_t)
RexxObject * floorInternal()
bool int64Value(int64_t *result, stringsize_t numDigits)
void liveGeneral(int reason)
bool unsignedNumberValue(uwholenumber_t &result, size_t precision)
static void createInstance()
static RexxNumberString * newInstanceFromUint64(uint64_t)
RexxString * stringValue()
RexxString * formatRexx(RexxObject *, RexxObject *, RexxObject *, RexxObject *)
RexxObject * ceilingInternal()
bool unsignedInt64Value(uint64_t *result, stringsize_t numDigits)
RexxInteger * hasMethod(RexxString *)
RexxObject * evaluate(RexxActivation *, RexxExpressionStack *)
RexxInteger * integerValue(size_t)
bool checkIntegerDigits(stringsize_t numDigits, stringsize_t &numberLength, wholenumber_t &numberExponent, bool &carry)
RexxClass * classObject()
static char * multiplyBaseSixteen(char *, char *)
wholenumber_t strictComp(RexxObject *)
RexxInteger * Sign()
static RexxClass * classInstance
RexxNumberString * Min(RexxObject **, size_t, size_t)
RexxString * d2xD2c(RexxObject *, bool)
RexxNumberString * Division(RexxNumberString *, unsigned int)
void formatInt64(int64_t integer)
RexxNumberString * abs()
void setString(RexxString *)
RexxNumberString * clone()
RexxString * d2c(RexxObject *)
RexxInteger * strictLessOrEqual(RexxObject *)
RexxMethod * instanceMethod(RexxString *)
RexxObject * ceiling()
RexxObject * hashCode()
RexxObject * andOp(RexxObject *)
RexxNumberString * integerDivide(RexxObject *)
static RexxNumberString * newInstanceFromStringsize(stringsize_t)
RexxString * concat(RexxObject *)
RexxObject * getValue(RexxActivation *context)
RexxObject * orOp(RexxObject *)
RexxNumberString * Multiply(RexxNumberString *)
RexxArray * makeArray()
RexxNumberString * maxMin(RexxObject **, size_t, size_t, unsigned int)
RexxObject * unknown(RexxString *, RexxArray *, RexxDirectory *)
bool numberValue(wholenumber_t &result, size_t precision)
RexxObject * trunc(RexxObject *)
RexxInteger * strictNotEqual(RexxObject *)
static PCPPM operatorMethods[]
bool isInstanceOf(RexxClass *)
RexxNumberString * power(RexxObject *)
RexxNumberString * remainder(RexxObject *)
RexxObject * isInteger()
RexxInteger * strictGreaterOrEqual(RexxObject *)
virtual HashCode getHashValue()
RexxNumberString * prepareOperatorNumber(size_t, size_t, bool)
static RexxNumberString * newInstanceFromWholenumber(wholenumber_t)
RexxInteger * equal(RexxObject *)
RexxInteger * isGreaterOrEqual(RexxObject *)
RexxString * d2x(RexxObject *)
virtual wholenumber_t compareTo(RexxObject *)
bool isEqual(RexxObject *)
int format(const char *, size_t)
RexxInteger * isLessOrEqual(RexxObject *)
RexxObject * operatorNot(RexxObject *)
virtual bool logicalValue(logical_t &)
static RexxNumberString * newInstanceFromInt64(int64_t)
static char * addToBaseSixteen(int, char *, char *)
RexxNumberString * plus(RexxObject *)
RexxNumberString * divide(RexxObject *)
RexxString * formatInternal(size_t, size_t, size_t, size_t, RexxNumberString *, size_t, bool)
RexxSupplier * instanceMethods(RexxClass *)
bool doubleValue(double &result)
RexxInteger * notEqual(RexxObject *)
RexxNumberString * addSub(RexxNumberString *, unsigned int, size_t)
RexxNumberString * numberString()
virtual RexxInteger * hasMethod(RexxString *msg)
RexxSupplier * instanceMethods(RexxClass *)
void sendMessage(RexxString *, RexxArray *, RexxDirectory *, ProtectedObject &)
HashCode hash()
RexxMethod * instanceMethod(RexxString *)
bool messageSend(RexxString *, RexxObject **, size_t, size_t, ProtectedObject &, bool processUnknown=true, bool dynamicTarget=true)
bool truthValue(int)
bool isInstanceOf(RexxClass *)
RexxString * concatRexx(RexxObject *)
RexxObject * xorOp(RexxObject *)
const char * getStringData()
void setNumberString(RexxObject *)
RexxString * concatBlank(RexxObject *)
void set(size_t s, int c, size_t l)
char * getWritableData()
RexxObject * notOp()
RexxObject * andOp(RexxObject *)
bool isEqual(RexxObject *)
wholenumber_t comp(RexxObject *, RexxString *alternativeOperator=OREF_NULL, RexxInteger **alternativeOperatorResultPtr=NULL)
virtual HashCode getHashValue()
char putChar(size_t p, char c)
wholenumber_t compareTo(RexxObject *)
RexxObject * isInteger()
RexxObject * orOp(RexxObject *)
RexxArray * makeArray()
void put(size_t s, const void *b, size_t l)
wholenumber_t strictComp(RexxObject *, RexxString *alternativeOperator=NULL, RexxInteger **alternativeOperatorResultPtr=NULL)
static RexxString * packHex(const char *String, size_t StringLength)
Definition: StringUtil.cpp:875
int type
Definition: cmdparse.cpp:1888
size_t logical_t
Definition: rexx.h:231
ssize_t wholenumber_t
Definition: rexx.h:230
size_t stringsize_t
Definition: rexx.h:228
size_t uwholenumber_t
Definition: rexx.h:229
#define isnan(x)
#define UINT64_MAX
#define SIZE_MAX
signed __int64 int64_t
#define INT64_MIN
#define INT64_MAX
unsigned __int64 uint64_t