[Maria-developers] MariaDB test question (main.cast)
I have downloaded, built and tested MariaDB 5.3.2 Beta on HP-UX 11.31 and I get two test failures, I have a question about one of tests that I was hoping someone could help me with. The main.cast test fails and the problem is with this part of the test: select cast(cast(20010203101112.1 as double) as datetime(1)); It is converting the string "20010203101112.1" to a double value and then converting the double value to a date. The test expects "2001-02-03 10:11:12.1" to be output but I am getting "2001-02-03 10:11:12.0". I think the problem is with the conversion into floating point. When I use gdb to break sql at double_to_datetime, on HP-UX the value I have is 20010203101112.098, on Linux I see 20010203101112.102. Neither value is completely correct because 20010203101112.1 cannot be represented exactly as an IEEE floating point value. So I have two questions. Where did the string get converted into a floating point value? I couldn't find where this is happening, I assume it is using strtod or something but breaking on that function didn't do anything. Secondly, given that 20010203101112.1 cannot be represented exactly as a double precision floating point value, is this a valid test? FYI: The other failure I get is main.cast, this test is trying to check for a stack overflow before it happens but IA64 HP-UX has two stacks, a register stack and a user data stack. In this test case the recursion of p_ere and p_ere_exp wind up using only the register stack because all the local variables and arguments are stored in registers. The stack check in check_stack_overrun is checking the user stack which doesn't overflow (or even change) and so we eventually die with a register stack overflow. There is a way to check the register stack on IA64 HP-UX, but it would require using IA64 assembly language so it may not be worth doing. Steve Ellcey sje@cup.hp.com
Hi, sje! On Oct 24, sje@cup.hp.com wrote:
I have downloaded, built and tested MariaDB 5.3.2 Beta on HP-UX 11.31 and I get two test failures, I have a question about one of tests that I was hoping someone could help me with.
The main.cast test fails and the problem is with this part of the test:
select cast(cast(20010203101112.1 as double) as datetime(1));
It is converting the string "20010203101112.1" to a double value and then converting the double value to a date. The test expects "2001-02-03 10:11:12.1" to be output but I am getting "2001-02-03 10:11:12.0". I think the problem is with the conversion into floating point. When I use gdb to break sql at double_to_datetime, on HP-UX the value I have is 20010203101112.098, on Linux I see 20010203101112.102. Neither value is completely correct because 20010203101112.1 cannot be represented exactly as an IEEE floating point value.
Thanks. Good analysys!
So I have two questions. Where did the string get converted into a floating point value? I couldn't find where this is happening, I assume it is using strtod or something but breaking on that function didn't do anything. Secondly, given that 20010203101112.1 cannot be represented exactly as a double precision floating point value, is this a valid test?
Two answers: There should be no strtod, because the argument of the cast(... as double) is not a string, but a decimal number. I'd expect the conversion to happen in decimal2double() function. Secondly, I think you're right - it is not.
FYI: The other failure I get is main.cast, this test is trying to check for a stack overflow before it happens but IA64 HP-UX has two stacks, a register stack and a user data stack. In this test case the recursion of p_ere and p_ere_exp wind up using only the register stack because all the local variables and arguments are stored in registers. The stack check in check_stack_overrun is checking the user stack which doesn't overflow (or even change) and so we eventually die with a register stack overflow. There is a way to check the register stack on IA64 HP-UX, but it would require using IA64 assembly language so it may not be worth doing.
Okay. What would you suggest? Just disable the test in the test suite? Do not check for stack overflow on IA64 HP-UX at all? Check for both stacks? Regards, Sergei
On Thu, 2011-10-27 at 12:12 +0200, Sergei Golubchik wrote:
Two answers: There should be no strtod, because the argument of the cast(... as double) is not a string, but a decimal number. I'd expect the conversion to happen in decimal2double() function. Secondly, I think you're right - it is not.
OK, that is a big help. I looked at decimal2double and that is where the problem occurs. IA64 has an fma (fused multiply and add) instruction and if you use it you can get slightly different results then you would if you did a multiply followed by a separate add instruction because with fma the result of the multiplication is not truncated before you do the addition. If I put '#pragma STDC FP_CONTRACT OFF' before decimal2double (and #pragma STDC FP_CONTRACT ON) afterwards then the function does not use the fma instruction and the main.cast test does not fail. This would only work with the HP compiler though, if someone compiled with GCC on IA64, it would still fail because GCC does not honor the FP_CONTRACT pragma. I am not sure if we want to do this as a permanent fix though, if we fix the test to use a value that is exactly representable as a double (say .5 instead of .1 or something like that) then I would probably not try to add the pragma and/or use an option to turn off fma usage because that would slow the code down. If we need more accurate results then maybe we should consider using gmp like GCC and glibc do, but maybe we are OK with the fact that different systems (or the same system with different compiler optimization flags) may generate different results for values that cannot be represented exactly.
FYI: The other failure I get is main.cast, this test is trying to check for a stack overflow before it happens but IA64 HP-UX has two stacks, a register stack and a user data stack. In this test case the recursion of p_ere and p_ere_exp wind up using only the register stack because all the local variables and arguments are stored in registers. The stack check in check_stack_overrun is checking the user stack which doesn't overflow (or even change) and so we eventually die with a register stack overflow. There is a way to check the register stack on IA64 HP-UX, but it would require using IA64 assembly language so it may not be worth doing.
Okay. What would you suggest? Just disable the test in the test suite? Do not check for stack overflow on IA64 HP-UX at all? Check for both stacks?
I will spend some time seeing how easy/hard it would be to check both stacks. One question I have about the current stack check is in check_stack_overrun there is: if ((stack_used=used_stack(thd->thread_stack,(char*) &stack_used)) >= (long) (my_thread_stack_size - margin)) I believe that thd->thread_stack should be pointing at the base of the stack we are checking for overflow, but I see that that variable is set in a lot of places, mostly with: thd->thread_stack = (char*)&thd; Why is thd->thread_stack set in so many different places? If I need to save the base of the IA64 register stack in all those places too, that would be touching a lot of files. Steve Ellcey sje@cup.hp.com
Hi, Steve! On Oct 27, Steve Ellcey wrote:
On Thu, 2011-10-27 at 12:12 +0200, Sergei Golubchik wrote:
Two answers: There should be no strtod, because the argument of the cast(... as double) is not a string, but a decimal number. I'd expect the conversion to happen in decimal2double() function. Secondly, I think you're right - it is not.
OK, that is a big help. I looked at decimal2double and that is where the problem occurs. IA64 has an fma (fused multiply and add) instruction and if you use it you can get slightly different results then you would if you did a multiply followed by a separate add instruction because with fma the result of the multiplication is not truncated before you do the addition. If I put '#pragma STDC FP_CONTRACT OFF' before decimal2double (and #pragma STDC FP_CONTRACT ON) afterwards then the function does not use the fma instruction and the main.cast test does not fail. This would only work with the HP compiler though, if someone compiled with GCC on IA64, it would still fail because GCC does not honor the FP_CONTRACT pragma.
I am not sure if we want to do this as a permanent fix though, if we fix the test to use a value that is exactly representable as a double (say .5 instead of .1 or something like that) then I would probably not try to add the pragma and/or use an option to turn off fma usage because that would slow the code down.
Yes, I agree absolutely. Let's fix the test instead. Was that cast(cast(20010203101112.1 as double) as datetime(1)) the only one that failed?
FYI: The other failure I get is main.cast, this test is trying to check for a stack overflow before it happens but IA64 HP-UX has two stacks, a register stack and a user data stack.
Okay. What would you suggest? Just disable the test in the test suite? Do not check for stack overflow on IA64 HP-UX at all? Check for both stacks?
I will spend some time seeing how easy/hard it would be to check both stacks. One question I have about the current stack check is in check_stack_overrun there is:
if ((stack_used=used_stack(thd->thread_stack,(char*) &stack_used)) >= (long) (my_thread_stack_size - margin))
I believe that thd->thread_stack should be pointing at the base of the stack we are checking for overflow, but I see that that variable is set in a lot of places, mostly with:
thd->thread_stack = (char*)&thd;
Why is thd->thread_stack set in so many different places? If I need to save the base of the IA64 register stack in all those places too, that would be touching a lot of files.
Because new THD is created or initialized in all these places. The pattern is { THD *thd; thd= new THD; thd->thread_stack= (char*) &thd; ... // do some work delete new_thd; } Regards, Sergei
On Fri, 2011-10-28 at 09:12 +0200, Sergei Golubchik wrote:
Yes, I agree absolutely. Let's fix the test instead. Was that cast(cast(20010203101112.1 as double) as datetime(1)) the only one that failed?
Yes, that one is the only one that fails. I changed it to: select cast(cast(20010203101112.5 as double) as datetime(1)); and updated the master results file and the test then passed. Steve Ellcey sje@cup.hp.com
participants (3)
-
Sergei Golubchik
-
sje@cup.hp.com
-
Steve Ellcey