static Error
_pack2frac(
  floatnum x,
  p_ext_seq_desc n,
  int digits)
{
  floatstruct tmp;
  int exp;
  Error result;

  n->seq.digits -= n->seq.trailing0;
  n->seq.trailing0 = 0;
  switch(n->seq.base)
  {
  case IO_BASE_NAN:
    float_setnan(x);
    break;
  case IO_BASE_ZERO:
    float_setzero(x);
    break;
  default:
    if ((result = _pack2int(x, n)) != Success)
      return result;
    float_create(&tmp);
    float_setinteger(&tmp, n->seq.base);
    _raiseposi(&tmp, &exp, n->seq.digits, digits+2);
    float_div(x, x, &tmp, digits + 2);
    float_setexponent(x, float_getexponent(x) - exp);
    float_free(&tmp);
  }
  n->seq.digits += n->seq.trailing0;
  return Success;
}
static Error
_packdec2int(
  floatnum x,
  p_ext_seq_desc n)
{
  int ofs;
  int exp;
  int bufsz;
  int i;
  char buf[DECPRECISION];

  float_setnan(x);
  ofs = n->seq.leadingSignDigits;
  exp = n->seq.trailing0;
  bufsz = n->seq.digits - ofs - exp;
  if (bufsz > DECPRECISION)
    return IOBufferOverflow;
  if (bufsz == 0)
    float_setzero(x);
  else
    for (i = -1; ++i < bufsz;)
      buf[i] = n->getdigit(ofs++, &n->seq) + '0';
  float_setsignificand(x, NULL, buf, bufsz);
  float_setexponent(x, exp + bufsz - 1);
  return Success;
}
Exemple #3
0
/* series expansion of cos/cosh - 1 used for small x,
   |x| <= 0.01.
   The function returns 0, if an underflow occurs.
   The relative error seems to be less than 5e-100 for
   a 100-digit calculation with |x| < 0.01 */
char
cosminus1series(
  floatnum x,
  int digits,
  char alternating)
{
  floatstruct sum, smd;
  int expsqrx, pwrsz, addsz, i;

  expsqrx = 2 * float_getexponent(x);
  float_setexponent(x, 0);
  float_mul(x, x, x, digits+1);
  float_mul(x, x, &c1Div2, digits+1);
  float_setsign(x, alternating? -1 : 1);
  expsqrx += float_getexponent(x);
  if (float_iszero(x) || expsqrx < EXPMIN)
  {
    /* underflow */
    float_setzero(x);
    return expsqrx == 0;
  }
  float_setexponent(x, expsqrx);
  pwrsz = digits + expsqrx + 2;
  if (pwrsz <= 0)
    /* for very small x, cos/cosh(x) - 1 = (-/+)0.5*x*x */
    return 1;
  addsz = pwrsz;
  float_create(&sum);
  float_create(&smd);
  float_copy(&smd, x, pwrsz);
  float_setzero(&sum);
  i = 2;
  while (pwrsz > 0)
  {
    float_mul(&smd, &smd, x, pwrsz+1);
    float_divi(&smd, &smd, i*(2*i-1), pwrsz);
    float_add(&sum, &sum, &smd, addsz);
    ++i;
    pwrsz = digits + float_getexponent(&smd);
  }
  float_add(x, x, &sum, digits+1);
  float_free(&sum);
  float_free(&smd);
  return 1;
}
static Error
_outscidec(
  p_otokens tokens,
  floatnum x,
  p_number_desc n,
  int scale)
{
  float_checkedround(x, scale + 1);
  n->exp = float_getexponent(x);
  float_setexponent(x, 0);
  _setfndesc(n, x);
  return desc2str(tokens, n, scale);
}
static Error
_outengdec(
  p_otokens tokens,
  floatnum x,
  p_number_desc n,
  int scale)
{
  int shift;

  float_checkedround(x, scale + 1);
  n->exp = float_getexponent(x);
  if (n->exp < 0)
    shift = 2 - (-n->exp-1) % 3;
  else
    shift = n->exp % 3;
  float_setexponent(x, shift);
  n->exp -= shift;
  _setfndesc(n, x);
  return desc2str(tokens, n, scale - shift);
}
Exemple #6
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;
}