Post Reply 
Swapping Registers on HP calculators
03-27-2024, 12:50 PM (This post was last modified: 03-27-2024 12:54 PM by n1msr.)
Post: #1
Swapping Registers on HP calculators
I recently upgraded some older HP calcs (HP-65, HP-67, HP-41CX with USB battery) and used this opportunity to compare speed and implementation of a program to enumerate the permutations of up to 9 items (using digits 1 to 9, since the early machines have no alpha characters). I lazily took an algorithnm that had been implemented in Python. It requires two one-dimensional arrays (actually lists in Python). The algorithm needs to be able to swap two items in one of the lists, and this made me wonder if I am missing a tip/trick to doing this fast and/or using the fewest steps possible with the stack and some of the calculator capabilities. For example, on the HP-41CX the stack levels can be addressed programmatially, meaning you don't have to store one of the swapped values in a "temp" register. Because of stack lift (or not) with certain functions, using stack manipulation and not storing the "temp" value in a register requires care.

On the HP-67 my implementation finally worked - helped by Tony Nixon's 67 CPU upgrade running in turbo mode, coupled with his emulator that allowed me to see multiple registers at once (I needed both Primary and Secondary registers on the 67), plus the stack / flags as they changed. The 41CX is OK also, but no emulator this time, so harder/slower to debug The DM41X OK too (same as 41CX), and much faster. Now I am using the 15c+ (the 15c LE prototype from 2010) and I am trying to use its matrix capability to hold the two arrays (each one dimensional) and need to be able to swap array elements in one of the arrays (list a[] in the Python below). When I look at the number of program steps I use, it seems inefficient. I cannot use the auto-incrementing matrix indices in this implementation - I must be able to swap two non-sucessive elements. (PS is it possible to turn on/off USER mode on the 15c programmatically? - I haven't found a way.)

For now I am just interested to know if there are known register swapping technioques from the relatively early models. I have copied the Python algorithm below in case anyone really is curious. For brevity I have not copied any programmed calculator steps. I have highlighted the Python line that does the swap (line 12).

a = ['a', 'b', 'c', 'd'] # items to be permutated
N = len(a)
p = [num for num in range(N+1)]
i = 1
print(p,a)
while i < N:
p[i] -= 1
if i % 2 == 1:
j = p[i]
else:
j = 0
a[j], a[i] = a[i], a[j] <-- SWAP the ith and jth elements
print(p,a) # output current permutation
i = 1
while p[i] == 0:
p[i] = i
i += 1

Thank you,

Mark
Find all posts by this user
Quote this message in a reply
03-27-2024, 01:13 PM
Post: #2
RE: Swapping Registers on HP calculators
(03-27-2024 12:50 PM)n1msr Wrote:  PS is it possible to turn on/off USER mode on the 15c programmatically? - I haven't found a way.

I've only had the "true RPN" calculator for a while, so it's possible that you're asking about something else. But if I understand your question correctly, look in the thread https://www.hpmuseum.org/forum/thread-21466.html where it is mentioned (and yes, it is possible).

Prime, 15C CE
Find all posts by this user
Quote this message in a reply
03-27-2024, 08:05 PM
Post: #3
RE: Swapping Registers on HP calculators
(03-27-2024 12:50 PM)n1msr Wrote:  I have copied the Python algorithm below in case anyone really is curious. For brevity I have not copied any programmed calculator steps. I have highlighted the Python line that does the swap (line 12).

Hi,

You are welcome, but without any proper indentation, your Python code is really hard to read !

Code:
a = ['a', 'b', 'c', 'd']                   # items to be permutated
N = len(a)
p = [num for num in range(N+1)]
i = 1
print(p,a)
while i < N:
    p[i] -= 1
    if i % 2 == 1:
        j = p[i]
    else:
        j = 0
    a[j], a[i] = a[i], a[j]                   # <-- SWAP the ith and jth elements
    print(p,a)                                  # output current permutation
    i = 1
    while p[i] == 0:
        p[i] = i
        i += 1

I hope this helps anyone reading this thread...

I didn't quite understand the question, are you wondering if there are X<> IND _ _ or x<> (i) instructions on machines other than the HP-41C and HP-15C?

