Post Reply 
HP-11C/15C Code optimization
10-26-2024, 03:14 PM (This post was last modified: 10-26-2024 03:22 PM by jam.)
Post: #1
HP-11C/15C Code optimization
Hello everyone, I appreciate anyone who takes the time to read my concerns.
I am not an expert in programming the HP11C-15C. In some forum posts, I’ve seen very clever techniques to reduce the number of steps in certain programs, and I've been amazed. I'm trying to program the solution of the Colebrook equation to calculate the friction coefficient in a pipe using Newton’s method. Initially, with the parameters `4.2E-5 ENTER 126400 GSB B`, the runtime was 17 seconds. With the program below, the runtime was reduced to 10.18 seconds (on an HP11C, a bit longer on an HP15C).
Can anyone recommend any improvements?
My main interest is to increase execution speed, even if that means compromising a bit on program length. However, any suggestions are welcome.

The Colebrook equation:

\[
x = -2 \cdot \log(a + b \cdot x)
\]

where \( f = \frac{1}{x^2} \).

The evaluation of Newton's method gives the following approximation:

\[
x_{i+1} = x - \frac{x + 2 \cdot \log(a + b \cdot x)}{1 + \frac{2b}{\ln(10)(a + b \cdot x)}}
\]

LBL B
2.51
/
1/X
STO 3
2
X
10
LN
/
STO 7
X<>Y
3.7
/
STO 4
EEX
CHS
5
STO 5
10
STO 2
LBL 1
RCL 2
RCL 4
RCL 3
RCL 2
X
+
STO 6
LOG
2
X
+
RCL 7
RCL 6
/
1
+
/
-
STO 2
-
ABS
RCL 5
X<=Y
GOTO 1
RCL 2
X^2
1/X
RTN
Find all posts by this user
Quote this message in a reply
10-26-2024, 08:04 PM
Post: #2
RE: HP-11C/15C Code optimization
(10-26-2024 03:14 PM)jam Wrote:  Can anyone recommend any improvements?

The only thing that I see is replacing:
Code:
   047 {       30 } -
   048 {    44  2 } STO 2
   049 {       30 } -

Using storage arithmetics:
Code:
   047 { 44 30  2 } STO - 2

But I doubt that it will improve the runtime considerably.
After all it takes only 3 iterations to converge.

This is the listing for the HP-15C:
Code:
   001 { 42 21 12 } f LBL B
   002 {        2 } 2
   003 {       48 } .
   004 {        5 } 5
   005 {        1 } 1
   006 {       10 } /
   007 {       15 } 1/x
   008 {    44  3 } STO 3
   009 {        2 } 2
   010 {       20 } *
   011 {        1 } 1
   012 {        0 } 0
   013 {    43 12 } g ln
   014 {       10 } /
   015 {    44  7 } STO 7
   016 {       34 } X<=>Y
   017 {        3 } 3
   018 {       48 } .
   019 {        7 } 7
   020 {       10 } /
   021 {    44  4 } STO 4
   022 {       26 } EEX
   023 {       16 } CHS
   024 {        5 } 5
   025 {    44  5 } STO 5
   026 {        1 } 1
   027 {        0 } 0
   028 {    44  2 } STO 2
   029 { 42 21  1 } f LBL 1
   030 {    45  2 } RCL 2
   031 {    45  4 } RCL 4
   032 {    45  3 } RCL 3
   033 {    45  2 } RCL 2
   034 {       20 } *
   035 {       40 } +
   036 {    44  6 } STO 6
   037 {    43 13 } g log
   038 {        2 } 2
   039 {       20 } *
   040 {       40 } +
   041 {    45  7 } RCL 7
   042 {    45  6 } RCL 6
   043 {       10 } /
   044 {        1 } 1
   045 {       40 } +
   046 {       10 } /
   047 { 44 30  2 } STO - 2
   048 {    43 16 } g ABS
   049 {    45  5 } RCL 5
   050 { 43 30  8 } g TEST 8
   051 {    22  1 } GTO 1
   052 {    45  2 } RCL 2
   053 {    43 11 } g x^2
   054 {       15 } 1/x
   055 {    43 32 } g RTN

Another approach could be to use fixed-point iteration:
Code:
   056 { 42 21 11 } f LBL A
   057 { 45 20  3 } RCL * 3
   058 { 45 40  4 } RCL + 4
   059 {    43 13 } g log
   060 {        2 } 2
   061 {       16 } CHS
   062 {       20 } *
   063 {    43 32 } g RTN

Example

10
GSB A

