[DM16] Raising number to a power

Contributed software for the DM10, DM11, DM12, DM15 and DM16 goes here.

Please prefix the subject of your post with the model of the calculator that your program is for.
Post Reply
wile1411
Posts: 9
Joined: Mon Sep 28, 2020 9:48 am
Location: Canberra, Australia

[DM16] Raising number to a power

Post by wile1411 »

I'm still learning the machine and found that it doesn't have a function to raise a number to a power.
As such, I thought I would take a stab at trying to code up a function to do exactly that.

It's got a few flaws so I'm still trying to work out how to work around them. I used ABS to force the base number into the LSTx register for the loop. This means it only works for positive base numbers.

Happy to hear any suggestions - just note I'm new to this and I'm still learning what's possible with the DM16. I'm half expecting that there is something obvious I missed with this attempt.

Code: Select all

Command			Program Code
[g][LBL] E		001 - 43,22, E		Example program start 5^4 = 5 [Enter] 4 [GSB] E
[DEC]			002 - 24		Ensure in DEC mode
1			003 - 1		
[-] 			004 - 30		Subtract 1 from Exponent (used in loop)
[f][I]  		005 - 44 32		Store modified Exponent into I Register
[R Dwn]			006 - 33		Roll base number to X Register
[g][ABS]		007 - 43 8		Force base number into Lstx Register
[g][LBL] 0		008 - 43,22, 0		Loop '0' start
[g][LSTx]		009 - 43 36
[X] 			010 - 20		Multiply result by Base number
[g][DSZ]		011 - 43 23		Decrement the I register and
[GTO] 0			012 - 22  0		Repeat until I register = 0
[g][RTN]		013 - 43 21
DM16L SN: 00267(returned)
DM16L SN: 02149
pwarden42
Posts: 5
Joined: Mon May 10, 2021 12:32 pm

Re: [DM16] Raising number to a power

Post by pwarden42 »

Kind of late to the party, but, as another new DM16L owner, I was intrigued by post about adding this type of commonly used but unsupported feature on this calc. I like your implementation (using ABS to force the base into LASTX is pretty sneaky), but there were a few things I noticed:

1.) There's a typo on line -005-, the mnemonics should be STO I. The codes are right, but the [f] prefix key doesn't match.
2.) There's an edge case at an exponent of 0 that will break everything. I'm guessing it would subtract 1 from 0 and then keep decrementing and never finish.
3.) The [DEC] step is unnecessary. It would have no effect if you were already in binary mode (other than changing the displayed representation) and would cause a corruption of the X and Y registers if you had entered the base and exponent in floating-point mode.

Using what you had done, I started about setting up another implementation with some modifications:

Code: Select all

001  LBL E        | 43 22 E
002  x#0          |    43 48
003  GTO 0        |    22 0
004  1            |       1
005  RTN          |    43 21
006  LBL 0        | 43 22 0
007  CF 0         | 43 5 0
008  x<0          |    43 2
009  SF 0         | 43 4 0
010  ABS          |    43 8
011  1            |       1
012  -            |       30
013  STO I        |    44 32
014  CLX          |    43 35
015  x<>y         |       34
016  +            |       40
017  LBL 1        | 43 22 1
018  LST X        |    43 36
019  *            |       20
020  DSZ          |    43 23
021  GTO 1        |    22 1
022  F? 0         | 43 6 0
023  1/x          |    43 26
024  RTN          |    43 21

Code: Select all

