comparison UnitTestsSources/GenericToolboxTests.cpp @ 1183:2e52d1f4c9e3 broker

merge
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 22 Nov 2019 08:58:46 +0100
parents ba08f2b0a779 3076a8a66db5
children 09fc591d8ff9
comparison
equal deleted inserted replaced
1180:9c8f557ea799 1183:2e52d1f4c9e3
17 * You should have received a copy of the GNU Affero General Public License 17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 **/ 19 **/
20 20
21 #include <Framework/Toolbox/GenericToolbox.h> 21 #include <Framework/Toolbox/GenericToolbox.h>
22
23 #include <boost/chrono.hpp>
24 #include <boost/lexical_cast.hpp>
22 25
23 #include "gtest/gtest.h" 26 #include "gtest/gtest.h"
24 27
25 #include "stdint.h" 28 #include "stdint.h"
26 29
3840 #endif 3843 #endif
3841 EXPECT_NEAR(b, r, TOLERANCE); 3844 EXPECT_NEAR(b, r, TOLERANCE);
3842 } 3845 }
3843 } 3846 }
3844 3847
3848 static const size_t NUM_TIMINGS_CONVS = 2000;
3849
3850
3851 //4444444444444444$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
3852
3853 TEST(GenericToolbox, TestStringToDoubleHardNeg_lexical_cast_vs_StringToDouble)
3854 {
3855 using OrthancStone::GenericToolbox::StringToDouble;
3856 const double TOLERANCE = 0.00000000000001;
3857
3858 double total_us_StringToDouble = 0.0;
3859 double total_us_lexical_cast = 0.0;
3860 int64_t numConversions = 0;
3861
3862 size_t i = 0;
3863 const size_t COUNT = 125;
3864 //const double FACTOR = 1.000000000171271211;
3865 const double FACTOR = 1.71271211;
3866 for (double b = -1.0 * DBL_EPSILON; b < DBL_MAX && i < COUNT; ++i, b *= FACTOR)
3867 {
3868 char txt[1024];
3869 #if defined(_MSC_VER)
3870 sprintf_s(txt, "%.17f", b);
3871 #else
3872 snprintf(txt, sizeof(txt) - 1, "%.17f", b);
3873 #endif
3874
3875
3876 double r = 0.0;
3877
3878 bool ok = true;
3879
3880 {
3881 boost::chrono::system_clock::time_point start = boost::chrono::system_clock::now();
3882 for (size_t i = 0; i < NUM_TIMINGS_CONVS; ++i)
3883 {
3884 ok = StringToDouble(r, txt);
3885 }
3886 boost::chrono::system_clock::time_point end = boost::chrono::system_clock::now();
3887 boost::chrono::microseconds elapsed =
3888 boost::chrono::duration_cast<boost::chrono::microseconds>(end - start);
3889 total_us_StringToDouble += elapsed.count();
3890 }
3891
3892 {
3893 boost::chrono::system_clock::time_point start = boost::chrono::system_clock::now();
3894 for (size_t i = 0; i < NUM_TIMINGS_CONVS; ++i)
3895 {
3896 try
3897 {
3898 r = boost::lexical_cast<double>(txt);
3899 ok = true;
3900 }
3901 catch (boost::bad_lexical_cast& )
3902 {
3903 ok = false;
3904 }
3905 }
3906 boost::chrono::system_clock::time_point end = boost::chrono::system_clock::now();
3907 boost::chrono::microseconds elapsed =
3908 boost::chrono::duration_cast<boost::chrono::microseconds>(end - start);
3909 total_us_lexical_cast += elapsed.count();
3910 }
3911 numConversions += NUM_TIMINGS_CONVS;
3912
3913 #if 0
3914 if (ok)
3915 {
3916 printf("OK for txt = \"%s\" and r = %.17f\n", txt, r);
3917 }
3918 else
3919 {
3920 printf("Not ok for txt = \"%s\" and r = %.17f\n", txt, r);
3921 ok = StringToDouble(r, txt);
3922 }
3923 #endif
3924
3925 EXPECT_TRUE(ok);
3926
3927 #if 0
3928 if (fabs(b - r) > TOLERANCE)
3929 {
3930 printf("fabs(b (%.17f) - r (%.17f)) ((%.17f)) > TOLERANCE (%.17f)\n", b, r, fabs(b - r), TOLERANCE);
3931 }
3932 #endif
3933 EXPECT_NEAR(b, r, TOLERANCE);
3934 }
3935 std::cout << "Total time (us) for " << numConversions
3936 << " conversions using StringToDouble (with NO scientific notation) = "
3937 << static_cast<int64_t>(total_us_StringToDouble) << std::endl;
3938
3939 std::cout << "Time per conversion using StringToDouble (ns) = "
3940 << (int64_t)( (total_us_StringToDouble * 1000) /((double)numConversions)) << std::endl;
3941
3942 std::cout << "Total time (us) for " << numConversions
3943 << " conversions using boost::lexical_cast (with NO scientific notation) = "
3944 << static_cast<int64_t>(total_us_lexical_cast) << std::endl;
3945
3946 std::cout << "Time per conversion using boost::lexical_cast (ns) = "
3947 << (int64_t)( (total_us_lexical_cast * 1000) / ((double)numConversions)) << std::endl;
3948
3949 std::cout << "StringToDouble is " << (int)((total_us_lexical_cast / total_us_StringToDouble) + 0.5) << " times faster than boost::lexical_cast" << std::endl;
3950
3951 }
3952 //4444444444444444$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
3953
3845 3954
3846 TEST(GenericToolbox, TestStringToDoubleHardScientific) 3955 TEST(GenericToolbox, TestStringToDoubleHardScientific)
3847 { 3956 {
3848 using OrthancStone::GenericToolbox::StringToDouble; 3957 using OrthancStone::GenericToolbox::StringToDouble;
3849 const double TOLERANCE = 0.00000000000001; 3958 const double TOLERANCE = 0.00000000000001;
3953 EXPECT_NEAR(b, r, actualTolerance); 4062 EXPECT_NEAR(b, r, actualTolerance);
3954 } 4063 }
3955 } 4064 }
3956 4065
3957 4066
4067 TEST(GenericToolbox, TestStringToDoubleHardNegScientific_lexical_cast_vs_StringToDouble)
4068 {
4069 using OrthancStone::GenericToolbox::StringToDouble;
4070 const double TOLERANCE = 0.00000000000001;
4071
4072 size_t i = 0;
4073 const size_t COUNT = 125;
4074 //const double FACTOR = 1.000000000171271211;
4075 const double FACTOR = 1.71271211;
4076
4077 double total_us_StringToDouble = 0.0;
4078 double total_us_lexical_cast = 0.0;
4079 int64_t numConversions = 0;
4080
4081 for (double b = -1.0 * DBL_EPSILON; b < DBL_MAX && i < COUNT; ++i, b *= FACTOR)
4082 {
4083 // the tolerance must be adapted depending on the exponent
4084 double exponent = (b == 0) ? 0 : 1.0 + std::floor(std::log10(std::fabs(b)));
4085 double actualTolerance = TOLERANCE * pow(10.0, exponent);
4086
4087 char txt[1024];
4088 #if defined(_MSC_VER)
4089 sprintf_s(txt, "%.17e", b);
4090 #else
4091 snprintf(txt, sizeof(txt) - 1, "%.17e", b);
4092 #endif
4093 double r = 0.0;
4094
4095 bool ok = true;
4096
4097 {
4098 boost::chrono::system_clock::time_point start = boost::chrono::system_clock::now();
4099 for (size_t i = 0; i < NUM_TIMINGS_CONVS; ++i)
4100 {
4101 ok = StringToDouble(r, txt);
4102 }
4103 boost::chrono::system_clock::time_point end = boost::chrono::system_clock::now();
4104 boost::chrono::microseconds elapsed =
4105 boost::chrono::duration_cast<boost::chrono::microseconds>(end - start);
4106 total_us_StringToDouble += elapsed.count();
4107 }
4108
4109 {
4110 boost::chrono::system_clock::time_point start = boost::chrono::system_clock::now();
4111 for (size_t i = 0; i < NUM_TIMINGS_CONVS; ++i)
4112 {
4113 try
4114 {
4115 r = boost::lexical_cast<double>(txt);
4116 ok = true;
4117 }
4118 catch (boost::bad_lexical_cast& )
4119 {
4120 ok = false;
4121 }
4122 }
4123 boost::chrono::system_clock::time_point end = boost::chrono::system_clock::now();
4124 boost::chrono::microseconds elapsed =
4125 boost::chrono::duration_cast<boost::chrono::microseconds>(end - start);
4126 total_us_lexical_cast += elapsed.count();
4127 }
4128 numConversions += NUM_TIMINGS_CONVS;
4129
4130 #if 0
4131 if (ok)
4132 {
4133 printf("OK for txt = \"%s\" and r = %.17e\n", txt, r);
4134 }
4135 else
4136 {
4137 printf("Not ok for txt = \"%s\" and r = %.17e\n", txt, r);
4138 ok = StringToDouble(r, txt);
4139 }
4140 #endif
4141
4142 EXPECT_TRUE(ok);
4143
4144 #if 0
4145 if (fabs(b - r) > actualTolerance)
4146 {
4147 printf("NOK fabs(b (%.17f) - r (%.17f)) ((%.17f)) > actualTolerance (%.17f)\n", b, r, fabs(b - r), actualTolerance);
4148 printf("NOK fabs(b (%.17e) - r (%.17e)) ((%.17e)) > actualTolerance (%.17e)\n", b, r, fabs(b - r), actualTolerance);
4149 ok = StringToDouble(r, txt);
4150 }
4151 else
4152 {
4153 printf("OK fabs(b (%.17f) - r (%.17f)) ((%.17f)) <= actualTolerance (%.17f)\n", b, r, fabs(b - r), actualTolerance);
4154 printf("OK fabs(b (%.17e) - r (%.17e)) ((%.17e)) <= actualTolerance (%.17e)\n", b, r, fabs(b - r), actualTolerance);
4155 }
4156 #endif
4157 EXPECT_NEAR(b, r, actualTolerance);
4158 }
4159
4160 std::cout << "Total time (us) for " << numConversions
4161 << " conversions using StringToDouble (WITH scientific notation) = "
4162 << static_cast<int64_t>(total_us_StringToDouble) << std::endl;
4163
4164 std::cout << "Time per conversion using StringToDouble (ns) = "
4165 << (int64_t)( (total_us_StringToDouble*1000) / ((double)numConversions)) << std::endl;
4166
4167 std::cout << "Total time (us) for " << numConversions
4168 << " conversions using boost::lexical_cast (WITH scientific notation) = "
4169 << static_cast<int64_t>(total_us_lexical_cast) << std::endl;
4170
4171 std::cout << "Time per conversion using boost::lexical_cast (ns) = "
4172 << (int64_t)( (total_us_lexical_cast * 1000) / ((double)numConversions)) << std::endl;
4173
4174 std::cout << "StringToDouble is " << (int)((total_us_lexical_cast / total_us_StringToDouble)+ 0.5) << " times faster than boost::lexical_cast" << std::endl;
4175 }
4176
4177
3958 TEST(GenericToolbox, TestStringToIntegerHard) 4178 TEST(GenericToolbox, TestStringToIntegerHard)
3959 { 4179 {
3960 using OrthancStone::GenericToolbox::StringToInteger; 4180 using OrthancStone::GenericToolbox::StringToInteger;
3961 4181
3962 size_t i = 0; 4182 size_t i = 0;