Example #1
0
void
_cos(
  floatnum x,
  int digits)
{
  signed char sgn;

  float_abs(x);
  sgn = 1;
  if (float_cmp(x, &cPiDiv2) > 0)
  {
    sgn = -1;
    float_sub(x, &cPi, x, digits+1);
  }
  if (float_cmp(x, &cPiDiv4) <= 0)
  {
    if (2*float_getexponent(x)+2 < - digits)
      float_setzero(x);
    else
      _cosminus1ltPiDiv4(x, digits);
    float_add(x, x, &c1, digits);
  }
  else
  {
    float_sub(x, &cPiDiv2, x, digits+1);
    _sinltPiDiv4(x, digits);
  }
  float_setsign(x, sgn);
}
Example #2
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;
}
Example #3
0
/* evaluates ln(Gamma(x)) for all those x big
   enough to let the asymptotic series converge directly.
   Returns 0, if the result overflows
   relative error for a 100 gigit calculation < 5e-100 */
static char
_lngammabigx(
  floatnum x,
  int digits)
{
  floatstruct tmp1, tmp2;
  char result;

  result = 0;
  float_create(&tmp1);
  float_create(&tmp2);
  /* compute (ln x-1) * (x-0.5) - 0.5 + ln(sqrt(2*pi)) */
  float_copy(&tmp2, x, digits+1);
  _ln(&tmp2, digits+1);
  float_sub(&tmp2, &tmp2, &c1, digits+2);
  float_sub(&tmp1, x, &c1Div2, digits+2);
  if (float_mul(&tmp1, &tmp1, &tmp2, digits+2))
  {
    /* no overflow */
    lngammaasymptotic(x, digits);
    float_add(x, &tmp1, x, digits+3);
    float_add(x, x, &cLnSqrt2PiMinusHalf, digits+3);
    result = 1;
  }
  float_free(&tmp2);
  float_free(&tmp1);
  return result;
}
Example #4
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;
}
Example #5
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;
}
Example #6
0
char
_lngamma(
  floatnum x,
  int digits)
{
  floatstruct factor;
  int infinity;
  char result;

  if (float_cmp(x, &c1) == 0 || float_cmp(x, &c2) == 0)
    return _setzero(x);
  float_create(&factor);
  result = _lngamma_prim(x, &factor, &infinity, digits)
           && infinity == 0;
  if (result)
  {
    float_abs(&factor);
    _ln(&factor, digits + 1);
    result = float_sub(x, x, &factor, digits+1);
  }
  float_free(&factor);
  if (infinity != 0)
    return _seterror(x, ZeroDivide);
  if (!result)
    float_setnan(x);
  return result;
}
Example #7
0
char
_gamma0_5(
  floatnum x,
  int digits)
{
  floatstruct tmp;
  int ofs;

  if (float_getexponent(x) >= 2)
    return _gamma(x, digits);
  float_create(&tmp);
  float_sub(&tmp, x, &c1Div2, EXACT);
  ofs = float_asinteger(&tmp);
  float_free(&tmp);
  if (ofs >= 0)
  {
    float_copy(x, &c1Div2, EXACT);
    if(!_pochhammer_su(x, ofs, digits))
      return 0;
    return float_mul(x, x, &cSqrtPi, digits);
  }
  if(!_pochhammer_su(x, -ofs, digits))
    return 0;
  return float_div(x, &cSqrtPi, x, digits);
}
Example #8
0
char
float_arcosh(
  floatnum x,
  int digits)
{
  if (!chckmathparam(x, digits))
    return 0;
  float_sub(x, x, &c1, digits+1);
  return float_arcoshxplus1(x, digits);
}
Example #9
0
/* evaluates cos x - 1 for |x| <= pi.
   This function may underflow, which
   is indicated by the return value 0 */
char
_cosminus1(
  floatnum x,
  int digits)
{
  float_abs(x);
  if (float_cmp(x, &cPiDiv4) <= 0)
    return _cosminus1ltPiDiv4(x, digits);
  _cos(x, digits);
  float_sub(x, x, &c1, digits);
  return 1;
}
Example #10
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);
}
Example #11
0
/* evaluates arccos(1+x) for -0.5 <= x <= 0
   arccos(1+x) = arctan(sqrt(-x*(2+x))/(1+x))
   the relative error of a 100 digit result is < 5e-100 */
void
_arccosxplus1lt0_5(
  floatnum x,
  int digits)
{
  floatstruct tmp;

  float_create(&tmp);
  float_add(&tmp, x, &c2, digits+1);
  float_mul(x, x, &tmp, digits+1);
  float_setsign(x, 1);
  float_sqrt(x, digits);
  float_sub(&tmp, &tmp, &c1, digits);
  float_div(x, x, &tmp, digits+1);
  _arctan(x, digits);
  float_free(&tmp);
}
Example #12
0
/* evaluates arcsin x for -0.5 <= x <= 0.5
   arcsin x = arctan(x/sqrt(1-x*x))
   the relative error of a 100 digit result is < 5e-100 */
