testSpecFunc.cxx

Go to the documentation of this file.
00001 
00002 /* MathCore/tests/test_SpecFunc.cpp
00003  * 
00004  * Copyright (C) 2004 Andras Zsenei
00005  * 
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020  */
00021 
00022 
00023 /**
00024 
00025 Test file for the special functions implemented in MathMore. For
00026 the moment nothing exceptional. Evaluates the functions and checks
00027 if the value is right against values copied from the GSL tests.
00028 
00029 */
00030 
00031 
00032 
00033 
00034 
00035 #include <iostream> 
00036 #include <iomanip> 
00037 #include <string>
00038 #include <limits>
00039 
00040 #include "Math/SpecFuncMathMore.h"
00041 #ifndef NO_MATHCORE
00042 #include "Math/SpecFuncMathCore.h"
00043 #endif
00044 
00045 #ifdef CHECK_WITH_GSL
00046 #include <gsl/gsl_sf.h>
00047 #endif
00048 
00049 #ifndef PI
00050 #define PI       3.14159265358979323846264338328      /* pi */
00051 #endif
00052 
00053 
00054 int compare( const std::string & name, double v1, double v2, double scale = 2.0) {
00055   //  ntest = ntest + 1; 
00056 
00057    std::cout << std::setw(50) << std::left << name << ":\t";   
00058    
00059   // numerical double limit for epsilon 
00060    double eps = scale* std::numeric_limits<double>::epsilon();
00061    int iret = 0; 
00062    double delta = v2 - v1;
00063    double d = 0;
00064    if (delta < 0 ) delta = - delta; 
00065    if (v1 == 0 || v2 == 0) { 
00066       if  (delta > eps ) { 
00067          iret = 1; 
00068       }
00069    }
00070    // skip case v1 or v2 is infinity
00071    else { 
00072       d = v1; 
00073 
00074       if ( v1 < 0) d = -d; 
00075       // add also case when delta is small by default
00076       if ( delta/d  > eps && delta > eps ) 
00077          iret =  1; 
00078    }
00079 
00080    if (iret == 0) 
00081       std::cout <<" OK" << std::endl;
00082    else { 
00083       std::cout <<" FAILED " << std::endl;
00084       int pr = std::cout.precision (18);
00085       std::cout << "\nDiscrepancy in " << name << "() :\n  " << v1 << " != " << v2 << " discr = " << int(delta/d/eps) 
00086                 << "   (Allowed discrepancy is " << eps  << ")\n\n";
00087       std::cout.precision (pr);
00088       //nfail = nfail + 1;
00089    }
00090    return iret; 
00091 }
00092 
00093 
00094 
00095 // void showDiff(std::string name, double calculatedValue, double expectedValue, double scale = 1.0) {
00096 
00097 //    compare(calculatedValue, expectedValue, name, scale)
00098 
00099 //   std::cout << name << calculatedValue << " expected value: " << expectedValue;
00100 //   int prec = std::cout.precision();
00101 //   std::cout.precision(5);
00102 //   std::cout << " diff: " << (calculatedValue-expectedValue) << " reldiff: " << 
00103 //     (calculatedValue-expectedValue)/expectedValue << std::endl;
00104 //   std::cout.precision(prec);
00105 
00106 // }
00107 
00108 
00109 
00110 int testSpecFunc() { 
00111 
00112    using namespace ROOT::Math;
00113 
00114    int iret = 0; 
00115 
00116    std::cout.precision(20);
00117 
00118 #ifndef NO_MATHCORE 
00119 
00120    // explicit put namespace to be sure to use right ones
00121    
00122    iret |= compare("tgamma(9.0) ", ROOT::Math::tgamma(9.0), 40320.0, 4);
00123 
00124    iret |= compare("lgamma(0.1) ", ROOT::Math::lgamma(0.1),  2.252712651734205, 4);
00125 
00126    iret |= compare("inc_gamma(1,0.001) ", ROOT::Math::inc_gamma(1.0,0.001), 0.0009995001666250083319, 1);
00127 
00128    // increase tolerance when using Cephes (test values are correctly checked with Mathematica
00129    // GSL was more precise in this case
00130    iret |= compare("inc_gamma(100,99) ", ROOT::Math::inc_gamma(100.,99.), 0.4733043303994607, 100);
00131 
00132    iret |= compare("inc_gamma_c(100,99) ", ROOT::Math::inc_gamma_c(100.,99.), 0.5266956696005394, 100);
00133 
00134    // need to increase here by a further factor of 5 for Windows 
00135    iret |= compare("inc_gamma_c(1000,1000.1) ", ROOT::Math::inc_gamma_c(1000.,1000.1),  0.4945333598559338247, 5000);
00136 
00137    iret |= compare("erf(0.5) ", ROOT::Math::erf(0.5), 0.5204998778130465377);
00138    
00139    iret |= compare("erfc(-1.0) ", ROOT::Math::erfc(-1.0), 1.8427007929497148693);
00140    
00141    iret |= compare("beta(1.0, 5.0) ", ROOT::Math::beta(1.0, 5.0), 0.2);
00142 
00143    iret |= compare("inc_beta(1,1,1) ", ROOT::Math::inc_beta(1.0, 1.0, 1.0), 1.0);
00144 
00145    iret |= compare("inc_beta(0.5,0.1,1.0) ", ROOT::Math::inc_beta(0.5, 0.1, 1.0), 0.9330329915368074160 );
00146 
00147 
00148 #endif
00149 
00150    iret |= compare("assoc_laguerre(4,  2, 0.5) ", assoc_laguerre(4, 2, 0.5), 6.752604166666666667,8);
00151 
00152    iret |= compare("assoc_legendre(10, 1, -0.5) ", assoc_legendre(10, 1, -0.5), 2.0066877394361256516);
00153 
00154    iret |= compare("comp_ellint_1(0.50) ", comp_ellint_1(0.50), 1.6857503548125960429);
00155 
00156    iret |= compare("comp_ellint_2(0.50) ", comp_ellint_2(0.50), 1.4674622093394271555);
00157 
00158    iret |= compare("comp_ellint_3(0.5, 0.5) ", comp_ellint_3(0.5, 0.5), 2.41367150420119, 16);
00159 
00160    iret |= compare("conf_hyperg(1, 1.5, 1) ", conf_hyperg(1, 1.5, 1), 2.0300784692787049755);
00161 
00162    iret |= compare("cyl_bessel_i(1.0, 1.0) ", cyl_bessel_i(1.0, 1.0), 0.5651591039924850272);
00163 
00164    iret |= compare("cyl_bessel_j(0.75, 1.0) ", cyl_bessel_j(0.75, 1.0), 0.5586524932048917478, 16);
00165 
00166    iret |= compare("cyl_bessel_k(1.0, 1.0) ", cyl_bessel_k(1.0, 1.0), 0.6019072301972345747);
00167 
00168    iret |= compare("cyl_neumann(0.75, 1.0) ", cyl_neumann(0.75, 1.0), -0.6218694174429746383 );
00169 
00170    iret |= compare("ellint_1(0.50, PI/3.0) ", ellint_1(0.50, PI/3.0), 1.0895506700518854093);
00171 
00172    iret |= compare("ellint_2(0.50, PI/3.0) ", ellint_2(0.50, PI/3.0), 1.0075555551444720293);
00173 
00174    iret |= compare("ellint_3(-0.50, 0.5, PI/3.0) ", ellint_3(-0.50, 0.5, PI/3.0), 0.9570574331323584890);
00175 
00176    iret |= compare("expint(1.0) ", expint(1.0), 1.8951178163559367555);
00177 
00178    // std::cout << "Hermite polynomials: to do!" << std::endl;
00179 
00180    iret |= compare("hyperg(8, -8, 1, 0.5) ", hyperg(8, -8, 1, 0.5), 0.13671875);
00181 
00182    iret |= compare("laguerre(4, 1.) ", laguerre(4, 1.), -0.6250); // need to find more precise value
00183 
00184    iret |= compare("legendre(10, -0.5) ", legendre(10, -0.5), -0.1882286071777345);
00185 
00186    iret |= compare("riemann_zeta(-0.5) ", riemann_zeta(-0.5), -0.207886224977354566017307, 16);
00187 
00188    iret |= compare("sph_bessel(1, 10.0) ", sph_bessel(1, 10.0), 0.07846694179875154709000);
00189 
00190    iret |= compare("sph_legendre(3, 1, PI/2.) ", sph_legendre(3, 1, PI/2.), 0.323180184114150653007);
00191 
00192    iret |= compare("sph_neumann(0, 1.0) ", sph_neumann(0, 1.0), -0.54030230586813972);
00193 
00194    iret |= compare("airy_Ai(-0.5) ", airy_Ai(-0.5), 0.475728091610539583);           // wolfram alpha:  0.47572809161053958880
00195 
00196    iret |= compare("airy_Bi(0.5) ", airy_Bi(0.5), 0.854277043103155553);             // wolfram alpha:  0.85427704310315549330
00197 
00198    iret |= compare("airy_Ai_deriv(-2) ", airy_Ai_deriv(-2), 0.618259020741691145);   // wolfram alpha:  0.61825902074169104141
00199 
00200    iret |= compare("airy_Bi_deriv(-3) ", airy_Bi_deriv(-3), -0.675611222685258639);  // wolfram alpha: -0.67561122268525853767
00201 
00202    iret |= compare("airy_zero_Ai(2) ", airy_zero_Ai(2), -4.08794944413097028, 8);    // mathworld: -4.08795
00203 
00204    iret |= compare("airy_zero_Bi(2) ", airy_zero_Bi(2), -3.27109330283635291, 8);    // mathworld: -3.27109
00205 
00206    iret |= compare("airy_zero_Ai_deriv(2) ", airy_zero_Ai_deriv(2), -3.24819758217983656, 8);
00207 
00208    iret |= compare("airy_zero_Bi_deriv(2) ", airy_zero_Bi_deriv(2), -4.07315508907182799, 8);
00209 
00210    if (iret != 0) { 
00211       std::cout << "\n\nError:  Special Functions Test FAILED !!!!!" << std::endl;
00212    }
00213    return iret; 
00214 
00215 }
00216 
00217 void getGSLErrors() { 
00218 
00219 #ifdef CHECK_WITH_GSL
00220    gsl_sf_result r; 
00221    int iret; 
00222 
00223    iret = gsl_sf_ellint_P_e(PI/2.0, 0.5, -0.5, GSL_PREC_DOUBLE, &r);
00224    std::cout << "comp_ellint_3(0.50, 0.5) : " << r.val << " err:  " << r.err << "  iret:  " << iret << std::endl; 
00225 
00226    iret = gsl_sf_ellint_P_e(PI/3.0, 0.5, 0.5, GSL_PREC_DOUBLE, &r);
00227    std::cout << "ellint_3(0.50, 0.5, PI/3.0) : " << r.val << " err:  " << r.err << "  iret:  " << iret << std::endl; 
00228    
00229    iret = gsl_sf_zeta_e(-0.5, &r);
00230    std::cout << "riemann_zeta(-0.5) : " << r.val << " err:  " << r.err << "  iret:  " << iret << std::endl; 
00231 #endif
00232 
00233 
00234 }
00235 
00236 
00237 int main() { 
00238 
00239    int iret = 0; 
00240    iret |=  testSpecFunc();
00241 
00242    getGSLErrors(); 
00243    return iret; 
00244 }
00245 
00246 

Generated on Tue Jul 5 14:34:59 2011 for ROOT_528-00b_version by  doxygen 1.5.1