Esempio n. 1
0
_RETURN_TYPE
INTERNAL_FUNCTION_NAME (DEC_TYPE x)
{
  DEC_TYPE result;
  decContext context;
  decNumber dn_result;
  decNumber dn_x;
  decNumber dn_absx;
  decNumber dn_logx;
  decNumber dn_one;
  decNumber dn_cmp;
  enum rounding round;

  FUNC_CONVERT_TO_DN (&x, &dn_x);
  if (decNumberIsZero (&dn_x))
    {
      DFP_EXCEPT (FE_INVALID);
      DFP_ERRNO (EDOM);
      return _FBLOG0;
    }
  if (decNumberIsInfinite (&dn_x))
    {
      DFP_EXCEPT (FE_INVALID);
      DFP_ERRNO (EDOM);
      return decNumberIsNegative (&dn_x) ? _MIN_VALUE : _MAX_VALUE;
    }
  if (decNumberIsNaN (&dn_x))
    {
      DFP_EXCEPT (FE_INVALID);
      DFP_ERRNO (EDOM);
      return _FBLOGNAN;
    }

  decContextDefault (&context, DEFAULT_CONTEXT);

  decNumberAbs (&dn_absx, &dn_x, &context);

  /* For DFP, we use radix 10 instead of whatever FLT_RADIX happens to be */
  decNumberLog10 (&dn_logx, &dn_absx, &context);

  /* Capture the case where truncation will return the wrong result,
     by rounding up if -1.0 < x < 1.0  */
  round = DEC_ROUND_DOWN;
  decNumberFromInt32 (&dn_one, 1);
  decNumberCompare (&dn_cmp, &dn_x, &dn_one, &context);
  if (-decNumberIsNegative(&dn_cmp))
    {
      decNumberFromInt32 (&dn_one, -1);
      decNumberCompare (&dn_cmp, &dn_x, &dn_one, &context);
      if (!decNumberIsNegative(&dn_cmp) && !decNumberIsZero(&dn_cmp))
	round = DEC_ROUND_UP;
    }
  context.round = round;

  decNumberToIntegralValue (&dn_result, &dn_logx, &context);

  FUNC_CONVERT_FROM_DN (&dn_result, &result, &context);
  /* Use _Decimal* to int casting.  */
  return (_RETURN_TYPE) result;
}
Esempio n. 2
0
DEC_TYPE
INTERNAL_FUNCTION_NAME (DEC_TYPE x)
{
  decContext context;
  decNumber dn_result;
  DEC_TYPE result;
  decNumber dn_x;
  decNumber dn_tmp;
  decNumber dn_log10;
  decNumber dn_one;
  decNumber dn_cmp;
  enum rounding round;

  FUNC_CONVERT_TO_DN (&x, &dn_x);
  if (decNumberIsNaN (&dn_x))
    return x+x;
  if (decNumberIsInfinite (&dn_x))	/* +-Inf: Inf  */
    return DEC_INFINITY;
  if (decNumberIsZero (&dn_x))	/*  Pole Error if x==0 */
    {
      DFP_ERRNO (ERANGE);
      DFP_EXCEPT (FE_DIVBYZERO);
      return -DFP_HUGE_VAL;
    }
  if (decNumberIsInfinite (&dn_x) && decNumberIsNegative (&dn_x))
    return -x;

  decContextDefault (&context, DEFAULT_CONTEXT);
  decNumberAbs (&dn_tmp, &dn_x, &context);
  /*  For DFP, we use radix 10 instead of whatever FLT_RADIX
      happens to be */
  decNumberLog10 (&dn_log10, &dn_tmp, &context);

  /* Capture the case where truncation will return the wrong result,
     by rounding up if -1.0 < x < 1.0  */
  round = DEC_ROUND_DOWN;
  decNumberFromInt32 (&dn_one, 1);
  decNumberCompare (&dn_cmp, &dn_x, &dn_one, &context);
  if (-decNumberIsNegative(&dn_cmp))
    {
      decNumberFromInt32 (&dn_one, -1);
      decNumberCompare (&dn_cmp, &dn_x, &dn_one, &context);
      if (!decNumberIsNegative(&dn_cmp) && !decNumberIsZero(&dn_cmp))
	round = DEC_ROUND_UP;
    }
  context.round = round;

  decNumberToIntegralValue (&dn_result, &dn_log10, &context);

  FUNC_CONVERT_FROM_DN (&dn_result, &result, &context);

  return result;
}
void* decSingleFromInt32 (void* _res, int32_t ival) noexcept
{
  decNumber _resnum;
  decNumberFromInt32 (&_resnum, ival);
  std::decimal::decimal32::context ctx;
  return decSingleFromNumber (_res, &_resnum, (decContext*)&ctx);
}
Esempio n. 4
0
DecimalDecNumber::DecimalDecNumber(int rhs)
{
   decContextDefault(&m_context, DEC_INIT_BASE); // initialize
   m_context.traps = 0;                     // no traps, thank you
   m_context.digits = DECNUMDIGITS;         // set precision
   decNumberFromInt32(&m_value, rhs);
}
Esempio n. 5
0
bool DecimalDecNumber::toDecimalComponents(const DecimalDecNumber &val, int64& significand, int32& exponent)
{
	DecimalDecNumber valCopy = val;
	valCopy.m_context.digits = 18; // maximum number of digits which can be represented by int64 significand

	// Check if decimal is NaN or infinite - we can't represent these as components
	if (decNumberIsSpecial( &valCopy.m_value ))
	{
		exponent = 0;
		significand = 0;
		return false;
	}

	// Minimize the size of the number the significand needs to represent
	decNumberReduce( &valCopy.m_value, &valCopy.m_value, &valCopy.m_context );

	exponent = valCopy.m_value.exponent;

	decNumber numExponent;
	decNumberFromInt32( &numExponent, -valCopy.m_value.exponent );
	decNumberScaleB( &valCopy.m_value, &valCopy.m_value, &numExponent, &valCopy.m_context );

	if (::sscanf(valCopy.toString(0).c_str(), "%lld", &significand) != 1)
	{
		exponent = 0;
		significand = 0;
		return false;
	}

	return true;
}
Esempio n. 6
0
DecimalDecNumber power(const DecimalDecNumber &val, int32 exponent)
{
   decNumber dExponent;
   decNumberFromInt32(&dExponent, exponent);
   DecimalDecNumber result;
   decNumberPower(&result.m_value, &val.m_value, &dExponent, &val.m_context);
   return result;
}
Esempio n. 7
0
DecimalDecNumber DecimalDecNumber::fromDecimalComponents(const int64 significand, const int32 exponent)
{
	DecimalDecNumber number(significand);
	if ( exponent != 0 )
	{
		decNumber numExponent;
		decNumberFromInt32( &numExponent, exponent );
		decNumberScaleB( &number.m_value, &number.m_value, &numExponent, &number.m_context );
	}
	return number;
}
Esempio n. 8
0
DEC_TYPE
FUNC_NAME (_Decimal128 hi, _Decimal128 mid, _Decimal128 low)
{
  DEC_TYPE result;

  /*  hi = m_hi *  10^34
   * mid = m_mid * 10^17
   * low = m_low * 10^0
   *
   * Note, m_hi is only at most 5 digits for int128.
   */
  decNumber dn_hi, dn_mid, dn_low, dn_result;
  decNumber dn_hi_s, dn_mid_s, dn_result_s;
  decNumber dn_17, dn_34;
  decContext context;

  decContextDefault (&context, DEC_INIT_DECIMAL128);
  /* Hack, we're using 39 digits here. */
  context.digits = 39;

  decNumberFromInt32(&dn_17, 17);
  decNumberFromInt32(&dn_34, 34);

  __DECIMAL_TO_DECNUMBER (&hi,  &dn_hi,  128);
  __DECIMAL_TO_DECNUMBER (&mid, &dn_mid, 128);
  __DECIMAL_TO_DECNUMBER (&low, &dn_low, 128);

  /* Rotate addends into proper position.  */
  decNumberShift(&dn_hi_s,&dn_hi,&dn_34,&context);
  decNumberShift(&dn_mid_s,&dn_mid,&dn_17,&context);

  /* Sum the three components.  */
  decNumberAdd(&dn_result_s, &dn_hi_s, &dn_mid_s, &context);
  decNumberAdd(&dn_result, &dn_result_s, &dn_low, &context);

  /* Convert to the destination format.  */
  FUNC_CONVERT_FROM_DN (&dn_result, &result, &context);

  /* Don't care about exceptions here... I don't think.  */
  return result;
}
Esempio n. 9
0
DecimalDecNumber::DecimalDecNumber(int64 rhs)
{
   decContextDefault(&m_context, DEC_INIT_BASE); // initialize
   m_context.traps = 0;                     // no traps, thank you
   m_context.digits = DECNUMDIGITS;         // set precision

   if (   (rhs >= 0 && rhs <= std::numeric_limits<int>::max())
       || (rhs < 0  && rhs >= std::numeric_limits<int>::min()))
   {
      decNumberFromInt32(&m_value, static_cast<int>(rhs));
   }
   else
   {
      char buffer[64];
      int64_to_string(rhs, buffer);
      decNumberFromString(&m_value, buffer, &m_context);
   }
}
Esempio n. 10
0
const DecimalDecNumber DecimalDecNumber::round(uint32 decimalPlaces, RoundingMode mode, RoundIncrement roundIncrement)
{
   if (isZero())
      return *this;

   if (roundIncrement == RoundIncrement::HALF)
      decNumberMultiply(&m_value, &m_value, &DecimalDecNumber::TWO.m_value, &m_context);
   else if (roundIncrement == RoundIncrement::QUARTER)
      decNumberMultiply(&m_value, &m_value, &DecimalDecNumber::FOUR.m_value, &m_context);

   static const int BUFFER_SIZE = 256;
   char buffer[BUFFER_SIZE];
   decNumberToString(&m_value, buffer);

   char * b = buffer;
   char * e = buffer + strlen(buffer);
   char * f = std::find(b, e, 'E');
   if (f != e && (f+1) != e)
   {
      unpackScientificFormat(b, e, BUFFER_SIZE, 48);
      e = buffer + strlen(buffer);
   }

   const char * point = std::find(buffer, e, '.');

   const char * firstNonZeroDigitAfterDecimal = point;
   while (firstNonZeroDigitAfterDecimal != e && (*firstNonZeroDigitAfterDecimal < '1' || *firstNonZeroDigitAfterDecimal > '9'))
   {
      ++firstNonZeroDigitAfterDecimal;
   }

   if (firstNonZeroDigitAfterDecimal != e)
   {
      decContext tempContext;
      decContextDefault(&tempContext, DEC_INIT_BASE); 
      tempContext.traps = 0;

      // DecNumber rounding is expressed in significant figures; we want to round to a fixed number of decimal places.
      const char * firstDigit = *buffer == '-' ? (buffer+1) : buffer;
      const bool absValueLessThanOne = *firstDigit == '0';
      if (absValueLessThanOne)
      {
         tempContext.digits = decimalPlaces - (firstNonZeroDigitAfterDecimal - point - 1);

      }
      else
      {
         tempContext.digits = decimalPlaces + (point - firstDigit);
      }
      if (tempContext.digits < 0)
      {
         decNumberFromInt32(&m_value, 0);
         return *this;
      }
		 
      switch (mode)
      {
         case RoundingMode::ROUND_HALF_TO_POSITIVE_INFINITY:
            tempContext.round = isNegative() ? DEC_ROUND_HALF_DOWN : DEC_ROUND_HALF_UP;
         break;
         case RoundingMode::ROUND_HALF_TO_NEGATIVE_INFINITY: 
            tempContext.round = isNegative() ? DEC_ROUND_HALF_UP : DEC_ROUND_HALF_DOWN;
         break;
         case RoundingMode::ROUND_TO_POSITIVE_INFINITY:
            tempContext.round = isNegative() ? DEC_ROUND_DOWN : DEC_ROUND_UP;
         break;
         case RoundingMode::ROUND_TO_NEGATIVE_INFINITY:
            tempContext.round = isNegative() ? DEC_ROUND_UP : DEC_ROUND_DOWN;
         break;
         case RoundingMode::ROUND_AWAY_FROM_ZERO:
            tempContext.round = DEC_ROUND_UP;
         break;
         case RoundingMode::ROUND_TO_ZERO:
            tempContext.round = DEC_ROUND_DOWN;
         break;
         case RoundingMode::ROUND_HALF_AWAY_FROM_ZERO: 
            tempContext.round = DEC_ROUND_HALF_UP;
         break;
         case RoundingMode::ROUND_HALF_TO_ZERO: 
            tempContext.round = DEC_ROUND_HALF_DOWN; 
         break;
         case RoundingMode::ROUND_HALF_TO_EVEN:
            tempContext.round = DEC_ROUND_HALF_EVEN; 
         break;
         default :
            throw("Rounding mode is not supported - rounding using default mode which is DEC_ROUND_HALF_AWAY_FROM_ZERO");
            // LCRIT("Rounding mode[%d] is not supported - rounding using default mode which is DEC_ROUND_HALF_AWAY_FROM_ZERO", mode);
            // tempContext.round = DEC_ROUND_HALF_UP;
      }

      decNumberFromString(&m_value, buffer, &tempContext);
   }

   if (roundIncrement == RoundIncrement::HALF)
      decNumberDivide(&m_value, &m_value, &DecimalDecNumber::TWO.m_value, &m_context);
   else if (roundIncrement == RoundIncrement::QUARTER)
      decNumberDivide(&m_value, &m_value, &DecimalDecNumber::FOUR.m_value, &m_context);

   return *this;
}
Esempio n. 11
0
DecimalDecNumber &DecimalDecNumber::operator=(int rhs)
{
   decNumberFromInt32(&m_value, rhs);
   return *this;
}