HP Forums

Full Version: Valentin Albillo's "Boldly Going... Going Back to the roots" now for the HP-41 !
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
Hi all,

A few months back, I ported Valentin's albillo efficient complex solver (see his article) from the 35S to the 42S and to the 32SII/DM32.

Porting it to the 42S was trivial, as both the 35S and the 42S can deal with complex numbers easily (on the stack and in storage registers).

Porting it to the 32SII/DM32 was another pair of shoes. Those only have a 2-level complex stack instead of 4, and lack complex registers. So porting the program was more complicated: not only every STO/RCL had to be doubled, but moreover, anything needing more than 2 numbers on the stack (like / followed by +) had to use temporary storage.

Porting it to the 41 was even more complicated, since the 41 doesn'have complex numbers at all. Well, you have the Advantage Pack's crude RPN routines, but those use registers, which is a headache when your program also needs a lot of registers ! You could use Angel Martin's awesome MCODE 41Z module, or even the TOULMATH module (which replicated the 15C complex stack in MCODE), but none of these ware available to the user back in the day, so this would be cheating...

I found a simple way, reading the software library on this very forum: Jean-Marc Baillard actually wrote his own 2-level stack RPN complex functions (here), with several improvements over the Math/Advantage Pack:
- No registers used at all;
- Simpler usage;
- Complete trigs and hyperbolics.

Jean-Marc also wrote his own complex solvers, which work fine. However, they are not as elegantly simple as Valentins's, they require 2 or 3 estimates, or even to compute first and second order derivatives, vs. only one estimate. But this gave me the idea of the port...

So, first key-in Jean-Marc's complex stack functions. Hint: rather than your fingers (only the text is provided), copy the text, paste into Free42/Plus42 (pasting is very powerful), and then export it into a 41C-compatible raw file than you can email to yourself !

As for the port itself, here we go. Please note that whenever Valentin used a lettered 35S complex register, I used the corresponding numbered register (e.g. X became 24) for the real part, and then I used registers as needed for the imaginary parts, starting with 01. Registers 07 to 18 are free to use in your own equations programs. Register 00 has to hold the equation program's name in alphanumerical form (use ASTO 00 to store it).

The program is called "RZVA" for "Root Z (complex) from Valentin Albillo"
Code:

 01 LBL "RZVA"
 02 LBL 01
 03 STO 24
 04 RDN
 05 STO 01
 06 1 E-4
 07 STO 19
 08 X^2
 09 STO 20
 10 0.5
 11 STO 25
 12 LBL 02
 13 XEQ IND 00
 14 0
 15 RCL 25
 16 XEQ "Z/"
 17 STO 21
 18 RDN
 19 STO 02
 20 RCL 19
 21 ST+ 24
 22 XEQ IND 00
 23 STO 22
 24 RDN
 25 STO 03
 26 RCL 19
 27 ST- 24
 28 ST- 24
 29 XEQ IND 00
 30 STO 23
 31 RDN
 32 STO 04
 33 R^
 34 RCL 03
 35 RCL 22
 36 XEQ "Z+"
 37 RCL 02
 38 RCL 21
 39 XEQ "Z-"
 40 0
 41 RCL 20
 42 XEQ "Z/"
 43 STO 06
 44 RDN
 45 STO 05
 46 RCL 03
 47 RCL 22
 48 RCL 04
 49 RCL 23
 50 XEQ "Z-"
 51 0
 52 RCL 19
 53 ST+ 24
 54 XEQ "Z/"
 55 0
 56 RCL 25
 57 XEQ "Z*"
 58 STO 23
 59 RDN
 60 STO 04
 61 RCL 06
 62 RCL 05
 63 RCL 04
 64 RCL 23
 65 XEQ "Z/"
 66 STO 22
 67 RDN
 68 STO 03
 69 R^
 70 RCL 02
 71 RCL 21
 72 XEQ "Z*"
 73 RCL 04
 74 RCL 23
 75 XEQ "Z/"
 76 1
 77 -
 78 CHS
 79 X<>Y
 80 CHS
 81 X<>Y
 82 RCL 25
 83 XEQ "Z^X"
 84 1
 85 -
 86 RCL 03
 87 RCL 22
 88 XEQ "Z/"
 89 ST+ 24
 90 RDN
 91 ST+ 01
 92 R^
 93 RCL 01
 94 RCL 24
 95 XEQ "Z/"
 96 R-P
 97 RCL 20
 98 X<Y?
 99 GTO 02
