Donnerstag, 29. Januar 2009

Low Precision Ephemeris ist freigegeben

Das Assemblerprojekt "Ephemeriden niedriger Genauigkeit" ist nun fertiggestellt und bei Sourceforge zur Verwendung und Weiterentwicklung freigegeben.

http://lpe.sourceforge.net

Das Testframework, gewissermassen "MASM Unit", ist Teil des Projekts. Wesentlicher Bestandteil ist die Routine main, die der Reihe nach die Testroutinen test1, test2, ... aufruft. Die Gesamtzahl der Tests wird durch die Assemblervariable numTests festgelegt. Eine Prototyp-Anweisung für die Routinen ist nicht nötig, da sie eine feste Schnittstelle haben (nämlich ohne Parameter) und die Prototypen somit automatisch generiert werden können. Der Return Code (das heisst, der Inhalt von eax) muss für jede Testroutine Null sein, sonst gilt der Test als Nicht OK. Die Ausgabe erfolgt im "Test Anything Protocol" (TAP), das sich bei Bedarf automatisch weiterverarbeiten lässt, z.B. mit dem Perl-Modul TAP::Parser.

Auch wenn die Testroutine OK gibt, wird danach noch geprüft, ob die FPU wirklich im Initialzustand zurückgegeben wurde. Erst wenn das so ist, bekommt der Test das OK. Bevor eine Testroutine aufgerufen wird, wird zunächst die Routine setup_test aufgerufen, die allgemeinen Code zur Herstellung eines gesicherten Anfangszustands der Tests enthalten kann. Innerhalb jeder Testroutine können assert-Macros zum Testen von Erwartungen verwendet werden.

;----------------------------------------------------------------------
; main() executes the test suite: routines test1, ... test<numTests>
;----------------------------------------------------------------------
main proc

print SADD("1..")
print str$(numTests)
print offset cr_lf

invoke initTests
testCount = 0
repeat numTests
testCount = testCount + 1
invoke setup_test
; Prepare the routine name on macro level...
testCount$ textequ %testCount ; coerce number to text type
testsub catstr <test>,testCount$ ; prepend 'test'
; ... declare
testsub PROTO
; ... and call the test routine
invoke testsub

mov ebx, offset not_ok ; Set result pointer to "NOT OK"
or eax,eax ; EAX null?
jne @F
; Check that FPU has been left in clean state
invoke checkFPU
or eax, eax ; still no errors (EAX null)?
jne @F
mov ebx, offset ok ; Yes, then switch result to "OK"
@@:
print ebx
print ustr$(testCount)
print offset cr_lf
endm

; tearDown
invoke freeAll
ret

main endp


Das Projekt ist mit einem GNU Makefile versehen, dessen Defaultregel test (die Defaultregel ist immer die im Makefile zuoberst aufgeführte Regel) das Unittestprogramm ausführt. Das Unittestprogramm lpe_test.asm includiert dieselben Quelltexte wie die produktive Bibliothek lpe.asm, jedoch zusätzlich noch das Testframework. Auf diese Weise ist sichergestellt, dass bei jeder Änderung von produktivem Code nicht nur die DLL, sondern auch das Testprogramm neu erzeugt werden und dieses dann auch gleich ausgeführt wird. So sieht man, was das Entscheidende ist, bei jeder Änderung, ob bestehende Tests durch die Änderung verletzt werden.

test: lpe_test.exe
lpe_test.exe

lpe.dll: lpe.asm winlib.inc lpe_mac.inc lpe_sub.inc \
lpe_const.inc lpe_data.inc lpe_types.inc \
lpe_export.inc lpe_proto.inc
/masm32/bin/ml /c /coff lpe.asm
/masm32/bin/Link /SUBSYSTEM:WINDOWS /DEF:lpe.def /DLL lpe.obj

lpe_test.exe: lpe.dll lpe_test.asm lpe_test_sub.inc lpe_test_mac.inc \
lpe_test_proto.inc lpe_test_spikes.inc
/masm32/bin/ml /c /coff lpe_test.asm
/masm32/bin/Link /SUBSYSTEM:CONSOLE /OPT:NOREF lpe_test.obj

Kommentare :

Erika hat gesagt…

I wanted to use your library "Low Precision Ephemeris"
in a project using visual basic 6 because it is simple,
fast and has sufficient accuracy for the purpose.
But I discovered VB6 can not use "C" calling conventions.
The article at
http://support.microsoft.com/kb/153586
presents a solution but its implementation goes beyond my knowledge.
Do you have a solution to this?
(that does not require too much effort or time from you)

Thank you.

Rüdiger Plantiko hat gesagt…

Hi Erika,

good news. I have already performed such an access to a DLL with "C" calling conventions from within an Excel Sheet using VBA. I will try it out this evening with lpe.dll and will send you example code as a comment to this blog.

- Rüdiger

Rüdiger Plantiko hat gesagt…

Erika,
in this case the easiest thing was to re-assemble the source code, declaring the three non-Java public functions as stdcall instead of "C". I have published the new DLL on sourceforge in the new folder "stdcall", http://sourceforge.net/projects/lpe/files/stdcall/lpe.dll, it still has only about 10KB size.

Here is my sample code which works in Excel. On my computer, when I execute the function test_lpe, it gives for Mars on 1.1.2000 a longitude of 327.58. My "rosicrian ephemeris" lists the longitude as 27°34' which is 327.56 decimally.

If you test it, make sure that you have the new stdcall version of lpe, and put it, together with the .DAT files containing the compressed data, into the same folder where the excel sheet resp. VBA app resides.

' SetCurrentDirectory
' Needed since Excel uses "My Documents" as current directory by default
' It should use the path of the workbook itself
Public Declare Function SetCurrentDirectory Lib "kernel32" _
Alias "SetCurrentDirectoryA" ( _
ByVal lpPathName As String _
) As Long

'int lpeGetPlanet( unsigned int pPlanet, double pJD, double* pLBR);
Public Declare Function lpeGetPlanet Lib "lpe.dll" ( _
ByVal planet As Long, _
ByVal jd As Double, _
ByRef lbr As Double _
) As Long


Function test_lpe() As Double

Dim lbr(3) As Double
Dim jd As Double
Dim planet As Long
Dim rc As Long

planet = 4 ' Mars
jd = 2451544.5 ' 1.1.2000 0hET
SetCurrentDirectory (ThisWorkbook.path)

rc = lpeGetPlanet(planet, jd, lbr(0))


test_lpe = lbr(0)

End Function

Cheers,
Rüdiger

Rüdiger Plantiko hat gesagt…

Sorry, there was a typo: I use the "Rosicrucian Ephemeris", of course, and the position 27° 34' Aquarius. The rest of the text was correct. :-)

Erika hat gesagt…

It is certainly working now and it's lightning fast!
Your excellent example made it super easy.
Here is the output of my test:

planet longitude latitude distance
mars 327,5873155792 -1,073883638936 1,84709719241014

An astronomical unit of thanks for your help and effort, and for making your software public.

Rüdiger Plantiko hat gesagt…

Hi Erika,

thank you for your feedback! It's good for me to know that it works on your computer, too! :-)

The definition of the other two calls in VB, namely lpeGetPlanets() and lpeSetDirectory(), should be clear now.

Have fun with the LPE!

Regards,
Rüdiger