Loading mysql-test/r/type_float.result +7 −0 Original line number Diff line number Diff line Loading @@ -262,6 +262,13 @@ desc t3; Field Type Null Key Default Extra a decimal(21,2) NO 0.00 drop table t1,t2,t3; select 1e-308, 1.00000001e-300, 100000000e-300; 1e-308 1.00000001e-300 100000000e-300 0 1.00000001e-300 1e-292 select 10e307; 10e307 1e+308 End of 4.1 tests create table t1 (s1 float(0,2)); ERROR 42000: For float(M,D), double(M,D) or decimal(M,D), M must be >= D (column 's1'). create table t1 (s1 float(1,2)); Loading mysql-test/t/type_float.test +10 −1 Original line number Diff line number Diff line Loading @@ -178,7 +178,16 @@ show warnings; desc t3; drop table t1,t2,t3; # End of 4.1 tests # # Bug #22129: A small double precision number becomes zero # # check if underflows are detected correctly select 1e-308, 1.00000001e-300, 100000000e-300; # check if overflows are detected correctly select 10e307; --echo End of 4.1 tests # # bug #12694 (float(m,d) specifications) Loading strings/strtod.c +43 −24 Original line number Diff line number Diff line Loading @@ -30,7 +30,8 @@ #include "m_ctype.h" #define MAX_DBL_EXP 308 #define MAX_RESULT_FOR_MAX_EXP 1.79769313486232 #define MAX_RESULT_FOR_MAX_EXP 1.7976931348623157 #define MIN_RESULT_FOR_MIN_EXP 2.225073858507202 static double scaler10[] = { 1.0, 1e10, 1e20, 1e30, 1e40, 1e50, 1e60, 1e70, 1e80, 1e90 }; Loading @@ -57,10 +58,11 @@ double my_strtod(const char *str, char **end_ptr, int *error) { double result= 0.0; uint negative= 0, ndigits, dec_digits= 0, neg_exp= 0; int exp= 0, digits_after_dec_point= 0; int exp= 0, digits_after_dec_point= 0, tmp_exp; const char *old_str, *end= *end_ptr, *start_of_number; char next_char; my_bool overflow=0; double scaler= 1.0; *error= 0; if (str >= end) Loading Loading @@ -91,6 +93,7 @@ double my_strtod(const char *str, char **end_ptr, int *error) while ((next_char= *str) >= '0' && next_char <= '9') { result= result*10.0 + (next_char - '0'); scaler= scaler*10.0; if (++str == end) { next_char= 0; /* Found end of string */ Loading @@ -114,6 +117,7 @@ double my_strtod(const char *str, char **end_ptr, int *error) { result= result*10.0 + (next_char - '0'); digits_after_dec_point++; scaler= scaler*10.0; if (++str == end) { next_char= 0; Loading Loading @@ -144,39 +148,54 @@ double my_strtod(const char *str, char **end_ptr, int *error) } while (str < end && my_isdigit(&my_charset_latin1, *str)); } } if ((exp= (neg_exp ? exp + digits_after_dec_point : exp - digits_after_dec_point))) { double scaler; if (exp < 0) { exp= -exp; neg_exp= 1; /* neg_exp was 0 before */ } if (exp + ndigits >= MAX_DBL_EXP + 1 && result) tmp_exp= neg_exp ? exp + digits_after_dec_point : exp - digits_after_dec_point; if (tmp_exp) { int order; /* This is not 100 % as we actually will give an owerflow for 17E307 but not for 1.7E308 but lets cut some corners to make life simpler Check for underflow/overflow. order is such an integer number that f = C * 10 ^ order, where f is the resulting floating point number and 1 <= C < 10. Here we compute the modulus */ if (exp + ndigits > MAX_DBL_EXP + 1 || result >= MAX_RESULT_FOR_MAX_EXP) { order= exp + (neg_exp ? -1 : 1) * (ndigits - 1); if (order < 0) order= -order; if (order >= MAX_DBL_EXP && result) { double c; /* Compute modulus of C (see comment above) */ c= result / scaler * 10.0; if (neg_exp) { if (order > MAX_DBL_EXP || c < MIN_RESULT_FOR_MIN_EXP) { result= 0.0; goto done; } } else { if (order > MAX_DBL_EXP || c > MAX_RESULT_FOR_MAX_EXP) { overflow= 1; goto done; } } scaler= 1.0; } exp= tmp_exp; if (exp < 0) { exp= -exp; neg_exp= 1; /* neg_exp was 0 before */ } while (exp >= 100) { scaler*= 1.0e100; result= neg_exp ? result/1.0e100 : result*1.0e100; exp-= 100; } scaler*= scaler10[exp/10]*scaler1[exp%10]; scaler= scaler10[exp/10]*scaler1[exp%10]; if (neg_exp) result/= scaler; else Loading Loading
mysql-test/r/type_float.result +7 −0 Original line number Diff line number Diff line Loading @@ -262,6 +262,13 @@ desc t3; Field Type Null Key Default Extra a decimal(21,2) NO 0.00 drop table t1,t2,t3; select 1e-308, 1.00000001e-300, 100000000e-300; 1e-308 1.00000001e-300 100000000e-300 0 1.00000001e-300 1e-292 select 10e307; 10e307 1e+308 End of 4.1 tests create table t1 (s1 float(0,2)); ERROR 42000: For float(M,D), double(M,D) or decimal(M,D), M must be >= D (column 's1'). create table t1 (s1 float(1,2)); Loading
mysql-test/t/type_float.test +10 −1 Original line number Diff line number Diff line Loading @@ -178,7 +178,16 @@ show warnings; desc t3; drop table t1,t2,t3; # End of 4.1 tests # # Bug #22129: A small double precision number becomes zero # # check if underflows are detected correctly select 1e-308, 1.00000001e-300, 100000000e-300; # check if overflows are detected correctly select 10e307; --echo End of 4.1 tests # # bug #12694 (float(m,d) specifications) Loading
strings/strtod.c +43 −24 Original line number Diff line number Diff line Loading @@ -30,7 +30,8 @@ #include "m_ctype.h" #define MAX_DBL_EXP 308 #define MAX_RESULT_FOR_MAX_EXP 1.79769313486232 #define MAX_RESULT_FOR_MAX_EXP 1.7976931348623157 #define MIN_RESULT_FOR_MIN_EXP 2.225073858507202 static double scaler10[] = { 1.0, 1e10, 1e20, 1e30, 1e40, 1e50, 1e60, 1e70, 1e80, 1e90 }; Loading @@ -57,10 +58,11 @@ double my_strtod(const char *str, char **end_ptr, int *error) { double result= 0.0; uint negative= 0, ndigits, dec_digits= 0, neg_exp= 0; int exp= 0, digits_after_dec_point= 0; int exp= 0, digits_after_dec_point= 0, tmp_exp; const char *old_str, *end= *end_ptr, *start_of_number; char next_char; my_bool overflow=0; double scaler= 1.0; *error= 0; if (str >= end) Loading Loading @@ -91,6 +93,7 @@ double my_strtod(const char *str, char **end_ptr, int *error) while ((next_char= *str) >= '0' && next_char <= '9') { result= result*10.0 + (next_char - '0'); scaler= scaler*10.0; if (++str == end) { next_char= 0; /* Found end of string */ Loading @@ -114,6 +117,7 @@ double my_strtod(const char *str, char **end_ptr, int *error) { result= result*10.0 + (next_char - '0'); digits_after_dec_point++; scaler= scaler*10.0; if (++str == end) { next_char= 0; Loading Loading @@ -144,39 +148,54 @@ double my_strtod(const char *str, char **end_ptr, int *error) } while (str < end && my_isdigit(&my_charset_latin1, *str)); } } if ((exp= (neg_exp ? exp + digits_after_dec_point : exp - digits_after_dec_point))) { double scaler; if (exp < 0) { exp= -exp; neg_exp= 1; /* neg_exp was 0 before */ } if (exp + ndigits >= MAX_DBL_EXP + 1 && result) tmp_exp= neg_exp ? exp + digits_after_dec_point : exp - digits_after_dec_point; if (tmp_exp) { int order; /* This is not 100 % as we actually will give an owerflow for 17E307 but not for 1.7E308 but lets cut some corners to make life simpler Check for underflow/overflow. order is such an integer number that f = C * 10 ^ order, where f is the resulting floating point number and 1 <= C < 10. Here we compute the modulus */ if (exp + ndigits > MAX_DBL_EXP + 1 || result >= MAX_RESULT_FOR_MAX_EXP) { order= exp + (neg_exp ? -1 : 1) * (ndigits - 1); if (order < 0) order= -order; if (order >= MAX_DBL_EXP && result) { double c; /* Compute modulus of C (see comment above) */ c= result / scaler * 10.0; if (neg_exp) { if (order > MAX_DBL_EXP || c < MIN_RESULT_FOR_MIN_EXP) { result= 0.0; goto done; } } else { if (order > MAX_DBL_EXP || c > MAX_RESULT_FOR_MAX_EXP) { overflow= 1; goto done; } } scaler= 1.0; } exp= tmp_exp; if (exp < 0) { exp= -exp; neg_exp= 1; /* neg_exp was 0 before */ } while (exp >= 100) { scaler*= 1.0e100; result= neg_exp ? result/1.0e100 : result*1.0e100; exp-= 100; } scaler*= scaler10[exp/10]*scaler1[exp%10]; scaler= scaler10[exp/10]*scaler1[exp%10]; if (neg_exp) result/= scaler; else Loading