示例#1
0
char
_floatnum2logic(
  t_longint* longint,
  cfloatnum x)
{
  floatstruct tmp;
  int digits;

  digits = float_getexponent(x)+1;
  if (float_iszero(x) || digits <= 0)
  {
    longint->length = 1;
    longint->value[0] = 0;
  }
  else
  {
    if (digits > MATHPRECISION)
      return 0;

    float_create(&tmp);
    /* floatnum2longint rounds, we have to truncate first */
    float_copy(&tmp, x, digits);
    if (float_getsign(x) < 0)
      float_add(&tmp, &tmp, &c1, EXACT);
    _floatnum2longint(longint, &tmp);
    float_free(&tmp);
    if (_bitlength(longint) > LOGICRANGE)
      return 0;
  }
  _zeroextend(longint);
  if (float_getsign(x) < 0)
    _not(longint);
  return 1;
}
示例#2
0
char
float_gamma(
  floatnum x,
  int digits)
{
  signed char sign;
  char result;

  if (!chckmathparam(x, digits))
    return 0;
  sign = float_getsign(x);
  if (float_isinteger(x))
  {
    if (sign <= 0)
      return _seterror(x, ZeroDivide);
    result = _gammaint(x, digits);
  }
  else if (float_getlength(x) - float_getexponent(x) == 2
           && float_getdigit(x, float_getlength(x) - 1) == 5)
    result = _gamma0_5(x, digits);
  else
    result = _gamma(x, digits);
  if (!result)
  {
    if (sign < 0)
      float_seterror(Underflow);
    else
      float_seterror(Overflow);
    float_setnan(x);
  }
  return result;
}
示例#3
0
char
_doshift(
  floatnum dest,
  cfloatnum x,
  cfloatnum shift,
  char right)
{
  int ishift;
  t_longint lx;

  if (float_isnan(shift))
    return _seterror(dest, NoOperand);
  if (!float_isinteger(shift))
    return _seterror(dest, OutOfDomain);
  if(!_cvtlogic(&lx, x))
    return 0;
  if (float_iszero(shift))
  {
    float_copy(dest, x, EXACT);
    return 1;
  }
  ishift = float_asinteger(shift);
  if (ishift == 0)
    ishift = (3*LOGICRANGE) * float_getsign(shift);
  if (!right)
    ishift = -ishift;
  if (ishift > 0)
    _shr(&lx, ishift);
  else
    _shl(&lx, -ishift);
  _logic2floatnum(dest, &lx);
  return 1;
}
示例#4
0
char
_trigreduce(
  floatnum x,
  int digits)
{
  floatstruct tmp;
  int expx, save;
  signed char sgn;
  char odd;

  if (float_abscmp(x, &cPi) <= 0)
    return 1;
  expx = float_getexponent(x);
  if (expx > float_getlength(&cPi) - digits)
    return 0;
  save = float_setprecision(MAXDIGITS);
  float_create(&tmp);
  sgn = float_getsign(x);
  float_abs(x);
  float_divmod(&tmp, x, x, &cPi, INTQUOT);
  float_setprecision(save);
  odd = float_isodd(&tmp);
  if (odd)
    float_sub(x, x, &cPi, digits+1);
  if (sgn < 0)
    float_neg(x);
  float_free(&tmp);
  return 1;
}
示例#5
0
/* evaluates tan x for |x| <= pi.
   A return value of 0 indicates
   that x = +/- pi/2 within
   small tolerances, so that tan x
   cannot be reliable computed */
