Date: Tue, 2 Jun 92 15:46 +1000 From: Bill Metzenthen Subject: Yet another emu387 To: djgpp AT sun DOT soe DOT clarkson DOT edu Status: RO DJ Delorie has done a good job in giving us users of MS-DOS access to the GNU compilers. However, it seems to me that most people who are using djgpp are probably doing so on 80486 machines. I say this because I use an 80386 and have found a number of problems in using the 80387 emulator which is part of djgpp. The problems which most concern me fall into three classes: (a) speed, (b) accuracy, and (c) crashes. I have written a new emu387 for use with djgpp. It is actually derived from the djgpp emu387 but little of the code is now the same as the original. The current state of my emu387 is such that I can make it available to anyone who is interested. It should be regarded as a beta version. I am unaware of any bugs in my emu387 which affect its normal use with gnu C and C++. It does not tackle the problem of the lack of a proper mechanism to handle signals. My emu387 passes the "paranoia" test, giving results similar to those obtained with Turbo C. Neither the djgpp 1.06 emu387 nor the Japanese emu387 (which was announced on this list) will run the "paranoia" test. In addition, I have tested my emu387 with the "elefunt" floating point tests from netlib. Once again, the dsin, dtan, datan, dsqrt, dexp, and dlog tests give similar results to those obtained with Turbo C. The djgpp 1.06 emu387 won't run the the elefunt tests. The Japanese emu387 gives reasonable results in some of the tests for dexp, dsin, and dcos but fails or gives poor results with dsqrt, datan and dlog. Performance: In the following, I call my emu387 "WM emu387". Timing: Some simple timing tests have been made on the emu387 functions. The times include load/store instructions. All times are in microseconds measured on a 33MHz 386 with 64k cache. function Turbo C djgpp 1.06 Japanese WM emu387 + 60.5 154.8 93.8 76.5 - 61.1-65.5 157.3-160.8 93.5-96.6 76.2-79.5 * 71.0 190.8 95.4 79.6 / 61.2-75.0 261.4-266.9 91.4-185.0 75.3-91.6 sin() 310.8 4692.0 755.7 319.0 cos() 284.4 4855.2 758.4 308.0 tan() 495.0 8807.1 1350.3 394.9 atan() 328.9 4866.4 760.1 601.1 sqrt() 128.7 crashed 212.9 145.2 log() 413.1-419.1 5103.4-5354.2 627.6-628.1 254.7-282.2 exp() 479.1 6619.2 1041.2 469.1 Accuracy: The following table gives the accuracy of the sqrt(), trig and log functions. Each function was tested at about 400 points. Ideal results would be 64 bits. The reduced accuracy of cos() and tan() for arguments greater than pi/4 can be thought of as being due to the precision of the argument x; e.g. an argument of pi/2-(1e-10) which is accurate to 64 bits can result in a relative accuracy in cos() of about 64 + log2(cos(x)) = 31 bits. Worst result (bits) Function Tested x range WM emu387 Turbo C sqrt(x) 1 .. 2 63.4 63.2 atan(x) 1e-10 .. 200 62.4 62.8 cos(x) 0 .. pi/2-(1e-10) 62.5 (x <= pi/4) 62.4 35.2 (x = pi/2-(1e-10)) 31.9 sin(x) 1e-10 .. pi/2 62.7 62.8 tan(x) 1e-10 .. pi/2-(1e-10) 62.3 (x <= pi/4) 62.1 35.2 (x = pi/2-(1e-10)) 31.9 exp(x) 0 .. 1 63.1 62.9 log(x) 1+1e-6 .. 2 62.4 62.1 A comparison with results for the djgpp 1.06 or Japanese emu387s has not been made because of bugs, ..umm features, of these emu387s which make computation difficult. However, at least some of the algorithms used in these emu387s are relatively inaccurate. The worst appears to be atan(); compare atan(0.8) with the value obtained from a pocket calculator! --Bill 2/6/92