Sincerely.
Marc.
Find all posts by this user
Quote this message in a reply
03-27-2024, 09:43 PM
Post: #4
RE: Swapping Registers on HP calculators
n1msr Wrote:Now I am using the 15c+ [...] and need to be able to swap array elements in one of the arrays (list a[] in the Python below). When I look at the number of program steps I use, it seems inefficient. I cannot use the auto-incrementing matrix indices in this implementation - I must be able to swap two non-sucessive elements.

I suggest you forget about the Python program for the time being and just clearly explain with an example the basic manipulation you intend to perform, e.g.

"I have a 10x1 array A and another such B and I need the most efficient sequence of RPN steps to exchange element A(5,1) with element B(8,1). Also, how to exchange elements A(i,1) and A(i+1,1)"

or something like that. Also, do post your RPN code, however inefficient, to see exacctly how you're attempting to tackle the problem so that improvements can be suggested.

V.

  
All My Articles & other Materials here:  Valentin Albillo's HP Collection
 
Visit this user's website Find all posts by this user
Quote this message in a reply
03-28-2024, 09:21 AM (This post was last modified: 03-28-2024 09:35 AM by n1msr.)
Post: #5
RE: Swapping Registers on HP calculators
Thank you all for taking the time to reply, and apologies for the vagueness of the question.
Also, thank you Marc for indenting the Python!

Valentin summarised my question well: "I have a 1 x 9 array A and I need the most efficient sequence of RPN steps to exchange element A(1,i) with element A(1,j).
Also, I am [still] curious how to toggle USER mode programatically, if it is possible.

Below is the code for the HP-15C SWAP code to exchange two elements i and j in a single 1 x 9 matrix A.
USER mode is on, although I am not reliant on this for the SWAP
i is stored in R3
j is stored in R4
"temp" store for the SWAP is R5

*please note that I add 1 (one) to the column (i and j) because the algorithm uses 0 (zero)
as the index to the first element of the list/matrix, whereas the 15c uses 1 (one). Changing the
algorithm to use 1 (one) as the index to the first element would save several steps!

Code:

1           \\ row 1
RCL3      \\ column i
1           \\ add 1 to column*
+
RCL g A  \\ recall ith element of matrix A: A[1,i]
STO 5     \\ store ith element of A in "temp" register R5
1            \\ row 1
RCL 4     \\ column j
1            \\ add 1 to column*
+
RCL g A   \\ recall jth element of matrix A: A[i,j]
1            \\ row 1
RCL 3     \\ column i
1            \\ add 1 to column*
+
STO g A  \\ store A[1,j] into A[1,i]
RCL 5     \\ recall "temp" to get original A[1,i]
1           \\ row 1
RCL 4    \\ column j
1           \\ add 1 to column*
+
STO g A   \\ store original A[1,i] in A[1,j] to complete the SWAP
That's it. Thank you.
Find all posts by this user
Quote this message in a reply
03-28-2024, 10:11 AM (This post was last modified: 03-28-2024 10:22 AM by Didier Lachieze.)
Post: #6
RE: Swapping Registers on HP calculators
I don’t have a 15C with me to test but instead of the stack I would use R0 and R1 to access the matrix elements :

Code:
1
STO 0
RCL+ 3 
STO 1       i
RCL A       a(i) i
1
RCL+ 4      j a(i) i
STO 1
RCL A       a(j) j a(i) i
RUP         i a(j) j a(i)
STO 1
RDN         a(j) j a(i) i
STO A
RDN         j a(i) i a(j)
STO 1
RDN         a(i) i a(j) j
STO A
Find all posts by this user
Quote this message in a reply
03-28-2024, 12:38 PM
Post: #7
RE: Swapping Registers on HP calculators
1
STO 0
RCL+ 3
STO 1
RCL A
1
RCL+ 4
STO 1
X<>Y
X<> A
1
R^
STO g A

41CV†,42S,48GX,49G,DM42,DM41X,17BII,15CE,DM15L,12C,16CE
Find all posts by this user
Quote this message in a reply
03-28-2024, 12:49 PM (This post was last modified: 03-28-2024 01:28 PM by n1msr.)
Post: #8
RE: Swapping Registers on HP calculators
Didier,

Thank you.

After looking at other parts of my program (not shared) I agree that using the registers R0 and R1 is better.