char
_tan(
  floatnum x,
  int digits)
{
  signed char sgn;

  sgn = float_getsign(x);
  float_abs(x);
  if (float_cmp(x, &cPiDiv2) > 0)
  {
    float_sub(x, &cPi, x, digits+1);
    sgn = -sgn;
  }
  if (float_cmp(x, &cPiDiv4) <= 0)
    _tanltPiDiv4(x, digits);
  else
  {
    float_sub(x, &cPiDiv2, x, digits+1);
    if (float_iszero(x) || float_getexponent(x) < -digits)
      return 0;
    _tanltPiDiv4(x, digits);
    float_reciprocal(x, digits);
  }
  float_setsign(x, sgn);
  return 1;
}
示例#6
0
Error float_out(
  p_otokens tokens,
  floatnum x,
  int scale,
  signed char base,
  char outmode)
{
  t_number_desc n;

  _emptytokens(tokens);
  /* do some sanity checks first */
  if (!_validmode(outmode) || scale < 0 || !_isvalidbase(base))
    return InvalidParam;
  _clearnumber(&n);
  if (float_iszero(x))
    n.prefix.base = IO_BASE_ZERO;
  else if (!float_isnan(x))
    n.prefix.base = base;
  if (!_isvalidbase(n.prefix.base))
    /* NaN and 0 are handled here */
    return desc2str(tokens, &n, 0);
  n.prefix.sign = float_getsign(x);
  float_abs(x);
  switch (outmode)
  {
  case IO_MODE_FIXPOINT:
    return _outfixp(tokens, x, &n, scale);
  case IO_MODE_ENG:
    return _outeng(tokens, x, &n, scale);
  case IO_MODE_COMPLEMENT:
    return _outcompl(tokens, x, &n, 0);
  default:
    return _outsci(tokens, x, &n, scale);
  }
}
示例#7
0
static char
_lngamma_prim(
  floatnum x,
  floatnum revfactor,
  int* infinity,
  int digits)
{
  floatstruct tmp;
  char result;
  char odd;

  *infinity = 0;
  if (float_getsign(x) > 0)
    return _lngamma_prim_xgt0(x, revfactor, digits);
  float_copy(revfactor, x, digits + 2);
  float_sub(x, &c1, x, digits+2);
  float_create(&tmp);
  result = _lngamma_prim_xgt0(x, &tmp, digits);
  if (result)
  {
    float_neg(x);
    odd = float_isodd(revfactor);
    _sinpix(revfactor, digits);
    if (float_iszero(revfactor))
    {
      *infinity = 1;
      float_setinteger(revfactor, odd? -1 : 1);
    }
    else
      float_mul(&tmp, &tmp, &cPi, digits+2);
    float_div(revfactor, revfactor, &tmp, digits+2);
  }
  float_free(&tmp);
  return result;
}
示例#8
0
char
float_raise(
  floatnum power,
  cfloatnum base,
  cfloatnum exponent,
  int digits)
{
  signed char sgn;

  if (float_isnan(exponent) || float_isnan(base))
    return _seterror(power, NoOperand);
  if (digits <= 0 || digits > MATHPRECISION)
    return _seterror(power, InvalidPrecision);
  if (float_iszero(base))
  {
    switch(float_getsign(exponent))
    {
    case 0:
      return _seterror(power, OutOfDomain);
    case -1:
      return _seterror(power, ZeroDivide);
    }
    return _setzero(power);
  }
  sgn = float_getsign(base);
  if (sgn < 0)
  {
    if (!float_isinteger(exponent))
      return _seterror(power, OutOfDomain);
    if ((float_getdigit(exponent, float_getexponent(exponent)) & 1) == 0)
      sgn = 1;
  }
  float_copy(power, base, digits+1);
  float_abs(power);
  if (!_raise(power, exponent, digits))
  {
    float_seterror(Overflow);
    if (float_getexponent(base) * float_getsign(exponent) < 0)
      float_seterror(Underflow);
    return _setnan(power);
  }
  float_setsign(power, sgn);
  return 1;
}
示例#9
0
char
float_ln(floatnum x, int digits)
{
  if (!chckmathparam(x, digits))
    return 0;
  if (float_getsign(x) <= 0)
    return _seterror(x, OutOfDomain);
  _ln(x, digits);
  return 1;
}
示例#10
0
char
float_lnxplus1(
  floatnum x,
  int digits)
{
  if (!chckmathparam(x, digits))
    return 0;
  if (float_getsign(x) < 0 && float_getexponent(x) >= 0)
    return _seterror(x, OutOfDomain);
  _lnxplus1(x, digits);
  return 1;
}
示例#11
0
char
float_arcoshxplus1(
  floatnum x,
  int digits)
{
  if (!chckmathparam(x, digits))
    return 0;
  if (float_getsign(x) < 0)
    return _seterror(x, OutOfDomain);
  _arcoshxplus1(x, digits);
  return 1;
}
示例#12
0
char
float_arccosxplus1(
  floatnum x,
  int digits)
{
  if (!chckmathparam(x, digits))
    return 0;
  if (float_getsign(x) > 0 || float_abscmp(x, &c2) > 0)
    return _seterror(x, OutOfDomain);
  _arccosxplus1(x, digits);
  return 1;
}
示例#13
0
static char
_pochhammer_i(
  floatnum x,
  cfloatnum n,
  int digits)
{
  /* do not use the expensive Gamma function when a few
     multiplications do the same */
  /* pre: n is an integer */
  int ni;
  signed char result;

  if (float_iszero(n))
    return float_copy(x, &c1, EXACT);
  if (float_isinteger(x))
  {
    result = -1;
    float_neg((floatnum)n);
    if (float_getsign(x) <= 0 && float_cmp(x, n) > 0)
      /* x and x+n have opposite signs, meaning 0 is
         among the factors */
      result = _setzero(x);
    else if (float_getsign(x) > 0 && float_cmp(x, n) <= 0)
      /* x and x+n have opposite signs, meaning at one point
      you have to divide by 0 */
      result = _seterror(x, ZeroDivide);
    float_neg((floatnum)n);
    if (result >= 0)
      return result;
  }
  if (float_getexponent(x) < EXPMAX/100)
  {
    ni = float_asinteger(n);
    if (ni != 0 && ni < 50 && ni > -50)
      return _pochhammer_si(x, ni, digits+2);
  }
  return _pochhammer_g(x, n, digits);
}
示例#14
0
char
float_power10(
  floatnum x,
  int digits)
{
  signed char sign;

  if (!chckmathparam(x, digits))
    return 0;
  sign = float_getsign(x);
  if (_power10(x, digits))
    return 1;
  return sign > 0? _seterror(x, Overflow) : _seterror(x, Underflow);
}
示例#15
0
char
float_exp(
  floatnum x,
  int digits)
{
  signed char sgn;

  if (!chckmathparam(x, digits))
    return 0;
  sgn = float_getsign(x);
  if (_exp(x, digits))
    return 1;
  if (sgn < 0)
    return _seterror(x, Underflow);
  return _seterror(x, Overflow);
}
示例#16
0
char
float_tanh(
  floatnum x,
  int digits)
{
  signed char sgn;

  if (!chckmathparam(x, digits))
    return 0;
  sgn = float_getsign(x);
  float_abs(x);
  if (float_cmp(x, &c1Div2) >= 0)
    _tanhgt0_5(x, digits);
  else
    _tanhlt0_5(x, digits);
  float_setsign(x, sgn);
  return 1;
}
示例#17
0
/* evaluates arcsin x for -1 <= x <= 1.
   The result is in the range -pi/2 <= result <= pi/2 
   The relative error for a 100 digit result is < 8e-100 */
