HP Forums
Python to FOCAL Compiler - Printable Version

+- HP Forums (https://www.hpmuseum.org/forum)
+-- Forum: HP Calculators (and very old HP Computers) (/forum-3.html)
+--- Forum: General Forum (/forum-4.html)
+--- Thread: Python to FOCAL Compiler (/thread-4889.html)



Python to FOCAL Compiler - Thomas Klemm - 10-05-2015 10:58 PM

Python Byte-Code

Ever since I noticed the similarity of the generated byte-code of a Python-program with a FOCAL program I wondered if this could be used to create programs for the HP-41C.
Let's start with an example that calculates the area of a circle with radius r:

Code:
def circle(r):
    return pi * r ** 2

This will compile to byte-code which then can be disassembled:

Code:
  2           0 LOAD_GLOBAL              0 (pi)
              3 LOAD_FAST                0 (r)
              6 LOAD_CONST               1 (2)
              9 BINARY_POWER        
             10 BINARY_MULTIPLY     
             11 RETURN_VALUE

The goal is to generate the following FOCAL-program:

Code:
LBL "CIRCLE"
STO 00 ; r
RDN
PI
RCL 00 ; r
2
Y↑X
*
RTN

Of course this can't work in general due to the limitations of the HP-41C. But nonetheless the results so far are promising:

Celsius to Fahrenheit conversion

Code:
def fahrenheit(celsius):
    return 9 * celsius / 5 + 32

Code:
LBL "FAHRENH"
STO 00 ; celsius
RDN
9
RCL 00 ; celsius
*
5
/
32
+
RTN

But can we deal with complex expressions involving mathematical functions?

Spherical Law of Cosines

Code:
def spherical_law_of_cosines(a, C, b):
    return acos(cos(a)*cos(b)+sin(a)*sin(b)*cos(C))

Code:
LBL "SPHERIC"
STO 02 ; b
RDN
STO 01 ; C
RDN
STO 00 ; a
RDN
RCL 00 ; a
COS
RCL 02 ; b
COS
*
RCL 00 ; a
SIN
RCL 02 ; b
SIN
*
RCL 01 ; C
COS
*
+
ACOS
RTN

Mach Number

Sometimes we have to rearrange the expression a little to avoid stack-overflow as with the famous formula for the mach number:

Code:
def mach():
    # original: Sqrt(5*(((((1+.2*(350/661.5)^2)^3.5-1)*(1-6.875E-6*25500)^-5.2656)+1)^.286-1))
    return sqrt((((((.2*(350/661.5)**2+1)**3.5-1)*(1-6.875E-6*25500)**-5.2656)+1)**.286-1)*5)

Code:
LBL "MACH"
0.2
350
661.5
/
2
Y↑X
*
1
+
3.5
Y↑X
1
-
1
0.1753125
-
-5.2656
Y↑X
*
1
+
0.286
Y↑X
1
-
5
*
SQRT
RTN

You may notice that the result isn't exactly how it is solved in the HP-67 manual as the expression 6.875E-6*25500 is simplified to 0.1753125.

Or then we can avoid stack-overflow by using local variables.

Quadratic Equation

Code:
def qe(a, b, c):
    p = b / a / -2
    q = c / a
    D = sqrt(p**2 - q)
    return p + D, p - D

Code:
LBL "QE"
STO 02 ; c
RDN
STO 01 ; b
RDN
STO 00 ; a
RDN
RCL 01 ; b
RCL 00 ; a
/
-2
/
STO 03 ; p
RDN
RCL 02 ; c
RCL 00 ; a
/
STO 04 ; q
RDN
RCL 03 ; p
2
Y↑X
RCL 04 ; q
-
SQRT
STO 05 ; D
RDN
RCL 03 ; p
RCL 05 ; D
+
RCL 03 ; p
RCL 05 ; D
-
RTN

In some cases the RDN command after each STO command could be removed but not in all. Thus the generated code isn't optimized but that can easily be done manually to shave off a byte here and there.

Fizz Buzz

The famous simple coding interview question:

Code:
def fizbuz(n):
    if n % 15 == 0:
        print 'FIZZBUZZ'
    elif n % 3 == 0:
        print 'FIZZ'
    elif n % 5 == 0:
        print 'BUZZ'
    else:
        print n

Code:
LBL "FIZBUZ"
STO 00 ; n
RDN
RCL 00 ; n
15
MOD
0
X#Y?
GTO 00
"FIZZBUZZ"
AVIEW
GTO 03
LBL 00
RCL 00 ; n
3
MOD
0
X#Y?
GTO 01
"FIZZ"
AVIEW
GTO 03
LBL 01
RCL 00 ; n
5
MOD
0
X#Y?
GTO 02
"BUZZ"
AVIEW
GTO 03
LBL 02
RCL 00 ; n
AVIEW
LBL 03
RTN

A print statement is currently just mapped to the AVIEW command. But the last one should be VIEW X instead. I didn't come up with a simple solution for this but think this can easily be fixed manually. You may notice that all branches go to LBL 03 as a common exit-point. You can of course just use RTN instead.

Greatest Common Divisor

What about loops, you may wonder.

Code:
def gcd(a, b):
    while b != 0:
        a, b = b, a % b
    return a

Code:
LBL "GCD"
STO 01 ; b
RDN
STO 00 ; a
RDN
LBL 00
RCL 01 ; b
0
X=Y?
GTO 01
RCL 01 ; b
RCL 00 ; a
RCL 01 ; b
MOD
X<>Y
STO 00 ; a
RDN
STO 01 ; b
RDN
GTO 00
LBL 01
LBL 02
RCL 00 ; a
RTN

While the code is correct we can certainly remove LBL 02 as it isn't used. And then there's no need to swap a and b before storing them. Of course we're far away from the optimized solution below but it might be a good starting point.

Code:
LBL "GCD"
LBL 00
X=0?
GTO 01
STO Z
MOD
GTO 00
LBL 01
RDN
END

Conditionals

How would you translate the following conditional?

Code:
def conditional(n):
    if 0 <= n and n < 13 or n % 3 == 0:
        print 'FOUND'
    else:
        print 'NOT FOUND'

Isn't it nice that you can let the compiler do the hard work?

Code:
LBL "CONDITI"
STO 00 ; n
RDN
0
RCL 00 ; n
X<Y?
GTO 00
RCL 00 ; n
13
X>Y?
GTO 01
LBL 00
RCL 00 ; n
3
MOD
0
X#Y?
GTO 02
LBL 01
"FOUND"
AVIEW
GTO 03
LBL 02
"NOT FOUND"
AVIEW
LBL 03
RTN

Nested loop and break

This primitive program lists all prime factors of a given number:

Code:
def factor(n):
    p = 2
    while n > 1:
        if p**2 > n:
            print n
            break
        while n % p == 0:
            print p
            n /= p
        p += 1

Here again we have to replace AVIEW by VIEW X:

Code:
LBL "FACTOR"
STO 00 ; n
RDN
2
STO 01 ; p
RDN
LBL 00
RCL 00 ; n
1
X>=Y?
GTO 05
RCL 01 ; p
2
Y↑X
RCL 00 ; n
X>=Y?
GTO 01
RCL 00 ; n
AVIEW
GTO 06 ; break
GTO 01
LBL 01
LBL 02
RCL 00 ; n
RCL 01 ; p
MOD
0
X#Y?
GTO 03
RCL 01 ; p
AVIEW
RCL 00 ; n
RCL 01 ; p
/
STO 00 ; n
RDN
GTO 02
LBL 03
LBL 04
RCL 01 ; p
1
+
STO 01 ; p
RDN
GTO 00
LBL 05
LBL 06
RTN

Mutual Inductunce of Coil Pair

This example stems from a recent thread:

Code:
def mutind(r, R, x):
    m = 4*r*R/((R+r)**2+x**2)
    k = sqrt(m)
    K = EllipticF(m)
    E = EllipticE(m)
    return ((1-m/2)*K-E)*8*pi*1e-7*sqrt(r*R)/k

We assume that we can use functions to calculate the complete elliptic integrals. For this we have to add a customized mapping:

Code:
function = {
    (...)
    # custom
    'EllipticE' : 'ELLIPE',
    'EllipticF' : 'ELLIPF',
}

The generated code has some similarities to the listing for the HP-67 in APPENDIX A:

Code:
LBL "MUTIND"
STO 02 ; x
RDN
STO 01 ; R
RDN
STO 00 ; r
RDN
4
RCL 00 ; r
*
RCL 01 ; R
*
RCL 01 ; R
RCL 00 ; r
+
2
Y↑X
RCL 02 ; x
2
Y↑X
+
/
STO 03 ; m
RDN
RCL 03 ; m
SQRT
STO 04 ; k
RDN
RCL 03 ; m
ELLIPF
STO 05 ; K
RDN
RCL 03 ; m
ELLIPE
STO 06 ; E
RDN
1
RCL 03 ; m
2
/
-
RCL 05 ; K
*
RCL 06 ; E
-
8
*
PI
*
1e-07
*
RCL 00 ; r
RCL 01 ; R
*
SQRT
*
RCL 04 ; k
/
RTN

Conclusions

There are some limitations:
  • Runs only with Python 2.7.
  • For-loop isn't supported.
  • All functions use the same registers counting from 00.
  • Recursion doesn't work.
  • Probably a lot of things I'm not aware of.

It was fun to tinker a little with Python byte-code. I hope the result may be inspiring.

Kind regards
Thomas

Code:
Archive:  python_to_focal_compiler.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
     5744  10-06-2015 00:01   compiler.py
     1482  10-05-2015 23:40   examples.py
     1951  10-05-2015 23:41   examples.hp
---------                     -------
     9177                     3 files

To translate the examples in examples.py just run:

python compiler.py

The result is listed in examples.hp.


RE: Python to FOCAL Compiler - Sukiari - 10-06-2015 03:36 AM

This is incredible.

Now I need an HP-41CL!


RE: Python to FOCAL Compiler - Massimo Gnerucci - 10-06-2015 05:50 AM

Thank you very much Thomas!

I will try to play with it a little.


RE: Python to FOCAL Compiler - Ángel Martin - 10-06-2015 11:16 AM

Thanks for this one, very well put together - as usual with your contribution Thomas! Maybe I should start using Python, this is a good incentive...

Dont mean to hijaak this thread but the attached code does the calculation of the mutual inductance example using the SandMath's versions of the eliptic integrals (see lines 28 and 32) - just thought it would be fun to try and sure enough works as advertised.

Code:

01  LBL "MIND"
02  "R1=?"
03  PROMPT
04  STO 06
05  "R2=?"
06  PROMPT
07  STO 07
08  LBL 00
09  "d=?"
10  PROMPT
11  LBL C
12  STO 05
13  RCL 07
14  RCL 06
15  *
16  4
17  *
18  RCL 06
19  RCL 07
20  +
21  X^2
22  RCL 05
23  X^2
24  +
25  /
26  STO 05
27  90
28  ELIPF (SFL# 45)
29  STO 08
30  RCL 05
31  90
32  LEI2  (SFL# 46)
33  STO 09
34  E
35  RCL 05
36  2
37  /
38  -
39  RCL 08
40  *
41  RCL 09
42  -
43  PI
44  *
45  8 E-7
46  *
47  RCL 06
48  RCL 07
49  *
50  RCL 05
51  /
52  SQRT
53  *
54  "MI="
55  ARCL X
56  PROMPT
57  GTO 00
58  END

I added the text prompts and an entry for repeat calculation at different distances. Should be obvious reading the examples in page 83 of the NASA document.

Cheers,
ÁM


RE: Python to FOCAL Compiler - Gerson W. Barbosa - 10-06-2015 03:58 PM

(10-06-2015 11:16 AM)Ángel Martin Wrote:  Dont mean to hijaak this thread but the attached code does the calculation of the mutual inductance example using the SandMath's versions of the eliptic integrals (see lines 28 and 32) - just thought it would be fun to try and sure enough works as advertised.

Hola, Ángel, ¿Qué tal?

Wonderful work Thomas Klemm has done! Alas for me python is just a snake. Basic to FOCAL or Pascal to FOCAL would be great, but who cares about these archaic programming languages (going dead?) nowadays?
I don't mean to hijack this thread either, but since you've talked about elliptic integrals and you appear to be in the mood, what about converting the fast algorithm presented by Hugh Steers here to RPN? I should have done this already, but I left it aside for some reason. Perhaps it might be easier from the BASIC version (it's MSX BASIC, where all variables are double precision by default). The FreePascal version was intended to the RPL conversion, which I haven't done yet either.

Thanks,

Gerson.

Code:

10 CLS
15 INPUT "A, B "; A,B
20 W=A
25 B=B/A: S=(1+B*B)/2: A=1: T=1
30 A1=(A+B)/2
35 IF A=A1 THEN 65
40 C=(A-B)/2
45 B=SQR(A*B)
50 A=A1
55 S=S-T*C*C: T=T+T
60 GOTO 30
65 PI=4*ATN(1)
70 PRINT 2*W*PI*S/A

Code:

Program Ellipse;                                                               
 Uses Crt;                                                                      
 const PI = 3.14159265358979324;                                                
 var a, a1, b, c, s, t, w: double;                                              
 begin                                                                          
   ClrScr;                                                                      
   Write('a b: ');                                                              
   ReadLn(a, b);                                                                
   w := a;                                                                      
   b := b/a;                                                                    
   s := (1 + b*b)/2;                                                            
   a := 1;                                                                      
   t := 1;                                                                      
   repeat                                                                       
     a1 := (a + b)/2;                                                           
     c := (a - b)/2;                                                            
     b := Sqrt(a*b);                                                            
     a := a1;                                                                   
     s := s - t*c*c;                                                            
     t := t + t                                                                 
   until c = 0;
   WriteLn(2*w*PI*s/a:22:16);                                                   
   ReadKey;                                                                     
 end.



RE: Python to FOCAL Compiler - Thomas Klemm - 10-06-2015 07:11 PM

(10-06-2015 03:58 PM)Gerson W. Barbosa Wrote:  I don't mean to hijack this thread either, but since you've talked about elliptic integrals and you appear to be in the mood, what about converting the fast algorithm presented by Hugh Steers here to RPN?

Here's a Python program based on Hugh's implementation:

Code:
def ellipse(a, b):
    u = 1
    v = b / a
    s = (1 + v**2)/2
    t = 1
    while 0 == 0:
        m = (u + v)/2
        if m == u:
            break
        w = (u - v)/2
        v = sqrt(u * v)
        u = m
        s = s - t * w**2
        t = t * 2
    return 2 * pi * a * s / u

And that's the generated FOCAL program using 113 bytes:

Code:
LBL "ELLIPSE"
STO 01 ; b
RDN
STO 00 ; a
RDN
1
STO 02 ; u
RDN
RCL 01 ; b
RCL 00 ; a
/
STO 03 ; v
RDN
1
RCL 03 ; v
2
Y↑X
+
2
/
STO 04 ; s
RDN
1
STO 05 ; t
RDN
LBL 00
0
0
X#Y?
GTO 02
RCL 02 ; u
RCL 03 ; v
+
2
/
STO 06 ; m
RDN
RCL 06 ; m
RCL 02 ; u
X#Y?
GTO 01
GTO 03 ; break
GTO 01
LBL 01
RCL 02 ; u
RCL 03 ; v
-
2
/
STO 07 ; w
RDN
RCL 02 ; u
RCL 03 ; v
*
SQRT
STO 03 ; v
RDN
RCL 06 ; m
STO 02 ; u
RDN
RCL 04 ; s
RCL 05 ; t
RCL 07 ; w
2
Y↑X
*
-
STO 04 ; s
RDN
RCL 05 ; t
2
*
STO 05 ; t
RDN
GTO 00
LBL 02
LBL 03
2
PI
*
RCL 00 ; a
*
RCL 04 ; s
*
RCL 02 ; u
/
RTN

But we can easily bring this down to 77 bytes:

Code:
LBL "ELLIPSE"
STO 01 ; b
RDN
STO 00 ; a
1
STO 02 ; u
STO 05 ; t
RCL 01 ; b
RCL 00 ; a
/
STO 03 ; v
X↑2
+
2
/
STO 04 ; s
LBL 00
RCL 02 ; u
RCL 03 ; v
+
2
/
STO 06 ; m
RCL 02 ; u
X=Y?
GTO 03 ; break
RCL 02 ; u
RCL 03 ; v
-
2
/
STO 07 ; w
RCL 02 ; u
RCL 03 ; v
*
SQRT
STO 03 ; v
RCL 06 ; m
STO 02 ; u
RCL 05 ; t
RCL 07 ; w
X↑2
*
ST- 04 ; s
2
ST* 05 ; t
GTO 00
LBL 03
2
PI
*
RCL 00 ; a
*
RCL 04 ; s
*
RCL 02 ; u
/
RTN

Kind regards
Thomas

PS: We can't use True in conditions as there's no corresponding comparison operator in the HP-41C. That's why I used 0 == 0 instead in the while-loop. The generated code could then be removed in the optimized variant of the program:

Code:
0
0
X#Y?
GTO 02



RE: Python to FOCAL Compiler - Thomas Klemm - 10-06-2015 07:55 PM

(10-06-2015 11:16 AM)Ángel Martin Wrote:  Maybe I should start using Python, this is a good incentive...

You can use Python in your browser if you don't have access to an installation: Python to FOCAL Compiler

Just run the program and the function gcd will be translated. You can create your own functions either in the listing on the left (but then you have to run the program again) or then directly in the REPL in the right window.

You can translate a function to FOCAL:
Code:
>>> translate(gcd.__code__)
LBL "GCD"
STO 01 ; b
RDN
STO 00 ; a
RDN
LBL 00
RCL 01 ; b
0
X=Y?
GTO 01
RCL 01 ; b
RCL 00 ; a
RCL 01 ; b
MOD
X<>Y
STO 00 ; a
RDN
STO 01 ; b
RDN
GTO 00
LBL 01
LBL 02
RCL 00 ; a
RTN

And then you can compare it with the disassembled byte-code:
Code:
>>> dis.dis(gcd)
 27           0 SETUP_LOOP              33 (to 36)
        >>    3 LOAD_FAST                1 (b)
              6 LOAD_CONST               1 (0)
              9 COMPARE_OP               3 (!=)
             12 POP_JUMP_IF_FALSE       35

 28          15 LOAD_FAST                1 (b)
             18 LOAD_FAST                0 (a)
             21 LOAD_FAST                1 (b)
             24 BINARY_MODULO
             25 ROT_TWO
             26 STORE_FAST               0 (a)
             29 STORE_FAST               1 (b)
             32 JUMP_ABSOLUTE            3
        >>   35 POP_BLOCK

 29     >>   36 LOAD_FAST                0 (a)
             39 RETURN_VALUE

Of course you can also just use a function:
Code:
>>> gcd(91, 35)
7
>>> factor(5040)
2
2
2
2
3
3
5
7

Cheers
Thomas


RE: Python to FOCAL Compiler - Gerson W. Barbosa - 10-06-2015 08:19 PM

(10-06-2015 07:11 PM)Thomas Klemm Wrote:  [quote='Gerson W. Barbosa' pid='43596' dateline='1444147083']
I don't mean to hijack this thread either, but since you've talked about elliptic integrals and you appear to be in the mood, what about converting the fast algorithm presented by Hugh Steers here to RPN?

Here's a Python program based on Hugh's implementation:

Code:
def ellipse(a, b):
    u = 1
    v = b / a
    s = (1 + v**2)/2
    t = 1
    while 0 == 0:
        m = (u + v)/2
        if m == u:
            break
        w = (u - v)/2
        v = sqrt(u * v)
        u = m
        s = s - t * w**2
        t = t * 2
    return 2 * pi * a * s / u

And that's the generated FOCAL program using 113 bytes:

Code:
LBL "ELLIPSE"
STO 01 ; b
RDN
STO 00 ; a
RDN
1
STO 02 ; u
RDN
RCL 01 ; b
RCL 00 ; a
/
STO 03 ; v
RDN
1
RCL 03 ; v
2
Y↑X
+
2
/
STO 04 ; s
RDN
1
STO 05 ; t
RDN
LBL 00
0
0
X#Y?
GTO 02
RCL 02 ; u
RCL 03 ; v
+
2
/
STO 06 ; m
RDN
RCL 06 ; m
RCL 02 ; u
X#Y?
GTO 01
GTO 03 ; break
GTO 01
LBL 01
RCL 02 ; u
RCL 03 ; v
-
2
/
STO 07 ; w
RDN
RCL 02 ; u
RCL 03 ; v
*
SQRT
STO 03 ; v
RDN
RCL 06 ; m
STO 02 ; u
RDN
RCL 04 ; s
RCL 05 ; t
RCL 07 ; w
2
Y↑X
*
-
STO 04 ; s
RDN
RCL 05 ; t
2
*
STO 05 ; t
RDN
GTO 00
LBL 02
LBL 03
2
PI
*
RCL 00 ; a
*
RCL 04 ; s
*
RCL 02 ; u
/
RTN

But we can easily bring this down to 77 bytes:

Code:
LBL "ELLIPSE"
STO 01 ; b
RDN
STO 00 ; a
1
STO 02 ; u
STO 05 ; t
RCL 01 ; b
RCL 00 ; a
/
STO 03 ; v
X↑2
+
2
/
STO 04 ; s
LBL 00
RCL 02 ; u
RCL 03 ; v
+
2
/
STO 06 ; m
RCL 02 ; u
X=Y?
GTO 03 ; break
RCL 02 ; u
RCL 03 ; v
-
2
/
STO 07 ; w
RCL 02 ; u
RCL 03 ; v
*
SQRT
STO 03 ; v
RCL 06 ; m
STO 02 ; u
RCL 05 ; t
RCL 07 ; w
X↑2
*
ST- 04 ; s
2
ST* 05 ; t
GTO 00
LBL 03
2
PI
*
RCL 00 ; a
*
RCL 04 ; s
*
RCL 02 ; u
/
RTN

Thank you very much for the HP-41 programs!

As a compensation for my laziness, here is a 163-byte RPL stack-only version of the Pascal program, if you don't mind the off-topic content:

Code:

%%HP: T(3)A(D)F(.);
\<< OVER / DUP SQ 1. + 2. / 1. ROT 1.
  DO DUP2 DUP2 * \v/ UNROT - 2. / 4. ROLLD UNROT + 2. / 4. ROLL 4. ROLL DUP2 SQ * NEG 6. ROLL + ROT DUP + SWAP 5. ROLLD 4. ROLLD ABS
  UNTIL .00000000001 <
  END UNROT DROP2 / * DUP + \pi *
\>>

RPL masters might shorten this a bit and do more elegant stack manipulations. It's not an exact implementation of Hugh's algorithm because there is no break from RPL structures.


Best regards,

Gerson .

P.S.: Just tested your second program on my HP-41CV (because it's shorter). Very fast! (less than 5 seconds!). Thanks again!

Edited to add a missing s lest I am given a free grammar lesson :-)


RE: Python to FOCAL Compiler - Thomas Klemm - 10-06-2015 08:28 PM

(10-06-2015 03:58 PM)Gerson W. Barbosa Wrote:  Basic to FOCAL or Pascal to FOCAL would be great

This HP-41C program compiles BASIC to FOCAL.


RE: Python to FOCAL Compiler - Gerson W. Barbosa - 10-07-2015 01:47 AM

(10-06-2015 08:28 PM)Thomas Klemm Wrote:  
(10-06-2015 03:58 PM)Gerson W. Barbosa Wrote:  Basic to FOCAL or Pascal to FOCAL would be great

This HP-41C program compiles BASIC to FOCAL.

It looks interesting, but it won't take a BASIC source code in text format and return a FOCAL listing, like yours. Easier to learn Python :-)

Regards,

Gerson.


RE: Python to FOCAL Compiler - Thomas Klemm - 10-07-2015 04:34 AM

(10-07-2015 01:47 AM)Gerson W. Barbosa Wrote:  Easier to learn Python :-)

My recommendation is: Learn Python the Hard Way

Quote:Do Not Copy-Paste
You must type each of these exercises in, manually. If you copy and paste, you might as well not even do them. The point of these exercises is to train your hands, your brain, and your mind in how to read, write, and see code. If you copy-paste, you are cheating yourself out of the effectiveness of the lessons.

Cheers
Thomas


RE: Python to FOCAL Compiler - Massimo Gnerucci - 10-07-2015 05:38 AM

(10-07-2015 04:34 AM)Thomas Klemm Wrote:  
Quote:Do Not Copy-Paste
You must type each of these exercises in, manually. If you copy and paste, you might as well not even do them. The point of these exercises is to train your hands, your brain, and your mind in how to read, write, and see code. If you copy-paste, you are cheating yourself out of the effectiveness of the lessons.

Cheers
Thomas

Ach! You copy-pasted this from the intro! ;)


Java to FOCAL Compiler - Thomas Klemm - 10-07-2015 04:38 PM

(10-06-2015 03:58 PM)Gerson W. Barbosa Wrote:  what about converting the fast algorithm presented by Hugh Steers here to RPN?

Since the Java-VM is a stack-machine too we can do a similar thing with the generated byte-code. The original C-code can be used without major changes:

Code:
class Compiler {

     double ellipse(double a, double b) {
        double u = 1;
        double v = b/a;
        double s = (1 + v*v)/2;
        double t = 1;

        for (;;) {
            double a1 = (u + v)/2;
            if (u == a1)
                break;
            double c = (u - v)/2;
            v = Math.sqrt(u*v);
            u = a1;
            s = s - t*c*c;
            t = t * 2;
        }
        return 2*Math.PI*a*s/u;
    }
}

We compile this to a class-file and use javap to disassemble the code:

javac Compiler.java
javap -c Compiler


This is what we get:
Code:
Compiled from "Compiler.java"                                        
class Compiler {
  Compiler();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  double ellipse(double, double);
    Code:
       0: dconst_1
       1: dstore        5
       3: dload_3
       4: dload_1
       5: ddiv
       6: dstore        7
       8: dconst_1
       9: dload         7
      11: dload         7
      13: dmul
      14: dadd
      15: ldc2_w        #2                  // double 2.0d
      18: ddiv
      19: dstore        9
      21: dconst_1
      22: dstore        11
      24: dload         5
      26: dload         7
      28: dadd
      29: ldc2_w        #2                  // double 2.0d
      32: ddiv
      33: dstore        13
      35: dload         5
      37: dload         13
      39: dcmpl
      40: ifne          46
      43: goto          95
      46: dload         5
      48: dload         7
      50: dsub
      51: ldc2_w        #2                  // double 2.0d
      54: ddiv
      55: dstore        15
      57: dload         5
      59: dload         7
      61: dmul
      62: invokestatic  #4                  // Method java/lang/Math.sqrt:(D)D
      65: dstore        7
      67: dload         13
      69: dstore        5
      71: dload         9
      73: dload         11
      75: dload         15
      77: dmul
      78: dload         15
      80: dmul
      81: dsub
      82: dstore        9
      84: dload         11
      86: ldc2_w        #2                  // double 2.0d
      89: dmul
      90: dstore        11
      92: goto          24
      95: ldc2_w        #5                  // double 6.283185307179586d
      98: dload_1
      99: dmul
     100: dload         9
     102: dmul
     103: dload         5
     105: ddiv
     106: dreturn
}

Since a double occupies two registers only odd indexes are used. But we can still see the similarities to the generated FOCAL program using Python. Thus we could probably generate FOCAL programs from class-files as well.

Kind regards
Thomas