DM16
04  00000000000000  00000000f00000  c02f0008fff000  eae00000000000
08  00000000000000  2faf8befbe2280  bef20200bcaf80  00000000000000
f8  00000000000000  00000000d4a430  41a1cea601ccca  c0d6cdf1d810d2
fc  2000d4f140a90e  00000000000000  000000000003f9  00000000000000
A: 00000000000000  B: 00000000000eae  C: eae00000000000
S: 00011100000000
M: 00000000000000  N: 00000000000000  G: 0a
This method assumes that you have already set the word size and are already in binary mode OR that you are in floating-point mode and planning to stay there. It will work with negative bases in either mode (set 2's COMP for binary mode) and will work with both negative bases and negative exponents in floating-point mode. Bases must be integers in binary mode; exponents must be integers in either mode. If the exponent is 0, the result is 1. What's neat is that in binary mode, you can do exact math as long as you only need integers and its within the range that can be represented. Floating-point mode can represent a larger range, but that comes with the loss of precision, so you have to decide which is best for the case you're working in. One snag is that since 1/X is ignored in binary mode, negative exponents when in binary mode will be treated as positive exponents.

Some additional improvements I was thinking about would be to check for even or odd exponent, the do half as many steps, then duplicate and multiply X and Y (and multiply that by the base once more if the exponent was odd). That would cut it in half. If you could figure out the highest power of two that's less than your exponent, you could maybe make use of some of the DM16L-specifc bit manipulation features, but there isn't (AFAIK) any way to programmatically know whether you are in binary or floating-point mode or what your word size is, etc....

Anyway, thanks for inspiration...this is a much more interesting way to spend my lunch hour than reading articles on the internet.... :lol:

P.
pwarden42
Posts: 5
Joined: Mon May 10, 2021 12:32 pm

Re: [DM16] Raising number to a power

Post by pwarden42 »

I noticed a couple of things in my previous reply that were incorrect and thought it would be more useful to post again instead of editing my last post.

Issues were:
1.) Though I'm catching special case at exponents of 0, there is also a problem with exponents of +/- 1 that would result in a long calculation, then an overflow.
2.) There is likely an expectation from someone using a 'y^x' function that the result would be left in X and the stack would drop (T drops to Z, and leaves a duplicate in T), which was not the case in all scenarios.

I've also added comments to explain my reasoning. It seems like there should be a way to get away with fewer labels, but it wasn't immediately obvious to me.

Updated program (with a net change of +3 lines):

Code: Select all

001  LBL E        | 43 22 E         //y^x Program Start:
002  x#0          |    43 48        //If X is not zero...
003  GTO 0        |    22 0         //...go to label 0
004  *            |       20        //Else multiply Y by 0 to drop the stack.
005  1            |       1         //Put a 1 in X, stack lifts.
006  +            |       40        //Add the 1 to drop stack, leaving the 1.
007  RTN          |    43 21        //Program End
008  LBL 0        | 43 22 0         //Label 0:
009  CF 0         | 43 5 0          //Clear flag zero, we'll use it to test for negative exponents.
010  x<0          |    43 2         //If X is negative...
011  SF 0         | 43 4 0          //...set flag 0
012  ABS          |    43 8         //Get the absolute value of the exponent...
013  STO I        |    44 32        //...and store it in I
014  CLX          |    43 35        //Clear the X register
015  x<>y         |       34        //Swap it for the base in Y
016  F? 0         | 43 6 0          //If the exponent was negative...
017  1/x          |    43 26        //...use the reciprocal.
018  +            |       40        //Add the base (or its reciprocal) to the 0 in Y, loading LASTX with the base
019  DSZ          |    43 23        //Decrement the I register
020  GTO 1        |    22 1         //If I is not zero, continue to the multiplication loop...
021  RTN          |    43 21        //...otherwise end the program (leaving the base in the X register)
022  LBL 1        | 43 22 1         //Label 0: Multiplication loop start
023  LST X        |    43 36        //Recall the base from LASTX
024  *            |       20        //Multiply it by the current running product (originally in X, lifted to Y)
025  DSZ          |    43 23        //Decrement the I register
026  GTO 1        |    22 1         //If its not zero, keep looping.
027  RTN          |    43 21        //...otherwise end the program (leaving the base in the X register)

Code: Select all

DM16
00  00000000000000  00000000000000  00000000000000  03300000000001
04  00000000000000  00000000f00000  c22f0008fff000  eae00000000000
08  00000000000000  2faf8befbe2280  bef20200bcaf80  00000000000000
f8  00000000000000  00d441a1cea601  d441a1cca430ca  c0d6d810d22000
fc  d4ccf1ce40a90e  00000000000000  000000000006f9  00000000000000
A: 00000000000000  B: 00000000000eae  C: eae00000000000
S: 00010100000000
M: 00000000000000  N: 00000000000000  G: 0a
P.
DM16L, HP 15C, WP 31S, HP 33S (RIP/Broken Enter Key), HP 50G, HP 48G (x2), TI-86, TI-85 (RIP/Accidental Death and Dismemberment)
wile1411
Posts: 9
Joined: Mon Sep 28, 2020 9:48 am
Location: Canberra, Australia

Re: [DM16] Raising number to a power

Post by wile1411 »

Thanks for the corrections and new code. I figured mine would have some edge cases but had worked around those. Nice to have some more robust code now. Cheers!
DM16L SN: 00267(returned)
DM16L SN: 02149
Post Reply