<div dir="ltr"><div><div><div><div><div><div>Hi Eliot,<br></div>yes, because f2c translates FORTRAN to C, it necessarily follow some standard conventions.<br>(returning a double, and passing a complex result in first parameter by reference).<br></div><div>Then g77 just followed the f2c choices.<br></div>So the workaround was to:<br></div></div>- add a few FFI messages variant matching FFI conventions<br>- add a preference isCompiledWithF2Cconventions</div>- dispatch on this preference at upper level<br></div>- write a page on the wiki to inform about this mess, and tell how to recognize the convention in use<br> (this might be automated in a more clever system, but it means playing with cached values and resetting at each startup)<br><div><div><div><div><div><div><div><div class="gmail_extra"><br></div><div class="gmail_extra">It's just that I'll have to repeat this in the 2 other supported dialects,...<br></div><div class="gmail_extra"><br><div class="gmail_quote">2017-01-30 7:17 GMT+01:00 Eliot Miranda <span dir="ltr"><<a href="mailto:eliot.miranda@gmail.com" target="_blank">eliot.miranda@gmail.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
Hi Nicolas,<br>
<br>
isn't the solution to simply misdeckare the fact notion as returning a double? Provided the FFI mechanism supports all variants in use then it can collect values from all functions. That the necessary declaration doesn't match the function' declaration when compiled with a non-conforming toolchain is unfortunate but can be lived with.<br>
<br>
The issue is how to communicate the issue to programmers so they can diagnose and apply the work-around, which requires good documentation.<br>
<br>
_,,,^..^,,,_ (phone)<br>
<div class="gmail-HOEnZb"><div class="gmail-h5"><br>
> On Jan 26, 2017, at 4:57 PM, Nicolas Cellier <<a href="mailto:nicolas.cellier.aka.nice@gmail.com">nicolas.cellier.aka.nice@<wbr>gmail.com</a>> wrote:<br>
><br>
> Hi,<br>
> I have strange result with 64bits FFI function returning single precision float.<br>
> Here is an example:<br>
><br>
> (LapackSGEMatrix rows: #((2.3))) absMax.<br>
><br>
> This matrix has a single element, 2.3 rounded to single precision float<br>
> (2.299999952316284 when printed as a double precision)<br>
><br>
> absMax is supposed to take the maximum of absolute values in the matrix.<br>
> It does so thru Lapack function slange:<br>
> "<br>
> * Purpose<br>
> * =======<br>
> * SLANGE returns the value of the one norm, or the Frobenius norm, or<br>
> * the infinity norm, or the element of largest absolute value of a<br>
> * real matrix A.<br>
> "<br>
> <cdecl: float 'slange_'( char * long * long * float * long * float * long )><br>
><br>
> Unfortunately above snippet returns 3.6893488147419103e19<br>
><br>
> It correctly calls this:<br>
> floatRet = dispatchFunctionPointerwithwit<wbr>hwithwithwithwith(((float (*)(sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t, sqIntptr_t)) procAddr), ((calloutState-><wbr>integerRegisters))[0], ((calloutState-><wbr>integerRegisters))[1], ((calloutState-><wbr>integerRegisters))[2], ((calloutState-><wbr>integerRegisters))[3], ((calloutState-><wbr>integerRegisters))[4], ((calloutState-><wbr>integerRegisters))[5]);<br>
><br>
> which translates into something like:<br>
><br>
> 0x10833c537 <+2615>: movq -0x28(%rbp), %rax<br>
> 0x10833c53b <+2619>: movq -0xe8(%rbp), %rcx<br>
> 0x10833c542 <+2626>: movq 0xd8(%rcx), %rdi<br>
> 0x10833c549 <+2633>: movq -0xe8(%rbp), %rcx<br>
> 0x10833c550 <+2640>: movq 0xe0(%rcx), %rsi<br>
> 0x10833c557 <+2647>: movq -0xe8(%rbp), %rcx<br>
> 0x10833c55e <+2654>: movq 0xe8(%rcx), %rdx<br>
> 0x10833c565 <+2661>: movq -0xe8(%rbp), %rcx<br>
> 0x10833c56c <+2668>: movq 0xf0(%rcx), %rcx<br>
> 0x10833c573 <+2675>: movq -0xe8(%rbp), %r8<br>
> 0x10833c57a <+2682>: movq 0xf8(%r8), %r8<br>
> 0x10833c581 <+2689>: movq -0xe8(%rbp), %r9<br>
> 0x10833c588 <+2696>: movq 0x100(%r9), %r9<br>
> -> 0x10833c58f <+2703>: callq *%rax<br>
> 0x10833c591 <+2705>: cvtss2sd %xmm0, %xmm0<br>
> 0x10833c595 <+2709>: movsd %xmm0, -0x150(%rbp)<br>
><br>
> If I print $xmm0 just after the callq, then<br>
> (lldb) nexti<br>
> (lldb) print $xmm0<br>
> (unsigned char __attribute__((ext_vector_<wbr>type(16)))) $212 = (0x00, 0x00, 0x00, 0x60, 0x66, 0x66, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)<br>
><br>
> and just after the connversion to double precision:<br>
> (lldb) nexti<br>
> (lldb) print $xmm0<br>
> (unsigned char __attribute__((ext_vector_<wbr>type(16)))) $213 = (0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)<br>
><br>
> Let's see:<br>
><br>
> tmp := #[16r00 16r00 16r00 16r60 16r66 16r66 16r02 16r40 ].<br>
> {tmp doubleAt: 1.<br>
> tmp floatAt: 1}.<br>
> #(2.299999952316284 3.6893488147419103e19)<br>
><br>
> Bingo! that means that the value returned in xmm0 was already in double precision.<br>
> When we convert it back to single precision (it's like interpreting the 4 LSB of the double as a single precision), then we get the incorrect value...<br>
><br>
> So why was slange result promoted to double?<br>
> I can reproduce on macosx with pre-installed veclib, and in win64 compiling LAPACK 3.3.1 from sources (translated by f2c) with MSVC10.<br>
><br>
> Ah, Ah, f2c! Dont you promote float return values to double? YES<br>
> But why this does not happen with the 32bits VM ???<br>
> That's what drove me off the solution for a while...<br>
> It's the IA32 ABI... return value is stored in ST0 (allways promoted to double).<br>
> So converting it to a double again like we do is a no-op and just works in 32bits.<br>
><br>
> That's going to be a problem for FORTRAN functions on 64bits.<br>
> IF compiled thru g77 or f2c conventions, then float results are promoted to double!<br>
> IF compiled thru gfortran, then float result just remain float results.<br>
> It means a major source of incompatibility: how to guess how this binary was compiled? (for example vecLib...)<br>
><br>
> And how to adapt my FFI source code?<br>
> Last thing, f2c might also be non standard when returning a complex value<br>
> Big ball of mud...<br>
><br>
</div></div></blockquote></div><br></div></div></div></div></div></div></div></div></div>