Пример #1
0
real sqrtx2y2(const real& x, const real& y) throw()
// calculating sqrt(x^2 + y^2) in high accuracy. Blomquist 01.12.02
{
    real a,b,r;
    dotprecision dot;
    int exa,exb,ex;
    a = x;   b = y;
    exa = expo(a);  exb = expo(b);
    if (exb > exa)
    { // Permutation of a,b:
	r = a;  a = b;  b = r;
	ex = exa;  exa = exb;  exb = ex;
    }  // |a| >= |b|
    // a = |a| >= |b| > 0:
    ex = 511 - exa;   // scaling a with 2^ex --> expo(a) == 511, --> a*a and
    times2pown(a,ex); // b*b without overflow. An underflow of b*b will not
    times2pown(b,ex); // affect the accuracy of the result!
    dot = 0;
    accumulate(dot,a,a);
    accumulate(dot,b,b);
    r = rnd(dot);
    r = sqrt(r); // sqrt(...) declared in rmath.hpp
    times2pown(r,-ex); // back-scaling
    return r;
} // sqrtx2y2
Пример #2
0
void sqr2uv(const real& x, real& u, real& v)
// Liefert u,v für: x2 = u + v; EXAKTE Darstellung, falls kein overflow 
// auftritt und v im normalisierten Bereich liegt. u > |v|
// Vorsicht: Funktioniert zunächst nur auf INTEL-Systemen!!!
{
    real a,b,t,y1,y2;
    a = Cut26(x);
    b = x-a;  // x = a+b;
    u = x*x;
    t = u - a*a; // exakte Auswertung!
    y2 = a*b;
    times2pown(y2,1); // y2 = 2*a*b, exakt!
    t -= y2;
// Jetzt fehlt noch:  t2 - b*b, aber b*b wird nicht immer korrekt berechnet,
// daher nochmalige Aufspaltung von b in y1+y2!!
    y1 = Cut25(b);
    y2 = b - y1;   // b = y1+y2, exakt;
    t -= y1*y1;
    if (sign(y2)!=0)
    {
	a = y1*y2;
	times2pown(a,1); // a = 2*y1*y2, exakt!
	t -= a;
	t -= y2*y2;
    }
    v = -t;
} // sqr2uv
Пример #3
0
real sqrt1mx2(const real& x) throw(STD_FKT_OUT_OF_DEF)
// sqrt(1-x2);  rel. Fehlerschranke:  eps = 3.700747E-16 = e(f)
// Blomquist, 19.06.04;
{ 
    real t=x,res;
    int ex;
    if (sign(t)<0) t = -t; // Argument t >=0;
    if (t>1) cxscthrow(STD_FKT_OUT_OF_DEF("real sqrt1mx2(const real&)"));
    // For argument t now it holds: 0 <= t <=1;
    ex = expo(t);
    if (ex<=-26) res = 1; // t < 2^(-26) --> res = 1
    else if (ex<=-15) {   // t < 2^(-15) --> res = 1-x2/2
	res = t*t;  
	times2pown(res,-1);
	res = 1 - res;
    } else {
	if (ex>=0) 
	{  // ex>=0 --> t>=0.5; 
	    res = 1-t;   // res: delta = 1-t;
	    t = res * res;
	    times2pown(res,1); // res: 2*delta
	    res = res - t;     // res: 1-x2 = 2*delta - delta2
	} else res = 1-t*t;    // res: Maschinenwert von 1-x2
	res = sqrt(res);       // res: Nullte Naeherung 
    }
    return res;
} // sqrt1mx2
Пример #4
0
real expmx2(const real& x) throw()
// e^(-x^2);  rel. Fehlerschranke:  eps = 4.618919E-16 = e(f) gilt
// fuer alle |x| <= expmx2_x0 = 26.61571750925....
// Fuer |x| > expmx2_x0 --> expmx2(x) = 0;
// Blomquist, 05.07.04;
{ 
    real t=x,u,v,res=0;
    int ex;
    if (t<0) t = -t;  // t >= 0;
    ex = expo(t);
    if (ex<=-26) res = 1;  // t < 2^(-26)
    else if (ex<=-6)       // t < 2^(-6)
    {
	u = t*t;  v = u; 
	times2pown(v,-1);  // v: 0.5*x2
	res = 1-u*( 1-v*(1-u/3) );
    } else if (t<=expmx2_x0) {
	sqr2uv(x,u,v);  // u:= x*x,v aus S(2,53); x2 = u+v (exakt!)
	res = exp(-u); 
	if (v!=0) { 
	    times2pown(res,500);  // Die Skalierung verhindert, dass 
	    v *= res; // v*exp(-u) in den denormalisierten Bereich faellt
	    res -= v;
	    times2pown(res,-500); // Rueckskalierung
	}
    }
    return res;
} // expmx2
Пример #5
0
static void xscalbln(xcomplex *z, long int a)
{
  cxsc::real re = Re(*z), im = Im(*z);
  
  times2pown(re,a);
  times2pown(im,a);
  *z = cxsc::complex(re,im);
}
Пример #6
0
real expx2(const real& x)
// e^(+x^2);  rel. Fehlerschranke:  eps = 4.618958E-16 = e(f) gilt
// fuer alle |x| <= x0 = 26.64174755704632....
// x0 = 7498985273150791.0 / 281474976710656.0;
// Fuer |x| > x0 --> Programmabbruch
// Ausfuehrlich getestet;  Blomquist, 26.07.06;
{
    real t=x,u,v,res;
    int ex;
    if (t<0) t = -t;  // t >= 0;
    ex = expo(t);
    if (ex<=-26) res = 1;  // t < 2^(-26)
    else 
	if (ex<=-6)       // t < 2^(-6)
	{
	    u = t*t;  v = u;
	    times2pown(v,-1);  // v: 0.5*x^2
	    res = 1+u*( 1+v*(1+u/3) );
	} 
	else 
	{
	    sqr2uv(x,u,v);  // u := x*x und v aus S(2,53); 
                            // x^2 = u+v ist exakt!
	    res = exp(u);
	    v *= res;       // v*exp(+u)
	    res += v;
	}
    return res;
} // expx2
Пример #7
0
real sqrtx2m1(const real& x) 
// sqrt(x^2-1);  rel. Fehlerschranke:  eps = 2.221305E-16 = e(f)
// Blomquist, 13.04.04;
{    const real c1 = 1.000732421875, 
	       c2 = 44000.0,
               c3 = 1024.0;  // c1,c2,c3 werden exakt gespeichert!
    real res,ep,ep2,s1,s2,x1,x2,arg=x;
    if (sign(arg)<0) arg = -arg; // arg = |x| >= 0
    if (arg <= c1) { // x = 1+ep; x^2-1 = 2*ep + ep^2;
	ep = x - 1; // Differenz rundungsfehlerfrei!
	ep2 = ep*ep;  // ep2 i.a. fehlerbehaftet!
	times2pown(ep,1);  // ep = 2*ep;
	res = sqrt(ep+ep2); // res=y0: Startwert;
        // x - y0^2 = (2*eps - s1^2) + [eps^2 - s2*(y0 + s1)]
	s1 = Cut26(res);  s2 = res - s1; // Startwert y0 = s1 + s2;
	arg = ep - s1*s1;  // arg = 2*eps - s1^2;
	arg += (ep2 - s2*(res+s1));  // arg = x - y0^2
	if (sign(arg)>0) {
	arg = arg / res;
	times2pown(arg,-1);
	res += arg;  // 1. Newton-Schritt beendet; eps = 2.221261E-16
	}
    } else if (arg<c2) { 
        // x-y0^2 = [(x1^2-1)-s1^2] + [x2*(x+x1)-s2*(y0+s1)]
	x1 = Cut26(arg);  x2 = arg - x1;  // arg = x = x1 + x2;
	ep2 = x2*(arg+x1);  // ep2 ist fehlerbehaftet
	x2 = x1*x1;  ep = x2-1;
	res = sqrt(ep+ep2); // res ist Startwert für Newton-Verfahren
	s1 = Cut26(res);  s2 = res - s1;  // Startwert = s1 + s2;
	ep2 = ep2 - s2 * (res+s1); // ep2 = [x2*(x+x1)-s2*(y0+s1)]
	if (arg<c3) ep -= s1*s1;   // ep = (x1^2-1) - s1^2;
	else {
	    x2 -= s1*s1;  // x2 = x1^2-s1^2
	    ep = x2 - 1; }         // ep = (x1^2-s1^2) - 1;
	ep += ep2;        // ep = x - y0^2;
	ep /= res;
	times2pown(ep,-1);
	res = res + ep;  // 1. Newton-Schritt in hoher Genauigkeit
                         // beendet;  eps = 2.221305E-16
    } else { // arg = |x| >= 44000;
	res = -1/arg;
	times2pown(res,-1); // Multiplikation mit 0.5;
	res += arg;  // res = x - 1/(2*x);  eps = 2.221114E-16
    }
    return res;
} // sqrtx2m1 (Punktargumente)
Пример #8
0
real sqrtp1m1(const real& x) throw()
// sqrtp1m1(x) = sqrt(x+1)-1;
// Blomquist, 05.08.03; 
{
    real y = x;
    int ex = expo(x);
    if (ex<=-50) times2pown(y,-1);  // |x|<2^(-50); fast division by 2 
    else if (ex>=105) y = sqrt(x);  // x >= 2^(+104) = 2.02824...e+31
    else if (ex>=53) y = sqrt(x)-1; // x >= 2^(+52)  = 4.50359...e+15
    else if (x>-0.5234375 && x<=sqrtp1m1_s ) y = x / (sqrt(x+1) + 1);
    else y = sqrt(x+1)-1;
    return y;
}
Пример #9
0
real expx2m1(const real& x)
// e^(+x^2)-1; rel. Fehlerschranke: eps = 4.813220E-16 = e(f) gilt
// fuer alle x, mit:  2^(-511) <= x <= x0 = 26.64174755704632....
// x0 = 7498985273150791.0 / 281474976710656.0;
// Fuer x > x0 --> Programmabbruch wegen Overflow;
// Fuer 0 < x < 2^(-511) --> Programmabbruch, denorm. Bereich!!
// Ausfuehrlich getestet;  Blomquist, 10.08.2006;
{
    real t(x),u,v,y,res(0);
    int ex;
    if (t<0) t = -t;  // t >= 0;

    if (t>=6.5) res = expx2(t);
    else 
    {
	ex = expo(t);
	sqr2uv(x,u,v);  // u := x*x und v aus S(2,53); 
	if (ex>=2) // g4(x)
	{
	    y = exp(u); 
	    res = 1 - v*y;
	    res = y - res;
	}
	else 
	    if (ex>=-8) res = expm1(u) + v*exp(u); // g3(x)
	    else 
		if (ex>=-25) { // g2(x)
		    y = u*u;
                    times2pown(y,-1);
		    res = (1+u/3)*y + u;
		}
		else 
		    if(ex>=-510) res = u;  // g1(x)
		    else if (ex>=-1073) 
		    {
			std::cerr << "expx2m1: denormalized range!" 
                             << std::endl; exit(1);
		    }
    }

    return res;
} // expx2m1
Пример #10
0
real ln_sqrtx2y2(const real& x, const real& y) 
                                throw(STD_FKT_OUT_OF_DEF)