100 RCL 01
101 RCL 24
102 R-P
103 RDN
104 STO 23
105 SIN
106 ABS
107 RCL 20
108 X<=Y?
109 GTO 03
110 RCL 23
111 COS
112 ENTER
113 ABS
114 X!=0?
115 /
116 RCL 01
117 RCL 24
118 R-P
119 X<>Y
120 RDN
121 *
122 STO 24
123 LBL 03
124 RCL 01
125 RCL 24
126 RTN
127 END

Here is an example function to use. This is the first example from Valentin's article (Z^Z-R=0). The program expects the complex variable to be stored in X (from the 35S), which means register 26 (for the real part) and 01 (for the imaginary part). The constant R has to be stored in registers 9 (real) and 8 (imaginary). Here R = i, so R08 = 1 and R09 =0.

Code:

 01 LBL "EQ1"
 02 RCL 01
 03 RCL 24
 04 RCL 01
 05 RCL 24
 06 XEQ "Z^Z"
 07 RCL 08
 08 RCL 09
 09 XEQ "Z-"
 10 RTN
 11 END

Juste do EQ1 ASTO 00 to store the equation, put 1 and 0 on the stack for the estimate (i), and voilà.

This works perfectlly... except for one thing: it is slow as hell !! Basically, take Valentin's timings in his article, they are expressed in seconds, well, take the same numbers expressed in minutes, you'll get an idea on how slow it is. I cheated by accelerating the emulated 41 in i41cx+. Even at max speed, this is still quite slow. The 41 is a slow machine to begin with, the RPN complex routines and constant need for intermediate storage doesn't help either... but if you are patient, now your bare-bones 41 can solve any complex equation ! Smile

Comments welcome of cours.

Cheers,

Vincent
(04-16-2024 08:05 AM)Vincent Weber Wrote: [ -> ]Porting it to the 32SII/DM42 was another pair of shoes.

I think you meant 32SII/DM32 here.
(04-16-2024 08:19 AM)Massimo Gnerucci Wrote: [ -> ]
(04-16-2024 08:05 AM)Vincent Weber Wrote: [ -> ]Porting it to the 32SII/DM42 was another pair of shoes.

I think you meant 32SII/DM32 here.
Indeed ! I corrected it. Many thanks.
I managed to speed up the '41 program with some optimizations, mainly having the complex stack routines stored in HEPAX and all XEQs to them converted into XROMs. Now, in the above example where R=PI, instead of over 3 minutes, the program runs in 1min 40 seconds!

I made a 15C version. While the 15C is a ground-breaking machine with MCODE complex stack routines, it does not do much better: 1min 20 seconds. Maybe because its processor is slower than the 41's by half.