void
_arcsinlt0_5(
  floatnum x,
  int digits)
{
  floatstruct tmp;

  if (2*float_getexponent(x) < -digits)
    return;
  float_create(&tmp);
  float_mul(&tmp, x, x, digits);
  float_sub(&tmp, &c1, &tmp, digits);
  float_sqrt(&tmp, digits);
  float_div(x, x, &tmp, digits+1);
  _arctanlt1(x, digits);
  float_free(&tmp);
}
Example #13
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);
  }
}
Example #14
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);
}
Example #15
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;
}
Example #16
0
char
float_tanhminus1(
  floatnum x,
  int digits)
{
  if (!chckmathparam(x, digits))
    return 0;
  if (float_cmp(x, &c1Div2) >= 0)
    return _tanhminus1gt0(x, digits)? 1 : _seterror(x, Underflow);
  if (!float_iszero(x))
  {
    if (float_abscmp(x, &c1Div2) <= 0)
      _tanhlt0_5(x, digits);
    else
    {
      float_setsign(x, 1);
      _tanhgt0_5(x, digits);
      float_setsign(x, -1);
    }
  }
  return float_sub(x, x, &c1, digits);
}
Example #17
0
void
_tanltPiDiv4(
  floatnum x,
  int digits)
{
  floatstruct tmp;
  signed char sgn;

  if (2*float_getexponent(x)+2 < -digits)
    /* for small x: tan 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_sub(&tmp, &tmp, &c1, digits);
  float_div(x, x, &tmp, digits+1);
  float_setsign(x, sgn);
  float_free(&tmp);
}
Example #18
0
static char
_pochhammer_g(
  floatnum x,
  cfloatnum n,
  int digits)
{
  /* this generalizes the rising Pochhammer symbol using the
     formula pochhammer(x,n) = Gamma(x+1)/Gamma(x-n+1) */
  floatstruct tmp, factor1, factor2;
  int inf1, inf2;
  char result;

  float_create(&tmp);
  float_create(&factor1);
  float_create(&factor2);
  inf2 = 0;
  float_add(&tmp, x, n, digits+1);
  result = _lngamma_prim(x, &factor1, &inf1, digits)
           && _lngamma_prim(&tmp, &factor2, &inf2, digits)
           && (inf2 -= inf1) <= 0;
  if (inf2 > 0)
    float_seterror(ZeroDivide);
  if (result && inf2 < 0)
    float_setzero(x);
  if (result && inf2 == 0)
    result = float_div(&factor1, &factor1, &factor2, digits+1)
             && float_sub(x, &tmp, x, digits+1)
             && _exp(x, digits)
             && float_mul(x, x, &factor1, digits+1);
  float_free(&tmp);
  float_free(&factor2);
  float_free(&factor1);
  if (!result)
    float_setnan(x);
  return result;
}
Example #19
0
/**
 * \brief Fractal Algorithm without FPU optimization.
 */
static int draw_mandel_without_fpu(void)
{
  t_cpu_time timer;
  while (i_wofpu<HEIGHT/2+1)
  {
    cpu_set_timeout( cpu_us_2_cy(DELAY_US,pcl_freq_param.cpu_f), &timer );
    while(j_wofpu<WIDTH)
    {
      z_wofpu = 0;
      zi_wofpu = 0;
      inset_wofpu = 1;
      while (k_wofpu<iter_wofpu)
      {
        /* z^2 = (a+bi)(a+bi) = a^2 + 2abi - b^2 */
		newz_wofpu = float_add(
								float_sub(
										float_mul(z_wofpu,z_wofpu),
										float_mul(zi_wofpu,zi_wofpu)),
							    x_wofpu
					);
		newzi_wofpu = float_add(
								2*float_mul(
											z_wofpu,
											zi_wofpu),
								y_wofpu
					);
        z_wofpu = newz_wofpu;
        zi_wofpu = newzi_wofpu;
		if(float_add(
						float_mul(z_wofpu,z_wofpu),
						float_mul(zi_wofpu,zi_wofpu)
			) > 4)
		{
		  inset_wofpu = 0;
		  colour_wofpu = k_wofpu;
		  k_wofpu = iter_wofpu;
		}
        k_wofpu++;
      };
      k_wofpu = 0;
      // Draw Mandelbrot set
      if (inset_wofpu)
      {
       et024006_DrawPixel(j_wofpu+WIDTH,i_wofpu+OFFSET_DISPLAY,BLACK);
       et024006_DrawPixel(j_wofpu+WIDTH,HEIGHT-i_wofpu+OFFSET_DISPLAY,BLACK);
      }
      else
      {
        et024006_DrawPixel(j_wofpu+WIDTH,
			i_wofpu+OFFSET_DISPLAY,
			BLUE_LEV((colour_wofpu*255) / iter_wofpu )+
			GREEN_LEV((colour_wofpu*127) / iter_wofpu )+
			RED_LEV((colour_wofpu*127) / iter_wofpu ));
        et024006_DrawPixel(j_wofpu+WIDTH,
			HEIGHT-i_wofpu+OFFSET_DISPLAY,
			BLUE_LEV((colour_wofpu*255) / iter_wofpu )+
			GREEN_LEV((colour_wofpu*127) / iter_wofpu )+
			RED_LEV((colour_wofpu*127) / iter_wofpu ));
      }
      x_wofpu += xstep_wofpu;
      j_wofpu++;
    };
    j_wofpu = 0;
    y_wofpu += ystep_wofpu;
    x_wofpu = xstart_wofpu;
    i_wofpu++;
    if( cpu_is_timeout(&timer) )
    {
      return 0;
    }
  };
  return 1;
}