// ln( sqrt(x^2+y^2) ) == 0.5*ln(x^2+y^2); Blomquist, 21.11.03;
// Relative error bound: 5.160563E-016;
// Absolute error bound: 2.225075E-308; if x=1 and 0<=y<=b0;
{
    int j,N;
    real a,b,r,r1;
    dotprecision dot;
   
    a = sign(x)<0 ? -x : x;  // a = |x| >= 0;
    b = sign(y)<0 ? -y : y;  // b = |y| >= 0;
    int exa=expo(a), exb=expo(b), ex;
    if (b > a)
    {
	r = a;   a = b;   b = r;
	ex = exa;   exa = exb;   exb = ex;
    }
    // It holds now:   0 <= b <= a 
    if (sign(a)==0)
        cxscthrow(STD_FKT_OUT_OF_DEF
                    ("real ln_sqrtx2y2(const real&, const real&)"));
    if (exa>20) // to avoid overflow by calculating a^2 + b^2
    {  // a>=2^(20):
	j = Interval_Nr(B_lnx2y2_1,21,exa); // j: No. of subinterval
	N = B_lnx2y2_N1[j];    // N: Optimal int value
	if (exb-exa > -25)
	{   // For (exb-exa>-25) we use the complete term:  
            // N*ln(2) + [ln(2^(-N)*a)+0.5*ln(1+(b/a)^2)]
	    b = b/a;  // a > 0
	    b = lnp1(b*b);
	    times2pown(b,-1);  // exact division by 2
	    times2pown(a,-N);
	    r = b + ln(a); // [ ... ] calculated!
	    r += B_lnx2y2_c1[j];
	}
	else { // For (exb-exa<=-25) only two summands!: 
	    times2pown(a,-N);
	    r = ln(a) + B_lnx2y2_c1[j];
	}
    }
    else  // exa<=20 or a<2^(20):
    {     // Now calculation of a^2+b^2 without overflow:
	if (exa<=-20) // to avoid underflow by calculating a^2+b^2
	    if (exa<=-1022) // a in the denormalized range
	    {
		r = b/a;
		r = lnp1(r*r);  times2pown(r,-1); // r: 0.5*ln(1+..)
		times2pown(a,1067);
		r += ln(a);     // [ .... ] ready
		r -= ln2_1067;  // rel. error = 2.459639e-16;
	    }
	    else // MinReal=2^(-1022) <= a < 2^(-20)
	    {    // Calculating the number j of the subinterval:
		j = 20 - Interval_Nr(B_lnx2y2_2,21,exa);
		r = a;  times2pown(r,B_lnx2y2_N1[j]);
		r = ln(r);  // r: ln(2^N*a);
		if (exb-exa > -25) { // calculating the complete term
		    b = b/a;
		    a = lnp1(b*b);
		    times2pown(a,-1);
		    r += a;  // [ ... ] ready now
		}
                // We now have: exb-exa<=-25,  ==>  b/a <= 2^(-24);
		r -= B_lnx2y2_c1[j]; // 0.5*ln(1+(b/a)^2) neglected!
                // relative error = 4.524090e-16 in both cases;
	    }
	else // calculation of a^2+b^2 without overflow or underflow:
	{   // exa>-20  respective  a>=2^(-20):
	    dot = 0;
	    accumulate(dot,a,a);
	    accumulate(dot,b,b);  // dot = a^2+b^2, exact!
	    real s = rnd(dot);    // s = a^2 + b^2, rounded!
	    if (s>=0.25 && s<=1.75)
		if (s>=0.828125 && s<=1.171875)
		{ // Series:
		    if (a==1 && exb<=-28)
		    {
			r = b;  times2pown(r,-1);
			r *= b;
		    }
		    else {
			dot -= 1;
			r = rnd(dot); // r = a^2+b^2-1 rounded!
			r = lnp1(r);
			times2pown(r,-1);
		    }
		}
		else { // Reading dot = a^2+b^2 twice:
		    r = rnd(dot);
		    dot -= r;
		    r1 = rnd(dot); // a^2+b^2 = r+r1, rounded!
		    r1 = lnp1(r1/r);
		    r = ln(r) + r1;
		    times2pown(r,-1); // exact division by 2
		}
	    else { // calculating straight from: 0.5*ln(x^2+y^2)
		r = ln(s);
		times2pown(r,-1);
	    } 
	}
    }
    return r;
} // ln_sqrtx2y2