List:Commits« Previous MessageNext Message »
From:Alexey Kopytov Date:November 29 2007 9:38am
Subject:Re: bk commit into 5.1 tree (kaa:1.2521) BUG#12860
View as plain text  
Hi Sergei,

On Monday 01 October 2007 17:29:10, Sergei Golubchik wrote:
>Hi!
>
>On Sep 10, Alexey Kopytov wrote:
>> >> --- 1.656/sql/mysqld.cc	2007-06-17 19:20:16 +04:00
>> >> +++ 1.657/sql/mysqld.cc	2007-07-10 17:37:22 +04:00
>> >> @@ -478,6 +478,40 @@ ulong expire_logs_days = 0;
>> >>  ulong rpl_recovery_rank=0;
>> >>  const char *log_output_str= "TABLE";
>> >>
>> >> +const double log_10[] = {
>> >> +  1e000, 1e001, 1e002, 1e003, 1e004, 1e005, 1e006, 1e007, 1e008,
>> >> 1e009, +  1e010, 1e011, 1e012, 1e013, 1e014, 1e015, 1e016, 1e017,
>> >> 1e018, 1e019, +  1e020, 1e021, 1e022, 1e023, 1e024, 1e025, 1e026,
>> >> 1e027, 1e028, 1e029, +  1e030, 1e031, 1e032, 1e033, 1e034, 1e035,
>> >> 1e036, 1e037, 1e038, 1e039, +  1e040, 1e041, 1e042, 1e043, 1e044,
>> >> 1e045, 1e046, 1e047, 1e048, 1e049, +  1e050, 1e051, 1e052, 1e053,
>> >> 1e054, 1e055, 1e056, 1e057, 1e058, 1e059, +  1e060, 1e061, 1e062,
>> >> 1e063, 1e064, 1e065, 1e066, 1e067, 1e068, 1e069, +  1e070, 1e071,
>> >> 1e072, 1e073, 1e074, 1e075, 1e076, 1e077, 1e078, 1e079, +  1e080,
>> >> 1e081, 1e082, 1e083, 1e084, 1e085, 1e086, 1e087, 1e088, 1e089, + 
>> >> 1e090, 1e091, 1e092, 1e093, 1e094, 1e095, 1e096, 1e097, 1e098, 1e099, +
>> >>  1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109,
>> >> +  1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118,
>> >> 1e119, +  1e120, 1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127,
>> >> 1e128, 1e129, +  1e130, 1e131, 1e132, 1e133, 1e134, 1e135, 1e136,
>> >> 1e137, 1e138, 1e139, +  1e140, 1e141, 1e142, 1e143, 1e144, 1e145,
>> >> 1e146, 1e147, 1e148, 1e149, +  1e150, 1e151, 1e152, 1e153, 1e154,
>> >> 1e155, 1e156, 1e157, 1e158, 1e159, +  1e160, 1e161, 1e162, 1e163,
>> >> 1e164, 1e165, 1e166, 1e167, 1e168, 1e169, +  1e170, 1e171, 1e172,
>> >> 1e173, 1e174, 1e175, 1e176, 1e177, 1e178, 1e179, +  1e180, 1e181,
>> >> 1e182, 1e183, 1e184, 1e185, 1e186, 1e187, 1e188, 1e189, +  1e190,
>> >> 1e191, 1e192, 1e193, 1e194, 1e195, 1e196, 1e197, 1e198, 1e199, + 
>> >> 1e200, 1e201, 1e202, 1e203, 1e204, 1e205, 1e206, 1e207, 1e208, 1e209, +
>> >>  1e210, 1e211, 1e212, 1e213, 1e214, 1e215, 1e216, 1e217, 1e218, 1e219,
>> >> +  1e220, 1e221, 1e222, 1e223, 1e224, 1e225, 1e226, 1e227, 1e228,
>> >> 1e229, +  1e230, 1e231, 1e232, 1e233, 1e234, 1e235, 1e236, 1e237,
>> >> 1e238, 1e239, +  1e240, 1e241, 1e242, 1e243, 1e244, 1e245, 1e246,
>> >> 1e247, 1e248, 1e249, +  1e250, 1e251, 1e252, 1e253, 1e254, 1e255,
>> >> 1e256, 1e257, 1e258, 1e259, +  1e260, 1e261, 1e262, 1e263, 1e264,
>> >> 1e265, 1e266, 1e267, 1e268, 1e269, +  1e270, 1e271, 1e272, 1e273,
>> >> 1e274, 1e275, 1e276, 1e277, 1e278, 1e279, +  1e280, 1e281, 1e282,
>> >> 1e283, 1e284, 1e285, 1e286, 1e287, 1e288, 1e289, +  1e290, 1e291,
>> >> 1e292, 1e293, 1e294, 1e295, 1e296, 1e297, 1e298, 1e299, +  1e300,
>> >> 1e301, 1e302, 1e303, 1e304, 1e305, 1e306, 1e307, 1e308 +};
>> >
>> >It doesn't need to be that big now, does it ?
>> >perhaps we can get rid of it completely ?
>>
>> AFAIK, there is still one place where we need it, Field_real::truncate().
>> To be exact, the more powers of 10 we have here, the more chances to avoid
>> the "tight loop" here:
>>
>>     uint order= field_length - dec;
>>     uint step= array_elements(log_10) - 1;
>>     max_value= 1.0;
>>     for (; order > step; order-= step)
>>       max_value*= log_10[step];
>>     max_value*= log_10[order];
>>     max_value-= 1.0 / log_10[dec];
>
>Yes, so I'd limit the array size to about 20 elements.
>I don't see a need to put this static array in every binary to optimize
>for a case of a DOUBLE(200,30) column (large field_length, that is).
>

