|
forums.silverfrost.com Welcome to the Silverfrost forums
|
View previous topic :: View next topic |
Author |
Message |
rrobe71907
Joined: 26 Sep 2014 Posts: 10 Location: Tamaqua PA
|
Posted: Fri Nov 07, 2014 10:33 pm Post subject: Interesting EXP(X) problem Invalid Floating Point Operation |
|
|
Have an interesting problem. Over the years, have done a lot of mixed language programming (main program written in one language calling a subroutine written in another; subroutines written in different languages calling each other) on a couple of different platforms.
Currently playing with D main programs calling FORTRAN subroutines.
when the following is used as real function in FORTRAN
main program (ENG0010.exe) the function runs fine
--------------------------
C Series Resistance Capacitance Circuit
C Resistance Capacitance Time
C T : Seconds
C R : Ohms
C C : Farads
REAL FUNCTION ERCT (T, R, C) RESULT (X)
REAL T, R, C, X
X = T / (R * C)
X = EXP(X)
RETURN
END FUNCTION ERCT
when used in a .dll (mathproc.dll) called by a D command line
program (dmath.exe, compiled with DMD dmath.d mathproc.lib),
function crashes at X = EXP(X) with
object.Error@(0): Invalid Floating Point Operation
in RegisterWaitForInputIdle
(I suspect that is a DMD v2.066.0 compiler specific message/error)
The FORTRAN main program:
PROGRAM ENG0010
IMPLICIT NONE
REAL E, T, R, C, L, I, ERCT, VCAP, V, TMP
C = 0.000018;
R = 8100.0;
E = 20.0;
T = 0.31;
TMP = ERCT (T, R, C)
PRINT '(a,F7.2)',' ERCT (T, R, C): ', TMP
V = VCAP (E, T, R, C)
PRINT '(a,F7.2)',' VCAP (E, T, R, C): ', V
END
The D main program:
import std.stdio;
// mathproc.dll subroutine declarations
extern (Pascal)
{
float ERCT (ref float, ref float, ref float);
float VCAP (ref float, ref float, ref float, ref float);
}
int main(string[] args)
{
float C, R, t, E, L, V, I, tmp;
C = 0.000018;
R = 8100.0;
E = 20.0;
t = 0.31;
tmp = ERCT (C,R,t);
printf (" ERCT (C,R,t): %f \n", tmp);
V = VCAP(C,R,t,E);
printf (" VCAP(C,R,t,E): %f \n", V);
return (0);
}
[extern (Pascal) requires the parameters passed in reverse order; this was the only way I could get the D mains/FORTRAN .dll's compile/link cleanly]
Dependency Walker shows the ENG0010.exe version calls __FTN95INIT1_,
dmath.exe does not.
When dmath.exe profiled with Dependency Walker, received the following error:
Second chance exception 0xC0000090 (Float Invalid Operation) occurred in "SALFLIBC.DLL" at address 0x0053EB0A.
Have successfully called other float/REAL*4 FORTRAN functions from both
D command line and Windows programs; only time I have seen similar errors was when I should have used REAL*8 instead of REAL*4, so tried that correction; same result.
Can think of several possibilities:
1. I am blind and cannot see an obvious error
2. I need to call some sort of floating point initializer
or arithmetic trap; is it possible to call __FTN95INIT1_ (or its equivalent)
directly?
3. D calling FORTRAN function EXP(X) may have some minor
eccentricity/incompatibility.
Would someone like to admit my ignorance for me?
Would not be surprised if I did something goofy.
Thanks for reading this post. _________________ Rodney Roberts |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7933 Location: Salford, UK
|
Posted: Sat Nov 08, 2014 9:08 am Post subject: |
|
|
I think that you may need to find a way to load salflibc.dll at the start.
Perhaps a call to LoadLibrary will do the trick. There is a similar comment in the instructions for using FTN95 with Visual Basic. See the knowledge base of this forum or ftn95.chm. |
|
Back to top |
|
|
DanRRight
Joined: 10 Mar 2008 Posts: 2826 Location: South Pole, Antarctica
|
Posted: Sat Nov 08, 2014 11:56 am Post subject: |
|
|
Try adding
call mask_underflow@()
somewhere at the start |
|
Back to top |
|
|
rrobe71907
Joined: 26 Sep 2014 Posts: 10 Location: Tamaqua PA
|
Posted: Sat Nov 08, 2014 8:19 pm Post subject: Interesting EXP(X) problem Invalid Floating Point Operatio |
|
|
Gentlemen:
Thanks, I will follow up on both your approaches and let you know the results. _________________ Rodney Roberts |
|
Back to top |
|
|
rrobe71907
Joined: 26 Sep 2014 Posts: 10 Location: Tamaqua PA
|
Posted: Mon Nov 10, 2014 11:11 pm Post subject: Results of suggested fixes |
|
|
The results of your suggestions:
added
LoadLibraryA ("C:\\Program Files\\Silverfrost\\FTN95 Express\\salflibc.dll");
(DMD's implementation of LoadLibrary; more info at dlang.org) to dmath.d, same error
just for grins, removed the above, added
C ------------------------------------------------
F_STDCALL INTEGER FUNCTION LIBMAIN(hInst,ul,lpR)
INTEGER hInst,ul,lpR,hLibModule,LoadLibrary
hLibModule = LoadLibrary
2 ("C:\Program Files\Silverfrost\FTN95 Express\salflibc.dll")
C CALL mask_underflow@()
C ***** Initialise global data here
LIBMAIN=1
RETURN
END FUNCTION LIBMAIN
to mathproc.dll; was necessary to explicitly call LIBMAIN from
D main program (had a PRINT statement in LIBMAIN so I would know if it was called).
This produced a slightly different error
object.Error@(0): Breakpoint
during the LIBMAIN call itself.
Even without the LoadLibraryA call or modified LibMain, Dependency Walker still reported successful loading of salflibc.dll during profiling.
Also, having the same problem with SINH(), COSH(), TANH() - these functions also raise e to some power; suspect that is the central issue here. For what it is worth, SQRT(), SIN(), COS(), ACOS(), ATAN(), LOG() (surprise!), MOD(), IAND(), IOR(), ISHFT() are working fine - before playing with LoadLibraryA() and LoadLibrary().
At any rate, I appreciated your help. I will have to keep digging to figure out what is going wrong. _________________ Rodney Roberts |
|
Back to top |
|
|
DanRRight
Joined: 10 Mar 2008 Posts: 2826 Location: South Pole, Antarctica
|
Posted: Tue Nov 11, 2014 7:47 am Post subject: |
|
|
I had similar problems when the EXP approached area of denormal numbers.
What is there is still anyone's guess, but my observations were that EXP does not like approaching overflow and underflow areas. So please make sure that X in EXP(X) for real*4 numbers is safely less then 50-60 or -50 respectively. MASK_UNDERLOW@ helped me too. You may try also well documented trapping of exceptions (which has demo code in the Help) to find if it may expose the reason of such behavior
BTW, do you have any specific reason of using mixed language programming? If it was just for creating GUI then Clearwin+ is good enough for that (if not better then other options) with other advantages besides that you will not get that error |
|
Back to top |
|
|
mecej4
Joined: 31 Oct 2006 Posts: 1891
|
Posted: Tue Nov 11, 2014 5:41 pm Post subject: |
|
|
Rodney Roberts: Are you using the Windows-32 DMD compiler and the FTN95 compiler in your work? If so, how do you surmount the following obstacle?
FTN95 emits COFF32 format object files but the Optlink linker used by DMD requires OMF format object files.
How do you construct a DMD-compatible import library from an FTN95-generated DLL?
As you can infer from a quote of Walter Bright, the father of D Quote: | (Complaint: 1. DMD can only output OMF binaries
> 2. DMD cannot output 64bit code for Windows
> 3. DMD is not compatible with the MSVC linker or runtime)
Response: I intend to fix all of those, at least for 64 bit Windows, in the near term.) | things are easier in 64-bits. I built a DLL for your subroutine ERCT using IFORT-64, and the Windows DMD 64-bit compiler compiled and linked with the DLL quite nicely. I used this prototype in the D caller:
Code: | extern (C)
{
float ERCT (ref float, ref float, ref float);
}
|
Since IFort and DMD both use cdecl linkage, there is no need to reverse the order of arguments in the call in D: Code: | tmp = ERCT (t,R,C); |
|
|
Back to top |
|
|
rrobe71907
Joined: 26 Sep 2014 Posts: 10 Location: Tamaqua PA
|
Posted: Tue Nov 11, 2014 10:41 pm Post subject: to mecej4: |
|
|
Yes, I am using the Windows-32 DMD Compiler. The key is DMC's implib utility. For example:
implib sttstcs.lib sttstcs.dll
will read sttstcs.dll and create a DMD/OMF compliant sttstcs.lib
I have tutorial links at
http://rrroberts.50webs.com/cobindex.htm#DCALLS (has links somewhere for downloading implib).
I had a harder time in DMD linking in a D dll than a FORTRAN dll!
Biggest reason I am doing this is to stay sharp technology wise, learn a new programming language, learn WINAPI calls (instead of a visual IDE); also there are a lot of libraries out there that the source code is not available freely and you would have to reinvent the wheel.
I am one of those displaced mid-50s technology pros. When I was a HP3000 systems analyst I realized that there is no such thing as one-size-fits-all programming languages. We had a legacy ERP system interfaced with an EDI system. I used whatever tool would do the job quickly and reliably.
I only heard about D a couple of months ago; thanks for the info about
IFORT-64, and the Windows DMD 64-bit - that I did not know about. _________________ Rodney Roberts |
|
Back to top |
|
|
mecej4
Joined: 31 Oct 2006 Posts: 1891
|
Posted: Wed Nov 12, 2014 12:23 pm Post subject: |
|
|
Thanks for the link to bup.zip. I knew about implib; it was part of Turbo/Borland C (that was two decades ago!), and I suspected that I might need to download the whole DMC package just to obtain implib, and was not keen to do so at the moment.
With implib, I can make the DMD-Fortran combination work with Intel Fortran (32 or 64 bit, the latter without IMPLIB, as I described earlier). It also works correctly when the DLL is built using CVF6.6C, using df /iface:cref /LD <fortran_file> /link /export:_ERCT=ERCT, followed by producing the import library and building the D caller using DMD.
With FTN95, there is a problem. I compiled the Fortran subroutine using slink /dll ofar.obj /export:_ERCT=ERCT. I am able to link the D main to the import library but the resulting EXE crashes with an invalid floating point operation exception. I tried calling the same DLL from a C main program. The program builds without errors when compiled with the Salford C compiler SCC using scc cmain.c /ANSI_C, and even works correctly when run. However, when the C caller is compiled using MS or Intel C, the EXE crashes.
Perhaps you or another reader will find it interesting to investigate why this fails, so here are the sources for the subroutine and the caller.
Code: | REAL FUNCTION ERCT (T, R, C)
IMPLICIT NONE
REAL T, R, C
ERCT = T / (R * C)
!write(*,*)ERCT
ERCT = EXP(ERCT)
RETURN
END FUNCTION ERCT |
Code: | #include <stdio.h>
extern float ERCT (float*, float*, float*);
int main(){
float C, R, t, tmp;
C = 0.000018;
R = 8100.0;
t = 0.31;
tmp = ERCT (&t, &R, &C);
printf (" ERCT (t,R,C): %f \n", tmp);
return (0);
} |
|
|
Back to top |
|
|
rrobe71907
Joined: 26 Sep 2014 Posts: 10 Location: Tamaqua PA
|
Posted: Wed Nov 12, 2014 9:56 pm Post subject: To DanRRight |
|
|
Sorry I did not respond to your post yesterday, got cut short for time.
The input range to e**x functions (EXP, TANH) is in -2.13 to 2.36 range.
Just for grins, even replaced TANH with SINH/COSH. In the TANH() call,
made the passed argument REAL*8. Also tried placing call mask_underflow@()
in various locations.
Basically I am doing this to see if it can be done. _________________ Rodney Roberts |
|
Back to top |
|
|
rrobe71907
Joined: 26 Sep 2014 Posts: 10 Location: Tamaqua PA
|
Posted: Wed Nov 12, 2014 10:11 pm Post subject: To Everyone |
|
|
Forgot to mention I found an arithmetic error in the ERCT function - forgot a minus sign before T. Still no difference run/crash results - FORTRAN .exe still executes, D .exe still crashes and burns. The corrected version:
C Series Resistance Capacitance Circuit
C Resistance Capacitance Time
C T : Seconds
C R : Ohms
C C : Farads
REAL FUNCTION ERCT (T, R, C) RESULT (X)
REAL T, R, C, X
X = -T / (R * C)
X = EXP(X)
RETURN
END FUNCTION ERCT
----------------------------------------------
Just for grins, I will post D/FORTRAN EXP() problem to the D forum in the next day or two.
And found another problem in D/FORTRAN interfacing - COMPLEX real and imaginary parts swap positions when returned.
to mecej4:
Thanks for your insights - picked up a few things. _________________ Rodney Roberts |
|
Back to top |
|
|
mecej4
Joined: 31 Oct 2006 Posts: 1891
|
Posted: Thu Nov 13, 2014 12:03 am Post subject: |
|
|
Rodney: "..forgot a minus sign before T".
I noticed that, too, but figured that your clock probably ran anticlockwise. |
|
Back to top |
|
|
DanRRight
Joined: 10 Mar 2008 Posts: 2826 Location: South Pole, Antarctica
|
Posted: Thu Nov 13, 2014 12:28 am Post subject: |
|
|
Rodney,
That was very typical for someone stuck with multi-language programming... crashes, bugs, incompatibilities, compiler authors/companies appear and disappear with the speed of light...rarely you will end up with something solid.
Post your final circuit equations code here, will be good to learn from your experience.
I've made one years ago using just this compiler and nothing else. Here how its front looks. And even here since it uses external graphics library called Simpleplot (no control of source code. company is stone dead, authors are retired) we got tons of bugs you can read about in this forum
Last edited by DanRRight on Thu Nov 13, 2014 12:58 am; edited 8 times in total |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2556 Location: Sydney
|
Posted: Thu Nov 13, 2014 12:29 am Post subject: |
|
|
I would expect that the solution could be related to the use of STDCALL. Search ftn95.chm on STDCALL and this may provide a way of getting FTN95 to work.
I don't think that ISO_C_BINDING is available in FTN95.
Unfortunately this is a topic that I should know a lot more about, so I find this thread interesting.
John |
|
Back to top |
|
|
rrobe71907
Joined: 26 Sep 2014 Posts: 10 Location: Tamaqua PA
|
Posted: Thu Nov 13, 2014 10:12 pm Post subject: |
|
|
Everyone:
I will keep you informed of new developments on this issue (I will try to post in this topic) - with my luck I will find it when I stop looking for it.
DanRRight:
Your Circuit Equations is impressive! I must confess I am somewhere in between a craftsman, mechanic, and engineer - I can follow some from all three but not everything. Electronics is one of those subjects I can follow some of the basics of, but deep understanding eludes me. Every so often I try to learn a little more.
I was in Manufacturing(plastics) for a number of years, and the s/w tools I had to make to do with - I could tell some stories - as I am sure you can. What made it even more interesting was the EDI requirements of our automotive customers.
JohnCampbel:
The D extern(STD) {...} produced some sort of Symbol Undefined errors, finally found extern(Pascal) {...} worked, so that is what I went with. I have found programming can be like fine-tuning a Holly 4 barrel, stick with the recommendations, but sometimes you have to try something "outside of the box". Also, the F_STDCALL SUBROUTINE seemed not to produce any benefits.
This forum has turned into a good exchange of ideas, I picked up a few things as well - perhaps more than others.
mecej4:
You are trouble - we could be friends
_________________ Rodney Roberts |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|