7.35586

GSB A

7.60587

GSB A

7.57890

GSB A

7.58177

GSB A

7.58147

GSB A

7.58150

We can see that it takes more iterations to converge but each iteration is faster.
But I haven't compared the two methods. Usually Newton still wins.

In case of the HP-15C you can use recall arithmetics which might speed up the calculation a bit.
And then you could of course simply use SOLVE.
Find all posts by this user
Quote this message in a reply
10-26-2024, 08:56 PM
Post: #3
RE: HP-11C/15C Code optimization
(10-26-2024 08:04 PM)Thomas Klemm Wrote:  
(10-26-2024 03:14 PM)jam Wrote:  Can anyone recommend any improvements?

The only thing that I see is replacing:
Code:
   047 {       30 } -
   048 {    44  2 } STO 2
   049 {       30 } -

Using storage arithmetics:
Code:
   047 { 44 30  2 } STO - 2

But I doubt that it will improve the runtime considerably.
After all it takes only 3 iterations to converge.

This is the listing for the HP-15C:
Code:
   001 { 42 21 12 } f LBL B
   002 {        2 } 2
   003 {       48 } .
   004 {        5 } 5
   005 {        1 } 1
   006 {       10 } /
   007 {       15 } 1/x
   008 {    44  3 } STO 3
   009 {        2 } 2
   010 {       20 } *
   011 {        1 } 1
   012 {        0 } 0
   013 {    43 12 } g ln
   014 {       10 } /
   015 {    44  7 } STO 7
   016 {       34 } X<=>Y
   017 {        3 } 3
   018 {       48 } .
   019 {        7 } 7
   020 {       10 } /
   021 {    44  4 } STO 4
   022 {       26 } EEX
   023 {       16 } CHS
   024 {        5 } 5
   025 {    44  5 } STO 5
   026 {        1 } 1
   027 {        0 } 0
   028 {    44  2 } STO 2
   029 { 42 21  1 } f LBL 1
   030 {    45  2 } RCL 2
   031 {    45  4 } RCL 4
   032 {    45  3 } RCL 3
   033 {    45  2 } RCL 2
   034 {       20 } *
   035 {       40 } +
   036 {    44  6 } STO 6
   037 {    43 13 } g log
   038 {        2 } 2
   039 {       20 } *
   040 {       40 } +
   041 {    45  7 } RCL 7
   042 {    45  6 } RCL 6
   043 {       10 } /
   044 {        1 } 1
   045 {       40 } +
   046 {       10 } /
   047 { 44 30  2 } STO - 2
   048 {    43 16 } g ABS
   049 {    45  5 } RCL 5
   050 { 43 30  8 } g TEST 8
   051 {    22  1 } GTO 1
   052 {    45  2 } RCL 2
   053 {    43 11 } g x^2
   054 {       15 } 1/x
   055 {    43 32 } g RTN

Another approach could be to use fixed-point iteration:
Code:
   056 { 42 21 11 } f LBL A
   057 { 45 20  3 } RCL * 3
   058 { 45 40  4 } RCL + 4
   059 {    43 13 } g log
   060 {        2 } 2
   061 {       16 } CHS
   062 {       20 } *
   063 {    43 32 } g RTN

Example

10
GSB A

7.35586

GSB A

7.60587

GSB A

7.57890

GSB A

7.58177

GSB A

7.58147

GSB A

7.58150

We can see that it takes more iterations to converge but each iteration is faster.
But I haven't compared the two methods. Usually Newton still wins.

In case of the HP-15C you can use recall arithmetics which might speed up the calculation a bit.
And then you could of course simply use SOLVE.


Thank you very much! So, I understand that the storage arithmetic is working. Now the code takes 9.76 seconds.
Find all posts by this user
Quote this message in a reply
10-26-2024, 09:22 PM (This post was last modified: 10-27-2024 01:58 AM by naddy.)
Post: #4
RE: HP-11C/15C Code optimization
If we're talking micro-optimizations:
  • Is ENTER + faster than 2 ×?
  • Is multiplication faster than division? Then store the reciprocal in R7. (Never mind, I just failed middle school fractions.)

The best calculator is the one you actually use.
Find all posts by this user
Quote this message in a reply
10-26-2024, 10:24 PM (This post was last modified: 10-26-2024 10:59 PM by Albert Chan.)
Post: #5
RE: HP-11C/15C Code optimization
Hi, jam

It may be simpler to solve Colebrook with lambertw function.

x = -2 * log10(a*x + b)      // {a,b} switched to match https://en.wikipedia.org/wiki/Darcy_fric...r_formulae