I tried reducing the array size, and it doesn't work. We lose the precision 
when calculating the max_value in Field_real::truncate() which results in the 
following artifact:
-------------------------------------------------------
*** r/type_float.result Mon Sep 10 15:34:30 2007
--- r/type_float.reject Wed Nov 28 19:47:47 2007
***************
*** 347,352 ****
--- 347,355 ----
  create table t1 (f1 double(200, 0));
  insert into t1 values (1e199), (-1e199);
  insert into t1 values (1e200), (-1e200);
+ Warnings:
+ Warning       1264    Out of range value for column 'f1' at row 1
+ Warning       1264    Out of range value for column 'f1' at row 2
  insert into t1 values (2e200), (-2e200);
  Warnings:
  Warning       1264    Out of range value for column 'f1' at row 1
***************
*** 355,364 ****
  f1 + 0e0
  1e199
  -1e199
! 1e200
! -1e200
! 1e200
! -1e200
  drop table t1;
  create table t1 (f1 float(30, 0));
  insert into t1 values (1e29), (-1e29);
--- 358,367 ----
  f1 + 0e0
  1e199
  -1e199
! 9.999999999999998e199
! -9.999999999999998e199
! 9.999999999999998e199
! -9.999999999999998e199
  drop table t1;
  create table t1 (f1 float(30, 0));
  insert into t1 values (1e29), (-1e29);
-------------------------------------------------------

What's happening is that max_value is calculated imprecisely with 
multiplications which results in the above test failure.

We also get performance degradation in Field_real::truncate() and 
my_double_round() with this change.

Anyway, defining the above array increases the binary size by 309 * 8 = 2472 
bytes, which does not look significant to me.

>> >> --- 1.65/mysql-test/r/func_group.result	2007-05-29 16:57:16 +04:00
>> >> +++ 1.66/mysql-test/r/func_group.result	2007-07-10 17:37:18 +04:00
>> >> @@ -891,7 +891,7 @@ select 1e8 * sum(distinct df) from t1;
>> >>  330000000
>> >>  select 1e8 * min(df) from t1;
>> >>  1e8 * min(df)
>> >> -110000000
>> >> +110000000.00000001
>> >
>> >explain this change, please
>>
>> Two things:
>>
>> 1. Our decimal2double() conversion is imprecise due to 'naive' algorithm.
>> It would be better to just print the digits to a string buffer and then
>> run my_strtod() on it. Please let me know if you think this must be
>> included into the patch for WL#2934.
>
>Yes, I do.
>decimal2double() match the behaviour double2decimal().
>

Done it the new patch, though it didn't solve this particular problem :( The 
only reason for this change is the second one that I mentioned earlier:

>2. As a consequence of the above, we get 1.1000000000000001 when converting
> a DECIMAL '1.1' to double. But String::set_real() previously involved
> sprintf("%14g") for conversion, so it was just hiding the computational
> error introduced by decimal2double().

Multiplication of 1e8 by 1.1 does result in 110000000.00000001 due to 
computational error, it was just sprintf() which was hiding the fact 
previously.

Although changing decimal2double() to use my_strtod() was not useless, see 
fixes in sp.result in the new patch (we do have more precises results from 
it).

>> >> --- 1.34/mysql-test/r/insert.result	2007-05-31 13:19:10 +04:00
>> >> +++ 1.35/mysql-test/r/insert.result	2007-07-10 17:37:19 +04:00
>> >> @@ -159,6 +159,7 @@ set @value= "1e+1111111111a";
>> >>  insert into t1
>> >> values(null,@value,@value,@value,@value,@value,@value,@value,@value,@va
>> >>lue ); Warnings:
>> >>  Warning	1264	Out of range value for column 'f_double' at row 1
>> >> +Warning	1264	Out of range value for column 'f_double' at row 1
>> >
>> >why a duplicate warning ?
>>
>> We get one from my_strtod() when it truncates "1e+1111111111a" to +Inf,
>> and another from if Field_real::truncate() which truncates +Inf to
>> DBL_MAX.
>
>Why not to truncate to DBL_MAX in my_strtod() ?

Done in the new patch.

