ooRexx  4.2.0-source
About: ooRexx (Open Object Rexx) is a free implementation of Object Rexx. Object Rexx is an enhancement of the classic Rexx interpreter; a full-featured programming language with a human-oriented syntax.
  Fossies Dox: ooRexx-4.2.0-source.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

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