void
_arcsin(
  floatnum x,
  int digits)
{
  signed char sgn;

  if (float_abscmp(x, &c1Div2) <= 0)
    _arcsinlt0_5(x, digits);
  else
  {
    sgn = float_getsign(x);
    float_abs(x);
    _arccos(x, digits);
    float_sub(x, &cPiDiv2, x, digits);
    float_setsign(x, sgn);
  }
}
示例#18
0
/* evaluates arctan x for all x. The result is in the
   range -pi/2 < result < pi/2
   relative error for a 100 digit result is 9e-100 */
void
_arctan(
  floatnum x,
  int digits)
{
  signed char sgn;

  if (float_abscmp(x, &c1) > 0)
  {
    sgn = float_getsign(x);
    float_abs(x);
    float_reciprocal(x, digits);
    _arctanlt1(x, digits);
    float_sub(x, &cPiDiv2, x, digits+1);
    float_setsign(x, sgn);
  }
  else
    _arctanlt1(x, digits);
}
示例#19
0
/* evaluate sin x for |x| <= pi/4,
   using |sin x| = sqrt((1-cos x)*(2 + cos x-1)) 
   relative error for 100 digit results is < 6e-100*/
void
_sinltPiDiv4(
  floatnum x,
  int digits)
{
  floatstruct tmp;
  signed char sgn;

  if (2*float_getexponent(x)+2 < -digits)
    /* for small x: sin x approx.== x */
    return;
  float_create(&tmp);
  sgn = float_getsign(x);
  _cosminus1ltPiDiv4(x, digits);
  float_add(&tmp, x, &c2, digits+1);
  float_mul(x, x, &tmp, digits+1);
  float_abs(x);
  float_sqrt(x, digits);
  float_setsign(x, sgn);
  float_free(&tmp);
}
示例#20
0
char
float_artanhxplus1(
  floatnum x,
  int digits)
{
  if (!chckmathparam(x, digits))
    return 0;
  if (float_getsign(x) >= 0 || float_abscmp(x, &c2) >= 0)
    return _seterror(x, OutOfDomain);
  if (float_cmp(x, &c1Div2) < 0)
  {
    float_neg(x);
    _artanh1minusx(x, digits);
  }
  else
  {
    float_sub(x, &c1, x, digits+1);
    _artanh(x, digits);
  }
  return 1;
}
示例#21
0
/* evaluates arccos x for -1 <= x <= 1.
   The result is in the range 0 <= result <= pi.
   The relative error for a 100 digit result is < 5e-100 */
