// cl_hypot(). // General includes. #include "cl_sysdep.h" // Specification. #include "cl_C.h" // Implementation. #include "cln/real.h" #include "cl_R.h" #include "cln/rational.h" #include "cl_RA.h" #include "cl_F.h" #include "cl_SF.h" #include "cl_FF.h" #include "cl_DF.h" #include "cl_LF.h" namespace cln { const cl_R cl_hypot (const cl_R& a, const cl_R& b) { // Methode: // Falls a=0: (abs b). // Falls b=0: (abs a). // Falls a und b beide rational sind: // c:=a*a+b*b, liefere (sqrt c). // Falls a oder b Floats sind: // Falls einer von beiden rational ist, runde ihn zum selben Float-Typ // wie der andere und führe das UP durch. // Falls beide Floats sind, erweitere auf den genaueren, führe das UP // durch und runde wieder auf den ungenaueren. // Das Ergebnis ist ein Float >=0. // UP: [a,b Floats vom selben Typ] // a=0.0 -> liefere abs(b). // b=0.0 -> liefere abs(a). // e:=max(exponent(a),exponent(b)). // a':=a/2^e bzw. 0.0 bei Underflowmöglichkeit (beim Skalieren a':=a/2^e // oder beim Quadrieren a'*a': 2*(e-exponent(a))>exp_mid-exp_low-1 // d.h. exponent(b)-exponent(a)>floor((exp_mid-exp_low-1)/2) ). // b':=b/2^e bzw. 0.0 bei Underflowmöglichkeit (beim Skalieren b':=b/2^e // oder beim Quadrieren b'*b': 2*(e-exponent(b))>exp_mid-exp_low-1 // d.h. exponent(a)-exponent(b)>floor((exp_mid-exp_low-1)/2) ). // c':=a'*a'+b'*b', c':=sqrt(c'), liefere 2^e*c'. if (rationalp(a)) { DeclareType(cl_RA,a); if (eq(a,0)) // a=0 -> (abs b) return abs(b); if (rationalp(b)) { DeclareType(cl_RA,b); // a,b beide rational return sqrt(square(a)+square(b)); } else { DeclareType(cl_F,b); // a rational, b Float floatcase(b , return cl_hypot(cl_RA_to_SF(a),b); , return cl_hypot(cl_RA_to_FF(a),b); , return cl_hypot(cl_RA_to_DF(a),b); , return cl_hypot(cl_RA_to_LF(a,TheLfloat(b)->len),b); ); } } else { DeclareType(cl_F,a); if (rationalp(b)) { DeclareType(cl_RA,b); // a Float, b rational if (eq(b,0)) // b=0 -> (abs a) return abs(a); floatcase(a , return cl_hypot(a,cl_RA_to_SF(b)); , return cl_hypot(a,cl_RA_to_FF(b)); , return cl_hypot(a,cl_RA_to_DF(b)); , return cl_hypot(a,cl_RA_to_LF(b,TheLfloat(a)->len)); ); } else { DeclareType(cl_F,b); // a,b Floats #ifndef CL_LF_PEDANTIC GEN_F_OP2(a,b, cl_hypot, 1, 1, return); #else GEN_F_OP2(a,b, cl_hypot, 1, 0, return); #endif } } } } // namespace cln