let y = a*x+b, k = 2a/ln(10)

(y-b)/a = -k/a * ln(y)
y + k*ln(y) = b

--> y = k * W(z)            , where z = e^(b/k)/k

OP example

lua> a = 2.51/126400
lua> b = 4.2e-5/3.7
lua> k = 2*a/log(10)
lua> z = exp(b/k)/k

lua> z -- guess for exp(W(z))
111963.8779391653
lua> (_ + z) / (log(_) + 1)
17735.543271562103
lua> (_ + z) / (log(_) + 1)
12027.775216761022
lua> (_ + z) / (log(_) + 1)
11928.038961742051
lua> (_ + z) / (log(_) + 1)
11927.999039108403
lua> (_ + z) / (log(_) + 1) -- = exp(W(z))
11927.99903910197
lua> z / _ -- = W(z)
9.386643775886386

lua> (k*_ - b)/a -- = x
7.5814974176865215

Or, slightly more complicated Newton setup, straight for W(z)

lua> log(z) -- guess for W(z)
11.625931579856678
lua> _ - (_ + log(_/z)) / (1+1/_)
9.366995046326272
lua> _ - (_ + log(_/z)) / (1+1/_)
9.386641790802015
lua> _ - (_ + log(_/z)) / (1+1/_)
9.386643775886366
lua> _ - (_ + log(_/z)) / (1+1/_)
9.386643775886386
Find all posts by this user
Quote this message in a reply
10-27-2024, 12:21 AM
Post: #6
RE: HP-11C/15C Code optimization
(10-26-2024 09:22 PM)naddy Wrote:  If we're talking micro-optimizations:
  • Is ENTER + faster than 2 ×?
  • Is multiplication faster than division? Then store the reciprocal in R7.

Thank you. I've gained a few hundredths of a second with ENTER +. Storing the inverse in R7 would mean including divisions in the loop, so I don’t think it would work as well, or I apologize if I didn’t understand you.
Find all posts by this user
Quote this message in a reply
10-27-2024, 12:28 AM
Post: #7
RE: HP-11C/15C Code optimization
(10-26-2024 10:24 PM)Albert Chan Wrote:  Hi, jam

It may be simpler to solve Colebrook with lambertw function.

x = -2 * log10(a*x + b)      // {a,b} switched to match https://en.wikipedia.org/wiki/Darcy_fric...r_formulae

let y = a*x+b, k = 2a/ln(10)

(y-b)/a = -k/a * ln(y)
y + k*ln(y) = b

--> y = k * W(z)            , where z = e^(b/k)/k

OP example

lua> a = 2.51/126400
lua> b = 4.2e-5/3.7
lua> k = 2*a/log(10)
lua> z = exp(b/k)/k

lua> z -- guess for exp(W(z))
111963.8779391653
lua> (_ + z) / (log(_) + 1)
17735.543271562103
lua> (_ + z) / (log(_) + 1)
12027.775216761022
lua> (_ + z) / (log(_) + 1)
11928.038961742051
lua> (_ + z) / (log(_) + 1)
11927.999039108403
lua> (_ + z) / (log(_) + 1) -- = exp(W(z))
11927.99903910197
lua> z / _ -- = W(z)
9.386643775886386

lua> (k*_ - b)/a -- = x
7.5814974176865215

Or, slightly more complicated Newton setup, straight for W(z)

lua> log(z) -- guess for W(z)
11.625931579856678
lua> _ - (_ + log(_/z)) / (1+1/_)
9.366995046326272
lua> _ - (_ + log(_/z)) / (1+1/_)
9.386641790802015
lua> _ - (_ + log(_/z)) / (1+1/_)
9.386643775886366
lua> _ - (_ + log(_/z)) / (1+1/_)
9.386643775886386

Yes, it's a great idea; even the asymptotic approximations of the Lambert W function work very well. However, the purpose of this post is to learn a bit about code optimization on these beautiful calculators (HP-11C, 15C).

In professional work (when I’m not using a specialized simulator), what I usually do is enable iterative calculation in Microsoft Excel and calculate friction coefficients using the fixed-point method.

I’m a big fan of the HP Voyager series, and they've become a hobby. I’m not really interested in the new versions (15C LE, CE); what’s charming about the first machines is how clever the engineers were in getting the most out of them. I wish I could have lived in that era; for now, I'm content to be just an enthusiast.
Find all posts by this user
Quote this message in a reply
Post Reply 




User(s) browsing this thread: 1 Guest(s)