In addition, the 15C program is not really simpler nor shorter than the '41 one, because the 15C lacks complex registers, so you have to write 4 steps for each store and recall operation. Furthermore Valentin's original program for the 35S makes heavy use of complex recall arithmetics, not possible on the 15C precisely because of this lack of complex registers. The only real advantage of the 15C is that you have a 4-level stack instead of 2, so intermediate computation storage is not necessary (but this happens only once in the '41 version).

So,' 41 and 15C almost on par on this one! Smile
Vincent, nice job indeed. Can you post the link to your HP-42 version of the program? I'd like to try a direct conversion using the 41Z as well...

Cheers,
ÁM
(04-18-2024 07:22 AM)Ángel Martin Wrote: [ -> ]Vincent, nice job indeed. Can you post the link to your HP-42 version of the program? I'd like to try a direct conversion using the 41Z as well...

Cheers,
ÁM
Hi Angel,
You mean the.raw of the 41 version? Or the 42s version? The 42s doesn't need 41Z Smile
No doubt that 41Z will outperform everything but the 42 variant... But 41Z was not available in the 80s Smile
Cheers
(04-18-2024 07:25 AM)Vincent Weber Wrote: [ -> ]Hi Angel,
You mean the.raw of the 41 version? Or the 42s version? The 42s doesn't need 41Z Smile
No doubt that 41Z will outperform everything but the 42 variant... But 41Z was not available in the 80s Smile
Cheers

I mean the HP-42s version, a text listing will work.

Thanks
I had posted the (Plus42, not 42s) version in this thread:
https://www.hpmuseum.org/forum/thread-21036.html

As extra features over the 42S, it only makes use of LSTO, and the equation to be solved is stored as a Plus42 equation rather than a RPN program.
I see, well those pesky equations really get in the way to do a port of the code as-is, I guess it'll be a moot point reinventing the wheel you have already done.

I went back and checked the root-finding sections in the 41Z manual, it's been a while but it offers a couple of decent methods. I'll do a timing comparison to see how they fare compared to yours.

Cheers,
ÁM
The equations at the beginning are actually just cosmetic. They are used only at the end of the program, to check whether the found root's imaginary part is small enough to be ignored, so that the root is displayed as real. You could ignore this part altogether, just display the root when existing the main loop...
(04-17-2024 10:32 AM)Vincent Weber Wrote: [ -> ]I made a 15C version. While the 15C is a ground-breaking machine with MCODE complex stack routines, it does not do much better: 1min 20 seconds. Maybe because its processor is slower than the 41's by half.

Have you compared it to my program in (15C) Halley's Method?
Don't forget to remove the PSE-command in line 058.

It would be interesting to see your program.
(04-18-2024 07:30 PM)Thomas Klemm Wrote: [ -> ]
(04-17-2024 10:32 AM)Vincent Weber Wrote: [ -> ]I made a 15C version. While the 15C is a ground-breaking machine with MCODE complex stack routines, it does not do much better: 1min 20 seconds. Maybe because its processor is slower than the 41's by half.

Have you compared it to my program in (15C) Halley's Method?
Don't forget to remove the PSE-command in line 058.

It would be interesting to see your program.
I will try your program.
I wrote mine on the go15c precise emulator for Android. It does not allow to export memory, so it is difficult to type it again here. But basically I did the following:
-Start with Valentin's 35S program;
-Replace lettered registers with numbered ones (e.g X became 4 for the real part and .4 for the imaginary part)
-Everywhere you have a STO, replace it with something like: STO 6, Re<>Im, STO .6, Re<>Im
-Everywhere you have a RCL, replace it with: RCL .6, Re<>Im, CLX, RCL 6
-Replace the equations at the beginning with RPN code.
-Ignore recall arithmetics altogher: RCL* becomes RCL, then *
-Ignore the cosmetic ending about considering the a root is real if its imaginary part is very small. Pointless with the 15C display capabilities.

Of course this is not optimized compared to a native 15C program!

Cheers
(04-18-2024 07:44 PM)Vincent Weber Wrote: [ -> ]I wrote mine on the go15c precise emulator for Android.

If you don't mind using this simulator you can just copy and paste the following programs A - E:
Code:
   001 {    42 21 11 } f LBL A
   002 {       44  1 } STO 1
   003 {       42 30 } f Re↔Im
   004 {       44  2 } STO 2
   005 {    42 21  0 } f LBL 0
   006 {       45  0 } RCL 0
   007 {          16 } CHS
   008 {       32  1 } GSB 1
   009 {       44  3 } STO 3
   010 {       42 30 } f Re↔Im
   011 {       44  4 } STO 4
   012 {           0 } 0
   013 {       32  1 } GSB 1
   014 {       44  5 } STO 5
   015 {       42 30 } f Re↔Im
   016 {       44  6 } STO 6
   017 {       45  0 } RCL 0
   018 {       32  1 } GSB 1
   019 {          36 } ENTER
   020 {          36 } ENTER
   021 {       45  3 } RCL 3
   022 {       45  4 } RCL 4
   023 {       42 25 } f I
   024 {          40 } +
   025 {          34 } x↔y
   026 {       43 36 } g LSTx
   027 {          30 } −
   028 {           2 } 2
   029 {          10 } ÷
   030 {          34 } x↔y
   031 {       45  5 } RCL 5
   032 {       45  6 } RCL 6
   033 {       42 25 } f I
   034 {          36 } ENTER
   035 {          40 } +
   036 {          30 } −
   037 {           1 } 1
   038 {       43 36 } g LSTx
   039 {       43 33 } g R⬆
   040 {          10 } ÷
   041 {       43 33 } g R⬆
   042 {       43 36 } g LSTx
   043 {          10 } ÷
   044 {          34 } x↔y
   045 {          20 } ×
   046 {       43 36 } g LSTx
   047 {          33 } R⬇
   048 {          30 } −
   049 {          11 } √x̅
   050 {          40 } +
   051 {          10 } ÷
   052 {       45  0 } RCL 0
   053 {          20 } ×
   054 {    44 30  1 } STO − 1
   055 {       42 30 } f Re↔Im
   056 {    44 30  2 } STO − 2
   057 {       43 16 } g ABS
   058 {       42 31 } f PSE
   059 {       45  0 } RCL 0
   060 {       43 11 } g x²
   061 {    43 30  8 } g TEST x<y
   062 {       22  0 } GTO 0
   063 {       45  1 } RCL 1
   064 {       45  2 } RCL 2
   065 {       42 25 } f I
   066 {       43 32 } g RTN
   067 {    42 21  1 } f LBL 1
   068 {       45  1 } RCL 1
   069 {       45  2 } RCL 2
   070 {       42 25 } f I
   071 {          40 } +
   072 {          36 } ENTER
   073 {          36 } ENTER
   074 {          36 } ENTER
   075 {       22 25 } GTO I
   076 {    42 21 12 } f LBL B
   077 {          14 } yˣ
   078 {       43 26 } g π
   079 {          30 } −
   080 {       43 32 } g RTN
   081 {    42 21 13 } f LBL C
   082 {           2 } 2
   083 {          36 } ENTER
   084 {           3 } 3
   085 {       42 25 } f I
   086 {          20 } ×
   087 {           1 } 1
   088 {          36 } ENTER
   089 {           2 } 2
   090 {       42 25 } f I
   091 {          30 } −
   092 {          20 } ×
   093 {           3 } 3
   094 {          36 } ENTER
   095 {           4 } 4
   096 {       42 25 } f I
   097 {          30 } −
   098 {          20 } ×
   099 {           6 } 6
   100 {          36 } ENTER
   101 {           8 } 8
   102 {       42 25 } f I
   103 {          30 } −
   104 {       43 32 } g RTN
   105 {    42 21 14 } f LBL D
   106 {       43 11 } g x²
   107 {           6 } 6
   108 {          30 } −
   109 {          20 } ×
   110 {           2 } 2
   111 {          30 } −
   112 {       43 32 } g RTN
   113 {    42 21 15 } f LBL E
   114 {           2 } 2
   115 {          40 } +
   116 {          20 } ×
   117 {           1 } 1
   118 {           0 } 0
   119 {          40 } +
   120 {          20 } ×
   121 {           2 } 2
   122 {           0 } 0
   123 {          30 } −
   124 {       43 32 } g RTN

According to its help it "yields performance about 3x the original".
Program B took about 18s which means a bit less than 1 minute on the original hardware.
This is a simulator, not an emulator.

You just can't do performances comparisons with the original, it's like comparing apples to oranges.
Besides, I usually don't trust simulators, especially when dealing with advanced math features as in the 15C, as I have no ideas of how they were coded.
Exceptions include free42/plus42 (outstanding compatibility) and Willy's simulators on ios (high quality).
(04-18-2024 08:15 PM)Thomas Klemm Wrote: [ -> ]If you don't mind using this simulator you can just copy and paste …

Nice features, thanks!

However, if the steps 014 and 015 below are exchanged the program won’t work as expected. No problem on my HP-15C.

Code:

#  Program produced by JRPN 15C.
#  Generated 2024-4-18 17:53 Horário Padrão de Brasília.
#  Program occupies 21 bytes.

   000 {          } 
   001 { 42 21 11 } f LBL A
   002 {        5 } 5
   003 {       48 } .
   004 {        7 } 7
   005 {        7 } 7
   006 {        2 } 2
   007 {        1 } 1
   008 {        5 } 5
   009 {        6 } 6
   010 {        6 } 6
   011 {        4 } 4
   012 {        9 } 9
   013 {       26 } EEX
   014 {        1 } 1
   015 {       16 } CHS
   016 {    43 32 } g RTN

# End.
(04-18-2024 08:34 PM)Vincent Weber Wrote: [ -> ]Besides, I usually don't trust simulators, especially when dealing with advanced math features as in the 15C, as I have no ideas of how they were coded.

The code is here on GitHub: jrpn
(04-19-2024 01:27 AM)Gerson W. Barbosa Wrote: [ -> ]However, if the steps 014 and 015 below are exchanged the program won’t work as expected. No problem on my HP-15C.

The problem is also present in the GUI:

EEX CHS 1

vs.

EEX 1 CHS

In both cases this should lead to 0.1.
The CHS in the first example is ignored.

Using Help → Submit Issue (Web) allows to report it.
Or you can send Bill a message.
I'm back with some time records.

ZHALL (using Hall's method, one guess) takes about 1'15" on V41 in default speed, or about 3 seconds in TURBO mode. The root found is 1,854105967+J0, for which the function yields -0,000000006+J0
Without a comparison with your program one could argue all we're measuring here is the PC speed, so I prepared the attached RAW file with your code and tried it on V41. Unfortunately the execution never stops, I must be misinterpreting the user instructions? You indicate the program uses {R01, R26} for X but in the LBL EQ1 code it appears R24 is used instead?

On the other hand, ZSOLVE (using Newton's method, two guesses) gets into OUT OF RANGE trouble with the example f(z)=z^z - pi, I should look into it next.

Cheers,
ÁM
Angel, can you give me your email? I only have a dead one I think...
Vincent, I figured out the issue - I wasn't using JMB's routines, oops..
So now I can report the times running RZVA on my system's V41
(face value, not using your HEPAX trick = thus heavily loaded by all the RAM global labels searches)

Normal speed: about 4'30" (pretty similar to your reported times)
TURBO mode: 5.5 seconds

ÁM
Pages: 1 2
Reference URL's