I just found the manual page for the 15c that confirms that "f USER" is not a programmable function :-(
(I would have liked USER mode ON to initialise the arrays, where the R1 value is automatically incremented.
However, I would prefer that R1 is NOT auto-incremented in other areas of the program such as the SWAP and two subroutines that I have not shared, where I need to increment and decrement an element of the B matrix.)

A possible 'quirk' of the HP15? If I want to add an element of matrix A to the number on the stack (X) in a program, it seems that I have to have a NOP (or duplicate the key operation) to get it to work. I think this is a "feature" of the 15c because I came across a duplicate operation like this in one of the forum threads on the 15c with matrix operations in a program. I have lost the post so cannot provide a link, sorry.

Here is my listing to display the entire matrix A (1,9) in the X register for display of a permutation.
My listing does not show the "u" for the matrix operations RCL A, which the 15c does.
(USER mode is ON)

Code:

f LBL E
f MATRIX 1 \\initialise matrix indices to 1 (R0 & R1)
8.00001     \\number all on one line here for brevity
STO I
0                \\ 0 on stack ready for arithmetic
f LBL 9
RCL I
g INT
10^X          \\ use the I register with 10^X to position the ith digit in X
RCL A          \\ get ith element of matrix A
x
+
f DSE I        \\ decrement I
GTO 9         \\ loop until I is zero        
RCL A          \\ i is zero is final element (1,9)
+                \\ this is a NOP in effect.  The calculator does not run it after the RCL A operation
+                \\ this + is executed by the calculator
R/S
g RTN




Regards,

Mark.
Find all posts by this user
Quote this message in a reply
03-28-2024, 01:30 PM (This post was last modified: 03-28-2024 01:32 PM by n1msr.)
Post: #9
RE: Swapping Registers on HP calculators
Werner,

Your code is short, and uses the '1' on the stack to save keystrokes so thank you.
I don't think you can do x <> A though, unfortunately :-) I realise you didn't have your 15c with you when you replied.

STO 0
RCL+ 3
STO 1
RCL A
1
RCL+ 4
STO 1
X<>Y
X<> A <-- I don't think this is possible. Would that it were :-)
1
R^
STO g A
Find all posts by this user
Quote this message in a reply
03-28-2024, 05:46 PM
Post: #10
RE: Swapping Registers on HP calculators
(03-28-2024 01:30 PM)n1msr Wrote:  Werner,

I don't think you can do x <> A though, unfortunately :-) I realise you didn't have your 15c with you when you replied

If only you had tried it out on your 15c before replying ;-)
Or read pg 173 of the User’s manual ;-)

Cheers, Werner

41CV†,42S,48GX,49G,DM42,DM41X,17BII,15CE,DM15L,12C,16CE
Find all posts by this user
Quote this message in a reply
03-29-2024, 12:29 AM
Post: #11
RE: Swapping Registers on HP calculators
.
Hi again, n1msr,