void
_arccos(
  floatnum x,
  int digits)
{
  signed char sgn;

  sgn = float_getsign(x);
  float_abs(x);
  if (float_cmp(x, &c1Div2) > 0)
  {
    float_sub(x, x, &c1, digits+1);
    _arccosxplus1lt0_5(x, digits);
  }
  else
  {
    _arcsinlt0_5(x, digits);
    float_sub(x, &cPiDiv2, x, digits+1);
  }
  if (sgn < 0)
    float_sub(x, &cPi, x, digits+1);
}
示例#22
0
char
float_lg(
  floatnum x,
  int digits)
{
  floatstruct tmp;
  int expx;

  if (!chckmathparam(x, digits))
    return 0;
  if (float_getsign(x) <= 0)
    return _seterror(x, OutOfDomain);
  float_create(&tmp);
  expx = float_getexponent(x);
  float_setexponent(x, 0);
  _ln(x, digits);
  float_div(x, x, &cLn10, digits);
  float_setinteger(&tmp, expx);
  float_add(x, x, &tmp, digits);
  float_free(&tmp);
  return 1;
}
示例#23
0
/* evaluates sin x for |x| <= pi. */
void
_sin(
  floatnum x,
  int digits)
{
  signed char sgn;

  sgn = float_getsign(x);
  float_abs(x);
  if (float_cmp(x, &cPiDiv2) > 0)
    float_sub(x, &cPi, x, digits+1);
  if (float_cmp(x, &cPiDiv4) <= 0)
    _sinltPiDiv4(x, digits);
  else
  {
    float_sub(x, &cPiDiv2, x, digits+1);
    if (2*float_getexponent(x)+2 < - digits)
      float_setzero(x);
    else
      _cosminus1ltPiDiv4(x, digits);
    float_add(x, x, &c1, digits);
  }
  float_setsign(x, sgn);
}