inline std::string platform_string() { std::ostringstream os; os << "OpenVPN core " << OPENVPN_VERSION; os << ' ' << platform_name(); # if defined(__amd64__) || defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) os << " x86_64"; # elif defined(__i386__) || defined(_M_IX86) os << " i386"; # elif defined(__aarch64__) || defined(__arm64__) os << " arm64"; # elif defined(__arm__) || defined(_M_ARM) # if defined(__ARM_ARCH_7S__) || defined(_ARM_ARCH_7S) os << " armv7s"; # elif defined(__ARM_ARCH_7A__) os << " armv7a"; # elif defined(__ARM_V7__) || defined(_ARM_ARCH_7) os << " armv7"; # else os << " arm"; # endif # if defined(__thumb2__) os << " thumb2"; # elif defined(__thumb__) || defined(_M_ARMT) os << " thumb"; # endif # endif os << ' ' << (sizeof(void *) * 8) << "-bit"; return os.str(); }
int main() { # include "laguerre2.ipp" add_data(laguerre2); unsigned data_total = data.size(); screen_data([](const std::vector<double>& v){ return boost::math::laguerre(v[0], v[1]); }, [](const std::vector<double>& v){ return v[2]; }); #if defined(TEST_LIBSTDCXX) && !defined(COMPILER_COMPARISON_TABLES) screen_data([](const std::vector<double>& v){ return std::tr1::laguerre(v[0], v[1]); }, [](const std::vector<double>& v){ return v[2]; }); #endif #if defined(TEST_GSL) && !defined(COMPILER_COMPARISON_TABLES) screen_data([](const std::vector<double>& v){ return gsl_sf_laguerre_n(v[0], 0, v[1]); }, [](const std::vector<double>& v){ return v[2]; }); #endif unsigned data_used = data.size(); std::string function = "laguerre[br](" + boost::lexical_cast<std::string>(data_used) + "/" + boost::lexical_cast<std::string>(data_total) + " tests selected)"; std::string function_short = "laguerre"; double time; time = exec_timed_test([](const std::vector<double>& v){ return boost::math::laguerre(v[0], v[1]); }); std::cout << time << std::endl; #if !defined(COMPILER_COMPARISON_TABLES) && (defined(TEST_GSL) || defined(TEST_RMATH) || defined(TEST_LIBSTDCXX)) report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, boost_name()); #endif report_execution_time(time, std::string("Compiler Comparison on ") + std::string(platform_name()), function_short, compiler_name() + std::string("[br]") + boost_name()); // // Boost again, but with promotion to long double turned off: // #if !defined(COMPILER_COMPARISON_TABLES) if(sizeof(long double) != sizeof(double)) { time = exec_timed_test([](const std::vector<double>& v){ return boost::math::laguerre(v[0], v[1], boost::math::policies::make_policy(boost::math::policies::promote_double<false>())); }); std::cout << time << std::endl; #if !defined(COMPILER_COMPARISON_TABLES) && (defined(TEST_GSL) || defined(TEST_RMATH) || defined(TEST_LIBSTDCXX)) report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, boost_name() + "[br]promote_double<false>"); #endif report_execution_time(time, std::string("Compiler Comparison on ") + std::string(platform_name()), function_short, compiler_name() + std::string("[br]") + boost_name() + "[br]promote_double<false>"); } #endif #if defined(TEST_LIBSTDCXX) && !defined(COMPILER_COMPARISON_TABLES) time = exec_timed_test([](const std::vector<double>& v){ return std::tr1::laguerre(v[0], v[1]); }); std::cout << time << std::endl; report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, "tr1/cmath"); #endif #if defined(TEST_GSL) && !defined(COMPILER_COMPARISON_TABLES) time = exec_timed_test([](const std::vector<double>& v){ return gsl_sf_laguerre_n(v[0], 0, v[1]); }); std::cout << time << std::endl; report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, "GSL " GSL_VERSION); #endif return 0; }
int main() { # include "ibeta_small_data.ipp" # include "ibeta_data.ipp" # include "ibeta_large_data.ipp" # include "ibeta_int_data.ipp" add_data(ibeta_small_data); add_data(ibeta_data); add_data(ibeta_large_data); add_data(ibeta_int_data); unsigned data_total = data.size(); std::cout << "Screening boost data:\n"; screen_data([](const std::vector<double>& v){ return boost::math::ibetac(v[0], v[1], v[2]); }, [](const std::vector<double>& v){ return v[6]; }); #if defined(TEST_RMATH) && !defined(COMPILER_COMPARISON_TABLES) std::cout << "Screening libstdc++ data:\n"; screen_data([](const std::vector<double>& v){ return ::pbeta(v[2], v[0], v[1], 0, 0); }, [](const std::vector<double>& v){ return v[6]; }); #endif unsigned data_used = data.size(); std::string function = "ibetac[br](" + boost::lexical_cast<std::string>(data_used) + "/" + boost::lexical_cast<std::string>(data_total) + " tests selected)"; std::string function_short = "ibetac"; double time; time = exec_timed_test([](const std::vector<double>& v){ return boost::math::ibetac(v[0], v[1], v[2]); }); std::cout << time << std::endl; #if !defined(COMPILER_COMPARISON_TABLES) && (defined(TEST_GSL) || defined(TEST_RMATH)) report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, boost_name()); #endif report_execution_time(time, std::string("Compiler Comparison on ") + std::string(platform_name()), function_short, compiler_name() + std::string("[br]") + boost_name()); // // Boost again, but with promotion to long double turned off: // #if !defined(COMPILER_COMPARISON_TABLES) if(sizeof(long double) != sizeof(double)) { time = exec_timed_test([](const std::vector<double>& v){ return boost::math::ibetac(v[0], v[1], v[2], boost::math::policies::make_policy(boost::math::policies::promote_double<false>())); }); std::cout << time << std::endl; #if !defined(COMPILER_COMPARISON_TABLES) && (defined(TEST_GSL) || defined(TEST_RMATH)) report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, boost_name() + "[br]promote_double<false>"); #endif report_execution_time(time, std::string("Compiler Comparison on ") + std::string(platform_name()), function_short, compiler_name() + std::string("[br]") + boost_name() + "[br]promote_double<false>"); } #endif #if defined(TEST_RMATH) && !defined(COMPILER_COMPARISON_TABLES) time = exec_timed_test([](const std::vector<double>& v){ return ::pbeta(v[2], v[0], v[1], 0, 0); }); std::cout << time << std::endl; report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, "Rmath " R_VERSION_STRING); #endif return 0; }
/* update sys struct based on the sys.sys_product_name */ void update_map() { int i; char *platform = NULL; memset(&sys, 0, sizeof(sys_t)); sys.imap = -1; sys.fru_lookup1 = DEFAULT_FRU_LOOKUP1; sys.fru_lookup2 = DEFAULT_FRU_LOOKUP2; sys.fru_lookup3 = DEFAULT_FRU_LOOKUP3; sys.sys_product_name = platform_name(); if (sys.sys_product_name) { platform = strip(sys.sys_product_name); /* normalize */ if (platform) { sys.platform = strdup(platform); for (i = 0; maps[i].platform != NULL; i++) { if (verbose) printf("platform alias = %s\n", maps[i].alias); if (strstr(maps[i].alias, platform)) { if (verbose) printf("found alias = %s in name=%s, i=%d\n", maps[i].alias, platform, i); sys.imap = i; if (maps[i].fru_lookup1) sys.fru_lookup1 = maps[i].fru_lookup1; if (maps[i].fru_lookup2) sys.fru_lookup2 = maps[i].fru_lookup2; if (maps[i].fru_lookup3) sys.fru_lookup3 = maps[i].fru_lookup3; if (maps[i].dmi_lookup1) sys.dmi_lookup1 = maps[i].dmi_lookup1; if (maps[i].dmi_lookup2) sys.dmi_lookup2 = maps[i].dmi_lookup2; break; } } } } if (verbose) { if (sys.fru_lookup1) printf ("fru_lookup1 = %s\n", sys.fru_lookup1); if (sys.fru_lookup2) printf ("fru_lookup2 = %s\n", sys.fru_lookup2); if (sys.fru_lookup3) printf ("fru_lookup3 = %s\n", sys.fru_lookup3); if (sys.dmi_lookup1) printf ("dmi_lookup1 = %s\n", sys.dmi_lookup1); if (sys.dmi_lookup2) printf ("dmi_lookup2 = %s\n", sys.dmi_lookup2); } if (sys.imap == -1) { if (verbose) printf (" %s not supported yet\n", sys.platform); } }
int main() { typedef double T; #define SC_(x) static_cast<double>(x) # include "test_gamma_data.ipp" add_data(factorials); add_data(near_0); add_data(near_1); add_data(near_2); add_data(near_m10); add_data(near_m55); unsigned data_total = data.size(); screen_data([](const std::vector<double>& v){ return boost::math::lgamma(v[0]); }, [](const std::vector<double>& v){ return v[2]; }); #if defined(TEST_C99) && !defined(COMPILER_COMPARISON_TABLES) screen_data([](const std::vector<double>& v){ return ::lgamma(v[0]); }, [](const std::vector<double>& v){ return v[2]; }); #endif #if defined(TEST_LIBSTDCXX) && !defined(COMPILER_COMPARISON_TABLES) screen_data([](const std::vector<double>& v){ return std::tr1::lgamma(v[0]); }, [](const std::vector<double>& v){ return v[2]; }); #endif #if defined(TEST_GSL) && !defined(COMPILER_COMPARISON_TABLES) screen_data([](const std::vector<double>& v){ return gsl_sf_lngamma(v[0]); }, [](const std::vector<double>& v){ return v[2]; }); #endif #if defined(TEST_RMATH) && !defined(COMPILER_COMPARISON_TABLES) screen_data([](const std::vector<double>& v){ return lgammafn(v[0]); }, [](const std::vector<double>& v){ return v[2]; }); #endif unsigned data_used = data.size(); std::string function = "lgamma[br](" + boost::lexical_cast<std::string>(data_used) + "/" + boost::lexical_cast<std::string>(data_total) + " tests selected)"; std::string function_short = "lgamma"; double time = exec_timed_test([](const std::vector<double>& v){ return boost::math::lgamma(v[0]); }); std::cout << time << std::endl; #if !defined(COMPILER_COMPARISON_TABLES) && (defined(TEST_GSL) || defined(TEST_RMATH) || defined(TEST_C99) || defined(TEST_LIBSTDCXX)) report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, boost_name()); #endif report_execution_time(time, std::string("Compiler Comparison on ") + std::string(platform_name()), function_short, compiler_name() + std::string("[br]") + boost_name()); // // Boost again, but with promotion to long double turned off: // #if !defined(COMPILER_COMPARISON_TABLES) if(sizeof(long double) != sizeof(double)) { double time = exec_timed_test([](const std::vector<double>& v){ return boost::math::lgamma(v[0], boost::math::policies::make_policy(boost::math::policies::promote_double<false>())); }); std::cout << time << std::endl; #if !defined(COMPILER_COMPARISON_TABLES) && (defined(TEST_GSL) || defined(TEST_RMATH) || defined(TEST_C99) || defined(TEST_LIBSTDCXX)) report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, boost_name() + "[br]promote_double<false>"); #endif report_execution_time(time, std::string("Compiler Comparison on ") + std::string(platform_name()), function_short, compiler_name() + std::string("[br]") + boost_name() + "[br]promote_double<false>"); } #endif #if defined(TEST_C99) && !defined(COMPILER_COMPARISON_TABLES) time = exec_timed_test([](const std::vector<double>& v){ return ::lgamma(v[0]); }); std::cout << time << std::endl; report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, "math.h"); #endif #if defined(TEST_LIBSTDCXX) && !defined(COMPILER_COMPARISON_TABLES) time = exec_timed_test([](const std::vector<double>& v){ return std::tr1::lgamma(v[0]); }); std::cout << time << std::endl; report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, "tr1/cmath"); #endif #if defined(TEST_GSL) && !defined(COMPILER_COMPARISON_TABLES) time = exec_timed_test([](const std::vector<double>& v){ return gsl_sf_lngamma(v[0]); }); std::cout << time << std::endl; report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, "GSL " GSL_VERSION); #endif #if defined(TEST_RMATH) && !defined(COMPILER_COMPARISON_TABLES) time = exec_timed_test([](const std::vector<double>& v){ return lgammafn(v[0]); }); std::cout << time << std::endl; report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, "Rmath " R_VERSION_STRING); #endif return 0; }
int main() { typedef double T; #define SC_(x) static_cast<double>(x) # include "digamma_data.ipp" # include "digamma_root_data.ipp" # include "digamma_small_data.ipp" # include "digamma_neg_data.ipp" static const boost::array<boost::array<T, 2>, 5> digamma_bugs = {{ // Test cases from Rocco Romeo: {{ static_cast<T>(std::ldexp(1.0, -100)), SC_(-1.26765060022822940149670320537657721566490153286060651209008e30) }}, {{ static_cast<T>(-std::ldexp(1.0, -100)), SC_(1.26765060022822940149670320537542278433509846713939348790992e30) }}, {{ static_cast<T>(1), SC_(-0.577215664901532860606512090082402431042159335939923598805767) }}, {{ static_cast<T>(-1) + static_cast<T>(std::ldexp(1.0, -20)), SC_(-1.04857557721314249602848739817764518743062133735858753112190e6) }}, {{ static_cast<T>(-1) - static_cast<T>(std::ldexp(1.0, -20)), SC_(1.04857642278181269259522681939281063878220298942888100442172e6) }}, }}; static const boost::array<boost::array<T, 2>, 40> digamma_integers = { { { 1, SC_(-0.57721566490153286060651209008240243) }, { 2, SC_(0.42278433509846713939348790991759757) }, { 3, SC_(0.92278433509846713939348790991759757) }, { 4, SC_(1.2561176684318004727268212432509309) }, { 5, SC_(1.5061176684318004727268212432509309) }, { 6, SC_(1.7061176684318004727268212432509309) }, { 7, SC_(1.8727843350984671393934879099175976) }, { 8, SC_(2.0156414779556099965363450527747404) }, { 9, SC_(2.1406414779556099965363450527747404) }, { SC_(10.0), SC_(2.2517525890667211076474561638858515) }, { SC_(11.0), SC_(2.3517525890667211076474561638858515) }, { SC_(12.0), SC_(2.4426616799758120167383652547949424) }, { SC_(13.0), SC_(2.5259950133091453500716985881282758) }, { SC_(14.0), SC_(2.6029180902322222731486216650513527) }, { SC_(15.0), SC_(2.6743466616607937017200502364799241) }, { SC_(16.0), SC_(2.7410133283274603683867169031465908) }, { SC_(17.0), SC_(2.8035133283274603683867169031465908) }, { SC_(18.0), SC_(2.8623368577392250742690698443230614) }, { SC_(19.0), SC_(2.9178924132947806298246253998786169) }, { SC_(20.0), SC_(2.9705239922421490508772569788259854) }, { SC_(21.0), SC_(3.0205239922421490508772569788259854) }, { SC_(22.0), SC_(3.0681430398611966699248760264450330) }, { SC_(23.0), SC_(3.1135975853157421244703305718995784) }, { SC_(24.0), SC_(3.1570758461853073418616349197256654) }, { SC_(25.0), SC_(3.1987425128519740085283015863923321) }, { SC_(26.0), SC_(3.2387425128519740085283015863923321) }, { SC_(27.0), SC_(3.2772040513135124700667631248538705) }, { SC_(28.0), SC_(3.3142410883505495071038001618909076) }, { SC_(29.0), SC_(3.3499553740648352213895144476051933) }, { SC_(30.0), SC_(3.3844381326855248765619282407086415) }, { SC_(31.0), SC_(3.4177714660188582098952615740419749) }, { SC_(32.0), SC_(3.4500295305349872421533260901710071) }, { SC_(33.0), SC_(3.4812795305349872421533260901710071) }, { SC_(34.0), SC_(3.5115825608380175451836291204740374) }, { SC_(35.0), SC_(3.5409943255438998981248055910622727) }, { SC_(36.0), SC_(3.5695657541153284695533770196337013) }, { SC_(37.0), SC_(3.5973435318931062473311547974114791) }, { SC_(38.0), SC_(3.6243705589201332743581818244385061) }, { SC_(39.0), SC_(3.6506863483938174848844976139121903) }, { SC_(40.0), SC_(3.6763273740348431259101386395532160) } } }; static const boost::array<boost::array<T, 2>, 41> digamma_half_integers = { { { SC_(0.5), SC_(-1.9635100260214234794409763329987556) }, { SC_(1.5), SC_(0.036489973978576520559023667001244433) }, { SC_(2.5), SC_(0.70315664064524318722569033366791110) }, { SC_(3.5), SC_(1.1031566406452431872256903336679111) }, { SC_(4.5), SC_(1.3888709263595289015114046193821968) }, { SC_(5.5), SC_(1.6110931485817511237336268416044190) }, { SC_(6.5), SC_(1.7929113303999329419154450234226009) }, { SC_(7.5), SC_(1.9467574842460867880692911772687547) }, { SC_(8.5), SC_(2.0800908175794201214026245106020880) }, { SC_(9.5), SC_(2.1977378764029495331673303929550292) }, { SC_(10.5), SC_(2.3030010342976863752725935508497661) }, { SC_(11.5), SC_(2.3982391295357816133678316460878613) }, { SC_(12.5), SC_(2.4851956512749120481504403417400352) }, { SC_(13.5), SC_(2.5651956512749120481504403417400352) }, { SC_(14.5), SC_(2.6392697253489861222245144158141093) }, { SC_(15.5), SC_(2.7082352425903654325693420020210058) }, { SC_(16.5), SC_(2.7727513716226234970854710342790703) }, { SC_(17.5), SC_(2.8333574322286841031460770948851310) }, { SC_(18.5), SC_(2.8905002893715412460032199520279881) }, { SC_(19.5), SC_(2.9445543434255953000572740060820421) }, { SC_(20.5), SC_(2.9958363947076465821085560573640934) }, { SC_(21.5), SC_(3.0446168825125246308890438622421422) }, { SC_(22.5), SC_(3.0911285104195013750750903738700492) }, { SC_(23.5), SC_(3.1355729548639458195195348183144936) }, { SC_(24.5), SC_(3.1781261463533075216471943927825787) }, { SC_(25.5), SC_(3.2189424728839197665451535764560481) }, { SC_(26.5), SC_(3.2581581591584295704667222039070285) }, { SC_(27.5), SC_(3.2958940082150333440516278642843870) }, { SC_(28.5), SC_(3.3322576445786697076879915006480234) }, { SC_(29.5), SC_(3.3673453638769153217230792199462690) }, { SC_(30.5), SC_(3.4012436689616610844349436267259300) }, { SC_(31.5), SC_(3.4340305542075627237792059218078972) }, { SC_(32.5), SC_(3.4657765859535944698109519535539290) }, { SC_(33.5), SC_(3.4965458167228252390417211843231597) }, { SC_(34.5), SC_(3.5263965629914819554596316320843538) }, { SC_(35.5), SC_(3.5553820702378587670538345306350784) }, { SC_(36.5), SC_(3.5835510843223658093073556573956418) }, { SC_(37.5), SC_(3.6109483445963384120470816847929021) }, { SC_(38.5), SC_(3.6376150112630050787137483514595687) }, { SC_(39.5), SC_(3.6635890372370310527397223774335947) }, { SC_(40.5), SC_(3.6889054929332335843852919976867593) } } }; add_data(digamma_data); add_data(digamma_root_data); add_data(digamma_small_data); add_data(digamma_neg_data); add_data(digamma_bugs); add_data(digamma_integers); add_data(digamma_half_integers); unsigned data_total = data.size(); screen_data([](const std::vector<double>& v){ return boost::math::digamma(v[0]); }, [](const std::vector<double>& v){ return v[1]; }); #if defined(TEST_GSL) && !defined(COMPILER_COMPARISON_TABLES) screen_data([](const std::vector<double>& v){ return gsl_sf_psi(v[0]); }, [](const std::vector<double>& v){ return v[1]; }); #endif #if defined(TEST_RMATH) && !defined(COMPILER_COMPARISON_TABLES) screen_data([](const std::vector<double>& v){ return ::digamma(v[0]); }, [](const std::vector<double>& v){ return v[1]; }); #endif unsigned data_used = data.size(); std::string function = "digamma[br](" + boost::lexical_cast<std::string>(data_used) + "/" + boost::lexical_cast<std::string>(data_total) + " tests selected)"; std::string function_short = "digamma"; double time = exec_timed_test([](const std::vector<double>& v){ return boost::math::digamma(v[0]); }); std::cout << time << std::endl; #if !defined(COMPILER_COMPARISON_TABLES) && (defined(TEST_GSL) || defined(TEST_RMATH)) report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, boost_name()); #endif report_execution_time(time, std::string("Compiler Comparison on ") + std::string(platform_name()), function_short, compiler_name() + std::string("[br]") + boost_name()); // // Boost again, but with promotion to long double turned off: // #if !defined(COMPILER_COMPARISON_TABLES) if(sizeof(long double) != sizeof(double)) { double time = exec_timed_test([](const std::vector<double>& v){ return boost::math::digamma(v[0], boost::math::policies::make_policy(boost::math::policies::promote_double<false>())); }); std::cout << time << std::endl; #if !defined(COMPILER_COMPARISON_TABLES) && (defined(TEST_GSL) || defined(TEST_RMATH)) report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, boost_name() + "[br]promote_double<false>"); #endif report_execution_time(time, std::string("Compiler Comparison on ") + std::string(platform_name()), function_short, compiler_name() + std::string("[br]") + boost_name() + "[br]promote_double<false>"); } #endif #if defined(TEST_GSL) && !defined(COMPILER_COMPARISON_TABLES) time = exec_timed_test([](const std::vector<double>& v){ return gsl_sf_psi(v[0]); }); std::cout << time << std::endl; report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, "GSL " GSL_VERSION); #endif #if defined(TEST_RMATH) && !defined(COMPILER_COMPARISON_TABLES) time = exec_timed_test([](const std::vector<double>& v){ return ::digamma(v[0]); }); std::cout << time << std::endl; report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, "Rmath " R_VERSION_STRING); #endif return 0; }
int main() { typedef double T; #define SC_(x) static_cast<double>(x) # include "../../test/cbrt_data.ipp" add_data(cbrt_data); unsigned data_total = data.size(); screen_data([](const std::vector<double>& v){ return boost::math::cbrt(v[1]); }, [](const std::vector<double>& v){ return v[0]; }); #if defined(TEST_C99) && !defined(COMPILER_COMPARISON_TABLES) screen_data([](const std::vector<double>& v){ return ::cbrt(v[1]); }, [](const std::vector<double>& v){ return v[0]; }); #endif #if defined(TEST_LIBSTDCXX) && !defined(COMPILER_COMPARISON_TABLES) screen_data([](const std::vector<double>& v){ return std::tr1::cbrt(v[1]); }, [](const std::vector<double>& v){ return v[0]; }); #endif unsigned data_used = data.size(); std::string function = "cbrt[br](" + boost::lexical_cast<std::string>(data_used) + "/" + boost::lexical_cast<std::string>(data_total) + " tests selected)"; std::string function_short = "cbrt"; double time = exec_timed_test([](const std::vector<double>& v){ return boost::math::cbrt(v[1]); }); std::cout << time << std::endl; #if defined(COMPILER_COMPARISON_TABLES) report_execution_time(time, std::string("Compiler Option Comparison on ") + platform_name(), "boost::math::cbrt", get_compiler_options_name()); #else #if !defined(COMPILER_COMPARISON_TABLES) && (defined(TEST_GSL) || defined(TEST_RMATH) || defined(TEST_C99) || defined(TEST_LIBSTDCXX)) report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, boost_name()); #endif report_execution_time(time, std::string("Compiler Comparison on ") + std::string(platform_name()), function_short, compiler_name() + std::string("[br]") + boost_name()); #endif // // Boost again, but with promotion to long double turned off: // #if !defined(COMPILER_COMPARISON_TABLES) if(sizeof(long double) != sizeof(double)) { double time = exec_timed_test([](const std::vector<double>& v){ return boost::math::cbrt(v[1], boost::math::policies::make_policy(boost::math::policies::promote_double<false>())); }); std::cout << time << std::endl; #if !defined(COMPILER_COMPARISON_TABLES) && (defined(TEST_GSL) || defined(TEST_RMATH) || defined(TEST_C99) || defined(TEST_LIBSTDCXX)) report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, boost_name() + "[br]promote_double<false>"); #endif report_execution_time(time, std::string("Compiler Comparison on ") + std::string(platform_name()), function_short, compiler_name() + std::string("[br]") + boost_name() + "[br]promote_double<false>"); } #endif #if defined(TEST_C99) && !defined(COMPILER_COMPARISON_TABLES) time = exec_timed_test([](const std::vector<double>& v){ return ::cbrt(v[1]); }); std::cout << time << std::endl; report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, "math.h"); #endif #if defined(TEST_LIBSTDCXX) && !defined(COMPILER_COMPARISON_TABLES) time = exec_timed_test([](const std::vector<double>& v){ return std::tr1::cbrt(v[1]); }); std::cout << time << std::endl; report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, "tr1/cmath"); #endif return 0; }
int main() { #include "jacobi_elliptic.ipp" #include "jacobi_elliptic_small.ipp" #include "jacobi_near_1.ipp" #include "jacobi_large_phi.ipp" add_data(data1); add_data(jacobi_elliptic); add_data(jacobi_elliptic_small); add_data(jacobi_near_1); add_data(jacobi_large_phi); unsigned data_total = data.size(); std::cout << "Screening Boost data:\n"; screen_data([](const std::vector<double>& v) { return boost::math::jacobi_dn(v[1], v[0]); }, [](const std::vector<double>& v) { return v[4]; }); #if defined(TEST_GSL) && !defined(COMPILER_COMPARISON_TABLES) std::cout << "Screening GSL data:\n"; screen_data([](const std::vector<double>& v) { double s, c, d; gsl_sf_elljac_e(v[0], v[1] * v[1], &s, &c, &d); return d; }, [](const std::vector<double>& v) { return v[4]; }); #endif unsigned data_used = data.size(); std::string function = "jacobi_dn[br](" + boost::lexical_cast<std::string>(data_used) + "/" + boost::lexical_cast<std::string>(data_total) + " tests selected)"; std::string function_short = "jacobi_dn"; double time; time = exec_timed_test([](const std::vector<double>& v) { return boost::math::jacobi_dn(v[1], v[2]); }); std::cout << time << std::endl; #if !defined(COMPILER_COMPARISON_TABLES) && (defined(TEST_GSL) || defined(TEST_RMATH)) report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, boost_name()); #endif report_execution_time(time, std::string("Compiler Comparison on ") + std::string(platform_name()), function_short, compiler_name() + std::string("[br]") + boost_name()); // // Boost again, but with promotion to long double turned off: // #if !defined(COMPILER_COMPARISON_TABLES) if(sizeof(long double) != sizeof(double)) { time = exec_timed_test([](const std::vector<double>& v) { return boost::math::jacobi_dn(v[1], v[0], boost::math::policies::make_policy(boost::math::policies::promote_double<false>())); }); std::cout << time << std::endl; #if !defined(COMPILER_COMPARISON_TABLES) && (defined(TEST_GSL) || defined(TEST_RMATH)) report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, boost_name() + "[br]promote_double<false>"); #endif report_execution_time(time, std::string("Compiler Comparison on ") + std::string(platform_name()), function_short, compiler_name() + std::string("[br]") + boost_name() + "[br]promote_double<false>"); } #endif #if defined(TEST_GSL) && !defined(COMPILER_COMPARISON_TABLES) time = exec_timed_test([](const std::vector<double>& v) { double s, c, d; gsl_sf_elljac_e(v[0], v[1] * v[1], &s, &c, &d); return d; }); std::cout << time << std::endl; report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, "GSL " GSL_VERSION); #endif return 0; }
int main() { #include "bessel_j_int_data.ipp" add_data(j0_data); add_data(j0_tricky); add_data(j1_data); add_data(j1_tricky); add_data(jn_data); add_data(bessel_j_int_data); unsigned data_total = data.size(); screen_data([](const std::vector<double>& v){ return boost::math::cyl_bessel_j(static_cast<int>(v[0]), v[1]); }, [](const std::vector<double>& v){ return v[2]; }); #if defined(TEST_C99) && !defined(COMPILER_COMPARISON_TABLES) screen_data([](const std::vector<double>& v){ return ::jn(static_cast<int>(v[0]), v[1]); }, [](const std::vector<double>& v){ return v[2]; }); #endif #if defined(TEST_LIBSTDCXX) && !defined(COMPILER_COMPARISON_TABLES) screen_data([](const std::vector<double>& v){ return std::tr1::cyl_bessel_j(static_cast<int>(v[0]), v[1]); }, [](const std::vector<double>& v){ return v[2]; }); #endif #if defined(TEST_GSL) && !defined(COMPILER_COMPARISON_TABLES) screen_data([](const std::vector<double>& v){ return gsl_sf_bessel_Jn(static_cast<int>(v[0]), v[1]); }, [](const std::vector<double>& v){ return v[2]; }); #endif #if defined(TEST_RMATH) && !defined(COMPILER_COMPARISON_TABLES) screen_data([](const std::vector<double>& v){ return bessel_j(v[1], static_cast<int>(v[0])); }, [](const std::vector<double>& v){ return v[2]; }); #endif unsigned data_used = data.size(); std::string function = "cyl_bessel_j (integer order)[br](" + boost::lexical_cast<std::string>(data_used) + "/" + boost::lexical_cast<std::string>(data_total) + " tests selected)"; std::string function_short = "cyl_bessel_j (integer order)"; double time; time = exec_timed_test([](const std::vector<double>& v){ return boost::math::cyl_bessel_j(static_cast<int>(v[0]), v[1]); }); std::cout << time << std::endl; #if defined(COMPILER_COMPARISON_TABLES) report_execution_time(time, std::string("Compiler Option Comparison on ") + platform_name(), "boost::math::cyl_bessel_j (integer orders)", get_compiler_options_name()); #else #if !defined(COMPILER_COMPARISON_TABLES) && (defined(TEST_GSL) || defined(TEST_RMATH) || defined(TEST_C99) || defined(TEST_LIBSTDCXX)) report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, boost_name()); #endif report_execution_time(time, std::string("Compiler Comparison on ") + std::string(platform_name()), function_short, compiler_name() + std::string("[br]") + boost_name()); #endif // // Boost again, but with promotion to long double turned off: // #if !defined(COMPILER_COMPARISON_TABLES) if(sizeof(long double) != sizeof(double)) { time = exec_timed_test([](const std::vector<double>& v){ return boost::math::cyl_bessel_j(static_cast<int>(v[0]), v[1], boost::math::policies::make_policy(boost::math::policies::promote_double<false>())); }); std::cout << time << std::endl; #if !defined(COMPILER_COMPARISON_TABLES) && (defined(TEST_GSL) || defined(TEST_RMATH) || defined(TEST_C99) || defined(TEST_LIBSTDCXX)) report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, boost_name() + "[br]promote_double<false>"); #endif report_execution_time(time, std::string("Compiler Comparison on ") + std::string(platform_name()), function_short, compiler_name() + std::string("[br]") + boost_name() + "[br]promote_double<false>"); } #endif #if defined(TEST_C99) && !defined(COMPILER_COMPARISON_TABLES) time = exec_timed_test([](const std::vector<double>& v){ return ::jn(static_cast<int>(v[0]), v[1]); }); std::cout << time << std::endl; report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, "math.h"); #endif #if defined(TEST_LIBSTDCXX) && !defined(COMPILER_COMPARISON_TABLES) time = exec_timed_test([](const std::vector<double>& v){ return std::tr1::cyl_bessel_j(static_cast<int>(v[0]), v[1]); }); std::cout << time << std::endl; report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, "tr1/cmath"); #endif #if defined(TEST_GSL) && !defined(COMPILER_COMPARISON_TABLES) time = exec_timed_test([](const std::vector<double>& v){ return gsl_sf_bessel_Jn(static_cast<int>(v[0]), v[1]); }); std::cout << time << std::endl; report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, "GSL " GSL_VERSION); #endif #if defined(TEST_RMATH) && !defined(COMPILER_COMPARISON_TABLES) time = exec_timed_test([](const std::vector<double>& v){ return bessel_j(v[1], static_cast<int>(v[0])); }); std::cout << time << std::endl; report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, "Rmath " R_VERSION_STRING); #endif return 0; }
int main() { cl_int error_code = CL_SUCCESS; try { // find Intel platform cl_uint num_platforms = 0; error_code = clGetPlatformIDs(0, nullptr, &num_platforms); HANDLE_CL_ERROR(clGetPlatformIDs) std::unique_ptr<cl_platform_id[]> platform_ids( new cl_platform_id[static_cast<const std::size_t>(num_platforms)]); error_code = clGetPlatformIDs(num_platforms, platform_ids.get(), nullptr); HANDLE_CL_ERROR(clGetPlatformIDs) cl_platform_id platform = nullptr; for (std::size_t i = 0; i != static_cast<const std::size_t>(num_platforms); ++i) { std::size_t platform_name_size = 0; error_code = clGetPlatformInfo(platform_ids[i], CL_PLATFORM_NAME, 0, nullptr, &platform_name_size); HANDLE_CL_ERROR(clGetPlatformInfo) std::unique_ptr<char[]> platform_name(new char[platform_name_size]); error_code = clGetPlatformInfo(platform_ids[i], CL_PLATFORM_NAME, platform_name_size, platform_name.get(), nullptr); HANDLE_CL_ERROR(clGetPlatformInfo) if (std::strcmp(beignet_platform_name, platform_name.get()) == 0) { platform = platform_ids[i]; std::cout << "Platform: " << platform_name.get() << std::endl; break; } } if (platform == nullptr) { throw std::runtime_error(std::string("Couldn't find platform with name: ") + beignet_platform_name); } // find Intel GPU cl_device_id device = nullptr; error_code = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device, nullptr); HANDLE_CL_ERROR(clGetDeviceIDs) std::size_t device_name_size = 0; error_code = clGetDeviceInfo(device, CL_DEVICE_NAME, 0, nullptr, &device_name_size); HANDLE_CL_ERROR(clGetDeviceInfo) std::unique_ptr<char[]> device_name(new char[device_name_size]); error_code = clGetDeviceInfo(device, CL_DEVICE_NAME, device_name_size, device_name.get(), nullptr); HANDLE_CL_ERROR(clGetDeviceInfo) std::cout << "Device: " << device_name.get() << std::endl; // create OpenCL context, command queue, program and kernel const auto context = clCreateContext(nullptr, 1, &device, nullptr, nullptr, &error_code); HANDLE_CL_ERROR(clCreateContext) const auto command_queue = clCreateCommandQueue(context, device, 0, &error_code); HANDLE_CL_ERROR(clCreateCommandQueue) const char *source_strings[1]; source_strings[0] = kernel_source; const std::size_t source_size = std::strlen(kernel_source); const auto program = clCreateProgramWithSource(context, 1, source_strings, &source_size, &error_code); HANDLE_CL_ERROR(clCreateProgramWithSource) error_code = clBuildProgram(program, 1, &device, "", nullptr, nullptr); HANDLE_CL_ERROR(clBuildProgram) const auto kernel = clCreateKernel(program, "print_hello", &error_code); HANDLE_CL_ERROR(clCreateKernel) // enqueue kernel and set event completion handler cl_event event; std::size_t global_work_size = 1; error_code = clEnqueueNDRangeKernel(command_queue, kernel, 1, nullptr, &global_work_size, nullptr, 0, nullptr, &event); HANDLE_CL_ERROR(clEnqueueNDRangeKernel) error_code = clSetEventCallback(event, CL_COMPLETE, [](cl_event, cl_int, void *) { std::cout << "OpenCL callback" << std::endl; // Notify the waiting thread that the kernel is completed { std::lock_guard<std::mutex> cond_lock(cond_mutex); kernel_complete = true; } cond_var.notify_one(); }, nullptr); HANDLE_CL_ERROR(clSetEventCallback) error_code = clFlush(command_queue); HANDLE_CL_ERROR(clFlush) // simulate work std::this_thread::sleep_for(std::chrono::seconds(1)); // do work, dependent on kernel completion { std::unique_lock<std::mutex> cond_lock(cond_mutex); while (!kernel_complete) { if (cond_var.wait_for(cond_lock, std::chrono::seconds(5)) == std::cv_status::timeout) { std::cout << "WARNING: A 5 second timeout has been reached on the condition variable.\n" " This may be a deadlock." << std::endl; } } } // When using Beignet, this will never be called as a deadlock will occur. std::cout << "Doing work, dependent on the kernel's completion" << std::endl; } catch (const std::exception &e) { std::cout << "Error: " << e.what() << std::endl; } catch (...) { std::cout << "Unknown error" << std::endl; } }
Rt_map * setup(char **envp, auxv_t *auxv, Word _flags, char *_platform, int _syspagsz, char *_rtldname, ulong_t ld_base, ulong_t interp_base, int fd, Phdr *phdr, char *execname, char **argv, uid_t uid, uid_t euid, gid_t gid, gid_t egid, void *aoutdyn, int auxflags, uint_t *hwcap) { Rt_map *rlmp, *mlmp, *clmp, **tobj = NULL; Ehdr *ehdr; rtld_stat_t status; int features = 0, ldsoexec = 0; size_t eaddr, esize; char *str, *argvname; Word lmflags; mmapobj_result_t *mpp; Fdesc fdr = { 0 }, fdm = { 0 }; Rej_desc rej = { 0 }; APlist *ealp = NULL; /* * Now that ld.so has relocated itself, initialize our own 'environ' so * as to establish an address suitable for any libc requirements. */ _environ = (char **)((ulong_t)auxv - sizeof (char *)); _init(); _environ = envp; /* * Establish a base time. Total time diagnostics start from entering * ld.so.1 here, however the base time is reset each time the ld.so.1 * is re-entered. Note also, there will be a large time associated * with the first diagnostic from ld.so.1, as bootstrapping ld.so.1 * and establishing the liblddbg infrastructure takes some time. */ (void) gettimeofday(&DBG_TOTALTIME, NULL); DBG_DELTATIME = DBG_TOTALTIME; /* * Determine how ld.so.1 has been executed. */ if ((fd == -1) && (phdr == NULL)) { /* * If we received neither the AT_EXECFD nor the AT_PHDR aux * vector, ld.so.1 must have been invoked directly from the * command line. */ ldsoexec = 1; /* * AT_SUN_EXECNAME provides the most precise name, if it is * available, otherwise fall back to argv[0]. At this time, * there is no process name. */ if (execname) rtldname = execname; else if (argv[0]) rtldname = argv[0]; else rtldname = (char *)MSG_INTL(MSG_STR_UNKNOWN); } else { /* * Otherwise, we have a standard process. AT_SUN_EXECNAME * provides the most precise name, if it is available, * otherwise fall back to argv[0]. Provided the application * is already mapped, the process is the application, so * simplify the application name for use in any diagnostics. */ if (execname) argvname = execname; else if (argv[0]) argvname = execname = argv[0]; else argvname = execname = (char *)MSG_INTL(MSG_STR_UNKNOWN); if (fd == -1) { if ((str = strrchr(argvname, '/')) != NULL) procname = ++str; else procname = argvname; } /* * At this point, we don't know the runtime linkers full path * name. The _rtldname passed to us is the SONAME of the * runtime linker, which is typically /lib/ld.so.1 no matter * what the full path is. Use this for now, we'll reset the * runtime linkers name once the application is analyzed. */ if (_rtldname) { if ((str = strrchr(_rtldname, '/')) != NULL) rtldname = ++str; else rtldname = _rtldname; } else rtldname = (char *)MSG_INTL(MSG_STR_UNKNOWN); /* exec() brought in two objects for us. Count the second one */ cnt_map++; } /* * Initialize any global variables. */ at_flags = _flags; if ((org_scapset->sc_plat = _platform) != NULL) org_scapset->sc_platsz = strlen(_platform); if (org_scapset->sc_plat == NULL) platform_name(org_scapset); if (org_scapset->sc_mach == NULL) machine_name(org_scapset); /* * If pagesize is unspecified find its value. */ if ((syspagsz = _syspagsz) == 0) syspagsz = _sysconfig(_CONFIG_PAGESIZE); /* * Add the unused portion of the last data page to the free space list. * The page size must be set before doing this. Here, _end refers to * the end of the runtime linkers bss. Note that we do not use the * unused data pages from any included .so's to supplement this free * space as badly behaved .os's may corrupt this data space, and in so * doing ruin our data. */ eaddr = S_DROUND((size_t)&_end); esize = eaddr % syspagsz; if (esize) { esize = syspagsz - esize; addfree((void *)eaddr, esize); } /* * Establish initial link-map list flags, and link-map list alists. */ if (alist_append(&lml_main.lm_lists, NULL, sizeof (Lm_cntl), AL_CNT_LMLISTS) == NULL) return (0); lml_main.lm_flags |= LML_FLG_BASELM; lml_main.lm_lmid = LM_ID_BASE; lml_main.lm_lmidstr = (char *)MSG_ORIG(MSG_LMID_BASE); if (alist_append(&lml_rtld.lm_lists, NULL, sizeof (Lm_cntl), AL_CNT_LMLISTS) == NULL) return (0); lml_rtld.lm_flags |= (LML_FLG_RTLDLM | LML_FLG_HOLDLOCK); lml_rtld.lm_tflags |= LML_TFLG_NOAUDIT; lml_rtld.lm_lmid = LM_ID_LDSO; lml_rtld.lm_lmidstr = (char *)MSG_ORIG(MSG_LMID_LDSO); /* * Determine whether we have a secure executable. */ security(uid, euid, gid, egid, auxflags); /* * Make an initial pass of environment variables to pick off those * related to locale processing. At the same time, collect and save * any LD_XXXX variables for later processing. Note that this later * processing will be skipped if ld.so.1 is invoked from the command * line with -e LD_NOENVIRON. */ if (envp && (readenv_user((const char **)envp, &ealp) == 1)) return (0); /* * If ld.so.1 has been invoked directly, process its arguments. */ if (ldsoexec) { /* * Process any arguments that are specific to ld.so.1, and * reorganize the process stack to effectively remove ld.so.1 * from the stack. Reinitialize the environment pointer, as * this pointer may have been shifted after skipping ld.so.1's * arguments. */ if (rtld_getopt(argv, &envp, &auxv, &(lml_main.lm_flags), &(lml_main.lm_tflags), (aoutdyn != 0)) == 1) { eprintf(&lml_main, ERR_NONE, MSG_INTL(MSG_USG_BADOPT)); return (0); } _environ = envp; /* * Open the object that ld.so.1 is to execute. */ argvname = execname = argv[0]; if ((fd = open(argvname, O_RDONLY)) == -1) { int err = errno; eprintf(&lml_main, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), argvname, strerror(err)); return (0); } } /* * Having processed any ld.so.1 command line options, return to process * any LD_XXXX environment variables. */ if (ealp) { if (((rtld_flags & RT_FL_NOENVIRON) == 0) && (procenv_user(ealp, &(lml_main.lm_flags), &(lml_main.lm_tflags), (aoutdyn != 0)) == 1)) return (0); free(ealp); } /* * Initialize a hardware capability descriptor for use in comparing * each loaded object. The aux vector must provide AF_SUN_HWCAPVERIFY, * as prior to this setting any hardware capabilities that were found * could not be relied upon. */ if (auxflags & AF_SUN_HWCAPVERIFY) { rtld_flags2 |= RT_FL2_HWCAP; org_scapset->sc_hw_1 = (Xword)hwcap[0]; org_scapset->sc_hw_2 = (Xword)hwcap[1]; } /* * Create a mapping descriptor for ld.so.1. We can determine our * two segments information from known symbols. */ if ((mpp = calloc(2, sizeof (mmapobj_result_t))) == NULL) return (0); mpp[0].mr_addr = (caddr_t)M_PTRUNC(ld_base); mpp[0].mr_msize = (caddr_t)&_etext - mpp[0].mr_addr; mpp[0].mr_fsize = mpp[0].mr_msize; mpp[0].mr_prot = (PROT_READ | PROT_EXEC); mpp[1].mr_addr = (caddr_t)M_PTRUNC((uintptr_t)&r_debug); mpp[1].mr_msize = (caddr_t)&_end - mpp[1].mr_addr; mpp[1].mr_fsize = (caddr_t)&_edata - mpp[1].mr_addr; mpp[1].mr_prot = (PROT_READ | PROT_WRITE | PROT_EXEC); if ((fdr.fd_nname = stravl_insert(_rtldname, 0, 0, 0)) == NULL) return (0); if ((rlmp = elf_new_lmp(&lml_rtld, ALIST_OFF_DATA, &fdr, (Addr)mpp->mr_addr, (size_t)((uintptr_t)eaddr - (uintptr_t)ld_base), NULL, NULL, NULL)) == NULL) return (0); MMAPS(rlmp) = mpp; MMAPCNT(rlmp) = 2; PADSTART(rlmp) = (ulong_t)mpp[0].mr_addr; PADIMLEN(rlmp) = (ulong_t)mpp[0].mr_addr + (ulong_t)mpp[1].mr_addr + (ulong_t)mpp[1].mr_msize; MODE(rlmp) |= (RTLD_LAZY | RTLD_NODELETE | RTLD_GLOBAL | RTLD_WORLD); FLAGS(rlmp) |= (FLG_RT_ANALYZED | FLG_RT_RELOCED | FLG_RT_INITDONE | FLG_RT_INITCLCT | FLG_RT_FINICLCT | FLG_RT_MODESET); /* * Initialize the runtime linkers information. */ interp = &_interp; interp->i_name = (char *)rtldname; interp->i_faddr = (caddr_t)ADDR(rlmp); ldso_plt_init(rlmp); /* * Map in the file, if exec has not already done so, or if the file * was passed as an argument to an explicit execution of ld.so.1 from * the command line. */ if (fd != -1) { /* * Map the file. Once the object is mapped we no longer need * the file descriptor. */ (void) rtld_fstat(fd, &status); fdm.fd_oname = argvname; fdm.fd_ftp = map_obj(&lml_main, &fdm, status.st_size, argvname, fd, &rej); (void) close(fd); if (fdm.fd_ftp == NULL) { Conv_reject_desc_buf_t rej_buf; eprintf(&lml_main, ERR_FATAL, MSG_INTL(err_reject[rej.rej_type]), argvname, conv_reject_desc(&rej, &rej_buf, M_MACH)); return (0); } /* * Finish processing the loading of the file. */ if ((fdm.fd_nname = stravl_insert(argvname, 0, 0, 0)) == NULL) return (0); fdm.fd_dev = status.st_dev; fdm.fd_ino = status.st_ino; if ((mlmp = load_file(&lml_main, ALIST_OFF_DATA, NULL, &fdm, NULL)) == NULL) return (0); /* * We now have a process name for error diagnostics. */ if ((str = strrchr(argvname, '/')) != NULL) procname = ++str; else procname = argvname; if (ldsoexec) { mmapobj_result_t *mpp = MMAPS(mlmp); uint_t mnum, mapnum = MMAPCNT(mlmp); void *brkbase = NULL; /* * Since ld.so.1 was the primary executed object - the * brk() base has not yet been initialized, we need to * initialize it. For an executable, initialize it to * the end of the object. For a shared object (ET_DYN) * initialize it to the first page in memory. */ for (mnum = 0; mnum < mapnum; mnum++, mpp++) brkbase = mpp->mr_addr + mpp->mr_msize; if (brkbase == NULL) brkbase = (void *)syspagsz; if (_brk_unlocked(brkbase) == -1) { int err = errno; eprintf(&lml_main, ERR_FATAL, MSG_INTL(MSG_SYS_BRK), argvname, strerror(err)); return (0); } } } else { /* * Set up function ptr and arguments according to the type * of file class the executable is. (Currently only supported * types are ELF and a.out format.) Then create a link map * for the executable. */ if (aoutdyn) { #ifdef A_OUT mmapobj_result_t *mpp; /* * Create a mapping structure sufficient to describe * a single two segments. The ADDR() of the a.out is * established as 0, which is required but the AOUT * relocation code. */ if ((mpp = calloc(sizeof (mmapobj_result_t), 2)) == NULL) return (0); if ((fdm.fd_nname = stravl_insert(execname, 0, 0, 0)) == NULL) return (0); if ((mlmp = aout_new_lmp(&lml_main, ALIST_OFF_DATA, &fdm, 0, 0, aoutdyn, NULL, NULL)) == NULL) return (0); /* * Establish the true mapping information for the a.out. */ if (aout_get_mmap(&lml_main, mpp)) { free(mpp); return (0); } MSIZE(mlmp) = (size_t)(mpp[1].mr_addr + mpp[1].mr_msize) - S_ALIGN((size_t)mpp[0].mr_addr, syspagsz); MMAPS(mlmp) = mpp; MMAPCNT(mlmp) = 2; PADSTART(mlmp) = (ulong_t)mpp->mr_addr; PADIMLEN(mlmp) = mpp->mr_msize; /* * Disable any object configuration cache (BCP apps * bring in sbcp which can benefit from any object * cache, but both the app and sbcp can't use the same * objects). */ rtld_flags |= RT_FL_NOOBJALT; /* * Make sure no-direct bindings are in effect. */ lml_main.lm_tflags |= LML_TFLG_NODIRECT; #else eprintf(&lml_main, ERR_FATAL, MSG_INTL(MSG_ERR_REJ_UNKFILE), argvname); return (0); #endif } else if (phdr) { Phdr *pptr; Off i_offset = 0; Addr base = 0; ulong_t phsize; mmapobj_result_t *mpp, *fmpp, *hmpp = NULL; uint_t mapnum = 0; int i; size_t msize; /* * Using the executables phdr address determine the base * address of the input file. NOTE, this assumes the * program headers and elf header are part of the same * mapped segment. Although this has held for many * years now, it might be more flexible if the kernel * gave use the ELF headers start address, rather than * the Program headers. * * Determine from the ELF header if we're been called * from a shared object or dynamic executable. If the * latter, then any addresses within the object are used * as is. Addresses within shared objects must be added * to the process's base address. */ ehdr = (Ehdr *)((Addr)phdr - phdr->p_offset); phsize = ehdr->e_phentsize; if (ehdr->e_type == ET_DYN) base = (Addr)ehdr; /* * Allocate a mapping array to retain mapped segment * information. */ if ((fmpp = mpp = calloc(ehdr->e_phnum, sizeof (mmapobj_result_t))) == NULL) return (0); /* * Extract the needed information from the segment * headers. */ for (i = 0, pptr = phdr; i < ehdr->e_phnum; i++) { if (pptr->p_type == PT_INTERP) { i_offset = pptr->p_offset; interp->i_faddr = (caddr_t)interp_base; } if ((pptr->p_type == PT_LOAD) && (pptr->p_filesz || pptr->p_memsz)) { int perm = (PROT_READ | PROT_EXEC); size_t off; if (i_offset && pptr->p_filesz && (i_offset >= pptr->p_offset) && (i_offset <= (pptr->p_memsz + pptr->p_offset))) { interp->i_name = (char *) pptr->p_vaddr + i_offset - pptr->p_offset + base; i_offset = 0; } if (pptr->p_flags & PF_W) perm |= PROT_WRITE; /* * Retain segments mapping info. Round * each segment to a page boundary, as * this insures addresses are suitable * for mprotect() if required. */ off = pptr->p_vaddr + base; if (hmpp == NULL) { hmpp = mpp; mpp->mr_addr = (caddr_t)ehdr; } else mpp->mr_addr = (caddr_t)off; off -= (size_t)(uintptr_t)mpp->mr_addr; mpp->mr_msize = pptr->p_memsz + off; mpp->mr_fsize = pptr->p_filesz + off; mpp->mr_prot = perm; mpp++, mapnum++; } pptr = (Phdr *)((ulong_t)pptr + phsize); } mpp--; msize = (size_t)(mpp->mr_addr + mpp->mr_msize) - S_ALIGN((size_t)fmpp->mr_addr, syspagsz); if ((fdm.fd_nname = stravl_insert(execname, 0, 0, 0)) == NULL) return (0); if ((mlmp = elf_new_lmp(&lml_main, ALIST_OFF_DATA, &fdm, (Addr)hmpp->mr_addr, msize, NULL, NULL, NULL)) == NULL) return (0); MMAPS(mlmp) = fmpp; MMAPCNT(mlmp) = mapnum; PADSTART(mlmp) = (ulong_t)fmpp->mr_addr; PADIMLEN(mlmp) = (ulong_t)fmpp->mr_addr + (ulong_t)mpp->mr_addr + (ulong_t)mpp->mr_msize; } } /* * Establish the interpretors name as that defined within the initial * object (executable). This provides for ORIGIN processing of ld.so.1 * dependencies. Note, the NAME() of the object remains that which was * passed to us as the SONAME on execution. */ if (ldsoexec == 0) { size_t len = strlen(interp->i_name); if (expand(&interp->i_name, &len, 0, 0, (PD_TKN_ISALIST | PD_TKN_CAP), rlmp) & PD_TKN_RESOLVED) fdr.fd_flags |= FLG_FD_RESOLVED; } fdr.fd_pname = interp->i_name; (void) fullpath(rlmp, &fdr); /* * The runtime linker acts as a filtee for various dl*() functions that * are defined in libc (and libdl). Make sure this standard name for * the runtime linker is also registered in the FullPathNode AVL tree. */ (void) fpavl_insert(&lml_rtld, rlmp, _rtldname, 0); /* * Having established the true runtime linkers name, simplify the name * for error diagnostics. */ if ((str = strrchr(PATHNAME(rlmp), '/')) != NULL) rtldname = ++str; else rtldname = PATHNAME(rlmp); /* * Expand the fullpath name of the application. This typically occurs * as a part of loading an object, but as the kernel probably mapped * it in, complete this processing now. */ (void) fullpath(mlmp, 0); /* * Some troublesome programs will change the value of argv[0]. Dupping * the process string protects us, and insures the string is left in * any core files. */ if ((str = (char *)strdup(procname)) == NULL) return (0); procname = str; FLAGS(mlmp) |= (FLG_RT_ISMAIN | FLG_RT_MODESET); FLAGS1(mlmp) |= FL1_RT_USED; /* * It's the responsibility of MAIN(crt0) to call it's _init and _fini * section, therefore null out any INIT/FINI so that this object isn't * collected during tsort processing. And, if the application has no * initarray or finiarray we can economize on establishing bindings. */ INIT(mlmp) = FINI(mlmp) = NULL; if ((INITARRAY(mlmp) == NULL) && (FINIARRAY(mlmp) == NULL)) FLAGS1(mlmp) |= FL1_RT_NOINIFIN; /* * Identify lddstub if necessary. */ if (lml_main.lm_flags & LML_FLG_TRC_LDDSTUB) FLAGS1(mlmp) |= FL1_RT_LDDSTUB; /* * Retain our argument information for use in dlinfo. */ argsinfo.dla_argv = argv--; argsinfo.dla_argc = (long)*argv; argsinfo.dla_envp = envp; argsinfo.dla_auxv = auxv; (void) enter(0); /* * Add our two main link-maps to the dynlm_list */ if (aplist_append(&dynlm_list, &lml_main, AL_CNT_DYNLIST) == NULL) return (0); if (aplist_append(&dynlm_list, &lml_rtld, AL_CNT_DYNLIST) == NULL) return (0); /* * Reset the link-map counts for both lists. The init count is used to * track how many objects have pending init sections, this gets incre- * mented each time an object is relocated. Since ld.so.1 relocates * itself, it's init count will remain zero. * The object count is used to track how many objects have pending fini * sections, as ld.so.1 handles its own fini we can zero its count. */ lml_main.lm_obj = 1; lml_rtld.lm_obj = 0; /* * Initialize debugger information structure. Some parts of this * structure were initialized statically. */ r_debug.rtd_rdebug.r_map = (Link_map *)lml_main.lm_head; r_debug.rtd_rdebug.r_ldsomap = (Link_map *)lml_rtld.lm_head; r_debug.rtd_rdebug.r_ldbase = r_debug.rtd_rdebug.r_ldsomap->l_addr; r_debug.rtd_dynlmlst = &dynlm_list; /* * Determine the dev/inode information for the executable to complete * load_so() checking for those who might dlopen(a.out). */ if (rtld_stat(PATHNAME(mlmp), &status) == 0) { STDEV(mlmp) = status.st_dev; STINO(mlmp) = status.st_ino; } /* * Initialize any configuration information. */ if (!(rtld_flags & RT_FL_NOCFG)) { if ((features = elf_config(mlmp, (aoutdyn != 0))) == -1) return (0); } #if defined(_ELF64) /* * If this is a 64-bit process, determine whether this process has * restricted the process address space to 32-bits. Any dependencies * that are restricted to a 32-bit address space can only be loaded if * the executable has established this requirement. */ if (CAPSET(mlmp).sc_sf_1 & SF1_SUNW_ADDR32) rtld_flags2 |= RT_FL2_ADDR32; #endif /* * Establish any alternative capabilities, and validate this object * if it defines it's own capabilities information. */ if (cap_alternative() == 0) return (0); if (cap_check_lmp(mlmp, &rej) == 0) { if (lml_main.lm_flags & LML_FLG_TRC_ENABLE) { /* LINTED */ (void) printf(MSG_INTL(ldd_warn[rej.rej_type]), NAME(mlmp), rej.rej_str); } else { /* LINTED */ eprintf(&lml_main, ERR_FATAL, MSG_INTL(err_reject[rej.rej_type]), NAME(mlmp), rej.rej_str); return (0); } } /* * Establish the modes of the initial object. These modes are * propagated to any preloaded objects and explicit shared library * dependencies. * * If we're generating a configuration file using crle(1), remove * any RTLD_NOW use, as we don't want to trigger any relocation proc- * essing during crle(1)'s first past (this would just be unnecessary * overhead). Any filters are explicitly loaded, and thus RTLD_NOW is * not required to trigger filter loading. * * Note, RTLD_NOW may have been established during analysis of the * application had the application been built -z now. */ MODE(mlmp) |= (RTLD_NODELETE | RTLD_GLOBAL | RTLD_WORLD); if (rtld_flags & RT_FL_CONFGEN) { MODE(mlmp) |= RTLD_CONFGEN; MODE(mlmp) &= ~RTLD_NOW; rtld_flags2 &= ~RT_FL2_BINDNOW; } if ((MODE(mlmp) & RTLD_NOW) == 0) { if (rtld_flags2 & RT_FL2_BINDNOW) MODE(mlmp) |= RTLD_NOW; else MODE(mlmp) |= RTLD_LAZY; } /* * If debugging was requested initialize things now that any cache has * been established. A user can specify LD_DEBUG=help to discover the * list of debugging tokens available without running the application. * However, don't allow this setting from a configuration file. * * Note, to prevent recursion issues caused by loading and binding the * debugging libraries themselves, a local debugging descriptor is * initialized. Once the debugging setup has completed, this local * descriptor is copied to the global descriptor which effectively * enables diagnostic output. * * Ignore any debugging request if we're being monitored by a process * that expects the old getpid() initialization handshake. */ if ((rpl_debug || prm_debug) && ((rtld_flags & RT_FL_DEBUGGER) == 0)) { Dbg_desc _dbg_desc = {0}; struct timeval total = DBG_TOTALTIME; struct timeval delta = DBG_DELTATIME; if (rpl_debug) { if (dbg_setup(rpl_debug, &_dbg_desc) == 0) return (0); if (_dbg_desc.d_extra & DBG_E_HELP_EXIT) rtldexit(&lml_main, 0); } if (prm_debug) (void) dbg_setup(prm_debug, &_dbg_desc); *dbg_desc = _dbg_desc; DBG_TOTALTIME = total; DBG_DELTATIME = delta; } /* * Now that debugging is enabled generate any diagnostics from any * previous events. */ if (DBG_ENABLED) { DBG_CALL(Dbg_cap_val(&lml_main, org_scapset, alt_scapset, M_MACH)); DBG_CALL(Dbg_file_config_dis(&lml_main, config->c_name, features)); DBG_CALL(Dbg_file_ldso(rlmp, envp, auxv, LIST(rlmp)->lm_lmidstr, ALIST_OFF_DATA)); if (THIS_IS_ELF(mlmp)) { DBG_CALL(Dbg_file_elf(&lml_main, PATHNAME(mlmp), ADDR(mlmp), MSIZE(mlmp), LIST(mlmp)->lm_lmidstr, ALIST_OFF_DATA)); } else { DBG_CALL(Dbg_file_aout(&lml_main, PATHNAME(mlmp), ADDR(mlmp), MSIZE(mlmp), LIST(mlmp)->lm_lmidstr, ALIST_OFF_DATA)); } } /* * Enable auditing. */ if (rpl_audit || prm_audit || profile_lib) { int ndx; const char *aud[3]; aud[0] = rpl_audit; aud[1] = prm_audit; aud[2] = profile_lib; /* * Any global auditing (set using LD_AUDIT or LD_PROFILE) that * can't be established is non-fatal. */ if ((auditors = calloc(1, sizeof (Audit_desc))) == NULL) return (0); for (ndx = 0; ndx < 3; ndx++) { if (aud[ndx]) { if ((auditors->ad_name = strdup(aud[ndx])) == NULL) return (0); rtld_flags2 |= RT_FL2_FTL2WARN; (void) audit_setup(mlmp, auditors, PD_FLG_EXTLOAD, NULL); rtld_flags2 &= ~RT_FL2_FTL2WARN; } } lml_main.lm_tflags |= auditors->ad_flags; } if (AUDITORS(mlmp)) { /* * Any object required auditing (set with a DT_DEPAUDIT dynamic * entry) that can't be established is fatal. */ if (FLAGS1(mlmp) & FL1_RT_GLOBAUD) { /* * If this object requires global auditing, use the * local auditing information to set the global * auditing descriptor. The effect is that a * DT_DEPAUDIT act as an LD_AUDIT. */ if ((auditors == NULL) && ((auditors = calloc(1, sizeof (Audit_desc))) == NULL)) return (0); auditors->ad_name = AUDITORS(mlmp)->ad_name; if (audit_setup(mlmp, auditors, 0, NULL) == 0) return (0); lml_main.lm_tflags |= auditors->ad_flags; /* * Clear the local auditor information. */ free((void *) AUDITORS(mlmp)); AUDITORS(mlmp) = NULL; } else { /* * Establish any local auditing. */ if (audit_setup(mlmp, AUDITORS(mlmp), 0, NULL) == 0) return (0); AFLAGS(mlmp) |= AUDITORS(mlmp)->ad_flags; lml_main.lm_flags |= LML_FLG_LOCAUDIT; } } /* * Explicitly add the initial object and ld.so.1 to those objects being * audited. Note, although the ld.so.1 link-map isn't auditable, * establish a cookie for ld.so.1 as this may be bound to via the * dl*() family. */ if ((lml_main.lm_tflags | AFLAGS(mlmp)) & LML_TFLG_AUD_MASK) { if (((audit_objopen(mlmp, mlmp) == 0) || (audit_objopen(mlmp, rlmp) == 0)) && (AFLAGS(mlmp) & LML_TFLG_AUD_MASK)) return (0); } /* * Map in any preloadable shared objects. Establish the caller as the * head of the main link-map list. In the case of being exercised from * lddstub, the caller gets reassigned to the first target shared object * so as to provide intuitive diagnostics from ldd(). * * Note, it is valid to preload a 4.x shared object with a 5.0 * executable (or visa-versa), as this functionality is required by * ldd(1). */ clmp = mlmp; if (rpl_preload && (preload(rpl_preload, mlmp, &clmp) == 0)) return (0); if (prm_preload && (preload(prm_preload, mlmp, &clmp) == 0)) return (0); /* * Load all dependent (needed) objects. */ if (analyze_lmc(&lml_main, ALIST_OFF_DATA, mlmp, mlmp, NULL) == NULL) return (0); /* * Relocate all the dependencies we've just added. * * If this process has been established via crle(1), the environment * variable LD_CONFGEN will have been set. crle(1) may create this * process twice. The first time crle only needs to gather dependency * information. The second time, is to dldump() the images. * * If we're only gathering dependencies, relocation is unnecessary. * As crle(1) may be building an arbitrary family of objects, they may * not fully relocate either. Hence the relocation phase is not carried * out now, but will be called by crle(1) once all objects have been * loaded. */ if ((rtld_flags & RT_FL_CONFGEN) == 0) { DBG_CALL(Dbg_util_nl(&lml_main, DBG_NL_STD)); if (relocate_lmc(&lml_main, ALIST_OFF_DATA, mlmp, mlmp, NULL) == 0) return (0); /* * Inform the debuggers that basic process initialization is * complete, and that the state of ld.so.1 (link-map lists, * etc.) is stable. This handshake enables the debugger to * initialize themselves, and consequently allows the user to * set break points in .init code. * * Most new debuggers use librtld_db to monitor activity events. * Older debuggers indicated their presence by setting the * DT_DEBUG entry in the dynamic executable (see elf_new_lm()). * In this case, getpid() is called so that the debugger can * catch the system call. This old mechanism has some * restrictions, as getpid() should not be called prior to * basic process initialization being completed. This * restriction has become increasingly difficult to maintain, * as the use of auditors, LD_DEBUG, and the initialization * handshake with libc can result in "premature" getpid() * calls. The use of this getpid() handshake is expected to * disappear at some point in the future, and there is intent * to work towards that goal. */ rd_event(&lml_main, RD_DLACTIVITY, RT_CONSISTENT); rd_event(&lml_rtld, RD_DLACTIVITY, RT_CONSISTENT); if (rtld_flags & RT_FL_DEBUGGER) { r_debug.rtd_rdebug.r_flags |= RD_FL_ODBG; (void) getpid(); } } /* * Indicate preinit activity, and call any auditing routines. These * routines are called before initializing any threads via libc, or * before collecting the complete set of .inits on the primary link-map. * Although most libc interfaces are encapsulated in local routines * within libc, they have been known to escape (ie. call a .plt). As * the appcert auditor uses preinit as a trigger to establish some * external interfaces to the main link-maps libc, we need to activate * this trigger before exercising any code within libc. Additionally, * I wouldn't put it past an auditor to add additional objects to the * primary link-map. Hence, we collect .inits after the audit call. */ rd_event(&lml_main, RD_PREINIT, 0); if (aud_activity || ((lml_main.lm_tflags | AFLAGS(mlmp)) & LML_TFLG_AUD_ACTIVITY)) audit_activity(mlmp, LA_ACT_CONSISTENT); if (aud_preinit || ((lml_main.lm_tflags | AFLAGS(mlmp)) & LML_TFLG_AUD_PREINIT)) audit_preinit(mlmp); /* * If we're creating initial configuration information, we're done * now that the auditing step has been called. */ if (rtld_flags & RT_FL_CONFGEN) { leave(LIST(mlmp), 0); return (mlmp); } /* * Sort the .init sections of all objects we've added. If we're * tracing we only need to execute this under ldd(1) with the -i or -u * options. */ lmflags = lml_main.lm_flags; if (((lmflags & LML_FLG_TRC_ENABLE) == 0) || (lmflags & (LML_FLG_TRC_INIT | LML_FLG_TRC_UNREF))) { if ((tobj = tsort(mlmp, LIST(mlmp)->lm_init, RT_SORT_REV)) == (Rt_map **)S_ERROR) return (0); } /* * If we are tracing we're done. This is the one legitimate use of a * direct call to rtldexit() rather than return, as we don't want to * return and jump to the application. */ if (lmflags & LML_FLG_TRC_ENABLE) { unused(&lml_main); rtldexit(&lml_main, 0); } /* * Check if this instance of the linker should have a primary link * map. This flag allows multiple copies of the -same- -version- * of the linker (and libc) to run in the same address space. * * Without this flag we only support one copy of the linker in a * process because by default the linker will always try to * initialize at one primary link map The copy of libc which is * initialized on a primary link map will initialize global TLS * data which can be shared with other copies of libc in the * process. The problem is that if there is more than one copy * of the linker, only one copy should link libc onto a primary * link map, otherwise libc will attempt to re-initialize global * TLS data. So when a copy of the linker is loaded with this * flag set, it will not initialize any primary link maps since * presumably another copy of the linker will do this. * * Note that this flag only allows multiple copies of the -same- * -version- of the linker (and libc) to coexist. This approach * will not work if we are trying to load different versions of * the linker and libc into the same process. The reason for * this is that the format of the global TLS data may not be * the same for different versions of libc. In this case each * different version of libc must have it's own primary link map * and be able to maintain it's own TLS data. The only way this * can be done is by carefully managing TLS pointers on transitions * between code associated with each of the different linkers. * Note that this is actually what is done for processes in lx * branded zones. Although in the lx branded zone case, the * other linker and libc are actually gld and glibc. But the * same general TLS management mechanism used by the lx brand * would apply to any attempts to run multiple versions of the * solaris linker and libc in a single process. */ if (auxflags & AF_SUN_NOPLM) rtld_flags2 |= RT_FL2_NOPLM; /* * Establish any static TLS for this primary link-map. Note, regardless * of whether TLS is available, an initial handshake occurs with libc to * indicate we're processing the primary link-map. Having identified * the primary link-map, initialize threads. */ if (rt_get_extern(&lml_main, mlmp) == 0) return (0); if ((rtld_flags2 & RT_FL2_NOPLM) == 0) { if (tls_statmod(&lml_main, mlmp) == 0) return (0); rt_thr_init(&lml_main); rtld_flags2 |= RT_FL2_PLMSETUP; } else { rt_thr_init(&lml_main); } /* * Fire all dependencies .init sections. Identify any unused * dependencies, and leave the runtime linker - effectively calling * the dynamic executables entry point. */ call_array(PREINITARRAY(mlmp), (uint_t)PREINITARRAYSZ(mlmp), mlmp, SHT_PREINIT_ARRAY); if (tobj) call_init(tobj, DBG_INIT_SORT); rd_event(&lml_main, RD_POSTINIT, 0); unused(&lml_main); DBG_CALL(Dbg_util_call_main(mlmp)); rtld_flags |= (RT_FL_OPERATION | RT_FL_APPLIC); leave(LIST(mlmp), 0); return (mlmp); }