n1msr Wrote:I just found the manual page for the 15c that confirms that "f USER" is not a programmable function :-(

It doesn't need to be. Save for e.g. establishing the A-E keys as directly calling LBL A-E instead of using GSB A-E, I see no other use for it being programmable, as all the user-STO (uSTO), user-RCL (uRCL), etc. storage/recall instructions are programmable and effective on a per-instruction basis.

uSTO, which is entered into program memory when you are in User Mode, will automatically advance matrix indexes, from row to row, from one element to the next, while also having skip-if-done capabilities. Same for uRCL and all other such instructions.

On the other hand, plain-vanilla STO, which is entered into program memory when you are not in User Mode, simply stores the value and does not affect indexes nor has skip-if-done capabilities, it just stores the value, period.

Quote:(I would have liked USER mode ON to initialise the arrays, where the R1 value is automatically incremented.

Well, do it. Set User Mode active out of program mode, then enter program mode and key in as many uSTO and uRCL as you need, they will have the desired automations when executed afterwards. For other STO and RCL that you'd rather not automatically do anythin (update indexes, skip the next instruction when done), simply set User Mode deactivated out of program mode, then enter program mode and key in as many plain STO and RCL as needed, they will simply store/recall the value when executed and nothing else.

In other words, you can have any mix of uSTO/uRCL and STO/RCL as needed in the same program, as you see fit. The "u" ones must be keyed in in program mode while User mode is active, the plain ones must me keyed in in program mode while User mode is deactivated.

Note this: at execution time, when the program is being executed, none of these instructions will be affected by the current status of User Mode at the time they are executed: the "u" instructions will do automation regardless, the plain ones will not, period.

Quote:However, I would prefer that R1 is NOT auto-incremented in other areas of the program such as the SWAP and two subroutines that I have not shared, where I need to increment and decrement an element of the B matrix.)

Good. Do as I told you in the preceding paragraph, enter those STO/RCL into program memory while out of User Mode, they'll appear in program memory without the "u". Thus, there will be sections of your program with uSTO/uRCL and other sections with plain STO/RCL, merrily living together in love and harmony.

Quote:A possible 'quirk' of the HP15? If I want to add an element of matrix A to the number on the stack (X) in a program, it seems that I have to have a NOP (or duplicate the key operation) to get it to work. I think this is a "feature" of the 15c because [...]

As happened to you with Werner a few messages above, there's no such quirk in the HP-15C but in your understanding on how User Mode works with storage & recall operations. What is happening here is that you're incorrectly using an uRCL operation where a plain RCL would be needed and that's why the subsequent operation is skipped.

I'd suggest you read the HP-15C manual carefully and thoroughly because it's plainly obvious that you do not understand the subject matter as you'd need. Instead, you're assuming that Werner didn't had his calculator at hand or that the HP-15C has a "quirk".

Not so. Heed my advice and read and understand the manual before putting the blame on someone/something else, least you'd risk upsetting people and getting little help here.

V.

  
All My Articles & other Materials here:  Valentin Albillo's HP Collection
 
Visit this user's website Find all posts by this user
Quote this message in a reply
03-29-2024, 09:42 AM (This post was last modified: 03-29-2024 09:43 AM by n1msr.)
Post: #12
RE: Swapping Registers on HP calculators
Valentin,

Thank you very much for the clarification on the matrix USER mode.

You are correct, I did not understand the functionality in the 15C for this.

Regards,

Mark.
Find all posts by this user
Quote this message in a reply
03-30-2024, 01:04 AM
Post: #13
RE: Swapping Registers on HP calculators
.
Hi, n1msr,

I'm glad you found my comments useful. Considering your positive attitude, here you are, some additional comments on the code you posted, namely:

n1msr Wrote:My listing does not show the "u" for the matrix operations RCL A, which the 15c does.

You should really show the "u" for RCL A in your listing (i.e. uRCL A) because otherwise anyone examining it could be quite mystified about what the program is actually doing, since they behave very differently.

Quote:Code:

f LBL E
f MATRIX 1
8.00001

That 8.00001 should be just 8, since decrementing by 1 is the default and you'll save 6 bytes plus it executes faster.

Quote:STO I
0 \\ 0 on stack ready for arithmetic
f LBL 9
RCL I
g INT

The INT isn't necessary if you changed the 8.00001 to 8, which is already an integer.

Quote:10^X \\ use the I register with 10^X to position the ith digit in X
RCL A \\ get ith element of matrix A
x

Assuming this is a plain RCL A (not uRCL A, I can't tell), you can use RCLx A instead of RCL A, x, as it will be cleaner, faster and less disturbing for the stack (T won't be lost). If it is an uRCL A instead, then I'm not sure the logic is correct as it seems the last recall will cause the x instruction to be skipped if it was the last element of the matrix.

Quote:+
f DSE I \\ decrement I
GTO 9 \\ loop until I is zero
RCL A \\ i is zero is final element (1,9)
+ \\ this is a NOP in effect. The calculator does not run it after the RCL A operation

Wrong, if that + instruction is skipped it's just because the RCL A in the listing is actually an uRCL A in program memory. Again, you must include the "u" in the listings to avoid such unnecessary confusion.

Also, I think that the loop should really be rearranged to use an uRCL to perform both the element retrieval and the looping instead of the DSE, which would be redundant then.

Last and coming back to the main question of how to efficiently exchange elements, I think that perhaps you should forget about using matrices to store the elements and use registers instead. Simply store the 9 elements in a block of consecutive registers, say R.1 to R.9 or whatever range of registers suits you, and manipulate them (store, recall, whatever) by using indirect addressing via the I register.

This way you don't have to create 2-dimensional matrices with 2 indexes to manage (R0 and R1) but just a 1-dimensional block of registers with a single index (RI), which will be simpler and you can increment or decrement this index as needed using ISG I and DSE I at will.

Another important advantage is that to exchange two elements, e.g. those stored in R4 and R7, say, you just execute:

      X<> 4
      X<> 7
      X<> 4


and that's it, just three instructions and it leaves the whole stack utterly unaltered (including X and LASTX !). Simple and efficient, right ? Of course, the X<> instruction admits indirect addressing as well.

Regards.
V.

  
All My Articles & other Materials here:  Valentin Albillo's HP Collection
 
Visit this user's website Find all posts by this user
Quote this message in a reply
03-30-2024, 10:06 AM
Post: #14
RE: Swapping Registers on HP calculators
Valentin,

Thank you very much for taking t he time to reply in such detail. I learned a lot from the post you made previously and it cleared the confusion I had about USER mode and the User RCL A for matrices.

Your comments about the iterations and the use of registers versus 15c matrices for implementation of the algorithm are correct. In fact, I used registers (I had to) on the HP-67 and HP-41CX. My attempt on the 15c using matrices (which now works) was purely an exercise. However, I did learn a lot, thanks to you and others who replied.

You might not be surprised to know that the 15c program is longer (more steps) than the HP-67 and HP-41CX programs :-) As I said, I needed to try it. I hadn't used matrices on the 15c for about 40 years, so I have had a bit of a re-learning curve to climb :-) Plus some RTFM!