>Or, alternatively, not to issue a warning when truncating to Inf, as Inf
>will cause a warning later anyway.
>
>> >> --- 1.61/mysql-test/r/ps_2myisam.result	2007-06-05 19:51:44 +04:00
>> >> +++ 1.62/mysql-test/r/ps_2myisam.result	2007-07-10 17:37:19 +04:00
>> >> @@ -2822,10 +2822,10 @@ c1	c20	c21	c22	c23	c24	c25	c26	c27	c28	c
>> >>  51	5	51.0	51.0	51.0	51.0	51.0	51.0	51.0	51.0	51.0	51.0
>> >>  52	5	52.0	52.0	52.0	52.0	52.0	52.0	52.0	52.0	52.0	52.0
>> >>  53	5	53.0	53.0	53.0	53.0	53.0	53.0	53.0	53.0	53.0	53.0
>> >> -54	5	54	54	54.00	54.00	54.00	54.00	54.00	54.00	54.00	54.00
>> >> +54	0	54	54	54.00	54.00	54.00	54.00	54.00	54.00	54.00	54.00
>> >
>> >This is probably a bad idea.
>> >when you cannot convert a number to a string in a too small buffer
>> >you return 0. Old code was truncating the string, which I believe was
>> >correct. It's like assigning a long string to a short buffer -
>> >a string should be truncated.
>>
>> It looks like a "gray area" to me. The counter-argument would be that when
>> truncating a string the result is always a valid string. When truncating
>> string representations of a number, the result may not even be a valid
>> string representation of a number.
>
>Yes, but still - first you convert, then truncate.
>That's the old behaviour, at least.
>

Done in the new patch.

>> >> +INSERT INTO d1 VALUES (1.79769313486232e+308);
>> >> +SELECT * FROM d1;
>> >> +DROP TABLE d1;
>> >> +
>> >> --- 1.59/mysql-test/r/type_newdecimal.result	2007-05-21 21:31:05 +04:00
>> >> +++ 1.60/mysql-test/r/type_newdecimal.result	2007-07-10 17:37:20 +04:00
>> >> @@ -1175,21 +1167,21 @@ CAST(my_float   AS DECIMAL(65,30))	my_fl
>> >>  0.000000000000000001175494374380	1.17549e-18
>> >>  0.000000000000000011754943743802	1.17549e-17
>> >>  0.000000000000000117549432474939	1.17549e-16
>> >> -0.000000000000001175494324749389	1.17549e-15
>> >> -0.000000000000011754943671010360	1.17549e-14
>> >> -0.000000000000117549429933840000	1.17549e-13
>> >> -0.000000000001175494380653563000	1.17549e-12
>> >> -0.000000000011754943372854760000	1.17549e-11
>> >> -0.000000000117549428524377200000	1.17549e-10
>> >> -0.000000001175494368510499000000	1.17549e-09
>> >> -0.000000011754943685104990000000	1.17549e-08
>> >> -0.000000117549433298336200000000	1.17549e-07
>> >> -0.000001175494389826781000000000	1.17549e-06
>> >> -0.000011754943443520460000000000	1.17549e-05
>> >> +0.000000000000001175494324749389	0.00000000000000117549
>> >> +0.000000000000011754943671010362	0.0000000000000117549
>> >> +0.000000000000117549429933840040	0.000000000000117549
>> >> +0.000000000001175494380653563400	0.00000000000117549
>> >> +0.000000000011754943372854765000	0.0000000000117549
>> >> +0.000000000117549428524377220000	0.000000000117549
>> >> +0.000000001175494368510499000000	0.00000000117549
>> >> +0.000000011754943685104990000000	0.0000000117549
>> >> +0.000000117549433298336230000000	0.000000117549
>> >> +0.000001175494389826781100000000	0.00000117549
>> >> +0.000011754943443520460000000000	0.0000117549
>> >>  0.000117549432616215200000000000	0.000117549
>> >> -0.001175494398921728000000000000	0.00117549
>> >> +0.001175494398921728100000000000	0.00117549
>> >> -0.011754943057894710000000000000	0.0117549
>> >> +0.011754943057894707000000000000	0.0117549
>> >> -0.117549434304237400000000000000	0.117549
>> >> +0.117549434304237370000000000000	0.117549
>> >
>> >Hm. Here we cast a *float* to a decimal. From the results
>> >it's clear that dtoa uses a double precision here.
>> >Could you fix it so that it would use correct precision ?
>>
>> This is what WL#3977 is about. I have no idea how to fix this
>> "locally". We need float2decimal(), and then we need
>> Field::val_float() and so on.
>
>Ok. Please add a note to the test case (in type_newdecimal.test) that
>the result is not good (I avoid to use the word "wrong" here :), and
>improving it is the subject of WL#3977.
>

Done in the new patch.

Best regards,

-- 
Alexey Kopytov, Software Developer
MySQL AB, www.mysql.com

Are you MySQL certified?  www.mysql.com/certification
Thread
bk commit into 5.1 tree (kaa:1.2521) BUG#12860Alexey Kopytov10 Jul
  • Re: bk commit into 5.1 tree (kaa:1.2521) BUG#12860Sergei Golubchik26 Jul
    • Re: bk commit into 5.1 tree (kaa:1.2521) BUG#12860Alexey Kopytov10 Sep
      • Re: bk commit into 5.1 tree (kaa:1.2521) BUG#12860Sergei Golubchik1 Oct
        • Re: bk commit into 5.1 tree (kaa:1.2521) BUG#12860Alexey Kopytov29 Nov