Thanks again for taking the time to reply. Much appreciated.

Mark.
Find all posts by this user
Quote this message in a reply
04-02-2024, 10:19 PM
Post: #15
RE: Swapping Registers on HP calculators
.
Hi, n1msr,

(03-30-2024 10:06 AM)n1msr Wrote:  Thank you very much for taking t he time to reply in such detail.

You're welcome, I lean heavily on the verbose side. And excuse me for not replying sooner, I've been extremely busy creating and posting this to meet the April, 1st deadline.

Quote:I learned a lot from the post you made previously and it cleared the confusion I had about USER mode and the User RCL A for matrices.

I'm glad you did find my post useful. The HP-15C is a wonderful calc which packs tons of advanced functionalities in a small frame and thus it can be somewhat complicated for beginners or for owners who haven't used it for a long while. Myself, I don't usually remember how to deal with complex matrices as per the Owner's Handbook's instructions so I wrote my own routines.

Quote:In fact, I used registers (I had to) on the HP-67 and HP-41CX. My attempt on the 15c using matrices (which now works) was purely an exercise. However, I did learn a lot, thanks to you and others who replied.

Congratulations on making your program work using the matrix approach. And much as I loved it when I bought it new circa 1977, the HP-67 doesn't hold a candle to the HP-15C in terms of sheer power and functionality. But that red LED display, that sturdy built, that card reader ...

Quote:You might not be surprised to know that the 15c program is longer (more steps) than the HP-67 and HP-41CX programs :-) As I said, I needed to try it. I hadn't used matrices on the 15c for about 40 years, so I have had a bit of a re-learning curve to climb :-) Plus some RTFM

Good. Reading The Fantastic Manual is always a great idea. I do re-read it from time to time, it's always quite enjoyable and one usually discovers some features here and there which were passed by in earlier readings.

As for an efficient way to exchange two arbitrary registers, say Ra and Rb, these nine HP-15C steps will accomplish the task. It would be much easier if the HP-15C had a second indexing register J (as is the case with the HP35s) but as we only have RI, a little juggling is needed to load RI with a and b as needed to perform the required indirect RCL, X<> and STO operations. The procedure is highly symmetrical:
    To swap Ra with Rb, where initially a is in RI and b is in stack X:

      RCL (i) 
      X<>Y 
      X<> I 
      X<>Y 
      X<> (i) 
      X<>Y 
      X<> I 
      X<>Y
      STO (i)
At the end Ra and Rb have been exchanged and additionally Rb is in stack X, b is in stack Y and a is in RI.

Quote:Thanks again for taking the time to reply. Much appreciated.

Again, you're welcome.

Regards.
V.

  
All My Articles & other Materials here:  Valentin Albillo's HP Collection
 
Visit this user's website Find all posts by this user
Quote this message in a reply
04-08-2024, 07:50 AM
Post: #16
RE: Swapping Registers on HP calculators
Valentin,

Thanks for the extensive follwow-up.

Just a coment on the HP-67: I have Tony Nixon's board in it, which coupled with his PC emulator makes for a convenient development environment, albeit limited to the scope of the 67's capabilitiies. The bluetooth connectivity and turbo mode are fantastic.

Thanks for mentioning the 35s. That is the next machine on which I will implement the Python algorithm, having just worked with the DM42.

I saw your April 1st post - a bit ambitious for me! the GCD thing is, well, interesting/strange!

Mark
Find all posts by this user
Quote this message in a reply
Post Reply 




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