Latest 33s Display is Indeed Improved



#2

After the previous "improved" display on the HP-33s, I had my doubts.

But (as already reported by others) the latest version I've seen (at Wal-Mart) is very much like what should have been released initially. Each character matrix has been reduced in size, leaving more room between them for the larger decimal point. The contrast appears better too. I'll have to take a closer look to see if the spaces between the pixels have been narrowed.

I do notice that the latest model has embossed on (actually, molded into) its back a garbage can icon with a diagnoal line through it. I'm sure this is meant to suggest that we properly dispose of the batteries and/or circuit board. However, I can't help taking this as an admission that the earlier models should be thrown out! ;-)


#3

Does HP allow trade-ins for the 33S like they did with the 49G+? I forget.


#4

The only way to know would be to call support and find out.

They may take the line that there is no defect in the earlier 33S units. This is merely an incremental improvement.

But hey, if you are in the US, it is a toll free call.

#5

I bought a 33s with the older decimal point and bad keyboard, and called up and complained. This calculator didn't always register keystrokes. I told them that I design life-safety elements for a living (which is the truth), and that because the keys didn't always register, and because the decimal point was extremely difficult to distinguish, I couldn't rely on this calculator. The guy on the phone had me reset the thing, which did nothing, and then he said that he would send me a new one, which he did. He also said that he would specify as a special instruction that the replacement unit should have the improved decimal. I received this replacement unit in the mail very quickly, and it did have the improved display. I now use this calculator daily at work, with confidence.

If I was the owner of one of the previous versions of the 33s, I would call them to voice my displeasure over the decimal point issue, and ask if I could be sent a replacement unit with the improved display. You may be surprised, and they may do it. If they hadn't sent me a new one, I would never spend another cent on an HP. However, because they did send me an improved one, I bought another one at Wal Mart to have as a backup.

#6

. . . supposedly a new unit is on the way.

The voice recognition system kept hearing "HP 33S Scientific Calculator" as "Laser Printer", but later it dropped back and started listting product classes. "Handheld" got me to "Calculator" and (FYI) when asked "Home, Home office, or Business", I replied "Business".

From my converstaion with the very helpful attendant, I gather that it helps greatly to have a receipt showing purchase within the last 12-15 months. (Another, even older 33s has a serial # indicating that its replacement is a bit too much to ask, so I'll only be upgrading one of my two original-style units.)

I understand that, should they want my old unit, they'll send a mailing label. If no label, I can do what I want with the old one. ("Throw it out" comes to mind, but I know a high school student who might want it . . . )

So, "Hooray!" for HP calculator support. (And good luck to you all!)


#7

That's funny, I too had some funny recognitions to 'calculator'..Response: "Did you say Jukebox?" :)

But I did eventually get through, and the HP rep was quite helpful.

ECL


#8

Did you guys note how sometimes the voice would sound "frustrated"??!

LOL!

#9

FYI . . .

The replacement showed on Saturday. Calculator only (with batteries installed), wrapped in bubble wrap. Ser # CNA 442nnnnn, with the improved display.

It came with a curious circular beige sticker on the back, printed in black with "MARKETING SAMPLE", and some illegible handwriting.

Though it has the newest display, it seems to have the old (uncorrected) ROM.

   .1           ten minutes
->HR as decmial portion of hour (result: 0.1667)
1 one hour
- subtract (result: -0.8333)
->HMS convert (result: -0.4920)

(My newest unit -- Ser # CNA 532nnnnn -- gives -0.5000 .)

So, beware: there are some "transitional" units with newer displays, but old ROMs.

Curiously, it's got the worst keyboard of my several units -- seems to "miss" on the arithmetic operation keys occasionally. (I hadn't noticed a single problem with 33s keys until this one arrived.) I'll try the "wiggle fix" that seemed to clear up my 49G+ keys so well.

Hey! I'm not complaining! Thanks to H-P for the replacement. I'm just sharing to add to the knowlege base.

My son is using the older unit, in ALG mode, and with no idea yet how to program the thing. He considers it a glitzy upgrade from his previous 20S. And who am I to argue? The two-line display and 26+ variables are indeed steps up.


Edited: 14 Nov 2005, 12:58 p.m.


#10

I called today and the gentleman who responded got my information and set the replacement process underway. I suspect I might just remain a (satisfied) customer...

... funny thing, though, shades of 1984 or the V chip: I asked if he could tell from their records (I did register my calculator, if I recall correctly) where I bought it and in doing so, I mentioned that I have been buying their calculators since I was old enough to afford and buy my own calcs. To this he replied, "Oh, we have an EXTENSIVE record on you!" :P ::( ; I guess it must be extensive... for some of us
;) .

It would also be a gas if this fellow happens also to read our forum!
(I also hope on their records, I didn't come across as too whiny!!)

#11

Paul,

Sounds like you have a collector's item. For everybody else, I'd advise buying only units with serial numbers beginning with CNA5xx, or maybe even only CNA532 or later. I finally went to a local Walmart yesterday to see if they had any in stock. I found a hanger with several units hanging on it. I pulled the first one off, pushed the ON button through the blister pack and entered a string of twos. Sure enough, the display seemed much better than my original unit. The serial number on the back was CNA532xxxxx. Curious, I checked the next unit. Its serial number was something like CNA442xxxxx. I pushed its ON button and entered all twos, and saw the old tiny radix. All of the other units were in the same serial number range and had the old display. Needless to say, I put the bad units back and purchased the one good one. So if you want a 33S with the new display, don't buy one that begins CNA4, and your best bet is to actually check before you buy if you can.
Regarding the missing key presses and the need to try the "wiggle-fix", let's hope that is a problem only with your particular prototype (or whatever it is.) (Except for the collector's item aspect, I'd say you would have a right to complain and request yet another replacement.) For what it is worth, the keyboard on my new unit passes the self test, functions flawlessly in use, and feels noticeably better than my first 33S. The feel is a little softer and less "clicky". It is virtually indistinguishable from several pioneers to which I compared it.


#12

I noticed the same thing at my local Walmart. They a few of the newer machines with the improved display at the front, and towards the back were the older ones with the flawed display. I wonder how much additional bad blood directed against the 33s and HP as a result of people buying the older 33s with the horrible display.

My initial reaction to the 33s was extremely negative. I had spent about $60 for something with an unusable display, and if I hadn't heard in this forum that machines with the improved display were on the way HP would never have seen another dime of my money. After getting a replacement 33s with the improved display and buying another one from Walmart, I have given the 33s another chance, and have to admit that I actually like it. I think it could be in HP's best interest to recall any of the older 33s that are still on the shelves with the flawed display.

#13

Hi Paul,

Which ALGebraic stack logic does it have?

Is it the parallel stack, or the swap x.,y stack?


#14

If you mean the "swap" key function described here,

   it (# CNA442nnnnn) gives DIVIDE BY 0, 
just like my newest unit (# CNA532nnnnn),
while my oldest unit (# CN404nnnnn) gives 0.5 .

So it would appear there are at least three ROM versions?


#15

Yep.

So far, I have delineated:

REV   Description
beta Gene's Calc sample.
- Walmart initial release. (just before the EIT exam a few years ago).

A 1st full-time release
B Bugs fixed for the polar rect and the h.ms

Regarding ALG

beta and "-" have the same functionality, viz 24 / 12 SWAP <enter> gives 0.5

"A" and "B" give 24 / 12 SWAP <enter> give div 0. Note that you really need to see my old thread that desribes what is really happening here.

In short, the newer ones maintain two parallel independent algebraic stacks--you can actually run tow independent algebraic chain calculations simultanious ly. SWAP simply moves from one to the other, and so you can also link them.

The earlier ROMS gave the more familiar x<>Y swap which reverses the order--similar to the 20s.

The LCD display appears to be changed indepenedt of the ROM. In otherwords there is not synchronization between the two imporvements.


BETA and "-" may be the same ROM. But the keyboards were different with some of the functions (ask Gene about it! :-)


Edited: 15 Nov 2005, 12:56 p.m.


#16

Nope, all my 33S calculators have the same keyboard layout. :-(


#17

I stand corrected!

Funny though--I distincly remember something about that---was there an early "image" released before actual hardware, that you might have pointed out?

Answer me up-thread--we can kill this one?

I am correcting my post above, and so i will put "1234" here for erasing--then you can erase yours if you like (or has this feature been disabled?)

#18

Thanks. I'll chase down your older thread on the stack thingie.

Without knowing what's behind the curtain, I was surprised that the older units "behaved better" than the newer with regard to this (SWAP in ALG mode).

But I've assumed it's simply not an issue to an RPN user.


#19

"better"?

Don't you think it is kind of cool to have two parallel stacks?

(Of course the loss of the inversion capability is sort of vexing...)

Somewhat related, at least as far as ALG goes: the only unpleasant surprise for me, when I finally got a 27s, was that there is no swap command. the 17bii has it--but only because it *has* to because of the RPN mode.

Regards,

Bill

#20

Just out of interest, there is an example of the H.MS but in this thread but could someone supply an illustration of the way in which the polar to rect bug manifests itself...?

Thanks.

Mike T.


#21

Rectangular to Polar Conversion

When performing a rectangular to polar conversion of a number where the X or Y coordinate is equal to zero, the result might be inaccurate.

Workaround :
When performing rectangular to polar conversions, if any of the 2 input is 0, take the absolute value of the number before performing the rectangular to polar conversion to yield
the correct result.

Example :
10(enter)0(CHS)(ABS)(r-p) will yield the correct result (10, 90)
while
10(enter)0(CHS)(r-p) will not (10,270)

There was at one time a workaround posted on the HP website for all the 33S bugs, but I could not find it. The update was dated September 2004, while the newest manual (3rd Ed)is dated November 2004, the updates should have made it into the manual but I didn't check. Email me if you need a copy.

mike at safetyplans.net

Edited: 18 Nov 2005, 9:19 a.m.

#22

Here's something I've found:

                       CNA 442nnnnn               CNA 532nnnnn
... keystroke display display
... 10 x: 10 y: 0.00 x: 10 y: 0.00
... ENTER x: 10.00 y: 10.00 x: 10.00 y: 10.00
... 0 x: 0 y: 10.00 x: 0 y: 10.00
... ->theta,r x: 10.00 y: 90.00 x: 10.00 y: 90.00
... ->y,x x: 0.00 y: 10.00 x: 0 y: 10.00
... ->theta,r x: 10.00 y: 270.00 x: 10.00 y: 90.00
... ->y,x x: 0.00 y: -10.00 x: 0 y: 10.00
... ->theta,r x: 10.00 y: -90.00 x: 10.00 y: 90.00
... ->y,x x: 0.00 y: -10.00 x: 0 y: 10.00
... ->theta,r x: 10.00 y: -270.00 x: 10.00 y: 90.00
... ->y,x x: 0.00 y: 10.00 x: 0 y: 10.00

I assume that illustrates the bug?


#23

My CNA 51500163 seems to be a bastard:

1.) The display is perfectly OK; I can't compare to an older machine but I have no trouble reading the decimal point (a comma in my case.)

2.) The P-R bug is present, exactly as shown above.

3.) X<->Y in ALG mode doesn't exchange the last two numbers entered (as to reverse the result of - or /) but seems to use a shadow register that can be used for any purpose. (Very much like the t-Register on older AOS TI machines such as the TI-59)

Marcus


#24

Marcus,

Do this:

clear registers, clear stack in RPN
ALG
1 + 6 <enter>
<x<>Y>

If you see "6" then you have the original "pre-release" or rev "-".

If you see "0" then you have the second version of the ROM ("A"). (The third version would have bugs fixed).

Now, continuing from above, assuming you can see "0", then do this:

9
x
<x<>y>
{at this point you should be seeing "7" from the 1st calc}
+
<enter>

Notice that you have carried on two independent calculations, with their own x,y stacks, and you have tied them together by prefixing an operation (in this example <+>) followed by "swap" (<x<>y>).

The odd thing about this algebraic feature is that it is un-documented...and there was no change in the manual between the 1st and second issues (Rom "-" and rom "a" have edition 1 and edition 2 respectively).

Further, the PDF documents that were written and are available at HP have one spot where they explicitly use the "swap" functionality of rom "-". (A contributor here wrote them--and had that ROM).

So if you have the P-R and the H.ms bug, and the algebraic behavior, and the C.nr overflow bug, and the annunciator but after reset.(asre there more--see archives of Mike's post)...then you have ROM #3 (what I call "B") (as far as we can determine) or in other words, I am inferring from the anecdotes, that there have been three roms:

"-" bugs, ALG swap between last stack entry and current command line
(ealry walmart release--essentially a "pre-release")

"A" bugs, parallel ALG stack (1st full retail release)
"B" no bugs, parallel ALG stack

It looks like the new display (and there may be more than one iteration!) happened to some of "A" as well as to "B" ROM machines
Let's see if we find more!

(visions of "red-dots" dancing in my head...)

One other thing--does anyone have a rom "A" that does *not* have a CNA (as opposed to CN) serial? In otherwords, I think that rom "A" was instituted at factory "A" and perhaps not at the other? We'll see.

Regards,

Bill


Edited: 18 Nov 2005, 4:03 p.m.


#25

Here are my observations:

Keys               Display
---------------------------
1 + 6 <enter> 7.00
<x<>y> 0.00
9 9_
x 9.00
<x<>y> 7.00
+ 63.00
<enter> no change
----------------------------

The only thing I can see is that there is a shadow register holding the result of the first addition (7.) after x<>y. This result is then retrieved by the second x<>y and used in the calculation. I can't see any "secondary AOS stack" or whatsoever.

Marcus


#26

Hey Marcus,

You need to "play around" with the ALG more. THe example I gave you is only one very simple starting point. Try this:

1 + 6 <enter> 7.00
<x<>y> 0.00
9 9_
x 9.00
4 4_
<enter> 36.00
<x<>y> 7.00
<x<>y> 36.00
<x<>y> 7.00
+ 7.00
4 4_
<enter> 11.0
+ 11.0
<x<>y> 36.00
<enter> 47.00
+ 47.00
<x<>y> ......tell me where you take it from here!


As you can see, you can carry on parallel work indefinitely and link the work...


Regards,

Bill

#27

Yeah, as in "don't throw this one out!" LOL.

#28

I saw an HP33S in Walmart on Saturday that had a S/N that started with 530xxxx. The display was ALOT better. I could easily see the decimal with two "2's" next to each other from about 2 feet away. The digits looked thinner.

If I didn't already have 2, I might have bought it.


#29

Is there a definative way to tell if I have an improved 33s? I bought mine at Walmart about July of this year. I always thought I could see the decimal point clearly, but now I'm not so sure.
Thanks, Hal


#30

It may be helpful if some of you guys who have the ability to can post images of the pre- and post- displays.


#31

I recently lost my digital camera, or I'd post some today.

I've been film-photographing some stuff for eBay sales, so I'll get comparative views of the 33s displays as well, if no one else does it sooner.

#32

I also bought a new 33S from Wal-Mart. (Fry's didn't have the new ones.) I've been staring at the display for quite a while, porting YATZ to the calculator. I know this has been brought up before, but I'm now nose-to-nose with just how limiting 26 variables and 26 labels can be. The other capabilities of this machine are quite nice, but that lack of labels, particularly, leaves most of the ample 32K unused for me. If I were using this calculator professionally, I would be extremely frustrated with this shortcoming. Since there's no way to store and retrieve programs either internally or exernally, it means that all of the ways you might want to program the calculator have to fit into the 26 label limit at the same time!

So that leaves a big gap in HP's product line where the HP-41 and HP-42 used to live. Not that there weren't significant differences between those two, but both of those machines were considered the top of the line in their days. Today they would occupy a place midway between the 33S and the 49GX in my opinion. The RPL models are at least one, and possibly two orders of magnitude more complicated to program than the keystroke models. Their power also surpasses the older platforms, but not in the same ratio, again in my opinion. I therefore feel the lack of a nice keystroke programmable machine with higher arbitrary limits in things like the number of labels.

One approach to bringing back this sort of thing would be to add a keystroke mode to the current high-end. I'm not talking about simulators of older machines, such as the fine software by Hrastprogrammer and others, but rather an updated keystroke mode that made a fair percentage of the built in power of the high-end machine available. That could be done in software by the community, I suppose, at the cost of RAM and CPU overhead in running programs. It would be far better to have it implemented natively by the calculator vendor, not only from the (presumably) better integration, but from the standardization that would bring to the new mode if it were deployed on all the machines in a given model.


#33

No doubt about it, there's a limitation. Bummer.

FWIW, the 6 Stat variables are available indirectly, via i = 28 through 33.

And why they chose to make the i register available indirectly at i = 27 is beyond me! Zero would have been much better, leaving the limited available variable space uninterrupted.


#34

The should have kicked out the i, introducing an IND statement to indirectly access a few KBs of memory (including A-Z) from any variable A-Z. That would allow multidimensional arrays. My TI/Casio can do this and AFAIK the 41 can do this too, correct?

Thomas


#35

The 41C can do indirect addressing through any register. It's the only way to access registers above 99. Label indirection is similar, I think.

The limited programming model may have made sense in marketing terms with the 32S and 32SII. Those machines were low-to-midrange, and so either the programming model was deliberately crippled, or else the economics of RAM made it silly to allow more than that. But fast forward 15 years or so and the programming capability looks really lame compared with anything in else in the 33S'x class. This is just a consequence of outsourcing the calculator product development, and then not expecting much innovation from the O.E.M.

You know, just the capability to swap programs in and out of the name space would go a long way toward overcoming the limitation. I can probably avoid using all the labels in any given program, but not in half a dozen or so. If I could have one program, defined as a set of labels grouped by a metalabel, or dare I say it, a name, as the 'current" program, then I could be as liberal as I liked in my label usage. It would still suck to not be able to share common routines, but not half as hard as this ridiculously low ceiling does.


#36

I'm not so sure about lame outsourcing.

It really probably did cost HP less to drop in the 32K chip than finding one that held only 500 bytes or so.

Perhaps if they had chosen to increase the cost a couple of $$ then they could have dropped in the 500 byte chip and all these comments about "I can't use the ram" wouldn't have come up. :-)

After all, this is essentially a 32SII that was upgraded because of component obsolesence. Nothing more probably intended.

If there are a few new things, ok, but I doubt there was much intent to re-engineer a totally different machine here.

When one understands that the old processors were going away very quickly, HP had to make choices: Make machines as similar as we can to the existing ones with new processors or drop out altogether.

They stayed in and appear to be successful, some isolated problems notwithstanding.

Perhaps, given time, they may come out with totally different machines, but keep in mind...HP calculators are MUCH smaller than they used to be in terms of personnel, so I'm glad with whatever I get.


#37

I agree. On the 32/32s, memory was the overriding limitation, on what otherwise was a VERY simple, straightforward programming model.

Now, the memory limitation has effectively been eliminated. The current limitation is in program labels and variables.

If you want to get 'round those limits, you've got to go "retro" with a 32K 42s, or up to one of the graphical models.

But for a readily available, almost-cheap, shirt-pocket RPN programmable, we have a choice analogous to the old Model T's color selection: any H-P calculator, as long as it's the 33s.

#38

Quote:

It really probably did cost HP less to drop in the 32K chip than finding one that held only 500 bytes or so.


No doubt.

Quote:

Perhaps if they had chosen to increase the cost a couple of $$ then they could have dropped in the 500 byte chip and all these comments about "I can't use the ram" wouldn't have come up. :-)


No doubt. 8)

Quote:

After all, this is essentially a 32SII that was upgraded because of component obsolesence. Nothing more probably intended.

If there are a few new things, ok, but I doubt there was much intent to re-engineer a totally different machine here.


Obviously true. *whine*

That's what I meant by saying they weren't expecting innovation from their O.E.M.

Quote:

When one understands that the old processors were going away very quickly, HP had to make choices: Make machines as similar as we can to the existing ones with new processors or drop out altogether.

They stayed in and appear to be successful, some isolated problems notwithstanding.


True, as far as it goes.

Quote:

Perhaps, given time, they may come out with totally different machines, but keep in mind...HP calculators are MUCH smaller than they used to be in terms of personnel, so I'm glad with whatever I get.



Well, I'm not so complacent. For example, the 49G+, with all its warts, is an improvement on the 49G and the 48G. It's got modern I/O , a modern processor and modern storage. If I were starting out with calculators, and I picked up a recent version of that machine, I'd be pretty happy, assuming I wasn't overwhelmed with the complexity or the world's demands that I get a TI.

But if I were starting with the 33S, I'd definately be disappointed. The programming restrictions are too onerous. They make the machine practically unusable for a set of programmed tasks. The key thing there is that all programs share a single name space. So it's very difficult (I'd never say "impossible" around this place) to get a nice variety of useful programs into the darned thing. That makes the 32k sort of a cruel joke, as you alluded to.

I understand that HP lost the calculator wars to TI, and that that meant they faced a choice to either exit the market or drastically curtail their investment in it. I'm glad they chose the latter too. But I'm just not willing to give them a (rhetorical) pass on an obviously bad choice to bring their low end machine forward without addressing the, um, addressing. They did better than that for the high end machine, after all. I'm sure the MBAs crunched the numbers on that choice, but it still sucks in my book.


#39

Quote:
The programming restrictions are too onerous. They make the machine practically unusable for a set of programmed tasks. The key thing there is that all programs share a single name space. So it's very difficult (I'd never say "impossible" around this place) to get a nice variety of useful programs into the darned thing. That makes the 32k sort of a cruel joke, as you alluded to.

Hi Howard,

I disagree. In fact, the 33s has everything that the 32sii had, and then some. It has more than the 11c. It has more capability than the 67 in terms of variable names and labels. The only pocket calculators that exceed it are the 15c and the 42s--both of which were higher in the chain. (Is the 41 a pocket calculator? Not quite as much).

There were many many extremely useful programs written for the 67, the 11c, the 32s, the 32sii.

Sure, you can't do everything that the 41 or the 42 or the 15c did, but you can do a lot.

In fact, for some things, the 33s can do more than the 15c--if it is memory or lines of code that is a stumbling block, the 33s has efffectively 7k relative to the 15c.

(The memory structure of the 33s is less efficent and so it really isn't 32k).

When you consider that the 33s has equations as well as RPN, and the ability to use equations as prompts, and real command names rather than keycodes, then you have a much easier interface for programming.

Regards,
Bill


#40

Since I posted this rant, I've become aware that the 33S is better regarded as a programmable than I gave it credit for. You are right about all its advantages relative to the Voyagers and the 67/97. And it does have a much nicer set of capabilities in its built in functions, which of course makes the programming that much more powerful.

I guess I'm really comparing it to the 49G+. The fact that the comparison is unfair is exactly the point! 8)

#41

I agree on the limitating nature of a finite number of variables. But, as a student, and knowing that 'heavy' work is frequently done with PC software, it is actually very enjoyable to address the challenges of this machine.

For example, I enjoy being able to solve polynomials and do matrix multiplication, approximate % error, and other "little" stuff that does take some time to do via longhand. And to have the answer as they are just locating the application in their GameBoys' is even more fun.

However, if HP is listening, a 42s style machine (built-in matrices, alpha-num variables, and a sophisticated menu system) would be warmly received :)
ECL


#42

Interesting. Thanks for that perspective.

As a hobbyist, I enjoy a programming challenge too. But it was my frustration at trying to port a non-trivial game to the 33S that occasioned my fit of pique above. But what really burned my toast was the realization that nobody would ever use the game, once I succeeded in porting it, because it would basically turn the 33S into a one trick pony. And for fifty bucks, you can get a much nicer gaming experience than that nowadays.


#43

Howard,

If it can be written off as a pursuit in which you were confronted by a new problem, I say do it!

One of the 33s's pros to me is that I could outgrow it at some point. This may not frame my thoughts properly. Perhaps a better statement is that if I could load a C compiler and all the capabilities of such a language onto my 33s, I would likely try to write "The Complete Student-Engineer's Suite for the HP-33s" which would really derail me from my studies.

I appreciate the 33s for being somewhat limited, but to still be able to 'shirt-pocket' some very useful capabilities. All that said, I still dream of a 'lost' case of 42s' arriving at the local Fry's. Or even better, a new 33s/42s = 43s?? 34s? :) Thanks for the insights,
ECL

#44

Sorry to saturate the thread here, but I have noticed some elementary ways to get labels to go farther in my case. I have two programs that deal with matrices. One lets me input two rows for manipulation, and the other multiplies two matrices up to 3x3 (this one is brute force, and will be updated).

However, before operating on these rows and matrices, I have to build the matrix. Also, once done, I have to output the new values. I realized that I can have one short program do both. And then both matrix programs can call on the same 'builder/printer' routine. (sorry if this is exceedingly basic)


Routine to input and output matrix elements:
LBL A
FS? 1
INPUT (i)
FS? 2
VIEW (i)
ISG i
GTO A
RTN

So, if I am building the matrix, the main label will set flag 1 before calling on 'A', and if I am done, and want to output the results, I disable 1, and set flag 2 before calling 'A'. Hey, I think I see how I can fit this into the main label...That's another benefit to these discussions, I see how I could have been more efficient through sharing something :)
ECL


#45

Yeah, at least half the benefit of explaining what you are doing to other people is the fact you have to explain it to yourself first. 8)

Seriously off-topic: I think that's because when you speak, or even when you frame your thoughts to be spoken aloud, you engage parts of your cortex that aren't in gear when you are thinking to yourself. My intuition says talking aloud to yourself wouldn't have the same benefit. If that's so, then the clarifying power of telling others what you are up to is not due to the motor pathways for speech and hearing being warmed up. It would be interesting to test that experimentally, but I'd have to be working from home before I started talking to myself. 8)

Back on HP calculators. There's an article in the archive that discusses some techniques for optimizing for label usage, specifically for the 33S. It sounds like some of the items you mentioned are discussed there. But odds are you've had a thought or two that might make good additions.


#46

Howard,

Thanks, I copy/pasted Paul's article for some fun post-study reading tonight.

ECL

#47

I agree with you that the ability to name a program would go a long way to increasing the programming capability. I wonder how hard it would be for Kinpo to do this, assuming HP had the desire to look into it. Most of the programs I write are relatively simple, I have minimal subroutines or branches. I have several different programs that use the same same variable but in different equations, and to keep it straight I make a user prompt in equation mode explaining what the required input is. It chews up memory, but the 33s has lots of it.

When I think of the shortcomings of the 33s, I try to remember to be thankful that at least there is still a basic RPN calculator in the market. I "grew up" on the 11c and 32sii, and felt that the higher end models had too many features that I would never use, and were probably too complicated for the day to day calcs that I usually am doing at work. Now that HP has addressed the design flaw of the 33s display, maybe they can address some of the programing limitations of the 33s. A basic RPN calculator like the 33s, but with some enhanced programming features would be totally ideal for me.

To go off on a tangent, does anyone know how successful HP ahs been with sales of the 33s?

#48

Well, to each his own, but personally, I find the RPL models much easier to program than my 12C or 16C.

What's so "complicated" about programming in UserRPL? It's mostly the Reverse Polish Notation that everyone here is so familiar with, along with a few very useful program structures, and named local and global variables. What could be simpler to use?

You can simply start the command line with the \<< UserRPL program delimiter, simply press the keys in the same order that you'd use to solve the problem in "immediate" mode, and then press ENTER to put the program on the stack. Doesn't that sound much like "keystroke programming"? Now type in your program name and press STO, and you now have a named program that you can use whenever you want, including calling it by name from another program.

Yes, you can write complicated RPL programs. For example, utilizing local variables, elaborate nested program structures, and recursive programming, but you don't have to utilize all of the power of RPL to write some very useful programs.

Even SysRPL isn't much more complicated than UserRPL, though much less forgiving of mistakes. Assembler language isn't difficult, though perhaps rather tedious to program in. For these two, keep an archive of user memory on a card, or in the case of the 49 series, in flash memory, while you're programming and testing, and it's easy enough to restore when things go south.

To be sure, there are more commands than almost anyone will ever learn to use, but complaining about that seems much like complaining about your bride being "too beautiful". If you don't know what a command is useful for, then simply don't use it.

I suppose that it largely depends on which model first hooked you on HP calculators.

Regards,
James


#49

My concern with UserRPL is that I forget the keywords and syntax when away from it for some time;). But there is another issue: The missing 'break' statement strikes you especially when writing more complex programs for which keystroke programming wouldn't be suitable anymore. There are some (awkward) ways around it but would it have been much of a problem to implement it?

Thomas


#50

Quote:
My concern with UserRPL is that I forget the keywords and syntax when away from it for some time;).

The keywords are the same used in the menus. Granted, the menu system in the 49 series leaves a lot to be desired, but even there the menus for program structures are straight-forward, and you can use the CAT key to see all of the commands. What is there about the syntax that's easy to forget?

Quote:
But there is another issue: The missing 'break' statement strikes you especially when writing more complex programs for which keystroke programming wouldn't be suitable anymore. There are some (awkward) ways around it but would it have been much of a problem to implement it?

Maybe you mean something like the HALT command? You can use the DBUG operation to start single-stepping through a program. Or you can start single-stepping at the first HALT command, or CONT to the next HALT command.

Regards,
James


#51

I believe he is talking about a kind of EXIT or RTN statement that allows early exit from a subroutine. Though I rarely find the need for them when I do well structure programming. I only really need this kind of functionality when I am looking for the shortest and fastest way to do something. However, now with the speed and memory of the 49g+ it is only required for "challenges"

Arnaud

#52

I was talking about 'break' as in the C language. I'm often in need to leave a loop somewhere in the middle of the enclosed statements. This might not be the most elegant technique, but it is 'resource friendly' and a standard on several programming languages.

About the forgotten keywords, yes I can look them up but that takes some time. So basically RPL gets my job done but I'm usually faster with keystroke programming. And no, I'm not against RPL, I was just pointing out what I dislike about it. I have used it and will use it in the future, for sure.

Thomas


#53

Quote:
I was talking about 'break' as in the C language.

Ok, I'm not familiar with C, which explains why I didn't recognize
your "break", and got sidetracked to "break point" instead.

Quote:
I'm often in need to leave a loop somewhere in the middle of the
enclosed statements. This might not be the most elegant technique,
but it is 'resource friendly' and a standard on several
programming languages.

Which kind of loop?

Somehow, it seems to me that using a WHILE...REPEAT...END or
DO...UNTIL...END loop would satisfy your requirements quite
nicely.

Of course, you could also nest "conditional" program structures
within the loop clauses.

Even with a FOR index...NEXT loop, it's easy enough to force an
early stop to looping simply by storing an appropriate value in
the 'index' local variable.

Offhand, the only way that occurs to me to force a START...NEXT
loop to end early is to force an error (such as 0 DOERR), which of
course ends the entire program, unless you have the loop within an
error trap.

In the case of a FOR index...STEP or START...STEP loop, one could
force an early end by substituting a different value for STEP,
sort of forcing a "giant STEP".

Okay, some of those aren't simple methods. I suppose that the
simple answer would be that it depends on what you're trying to
accomplish.

Regards,[n]James


#54

Quote:

Even with a FOR index...NEXT loop, it's easy enough to force an
early stop to looping simply by storing an appropriate value in
the 'index' local variable.


Yes, but that would mean that you have to go through the rest of the current loop until the condition is queried the next time. A 'break' would leave it immediatley.

Quote:

Offhand, the only way that occurs to me to force a START...NEXT
loop to end early is to force an error (such as 0 DOERR), which of
course ends the entire program, unless you have the loop within an
error trap.


I tried that. Can't remember exactly but I think that was possible only once, while I was in need for several 'break's. Probably my fault but at that time I didn't found out how to accomplish that and haven't touched my 48G since then. I'll look at it again.

Thomas


#55

Quote:
Quote:
Even with a FOR index...NEXT loop, it's easy enough to force an
early stop to looping simply by storing an appropriate value in
the 'index' local variable.

Yes, but that would mean that you have to go through the rest of
the current loop until the condition is queried the next time. A
'break' would leave it immediatley.

Well, you want the "break" only if a certain condition is (or
isn't) met, right? So you're going to be testing for that
condition. How about something like this:
1 10                    @ Loop from 1 through 10.
FOR n @ Loop index is local variable 'n'.
@ Code to be executed before break test.
IF
@ Test, continue if true, break out if false.
THEN
@ Rest of code to be run in loop.
ELSE
@ Optionally record that a break was used.
10 'n' STO @ Actually, any value greater than 9
@ should work in this case.
END
NEXT @ Increments and tests loop index.
@ Optionally test whether a break was used.
You could use a CASE structure to allow for multiple break tests
within a loop, for example:
1 10                    @ Loop from 1 through 10.
FOR n @ Loop index is local variable 'n'.
CASE
@ Code to to run before first break test.
@ Test for first break condition.
THEN
@ Optionally save information on reason for breaking.
10
END
@ More code to be run.
@ Test for second break condition.
THEN
@ Optionally save information on reason for breaking.
10
END

@ Etc.

@ More code to be run.
@ Test for last break condition.
THEN
@ Optionally save information on reason for breaking.
10
END
n @ Use existing loop index value if no
@ break occurred.
END
'n' STO @ Store value in loop index.
@ Additional code to be run within loop.
NEXT @ Increments and tests loop index.
@ Optionally check reason for breaking.

Of course, you could also force a FOR...NEXT loop to run
indefinitely, just by storing a value at least 1 lower than the
stop value into the index every time.
Quote:
Quote:
Offhand, the only way that occurs to me to force a START...NEXT
loop to end early is to force an error (such as 0 DOERR), which of
course ends the entire program, unless you have the loop within an
error trap.

I tried that. Can't remember exactly but I think that was possible
only once, while I was in need for several 'break's. Probably my
fault but at that time I didn't found out how to accomplish that
and haven't touched my 48G since then. I'll look at it again.

The START loops are problematic to break out of early. The START
loops are basically simplified FOR loops, for use where the user
doesn't need access to the index. They don't test for whether to
loop again, like WHILE and DO loops. Like NEXT loops, they do use
a local variable for the index, but START's index local variable
is nullnamed, and thus inaccessible from "pure UserRPL". I suppose
that one could access it with SYSEVAL, but why bother when FOR
loops are available?

Maybe something like the following, but note that pressing CANCEL
just once may just cause breaking out of the loop, with a second
press required to abandon the program:

\<<                     @ Begin program.
RCLF \-> f @ Save current flags.
\<< @ Begin local environment defining procedure.
-55 CF @ Force Save last args for consistent error handling.

@ Code to be run before loop.

IFERR @ Start error trap.
1 10 @ Loop from 1 through 10.
START @ Loop index is not accessible by user.
CASE
@ Code to be executed before test for first break.
@ Test for first break condition, break if true.
THEN
@ Optionally save information on reason for breaking.
0 DOERR
END
@ More code to be executed.
@ Test for second break condition.
THEN
@ Optionally save information on reason for breaking.
0 DOERR
END

@ etc.

@ More code to be executed.
@ Test for last break condition.
THEN
@ Optionally save information on reason for breaking.
0 DOERR
END
@ More code to be executed if no breaks occurred.
END
NEXT @ Increments and tests hidden loop index.
THEN @ Start error clause.
IF
0 ERRN \=/ @ Was the error unexpected?
THEN
@ Optionally any additional error testing and cleanup.
f STOF @ Restore original flags.
ERRN DOERR @ Execute the error, abandoning program.
ELSE
@ Optionally any additional code based on reason for breaking.
END
END @ End error clause.

@ Code to be executed after loop.

f STOF @ Restore original flags.
\>> @ Abandon local environment.
\>> @ End program.

But it's easier to just use a FOR loop and use the index local
variable to break out, otherwise ignoring it if you have no other
use for it. I suppose the main value of this START...NEXT example
is to show that "there's more than one way to skin a cat", and
some ways are better than others.

Of course, if you want the loop to execute until some condition is
met, with a single test for breaking, then very simply use
something like:

WHILE
@ Code to be executed before break.
@ Test for break condition, false to break, true to continue.
REPEAT
@ Code to run if not breaking.
END
Although only the FOR loops have a user-accessible built-in loop
index, it's easy enough to add your own loop index to any loop
using your own local variable and INCR (or DECR), or for that
matter, doing any operation to modify the index value and storing
the new value back into the local variable.

For example:

\<<
0 \-> n @ Initialize loop index.
\<<
DO
@ Code to be looped through.
'n' INCR DROP @ Increment loop index value.
UNTIL
@ Test whether to loop again, optionally using the value of n.
END
@ The loop index value is still in n, even after the loop has
@ ended.
\>>
@ Now the loop index has been abandoned.
\>>
Or, for the following, the index is 2 to the power of the loop count.
\<<
1 \-> n @ Initialize loop index.
\<<
DO
@ Code to be looped through.
n 2 * 'n' STO @ Modify loop index value.
UNTIL
@ Test whether to loop again, optionally using the value of n.
END
@ The loop index value is still in n, even after the loop has
@ ended.
\>>
@ now the loop index has been abandoned.
\>>
Note that in a DO...UNTIL...END structure, the UNTIL can actually
be anywhere between the DO and the END, as long as it doesn't
occur within a nested program structure. The END uses the T/F
(zero/non-zero) stack flag, and the DO tells it where to "loop
back" to. The UNTIL usually divides the loop into a "loop clause"
and a "test clause", but that's only for reasons of program
legibility.

But the above doesn't hold for a WHILE...REPEAT...END structure.
In this case, REPEAT uses the T/F flag, END tells it where the
"loop clause" ends, and WHILE tells it where to "loop back" to for
the next "test clause".

A DO loop is always executed at least once, but with a WHILE loop,
the "loop clause" may not be executed at all.

Finally, note that what you're trying to do may well be easier in
SysRPL.

Regards,
James


#56

Yes, it is certainly possible to get the job done without 'break' and it might look even better. But compare your first solution

Quote:
1 10                    @ Loop from 1 through 10.
FOR n @ Loop index is local variable 'n'.
@ Code to be executed before break test.
IF
@ Test, continue if true, break out if false.
THEN
@ Rest of code to be run in loop.
ELSE
@ Optionally record that a break was used.
10 'n' STO @ Actually, any value greater than 9
@ should work in this case.
END
NEXT @ Increments and tests loop index.

with this one:

1 10
FOR n
@ Code to be executed before break test.
IF
@ Condition for a break is met
THEN
@ Optionally record that a break was used.
BREAK
END
@ Remaining code
NEXT @ Increments and tests loop index.

It's slightly shorter (I inserted 'Remaining code' to make clear why 'break' is of advantage here) so you can probably see why I really would appreciate the inclusion of a BREAK keyword.

Thomas


#57

Quote:
It's slightly shorter (I inserted 'Remaining code' to make clear
why 'break' is of advantage here) so you can probably see why I
really would appreciate the inclusion of a BREAK keyword.

Oh, I can easily see where your BREAK would be useful, at least in
some cases, but it's just not available. I don't see any pressing
need for it though. I don't suppose that it would be all that
difficult to develop, and the 49g+ does have upgradeable firmware.

Maybe ask on the comp.sys.hp48 newsgroup; I know that at least one
HP employee occasionally posts there. Other than that, someone who
programs a lot in SysRPL might be willing to develop it as a
add-in.

In the case that there's only one place that you might want to
BREAK, and you want an indefinite loop, the WHILE loop seems to me
to be suitable.

Regards,
James

Edited: 13 Nov 2005, 8:44 a.m.

#58

RPL beats RPN hands down with programming. For me, writing a User RPL program on an HP48/49 to do darn near anything is almost second nature now.

Indeed, I'm a bit amazed at how people can become excited over an ordinary scientific calculator, as they are in this thread. It's a free country, to each his own...

Edited: 9 Nov 2005, 7:43 a.m.

#59

Well, this is a can of worms, of course. It reminds me of the editor wars between emacs and vi, in fact. People take positions in that conflict and assume that anyone with a different stance is an idiot. Communication between the camps is replete with disclaimers like "to each hos own" and "YMMV" but those are usually preambles to blistering rhetorical attacks on the other side. Not that anyone has reached that level in this particular thread, but it's a danger.

When I look at the relative merits of emacs and vi I see that each editor is useful in different contexts. I spent the earliest 10 years of my career as a systems administrator, so I had to learn both in order to support my users. Though I started out an emacs partisan, I now use both editors in different situations, as I have for the latter 10 years of my career.

I have yet to write a non-trivial program in RPL, so I'm not as qualified to address the differences between it and RPN as I perhaps am the differences in Unix editors. But I'm in the process of tooling up for the exercise of porting YATZ to the HP48G*, and I've been spending lots of time on my 48 machines, learning what I will need for that application, principally the graphics subsystem.

I'm feeling more comfortable on the calculator, but I must say that it has taken me a lot longer to start getting up to speed on the 48/49/49G+. than it has for any other machine in my collection. In fact, it has taken an effort comparable to learning a new operating environment like Python, say, if you are used to Perl, or Java if you know C. This isn't just an RPL issue, but also stems from the very large command set. Yes, that is a nice thing to have, but it also, by definition, increases the complexity of the machine. I think partisans of RPL, all of whom presumably have gotten over the steep learning curve of the calculators that implement it, tend to downplay the complexity. This is natural, but it misses an important feature of these machines.

That complexity, in my opinion, contributed to the triumph of TI in the education market. The average teacher didn't have time or interest to learn the rudiments of RPL, when compared to the familar, BASIC-like TI programming model. I know it sucks. That's not the point. It's simpler. HP must have gotten feedback that RPL was a problem in the marketplace, because they added some TI BASIC like syntax. Of course, nobody uses them in the RPL world because they suck. But that's the opinion of self-selected RPL lovers!

I also don't want to start another HP vs TI flame war. I like HP. TI is devil-spawn. The better calculators lost the calculator wars, a situation not unlike the triumph of Windows over technically superior rivals. I also don't mean to suggest that complexity was the only determinate in that war. I do think that it was an important one, however.

But I'm a hobbyist, so I'm willing to take the time (sandwiched in between fits of work designing grid systems) to learn RPL. I must say, it kind of grows on you. The manuals are essential, basic and advanced, since the help systems are a joke. This is somewhat improved on the 49G+. but a basic problem remains: limited screen real estate. Complicated functions require lengthy explanations, and there just isn't room on even a 49G+'s expanded display. There's also an issue of covering your work while you read the instructions. Having the text side-by-side with the work in progress is the only way to go.

In the meantime, I can crank out 41C code at a high rate. I picked up the 33C in about half an hour. This was not only a function of my familiarity with keystroke programming, but of the fact that there are fewer functions to choose on the 33S. They almost all fit on the keyboard, in fact, with two shift keys and the addition of a few logically laid out menus. Simplicity counts when it comes to learning a new system.

Of course, another consequence of the simplicity of the 33S is less functionality. You can truly do a boatload of interesting stuff on the 48G. I have Hrastprogrammer's 71X simulator loaded in my 48GX, and it rocks. I have his earlier 41E on my 48G+ and it's cool too. There is no question that I will be able to implement YATZ on the 48. That program is non-trivial in BASIC or keystroke models, but I expect it will be a quick knock-off on the 48, once I learn enough about the darn thing. (I know there's a Yahtzee clone already available for the 48. Delivering something unique is not the point of my exercise.) I'm probably going to revisit YATZ on the 33S sometime, but it is shelved for now.

So I have an enthusiast's interest in the RPL models. But I still find the keystroke models easier to understand and to program. I believe that's not entirely due to my familiarity with the 41C. I took up 41C after a nearly 20 year hiatus this Spring, after all. I do think that RPL is, by golly, more complicated and difficult to learn. But my hobby is learning about complicated old (or new) systems, so this appeals to me. I also think that the model of keystroke programming hasn't been upddated in those same 20 years. That's a shame. The last 20 years have brought multiple revolutions in software engineering that a keystroke model coould benefit from.


#60

The war between different systems (or their users) will never stop. I once tried to point out just a few shortcomings of Windows to one over-enthusiastic user and was immediatley labeld a luddite and later accused for not being able to manage my system. I'm at an age where I can laugh at this and leave a discussion without further insiting on my point but a few years earlier the result would have been one of these endless flame wars. The good thing about HP calc users is that they apparently almost always have a working brain between their ears, capable of early stopping a pointless discussion a la 'mine is longer than yours'. A rare species indeed.

Thomas


#61

The old Usenet adage was to try to "shed more light than heat." I agree that's often a lost cause, and also that it may not be around here.

#62

Hi Howard,

Very good post and good points.

The key "issue" if there is one appears to be the "learning curve". Essentially, learning RPL is like learning PASCAL or C or some high level language. RPN keystroke is low-level machine code.

The machine code is mostly keystroke stuff, with the addition of some "indirection" and some boolean statements and flags. If you already know these tools, its easy.

What I cannot answer is whether the machine code approach is easier if you haven't been there already. Since I was an RPN programmer at age 14, I cannot answer that.

Of course it also seems to me that the dividends on learning a language such as RPL are greater than learning a machine code such as RPL keystroke.

I think what we get to is, that structured high-level programming can "do more" but takes more initial learning.

What is readily apparent to me is that the keystoke approach is frightful to de-bug if it is large and complex with many subroutines and conditionals between subroutines. Once it gets to be really big in either size or complexity, it is a bear and a nightmare, which is why HP made all those great "pacs" starting with the 55! That way an end-user could get a program on board and running without having to become a machine language expert. I don't think the HP RPN programming would have been the success it was without that.

With the RPL approach, you still have the opportunity to provide "pacs" but you also open up the possibility of meaningful structured programming by an end-user who has "structured high level programming" skills.

Just a thought.

I am personally not proficient with RPL and have not climbed the curve--mostly because I'd rather do other things, and I feel like if I am going to do structured hi-level stuff, I might as well use a language that I already know, i.e. PASCAL.

So that is that.

Edited: 9 Nov 2005, 12:27 p.m.


#63

Hi, Bill,

Thanks for your thoughtful reply.


Quote:

The key "issue" if there is one appears to be the "learning curve". Essentially, learning RPL is like learning PASCAL or C or some high level language. RPN keystroke is low-level machine code.


I'd generally agree, if we are talking about assembly rather than machine language. But I think the keystroke stuff is just a bit higher level than assembly. Perhaps assembly coding with a very rich library of canned routines would be closer.

Quote:

What I cannot answer is whether the machine code approach is easier if you haven't been there already. Since I was an RPN programmer at age 14, I cannot answer that.


I can't answer that either, since I learned HP-41C programming before assembler. 6502 and PDP-11 were my first assembly languages. Both were understandable to me immediately, whereas my peers seemed to have trouble. I attribute that to knowing the HP-41, so your general point is well taken.

Quote:

What is readily apparent to me is that the keystoke approach is frightful to de-bug if it is large and complex with many subroutines and conditionals between subroutines. Once it gets to be really big in either size or complexity, it is a bear and a nightmare, which is why HP made all those great "pacs" starting with the 55! That way an end-user could get a program on board and running without having to become a machine language expert. I don't think the HP RPN programming would have been the success it was without that.


Good points, and ones that keystroke proponents often overlook in their turn.

Quote:

With the RPL approach, you still have the opportunity to provide "pacs" but you also open up the possibility of meaningful structured programming by an end-user who has "structured high level programming" skills.


I think it's more than that. I've got a background as a polyglot programmer. My experience in computer languages that I actually did work in, in the order encountered, is HP41, Apple BASIC, 6502 Assembly, VAX BASIC, Pascal and FORTRAN, PDP-11 Assembly on the VAX (in emulation mode), Micro$oft BASIC, HP BASIC 2.0, HP Pascal 2.1, REXX on Amiga, Amiga BASIC (original and MBASIC) C on Amiga, BSD and VMS, DCL, FORTRAN, Pascal and C on VMS, BSD and Ultrix grep/awk/sed/sh, Ultrix Perl 3 and Perl 4, csh on SunOS and Ultrix, SunOS C, gcc on Ultrix and SunOS, Perl 5 on a plethora of platforms, Java on Solaris and Windows, Python on Linux, Javascript all over, PHP, ASP on Windows, C++ on Linux, XSL, SOAP, JSP and other things now being called part of "web services." That's what I remember off the top of my head, I've left many systems out that I came to know but didn't actually use. I'm probably missing one or two.

I'm not presenting that list to ring my own bell, (well, maybe a little,) but to show that I have the background to be able to acquire new computer systems and languages. I also think I'm in a good position to judge complexity in computer systems. I think RPL itself is somewhat complicated, but probably no more than necessary to acheive generality. But combine it with what would be called its standard library set in a big system context, and you have a whoppingly complicated system. That's OK too. You also get functionality for that complexity. I know some would question the utility of that much power in a calculator, but I'm not one of them. I like having it there, even if I'm not using it, yet.

Quote:

So that is that.


Thanks again for the response!


#64

Thanks for correcting me on that.

I am not a programmer and so while I see now exactly what was inaccurate in my statements, I did not see at the time.

Indeed, when I see actual "machine code" it is gobbledeydgueck. But Assembly language appears to be a human-interpretable item----yes nore like RPN.

I like your description--"assembly with a rich very subroutine library"

And yes, there is something daunting about 48gx & RPL and part of the reason I replied is that I still can't quite put my finger on it...it should be easier than it is, or something----it's all so logical, so then why can't I adapt faster? Is it really merely that there is so much there, or is there a difficulty doing the simple stuff without already understanding the complicated stuff, too? In other words I am looking at the structure of the RPL language from an epistemological standpoint---that it is not modular enough if you see what I mean.

Interestingly the manuals show you three ways to do things--including a stack-based semi RPN keystroke approach--and then say that you really aught to try using the structured approach...but I never really "get there" and get frustrated with syntax and it all comes crumbling down and so I go pick up my fiddle or guitar instead...


OT my cousin used to live in Burlingame. And Sunnyvale, not far from you, has got to be the HAM radio capital of the world (sorry, Dayton, O.!)


Edited: 9 Nov 2005, 2:44 p.m.


#65

Quote:

I am not a programmer and so while I see now exactly what was inaccurate in my statements, I did not see at the time.


It's a common mistake. Strictly speaking, machine language is the binary numbers the machine processes when it runs a program. Assembly, as you note, is the human readable souce code that is closest to machine language of any source system. There is usually a one-for-one correspondence between the mnemonic label, "STO," say, and the binary opcode that it generates in machine language. So the distinction is subtle, but important.

Quote:

And yes, there is something daunting about 48gx & RPL and part of the reason I replied is that I still can't quite put my finger on it...it should be easier than it is, or something----it's all so logical, so then why can't I adapt faster? Is it really merely that there is so much there, or is there a difficulty doing the simple stuff without already understanding the complicated stuff, too? In other words I am looking at the structure of the RPL language from an epistemological standpoint---that it is not modular enough if you see what I mean.

Interestingly the manuals show you three ways to do things--including a stack-based semi RPN keystroke approach--and then say that you really aught to try using the structured approach...but I never really "get there" and get frustrated with syntax and it all comes crumbling down and so I go pick up my fiddle or guitar instead...


I think it's both things. First, there really is too much detail that needs to be mastered before you can do something useful. Second, there are too many ways to do the same thing. Since there is so much detail, texts that try to teach you RPL tend to start in different places, and be pretty imposing. It's not unlike how mathematics texts differ among themselves. The second feature, the diversity of programming models and constructs, adds to the confusion by letting different authors write code that acts similarly or identically, but looks completely different. (C.F, the lame TI "BASIC" like statements.)

I have mastered another rich language in which There Is More Than One Way To Do It. The capitalization should clue those in the know that I am talking about Perl. Perl is an enormous language with a huge diversity of ways to accomplish things. The difference is that you can bootstrap into the language with very little effort. Tis is in line with another Perl dictum: to make hard things easy and impossible things possible. What do you suppose the following code does?

  #!/usr/bin/perl
use strict;
my $pattern="^h.*";
while (<>){
if /$pattern/ then print;
}

This searches the input for lines beginning with "h" and prints them. I think it's crystal clear from the code what it does, but I'm really not in a position to tell. What do you think?

The other advantage Perl has going for it is that its creator is a linguist. Larry Wall has attempted to design a computer langage that is conversational in style. But because people have widly varying conversational styles, even when they speak the same language, making Perl "conversational" means different things to different people. So Larry just put all the idioms in there that made sense to him. It really can lead to some horrible looking code that is hard to debug. On the other hand, it is possible to be quite elegant with all that lexical flexibility. The point of that is, it's possible to find a path through the totality of Perl syntax that approximates the way you look at the world. That has got to make learning easier, hasn't it? It did for me.

Quote:

OT my cousin used to live in Burlingame. And Sunnyvale, not far from you, has got to be the HAM radio capital of the world (sorry, Dayton, O.!)


I actually live in San Mateo, just across the line from Burlingame. My mailing address is in Burlingame, however.

#66

Kudos to Howard Owen and Bill Platt (in proper titlecase) for their discussion of learning RPL. I would echo practically everything they stated, based on my similar experiences.

I coveted the 41C and experimented with it at stores in 1980-81 as a 17-year-old, but just couldn't afford it. I bought a 15C in late 1983 after taking a liking to the 34C. I got into collecting in 2002 with a 41CV and a 34C, followed initially by the 42S as well as RPL models, including the 28C, 48G, and 49G.

Like Eric, I readily picked up the 41C right where I'd left off 21 years prior. It's only a bit more complicated than the 15C I'd used through three science and engineering programs, in conjunction with experience in Fortran, C, and similar data-oriented high-level languages.

However, I see little about RPL that is intuitive or practical for myself or for most users. RPL has been discussed quite thoroughly in the last two years by different contributors in at least a few threads, including several that I started:

RPL is like a Leisure Suit

RPL Programming challenge: Area between two curves

RPN vs. RPL discussions

(The last one includes quite a bit of articulate input from Valentin Albillo.)

-- KS


Edited: 10 Nov 2005, 12:44 a.m.


#67

This has personally been on my mind for a couple of months now: The old RPL vs. RPN problem. I have been trying to decide between my 48GX and my 41CX. Which should be my primary calc?

I used to program the 41 back in the 80's. Then a long period of no calc-programming. Then a couple of years back I picked up the 41 again. However, for more than 6 months I have now been eagerly programming the 48 in UserRPL.

I am now moving back to the 41 and it looks like the 41CX will be my primary calc.

The reason is this: The 41 is for me a better programming environment. It makes it faster to solve simple problems. It's got a superior debug environment.

RPL seems to be cross between RPN and Forth with some grains of Lisp. Had it only been pure Forth, I would probably have settled on the 48. I love Forth. RPL is somewhat cumbersome. RPN is very straight foreward.


#68

My invaluable 41CX (Math1 & Advantage) helped get my BS and MA degrees a decade past. While writing a function for finding sinh and cosh the machine locked up; it's still sick.

I had thought that its potential replacement was the 49GX2 for all the trig and matrix operations needed. Are the keyboard algebraic operations different too? It seems they are. Right? Learning a new keyboard layout was enough of a change. Graphing? My laptop has Mathcad. Time to find a spare 41CX here or on E-Bay.

#69

I have to support both parts here.

Me too am an "old school RPN programmer" and I begun the RPL approach 2004 with a first 48SX (now up to 48GX).

After many approaches to the RPL programming paradigma I still have to say that I am an RPL novice! Not so with RPN, the 41serie in mind.

Well, I have to admit that my higly active PPC years are back in the last century. Maybe I lost some drive to start over again and learn the new RPL approach with all stripes and bells... Maybe other elder mates here have the same problem? ;-)

The 1st step up the RPL stair was understanding that RPL is not well suited for easy going LBL...DSE loops. I begun to look at it like another professional programming language where program entry is only the final step after a well done analysis of the problem and maybe also some structured diagrams for the programming task. And all of this is done on a computer environment with good ASCII programming tools (like ultraedit et al.).

And every few lines there is an explanation block (@...) for later upgrades to the software.

But I still don't have a 49G+ because...

...I'm still waiting for a "RPN pac" for this machine. Not for programming, bevare, but for easy keystroke ad hoc calculating.

With this point of few I finally found my peace regarding the RPN vs. RPL thing. The 32SII or 15C are my favorite RPN everyday calcs. And the 48series are for the serious big RPL programming. And the 41series? Today I like to port a 48/49 RPL solution to a 41 in RPN; but - I suppose you know it already:

RPL is programming, sophisticated, complicated and reliable

but RPN is real fun!

Valentino


#70

Valentino Ducati and Ed Look have compared programming in RPN to RPL and Fortran. I generally concur with their assessments, and have similar experience.

RPN-based programming does not utilize a true "language". An RPN-based (or even an AOS-based, as on the HP-20S) keystroke program is essentially a recorded sequence of instructions -- the exact same ones that one would execute interactively, with some extensions to provide structure and control.

These extensions are quite analagous to those in Fortran -- the original high-level number-crunching language, predominant when computers were actually used for computing:

  • Numerical ("internal") labels are like statement labels.
  • Alphanumeric ("external") labels are like ENTRY and SUBROUTINE.
  • GTO and GSB/XEQ are like GOTO and CALL.
  • Flags are like logical variables.
  • All conditional tests ending with "?" (FS?; x=0?) are like IF.
  • DSE/ISG/DSZ/ISZ help automate looping (DO-loop)
  • RTN and END are like their Fortran namesakes RETURN and END.

NOTE: There is a distinction between internal and external labels -- as well as the END instruction that partions a block of programming -- only on the HP-41C* and HP-42S. On all other programmable RPN and AOS calc's by HP, all labels are external.

Any keystroke program is akin to assembly code in that there is only one instruction per line. However, there are no procedural requirements (e.g., declaration of variables), structural rules, or syntactical jargon to obey.

This is certainly not the case with RPL ("Reverse Polish LISP"), which seems to be an un-nautral melding of Object-Oriented Programming (OOP) with the spirit of RPN calculating methods. Language constructs are present (e.g., IF/THEN/ELSE, FOR/NEXT), but they are not intuitively arranged, as they are in Fortran, C, or BASIC.

I fail to see how anyone could possibly consider an RPN keystroke program "complicated", unless it implements a lengthy and highly branched-and-looped process, possibly using many variables. In such cases, a user program on a calculator is probably not the best platform for the application, anyway.

------------------------------------------------------------

Here's a fairly concise chronology of my training in programming tools:

1980-81: Discovered HP-41C; experimented with programming at store counter. Did not experience any confusion.

1982: Passed collegiate course in Fortran '77. Did not experience any confusion. Started work several years later, maintaining Fortran programs on mainframes.

1983: Bought HP-15C and wrote working programs as necessary -- including one to find the value represented by a 36-bit octal floating-point word.

1992: Introduced to Matlab; found it similar to Fortran, but more expedient.

1993: Introduced to MS Visual Basic and wrote successful programs.

1995: Passed collegiate course in C language. Wrote my own recursive program.

1996: Introduced to LISP and CLIPS object-oriented languages. Experienced much confusion.

2002: Bought HP-41CV and successfully entered and modified programs that performed properly.

2003: Bought HP-48G. Saw and entered RPL programs and went, "What the h--- ?" Successfully entered and ran trivial one-line programs, but that's all.

-----------------------------------------------------------------

Maybe the real determining factor isn't what one happened to learn first. Maybe it's more how one thinks, and organizes computational tasks. I've had little difficulty with data-oriented languages like Fortran, C, BASIC, and Matlab. However, I find little that is intuitive about the way certain object-oriented languages work, or RPL.

-- KS


Edited: 12 Nov 2005, 4:47 a.m.


#71

You are right on target about the 20S as it too, can be keystroke programmed. And it would be as easy as programming a Spice programmable (all RPN) or a RPN Pioneer programmable.

But I just want to quibble with you in that it really is a language, and while not as fundamental as assembler, it sort of speaks directly to the chip by encoding the keys as commands visible in the LED or LCD display while in its programming space. Obviously, though, it is not a true high level language like FORTH or LISP or FORTRAN (or even BASIC).

And, what you pressed into the program memory is a true program, no matter what!

#72

Quote:
I fail to see how anyone could possibly consider an RPN keystroke
program "complicated", unless it implements a lengthy and highly
branched-and-looped process, possibly using many variables. In
such cases, a user program on a calculator is probably not the
best platform for the application, anyway.

Okay, maybe "complicated" isn't the correct word. How about the
phrase "hard to program"? They're pretty darn nice when used as
non-programmable models, but as for programming them....

My first experience with trying to program my 16C went something
like this. It doesn't have any I/O, so I don't have the option of
writing the program on the PC and simply transferring it to the
calculator. Oh well, it's not going to be a very complicated
program anyway. I try to program something, and what do I see in
the display? A line number, and in most cases, a keycode, but the
number or letter where applicable. Oh yeah, these things can
display only numbers and a few (sort of) letters. It would've been
hard to write on the PC anyway. Oh well, it's sort of like using
the keycodes in the 48, except that the shift keys are separate
codes instead of planes; I can deal with this, even though it is a
nuisance to have to keep track of the row and column to see what
I've keyed in. Hmm, no program structures, but it does have GTO,
GSB, and RTN, and a few tests, much like assembler or BASIC, so I
can implement all of the conditional branching and indefinite
loops as easy as pie. Now where was I (imagine, a programmable
that displays only one line at a time, but come to think of it, it
was designed well before my Sharp was). Maybe I should've written
the program out on paper, with line numbers, no less; now that
brings back some memories. Hey good, I can even use the "Index
register" to implement definite loops, but DSZ and ISZ skip only
only at zero, so it's not as nice as a FOR loop. Now let's see, a
bunch of these "RPN" commands actually use prefix notation instead
of postfix notation; what were they thinking? I'm supposed to
memorize which ones work right and which one are bassackwards?
Okay, I've finally gotten it entered; now I'll try it out. Doesn't
work; better have a look at what I keyed in wrong. Blasted
keycodes again, so I'll translate them and write them out on
paper. Edit a few mistakes and try again; still doesn't work. Look
over the code; that should work. Double-check that that's really
what I keyed in. Hey, how can it fail? Single-step through it;
hmm, something very strange is going on, but it's hard to put my
finger on just what the problem could be. Run through it a few
more times. Looks as if the object that I know I put on the stack
just plain changed to something else; what the hell? Single-step
through it again; sure enough, the object has been changed; how
could that happen? Maybe a hardware problem? Oh! These damned
things can handle only 4 stack levels, and when my object gets to
level 5, it just goes in the bit bucket, without even erroring out
or giving me any warning at all. Stranger yet, when I take an
object off of the stack, so level 5 (if the damned thing had a
level 5) should drop down to level 4, the object that was in level
4 stays there, as well as dropping down to level 3. Hmm, the
manual says it's a feature; somehow, I've a hunch that that
feature started out as a bug that someone found a use for. Okay, I
suppose that it could be useful, now that I know about the !@#$%
calculator doing such a &%$^ counterintuitive thing.

The 12C is even worse for programming. Edit a program that I've
keyed in? Easy enough if I want to change a line. But inserting a
line? Sure, as long as I want to key in every damned thing from
that line down all over again. Oh, I can add a line just by
overwriting a perfectly good line with a GTO to branch past the
end of the program, add my lines there, and GTO back to what
should be the next line. Now that makes for some nice,
straight-forward code. Why not a GSB and RTN instead of a two
GTOs? Oh, you have to be kidding me, it just doesn't have them.
Sure, I can get along without them as long as I still have GTO,
but they were handy. What about deleting a line? The fine manual
doesn't seem to mention this, but I suppose that overwriting it
with a GTO the next line is about the best I can expect from this
one. And where's DSZ and ISZ? I guess that if I want a definite
loop, I have to set up my own loop index and test.

Hey, I could probably write a BASIC program for my Sharp with not
too much more difficulty than writing a program for one of these
things.

And many RPN users seem to have some sort of problems with RPL
models? Hard to understand; I'd have thought that anyone who could
learn to like the RPN models would find the RPL models amazingly
easy, but apparently not.

Okay, I can program them, but this "True RPN" stuff that so many
rave about sure doesn't seem to make things easy for me. And it
looks as if only a few programs could fit into memory at any one
time anyway, and there's no way to transfer anything into the
calculator except for keying it in. I'm going to write a program
for one of these only to have to purge it to make room for another
program, and then key it back in the next time that I want it? Not
likely!

These two are great as non-programmable calculators for the
special purposes that they were designed for, once I more or less
got used to some of their quirks, and maybe even to hold a very
few very carefully written programs more or less permanently.

But switch from the RPL models to any "True RPN" model for my
regular programmable scientific? I just can't see that ever
happening.

Of course, now I've been told that these two models are poor
examples for programming in "True RPN", but my experience with
them have put me off the whole idea of using anything but RPL
(well, assembler for time critical things such as I/O) for
programming calculators. When something works so well, why switch?

Now, if they came out with a low-cost shirt-pocket sized RPN
model, even if not "scientific", I'd sure like to have that, even
if programming it was too much of a hassle to bother with.

Regards,
James


#73

Wow, this is great! You've really given me a clear sense of what it's like to approach RPN programming from the standpoint of RPL. It's hard to argue with your perceptions. But I do think that many of them boil down to not liking the limitations of the older machines (category "A"), and the rest are direct mirrors of the difficulty of going the other way (category "B".) Both are perfectly understandable.

Quote:

My first experience with trying to program my 16C went something
like this. It doesn't have any I/O, so I don't have the option of
writing the program on the PC and simply transferring it to the
calculator. Oh well, it's not going to be a very complicated
program anyway. I try to program something, and what do I see in
the display? A line number, and in most cases, a keycode, but the
number or letter where applicable. Oh yeah, these things can
display only numbers and a few (sort of) letters. It would've been
hard to write on the PC anyway. Oh well, it's sort of like using
the keycodes in the 48, except that the shift keys are separate
codes instead of planes; I can deal with this, even though it is a
nuisance to have to keep track of the row and column to see what
I've keyed in. ..


Category A. The Voyager models were middle tier machines in their day. They incorporated a programming model very similar to the previous generation's high end machines, the HP 67/97. They both showed numeric key codes in program mode. But the HP-97 had a built in printer that would print an alohanumeric version of the program. That made the 97 better for software development. None of the voyager series had this capability, of course. The high end of the time was occupied by the 41C, 71B and later the 42S. The 71B was programmable in BASIC, of course. The other two had alphanumeric capability that made listing programs much nicer. And of course the 41C and 71B both had very nice I/O capability, with standard (for the day) paths to and from a PC.

Quote:
.. Hmm, no program structures, but it does have GTO,
GSB, and RTN, and a few tests, much like assembler or BASIC, so I
can implement all of the conditional branching and indefinite
loops as easy as pie. Now where was I (imagine, a programmable
that displays only one line at a time, but come to think of it, it
was designed well before my Sharp was). Maybe I should've written
the program out on paper, with line numbers, no less; now that
brings back some memories. Hey good, I can even use the "Index
register" to implement definite loops, but DSZ and ISZ skip only
only at zero, so it's not as nice as a FOR loop. Now let's see, a
bunch of these "RPN" commands actually use prefix notation instead
of postfix notation; what were they thinking? I'm supposed to
memorize which ones work right and which one are bassackwards? ..

One from column "A" and two from column "B".

"Much like assembler or BASIC" indeed! I'd say BASIC is easier, actually. But this is the model many of us were first introduced to, so it seems natural to us. For example, when we look at RPL, we see everything being postfix as a jarring change, not the other way around. If you learn a thing one way, however illogical it is intrinsically, you are bound to see it as the "normal" or "sensible" alternative. (Just consider English for instance. I'll bet many of our non-native English speakers could give many, many examples of how illogical it is as a language.)

Quote:
.. Okay, I've finally gotten it entered; now I'll try it out. Doesn't
work; better have a look at what I keyed in wrong. Blasted
keycodes again, so I'll translate them and write them out on
paper. Edit a few mistakes and try again; still doesn't work. Look
over the code; that should work. Double-check that that's really
what I keyed in. Hey, how can it fail? Single-step through it;
hmm, something very strange is going on, but it's hard to put my
finger on just what the problem could be. Run through it a few
more times. Looks as if the object that I know I put on the stack
just plain changed to something else; what the hell? Single-step
through it again; sure enough, the object has been changed; how
could that happen? Maybe a hardware problem? Oh! These damned
things can handle only 4 stack levels, and when my object gets to
level 5, it just goes in the bit bucket, without even erroring out
or giving me any warning at all. Stranger yet, when I take an
object off of the stack, so level 5 (if the damned thing had a
level 5) should drop down to level 4, the object that was in level
4 stays there, as well as dropping down to level 3. Hmm, the
manual says it's a feature; somehow, I've a hunch that that
feature started out as a bug that someone found a use for. Okay, I
suppose that it could be useful, now that I know about the !@#$%
calculator doing such a &%$^ counterintuitive thing.

One from column "A" and two from column "B". I can't speak to why the T register acts the way it does on the RPN models. I can say that it seems natural and normal to me. I occasionally make use of it in the way it's explained in just about every manual for an RPN model I've ever read: a way to store a constant without using a register. That's actually pretty rarely needed, it's true. So I concede the feature is archaic (column A) and "normal" for RPN users (column B). The other column B item is the fact that the unlimited stack of the 28C onward confuses many of us old RPN jockeys. I've articulated what I think is wrong with it elsewhere in this thread. We have been used to using registers (variables by any other name) instead of holding too many intermediate results on the stack. This is especially true if you started on the 41C like I did. That machine has plenty of registers on the CV and CX models.

Quote:
The 12C is even worse for programming. Edit a program that I've
keyed in? Easy enough if I want to change a line. But inserting a
line? Sure, as long as I want to key in every damned thing from
that line down all over again. Oh, I can add a line just by
overwriting a perfectly good line with a GTO to branch past the
end of the program, add my lines there, and GTO back to what
should be the next line. Now that makes for some nice,
straight-forward code. Why not a GSB and RTN instead of a two
GTOs? Oh, you have to be kidding me, it just doesn't have them.
Sure, I can get along without them as long as I still have GTO,
but they were handy. What about deleting a line? The fine manual
doesn't seem to mention this, but I suppose that overwriting it
with a GTO the next line is about the best I can expect from this
one. And where's DSZ and ISZ? I guess that if I want a definite
loop, I have to set up my own loop index and test.

You won't get any argument from me about the brain-dead nature of the 12C's programming model. I suspect you'd be hard pressed to find a defender of that model in the RPN ranks hearabouts. (Who knows, though? We'll see.)

Quote:
Hey, I could probably write a BASIC program for my Sharp with not
too much more difficulty than writing a program for one of these
things.

BASIC was my second programming language. It seems pretty natural to me too. I have gone on to more modern languages, as I've noted elsewhere. But BASIC probably doesn't seem as outrageously wordy and antiquated to me as it does to you. (But see
the rant in this README file for my generally unfavorable impression of BASIC.)

I do think BASIC is easier than RPN - or RPL!

Quote:
And many RPN users seem to have some sort of problems with RPL
models? Hard to understand; I'd have thought that anyone who could
learn to like the RPN models would find the RPL models amazingly
easy, but apparently not.

I didn't. They are distinctly different, as you can tell trying to go the other way. I think you'd hear the opposite opinion expressed by RPN devotees, that RPN should be easy for RPL coders. It clearly isn't in your case. I don't think either of us is an exception.

I am making an effort, and having some success, at coming up to speed on the 48G. It is a fun machine, after a period of getting to know it better.

Quote:

Okay, I can program them, but this "True RPN" stuff that so many
rave about sure doesn't seem to make things easy for me. And it
looks as if only a few programs could fit into memory at any one
time anyway, and there's no way to transfer anything into the
calculator except for keying it in. I'm going to write a program
for one of these only to have to purge it to make room for another
program, and then key it back in the next time that I want it? Not
likely!


Column B, but mostly column A.

There has been no development of new RPN machines since the RPL family took over HP's top of the line. The few programs that fit in a 16C, or even a 41C, reflects the cost of RAM back then. The limited number of labels in the voyager series fits with this limitation. The 33S is the current shipping RPN programmable from HP. It has a programming scheme similar to the voyagers with the addition of alphanumerics. So your listing, as you step through it with two lines visible at a time, is more readable. But because HP gave Kinpo the old 32SII code to port to a more modern chip, there are still only 30 or so possible registers and only 26 labels! This makes the 32K of RAM almost useless. If RPN models had been further developed, they would have come up with more elegant ways to use additional memory. But RPL was the king, so it saw the development, not RPN.

So the existing RPN programmables are not as capable as the 48/49 machines. But this is because development essentially stopped in the late 1980s. I've noted elsewhere that there have been numerous successive revolutions in computer architecture and software engineering since then, none of which have been incorporated into an RPN-style machine. It is a pity.

Quote:
These two are great as non-programmable calculators for the
special purposes that they were designed for, once I more or less
got used to some of their quirks, and maybe even to hold a very
few very carefully written programs more or less permanently.

But switch from the RPL models to any "True RPN" model for my
regular programmable scientific? I just can't see that ever
happening.

Of course, now I've been told that these two models are poor
examples for programming in "True RPN", but my experience with
them have put me off the whole idea of using anything but RPL
(well, assembler for time critical things such as I/O) for
programming calculators. When something works so well, why switch?


No reason at all. I only play with the RPL machines because I'm gadget happy. Come to think, that goes for the RPN machines too! 8)

Quote:
Now, if they came out with a low-cost shirt-pocket sized RPN
model, even if not "scientific", I'd sure like to have that, even
if programming it was too much of a hassle to bother with.

Regards,
James


Likewise,
Howard

Edited: 13 Nov 2005, 4:14 p.m.

#74

For the prices these things went for when they were new, it was expected that users would be pretty serious about it. I started with the TI-58c and then the 59, and the key-code recognition very soon became automatic, such that I wrote my programs as columns of key codes on paper, with a few comments to the right. The printer did indeed spell out the function the key was labeled with, but I certainly didn't need that for speed.

Now I often do use the PC with 132 columns (monospaced DOS) and 43 or 60 lines on the screen to write out a program before entering it into the HP-41. That way I can keep a clearer mental picture of the program, have more than one instruction per line, have plenty of room for comments, indent, add diagrams and special usage instructions, etc.. RPL give some of this, but how much can you do with a 2" screen? (I'm not saying anything against RPL, but just cautioning against being too critical of characteristics that were not always a problem, had easy ways to get around, etc..)

#75

James,

I wished I had a Voyager series machine, but at the time, my 34C was still going very strong and I could not justify at the time spending for even a beautiful unit as the 15C or 16C.

But truly, it ISN'T counterintuitive to program RPN keystrokes on a 34C, 32SII, or 33S. I assume you have a 33S? If not, then this is moot, but the looping controls in these models, while not as powerful as in, say, FORTRAN, they were more than adequate for programs to "automate" things you would repetitively do on a calculator until you got so bored and sick of it that you'd scream.

But, I will admit to the frustration many a time when it came to edit or correct something in the keystroke RPN program. You really just have to scroll through it!

Edited: 13 Nov 2005, 9:46 p.m.

#76

James --

I think Howard Owen's response was excellent; there's no need to quote or rehash his post or yours.

Just a few points I'd like to make:

  1. Keycodes:

    As Howard pointed out, some of your points seem to confuse RPN with the limitations of mid-level models and early models. The keycodes shown in programs on Voyagers stem from their 7-segment display, not RPN! All the LED-display programmable models had the same limitation (except the HP-97 printer, as Howard mentioned).

    The algebraic-entry HP-20S, and HP-21S also show keycodes due to their 7-segment display.

    By contrast, the HP-41 with its 14-segment display, and
    the dot-matrix HP-32S, HP-32SII, the HP-42, and the KinHPo 33S are RPN models that display symbols instead of keycodes.

  2. Programming paradigms:

    The Voyagers are and were not the best RPN models for programming, not only due to the 7-segment displays, but also lack of RAM, slow speed, and lack of functions to partition user programs and to manage catalogues of programs. They were really intended for "expedient and disposable programs" only.

    The HP-12C programming paradigm is indeed an abomination that originated with the HP-55 and was unfortunately carried forward to the HP-65, HP-25, and HP-10C, and maybe others.

    The HP-41 and HP-42S were much better suited for "keeper" programs; the HP-32S, HP-32SII are also useful for programming (albeit hampered by lack of RAM).

    Please have a look at my AC Power Transfer programs for the 32S/32SII/33S. These programs are quite well-suited to those models, but would be more straightforward if these calcs had more-sophisticated complex-number functions.

  3. "t" register on the 4-level stack:

    Since the stack depth is fixed, some value must occupy the top-level register after an operation "pops" a value out. Zero would certainly be logical, but retaining the value in the "t" register can conveniently provide the user an endless supply of that value for calculations -- e.g., a constant term, or an input variable used many times in an equation.

    The 4-level stack was a compromise of required utility with the hardware limitations of the early days. If an all-new RPN calculator were to be designed today, I would suggest a user-settable fixed stack of up to 9 levels (and possibly 19).

One slight quibble with Howard's statement about development of RPN calc's effectively ending in the late 1980's: I'd say that it was actually 1991-92. That's when the HP-32SII replaced the HP-32S with expanded capabilities:

  • Equation editor from the HP-22S
  • Fractional-math functionality that is really quite useful and impressive (after the bugs in the initial run were fixed)
  • Functions and conditional tests omitted from the HP-32S

1991 might also be when the HP-17BII replaced the algebraic-entry HP-17B, adding RPN mode along with with a nicer bezel and trim.

-- KS


Edited: 14 Nov 2005, 12:33 a.m.


#77

Quote:

The 4-level stack was a compromise of required utility with the hardware limitations of the early days. If an all-new RPN calculator were to be designed today, I would suggest a user-settable fixed stack of up to 9 levels (and possibly 19).
[/ol]


That's what I would have expected if development of RPN models had taken a more evolutionary approach. A settable fixed stack, perhaps with the inclusion of an unlimited stack as a choice, could have been one natural feature incorporated into RPN calcs to help make use of abundant memory.

Quote:
One slight quibble with Howard's statement about development of RPN calc's effectively ending in the late 1980's: I'd say that it was actually 1991-92. That's when the HP-32SII replaced the HP-32S with expanded capabilities:
  • Equation editor from the HP-22S
  • Fractional-math functionality that is really quite useful and impressive (after the bugs in the initial run were fixed)
  • Functions and conditional tests omitted from the HP-32S

1991 might also be when the HP-17BII replaced the algebraic-entry HP-17B, adding RPN mode along with with a nicer bezel and trim.


Thanks for that correction, Karl. That means we've had just about 15 years of neglect of RPN calculator OS software. Like I said, it is a pity.

Quote:
-- KS



Regards,
Howard

#78

All good responses everyone.

I do recognize that trying to use more than four stack registers
on an RPN model is purely a user error, but one that's easy to
commit, at least for someone whose experience is in RPL. In RPL,
using "too many" levels may result in an "Insufficient Memory"
error or even an "Out of Memory" error, which puts you into a
routine of choosing options for freeing up memory so you can use
the calculator again, but objects can never be pushed off of the
top of the stack.

As for duplicating the T register when the stack drops, the RPL
stack can indeed be empty, so what the RPL user expects when he
tries to take something from the stack that was never pushed there
is a "Too Few Arguments" error, not to use something that was
replicated down from a higher level.

I suppose that the small command set reflects the limited number
of keys and shifted keys feasible in a calculator, as well as the
other hardware limitations.

I've tried to figure out why the RPN models so often put the
operator first, followed by the argument, for example, with LBL,
GTO, GSB, and STO. The hypothesis that I've come up with is that
it's due to the 4-register stack. If the argument came first, it
would have to be stored somewhere, presumably on the stack. With
the operator coming first, the keystroke can be stored elsewhere
until the argument is entered to "complete the command", so the
argument never has to be put on stack, thus never using up a
precious stack register. Does this make sense?

Yes, many of limitations of the voyager series may be largely due
to to the hardware limitations at the time they were designed.
Expensive memory, 7-segment single line displays and so on.

Yes, RPN model development seems to have stopped in the early '90s
with the 33s resuming development, but how much does even the 33s
improve things over the basics of the Voyagers released in the
early '80s? Yes, the 33s has a dot-matrix 2-line display but,
that's a relatively minor improvement. It's still limited to a
4-level stack, and still has a limited number of labels. But I
gather that the development of the 33s amounts mostly to adapting
the 32SII to new hardware? So it's much like asking how much
things had been improved by the time the 32SII was released in
1991.

But I see that the 33s actually does have menus after all. Okay
now, I suppose that the program doesn't actually record the
keystrokes to get to the particular menu, but only the command
actually chosen from the menu? In that case, I'd say that it isn't
strictly "keystroke programming" after all, but rather "command
sequence programming". Somehow, this seems very much like
programming the RPL models; the difference being that in the RPN
models you have to use a special "program mode" to write a
program, and in the RPL models you simply start the command line
with the \<< UserRPL program delimiter, type in the rest of the
program, press ENTER to put it on the stack, and STO it in a
named global variable if you want to save it for later use.


So just what the heck is it that RPN users find so all-fired
"complicated" about RPL?

Just for the record, I don't find BASIC to be at all "outrageously
wordy and antiquated". Actually, I've always liked BASIC, but
preferring the versions that use labels instead of line numbers
for GOTOs and GOSUBs. But using line numbers instead of labels
isn't that difficult, provided you've left enough unused line
numbers that you don't need to renumber your lines. It did get a a
bit of a bad reputation because of the "spaghetti code" that one
could make with GOTOs all over the program, but I regard that as a
matter of poor programming practice, not anything inherently wrong
with the language. You could write spaghetti code in RPN or
assembler, for example, but that would be the fault of the
programmer, not the language. It is rather "old" now, but we all
know the "newer" isn't necessarily "better".

Regards,
James


#79

Quote:
I've tried to figure out why the RPN models so often put the operator first, followed by the argument, for example, with LBL, GTO, GSB, and STO. The hypothesis that I've come up with is that it's due to the 4-register stack. If the argument came first, it would have to be stored somewhere, presumably on the stack. With the operator coming first, the keystroke can be stored elsewhere until the argument is entered to "complete the command", so the argument never has to be put on stack, thus never using up a precious stack register. Does this make sense?

Yes it makes sense.

RPL people like to see this STO LBL GSB GTO stuff as inconsistent. In fact, is is perfectly consistent. You see, STO LBL GSB GTO are not mathematical operators; they are *control commands* and by their very nature have nothing to do with Juskawicz or Infix or Reverse Polish or whatever you want to call it.

So you are correct, it keeps these thing off the stack. But that is not merely to save stack. Think about error checking, argument checking etc. When you press a control function, that is how the machine knows that a control function is to happen "starting from now".

There is a major change in error-checking going from voyager to pioneer.

On an 11c etc, load the stack with say:

t   1
z 2
y 3
x 4

and then push GSB.
the screen will flash, waiting for a label. If you push <X> instead, you will see "12". Or, if you push <backspace> you will see "0".

In other words, classicaly, the *control commands* can be over-ridden by mathematical commands. It's a hierarchy thing.

On Pioneers it is different. IF you push <exq> you will see "exq_" and you cannot push anything but a valid label. If you push <X> you will get a <!> annunciator and you have to push *either* <backpsc> or <C> to get back to the stack view.

I think it is perfectly logical and in fact far more logical than the RPL idea that everything is a stack "argument" which leads to the distracting problem of everything out of order and stupid inane error messages like "too few arguments" etc.


Edited: 16 Nov 2005, 8:51 a.m.

#80

James --

Regarding your first query about why RPN models use postfix for commands such as STO, RCL, LBL, GSB/XEQ, GTO, FIX/SCI/ENG, etc:

Bill Platt explained it: These are non-mathematical operations that have nothing to do with RPN. In fact, I had discussed this in my "RPN is like a Leisure Suit" thread that you claimed to have read. An excerpt, discussing prefix notation, in which arguments must be specified before a command is executed:

Quote:
This approach -- the essence of RPN -- makes perfect sense for mathematical functions.

However, it is often counterintuitive for device-control functions, such as STO/RCL and FIX/SCI/ENG. On the RPN calculators, these functions (as well as LBL/GTO/GSB/XEQ) require an appended identifier, generally numerical, to complete the command. On the RPL units, the input identifier must be specified beforehand, in the interest of uniformity.

Which is easier and more intuitive:

"FIX 5" or "5 (ENTER) FIX"? 
"25.4 STO 4" or "25.4 (ENTER) 'R4' STO"?

As for your boldfaced question,

Quote:
So just what the heck is it that RPN users find so all-fired "complicated" about RPL?

I'll quote another excerpt from my "Leisure Suit" post:

Quote:
As for RPL programming, compare a sophisticated RPL statement with an equivalent line in C, Basic, Fortran, or any other high-level language:

"IF (A .LT. B)  A = A + 360.0"             (Fortran '77)
"<< IF A B < THEN A 360 + 'A' STO END >>" (approximate RPL syntax)

(Much to my surprise, that short RPL program I wrote but didn't test before posting actually did work properly!)

This example underscores my main statement, in that RPL is an ineffective compromise between a high-level language and a keystroke-programming system.

When a series of prefix instructions is listed one at a time (like an RPN program), it essentially looks like an assembly routine. "Jumps" (GTO) are necessary a part of that.

However, when a series of prefix instructions is listed on a single line, it just looks scrambled -- nothing like a line of a high-level-language. Adding IF-THEN-ELSE and other constructs to prefix instructions just doesn't work, in my estimation.

-- KS


#81

Karl,

Quote:
Regarding your first query about why RPN models use postfix for
commands such as STO, RCL, LBL, GSB/XEQ, GTO, FIX/SCI/ENG, etc:

Bill Platt explained it: These are non-mathematical operations
that have nothing to do with RPN.


I did notice his post.

Yes, of course those are non-mathematical operations. I agree that
intrinsically they have nothing to do with RPN; indeed, they're
used in many languages. In my opinion, what they have to do with
RPN in these discussions is that they are used in a stack-based
RPN language.

Quote:
In fact, I had discussed this in my "RPN is like a Leisure Suit"
thread that you claimed to have read. An excerpt, discussing
prefix notation, in which arguments must be specified before a
command is executed:

In fact, I had read that thread a few times, I read it again a few
more times, and now I've read it yet again a few more times. I
still disagree with you.
Quote:
Quote:
This approach -- the essence of RPN -- makes perfect sense for
mathematical functions.


I agree, although it seems that most of the world disagrees with
us on this point.
Quote:
Quote:
However, it is often counterintuitive for device-control
functions, such as STO/RCL and FIX/SCI/ENG.


Perhaps seeing them used as postfix commands often seems
counterintuitive to you because you've never seen them used that
way except in RPL?

Having them prefix seems counterintuitive to me, because although
RPN seems so similar to RPL, they're always postfix in RPL.

Quote:
Quote:
On the RPN calculators, these functions (as well as
LBL/GTO/GSB/XEQ) require an appended identifier, generally
numerical, to complete the command.


As I figured out for myself, using them that way in a "True RPN"
calculator has a major advantage in that it doesn't use up a
precious stack level. Now that I've realized what a severe penalty
having them postfix on these models would be, I'm quite satisfied
that having them prefix is indeed the much better choice.

With the RPL models, there are many more non-mathematical
operations, and they take a variety of object types as arguments,
often more than one, and sometimes the number of arguments is
determined by a number supplied as the first argument. Using up a
stack level for each argument is, in some cases, a minor
disadvantage of making them postfix operations. Some
non-mathematical operations also return results of various object
types and numbers of objects, sometimes with a count returned as
the last result. What's more, the + operation can be either
mathematical or non-mathematical, depending on which types of
arguments it finds; should it be postfix or prefix? Perhaps we'd
have to have two separate commands instead of loading so much into
just that one little command.

Quote:
Quote:
On the RPL units, the input identifier must be specified
beforehand, in the interest of uniformity.


The important reason for specifying the arguments before the
non-mathematical operations is functionality, just as it is for
mathematical operations.

In RPL, operations may be invoked from the keyboard, along with
their arguments. Operations may also be within programs, along
with predetermined arguments. If these were the only ways to
invoke non-mathematical opeerations, it would make little
difference whether they were prefix or postfix.

The arguments could also be objects that were on the stack before
the operation or the program containing it was invoked, or input
while a program was waiting for input, as with a PROMPT, INPUT, or
INFORM. They could be objects stored in a variable and retrieved
as needed. They could be objects created by the program that
contains the operations. In these cases, as long as the operations
are postfix, all the user or programmer has to do is ensure that
any arguments are available in the proper locations on the stack
before the operations are executed. This is the same as with
mathematical operations, and the same methods of ensuring the
stack locations are available.

But suppose that an operation is prefix, just because some
arbitrary rule says that certain operations shouldn't be postfix.
I don't have any way to move any object from the stack into the
runstream. What could be done is to allow prefix operations
operations to take name arguments. That way, what I could do is
arrange for the program to store the arguments of the prefix
operation in a variable, and then place the unquoted variable
names immediately after the operations in the program. Dealing
with several named variables is a lot of bother, so I'd like to
allow prefix operations that require more than one object to take
lists instead; but wait, lists are non-mathematical, so operating
on them means using a prefix operation, so using lists is out.
Well, now I'm back to using multiple variables and names.

It could be done, but it seems to me that all of this handling of
named objects is going to take up extra memory both in the program
itself and at run-time, and more execution time. In the case that
the arguments were already in the right location for using them
with postfix operations, the user would still have to go through
the trouble of storing them and placing the names after the
operations,

Why not just make every operation postfix so it can find its
arguments in the most natural place in a stack-based program,
right on the stack? It's been done that way in RPL ever since the
28C was released, and hasn't caused any problem yet.

Quote:
Quote:
Which is easier and more intuitive:
"FIX 5" or "5 (ENTER) FIX"?
"25.4 STO 4" or "25.4 (ENTER) 'R4' STO"?


To me, very much
"5 (ENTER) FIX" and "25.4 (ENTER) 'R4' STO",
although I'd key them in as
"5 FIX and "25.4 'R4' STO";
no sense using an extra keystroke when there's no need for it.
Quote:
As for your boldfaced question,
Quote:
So just what the heck is it that RPN users find so all-fired
"complicated" about RPL?

I'll quote another excerpt from my "Leisure Suit" post:
Quote:
As for RPL programming, compare a sophisticated RPL statement with
an equivalent line in C, Basic, Fortran, or any other high-level
language:
"IF (A .LT. B)  A = A + 360.0"             (Fortran '77)
"<< IF A B < THEN A 360 + 'A' STO END >>" (approximate RPL syntax)


Both are clear enough, but I'd give a slight edge to
"<< IF A B < THEN A 360 + 'A' STO END >>"
I did have to think about whether the Fortran '77 example made
sense.

It's even clearer to me when formatted as:

\<<
IF
A B <
THEN
A 360 +
'A' STO
END
\>>
But if you don't like program structures, how's this:
\<<
\<<
A B <
\>>
\<<
A 360 +
'A' STO
\>>
IFT
\>>
Quote:
(Much to my surprise, that short RPL program I wrote but didn't
test before posting actually did work properly!)

This example underscores my main statement, in that RPL is an
ineffective compromise between a high-level language and a
keystroke-programming system.

When a series of prefix instructions is listed one at a time (like
an RPN program), it essentially looks like an assembly routine.
"Jumps" (GTO) are necessary a part of that.

However, when a series of prefix instructions is listed on a
single line, it just looks scrambled -- nothing like a line of a
high-level-language. Adding IF-THEN-ELSE and other constructs to
prefix instructions just doesn't work, in my estimation.


You've really lost me in that paragraph. What I take away from all
of this is:

  • You don't like to see postfix non-mathematical operations because
    it seems counterintuitive to you.
  • I've given myself a good review of just why postfix operations are
    so important to making a stack-based language easy to use.
  • You find RPL program structures hard to read.
  • In general, you don't like RPL.
Actually, that last point I figured out a long time ago.

Regards,
James


#82

So RPL has postfix syntax for every operation for consistency, and for argument passing efficiency's sake. That's why RPL has 'A B > IF', right?

Oh.. wait.. 8)


#83

Forth, on the other hand is rather consistent :)


#84

Right, IF is a postfix operator in FORTH.

Pardon me, I meant to say 'IS' 'FORTH' 'OP' 'POSTFIX' 'IF'

8)

#85

James --

Your first indented multi-line RPL program is indeed clearer that the one-liner, in my view. Of course, the Fortran '77 program can also be written using multiple lines (and would have to be, if there were an ELSE clause):

IF (A .LT. B)  THEN
A = A + 360.0
ENDIF

(360 is written as 360.0 to avoid mixed-mode arithmetic, although that is not absolutely necessary. Fortran will handle mixed-mode calculations properly.)

Quote:
You've really lost me in that paragraph. What I take away from all of this is:

  • You don't like to see postfix non-mathematical operations because it seems counterintuitive to you.
  • I've given myself a good review of just why postfix operations are so important to making a stack-based language easy to use.

(Of course, I meant "postfix", not "prefix" in the paragraph you referred to. I'm sure that you understood that. My bad...)

I see some merit, but don't fully concur, on the first two points:

I believe that postfix non-mathematical operations (and RPL itself) is conterintuitive to many people, not just myself.

I do concede that a very complicated and "overloaded" function (i.e., multiple functions for one command) may be best to implement as fully postfix.

Quote:
  • You find RPL program structures hard to read.
  • In general, you don't like RPL.
Actually, that last point I figured out a long time ago.

Regards, James


Exactly, and "Right on!" about the last two points.


Now, James, would you care to try my RPL challenge from last year, and provide a solution different from those posted by Arnaud Amiel and Raymond Del Tondo? I'd like to see an RPL program that makes sense to non-RPL'ers as to what exactly is taking place. The structure of the HP-71B solution posted by Valentin was evident, I think, even to those who are not familiar with that machine but have learned any high-level data-oriented language.

Regards,

-- KS


#86

Hi, Karl,

I just happen to be coding my eyes out in RPL right now, and trying to make it easier for me to read. I looked at Arnaud's first two programs in the referenced thread, and I think I can make a version that scans better. I don't know how it will perform relative to the stack based versions however.

Here is some of the setup Arnaud specified:

Quote:
I store SIN(X) in F I store SQ(X-1.5)-1 in G

..

<< RAD F G - DUP 'X' 0 ROOT OVER 'X' 3 ROOT ROT 'X' S >>

S being the integral function.


The program is the second one he wrote. It's stack-oriented gibberish to me. I think this is better:

<< 
RAD @ Set Radians mode
F G - @ Create the expression SIN(X) - (X-1.5)^2 - 1
\-> d \<< @ Store it in 'd'
d 'X' 0 ROOT @ Solve d(X)=0 with intial guess of X=0.
d 'X' 3 ROOT @ Solve with guess of X=3
d 'X' S @ Integrate with respect to X, in the calculated interval
>>
>>

Regards,
Howard

Edited: 18 Nov 2005, 2:37 a.m.


#87

It took me some time to understand it myself but here we are:
<< RAD F G - DUP 'X' 0 ROOT OVER 'X' 3 ROOT ROT 'X' S >>

or

<< 
RAD @Set Radian Mode
F G - @Level 1 is F-G
DUP 'X' 0 @Stack is 4:'F-G' 3:'F-G' 2:'X' 1:0
ROOT @Stack is 2:'F-G' 1:Root1
OVER @Stack is 3:'F-G' 2:Root1 1:'F-G'
'X' 3 ROOT @Stack is 3:'F-G' 2:Root1 1:Root2
ROT @Stack is 3:Root1 2:Root2 1:'F-G'
'X' S @The result
>>
I can now find some ways to improve the program but the stack manipulation would be even more complicated.

Anyway, when programming anything slightly involved in RPL, I need to keep stack diagrams as on the comments above. Note the this example uses a maximum of 4 stack levels and would not be very different on an advaced RPN machine: OVER=RCL Y and ROT=RCL Z

Also note that this is really keystroke programming.

But anyway Howard solution is more directly accessible.

Arnaud


Edited: 18 Nov 2005, 10:44 a.m.


#88

Hi, Arnaud:

Arnaud wrote:

"It took me some time to understand it myself [...]"

    That's the point, indeed. Even the author of the code himself finds it difficult to understand a few lines of RPL code he wrote after a small amount of time has elapsed.

"... but here we are: << RAD F G - DUP 'X' 0 ROOT OVER 'X' 3 ROOT ROT 'X' S >>"

    without the comments you provide below, this line of code seems absolutely messed up, kind of an entry for the "Obfuscated C" contest (not that it would win, mind you !)
"I can now find some ways to improve the program but the stack manipulation would be even more complicated."
    So less apt to be understandable, even in the least, to someone not familiar with RPL, as Karl's challenge posits.
"when programming anything slightly involved in RPL, I need to keep stack diagrams as on the comments above"
    Once again, that's the point. Anything *slightly* involved in RPL means that you have to keep stack diagrams in order not to get lost and more or less find your way through the mess.
On the other hand, I can assure you that, in my extensive, 30-year experience with RPN, I've never found any need at all to keep or write down "stack diagrams". With just 4 levels, always present, and a few simple commands to deal with them, you can keep where everything is in your head ("... this is in LASTX now, and this other result is in T, I need to Rup it, then LASTX and +, ...") and I've *never* felt "lost" or insecure about where some results are on the stack. And if I did, a simple look at the program steps and some mental tracing would be sufficient to keep my bearings.

That's *not* something you can do with RPL, and certainly *not* if you make extensive use of the stack and avoid named variables. And, if you do resort to using them, dispensing with unfathomable stack manipulations, then BASIC is far, far, far more understandable and easy to use, even to RPN/RPL people, as my BASIC version of the above algorithm clearly demonstrates.

RPL may have its good points, if any, but clarity and understandability are not among them.

Best regards from V.


#89

Although I am a strong supporter of RPL, I fully agree with you. Although RPN is not any better.

Quote:
Once again, that's the point. Anything *slightly* involved in RPL means that you have to keep stack diagrams in order not to get lost and more or less find your way through the mess.

I have nearly the same problem when I am working with RPN, just instead of keeping stack level in my mind, I need to keep a table of registers. At least, those usually don't move.

When I have a bit more money, I will try to get myself a 71 and play with basic. However, what I like programming in RPL or RPN is exactly the fact that it is not straightforward. You have 2 challenges first find the algorithm, second code efficiently. With basic, step 2 is not very challengeing. I have spent days improveing a few lines of RPL.

Arnaud who sounds like a masochist :-(


#90

Quote:

I have nearly the same problem when I am working with RPN, just instead of keeping stack level in my mind, I need to keep a table of registers. At least, those usually don't move.


Other platforms call them "variables," 8) They leverage this odd human tendency to associate concrete or abstract things with names. (Like our stack diagrams or register tables help us to do.)

#91

I agree that RPL, as generally employed by the experts, is hard to read. It is also hard to remember what you were doing in a particular fit of impenetrable stack manipulation two weeks after you wrote it. However, I'd like to point out that Arnaud's approach uses at most four levels of the unlimited RPL stack. If you use his translation of OVER as RCL Y and ROT as RCL Z, then you have exactly the same set of manipulations you would have on an RPN stack! Assuming you had an RPN calc that could do symbolic math, a comparison might be as follows:

RPL RPN
=========================
F F
G G
- -
DUP ENTER^
'X' 'X'
0 0
ROOT XEQ 'ROOT'
OVER RCL Y
'X' 'X'
3 3
ROOT XEQ 'ROOT'
ROT RCL Z
'X' 'X'
S XEQ S

I naturally lean toward HP-41 syntax in my pseudo-RPN. 8)

My point is that keeping track of stack levels on an RPN calc can be troublesome, too. RPL is inherently worse for three reasons, IMHO. First, going over four stack levels is evil if you want to have any clarity in your code at all. Second, the RPL models have a richer set of program control structures, and frequently more than one of a particular kind. This allows RPL code to be more convoluted, more readily than RPN. Finally, the RPL calcs are more advanced than their RPN progenitors. This means that stuff you store on the stack can have an arbitrary amount of internal structure, further obscuring what a particular operation does. For instance subtraction in the example code composes a symbolic expression of the difference of two functions of X, not a simple arithmetic difference.

A fourth reason RPL is harder to read is not due to anything inherent in the language. It's the culture of RPL programmers who code it without regard for readibility. You can name your variables in RPL, at the expense of some efficiency, and reduce your dependence on the stack. You can code with comments and nice indentation in a PC file. Unfortunately, both niceties are lost when the text is transferred to the calculator. This would lead me on to a further rant about the usability of the HP-48 as a software development platform, except that I'd rather not root around in that can of worms right now. 8)

Regards,
Howard

Edited: 18 Nov 2005, 12:53 p.m.


#92

Quote:
My point is that keeping track of stack levels on an RPN
calc can be troublesome, too.

Yes, with an RPN model, there are only four stack registers to
keep track of, but things can be "pushed off" of the top of the
stack, and the content of the t register is propagated downward as
things are removed from the bottom (the stack can never be empty).
This may seem very intuitive to RPN programmers, but for someone
who first learned RPL, these are "gotchas". Of course, in RPN
there are also the Last X and storage registers that may be
utilized, in which case the user has to keep track of those too,
and a GSB may be used to call a subroutine, or a GTO to jump
anywhere, so those have to be kept track of.
Quote:
First, going over four stack levels is evil if you want to have
any clarity in your code at all.

Why exactly four stack levels for the maximum? Should we also
impose an arbitrary maximum for the number of storage registers or
variables to be used? Or how deeply program structures or
parentheses can be nested?

It's a matter of how easy it is for the individual programmer to
"see" the stack in his head. The high levels can often be regarded
as objects that are set aside for a while, until the user gets
back to them. Sometimes a large group of objects with a count are
treated as a "meta-object", as when a list or array is "exploded"
onto the stack, or as preparation in making a list or array.

Quote:
Second, the RPL models have a richer set of program control
structures, and frequently more than one of a particular kind.
This allows RPL code to be more convoluted, more readily than RPN.

I don't think that "convoluted" is quite the right word. A program
structure can never begin in one program structure clause and
continue or end outside of that clause. "Overlapping" structures
aren't permitted; any structure has to be entirely within the same
clause of any "outer" structure. You can indeed "nest" program
structures as deeply as you like (available memory allowing), but
you can never "jump" out of a program structure clause early. You
can also call programs by name, and a program may even call
another instance of itself, and execution of the calling program
resumes when the called program is finished. A clause may be
skipped over entirely, but execution always has to return to any
"outer" clause being executed to finish it up. Well, exceptions
being when the structure is within a IFERR clause and an error
occurs, in which case, the return stack is discarded back to the
IFERR structure's marker, and execution resumes with the IFERR's
THEN clause, and when execution is abandoned entirely due to an
error. The compilers enforce the rules, returning an "Invalid
Syntax" error if you don't stick to the rules.

An RPL subroutine is a quoted procedure already placed on the
stack earlier in the program, or a local or global variable,
instead of being jumped to with a GOSUB, as in many other
languages.

Internally, RPL keeps track of where execution is to resume with a
separate return stack. Indeed, the built-in commands (actually
special SysRPL programs) use both stacks heavily. Like the data
stack, the return stack has variable depth, limited only by
available memory. In SysRPL, the programmer has some commands to
work with the return stack, but in UserRPL, the user utilizes the
return stack with program structures and calls to variables, and
may not even be aware of its existence.

Execution can be suspended with the HALT command (or PROMPT or in
the debugger, for examples), in which case the "suspended" program
is kept in memory, ready to be resumed with the current data stack
by CONT or a single-step operation, or abandoned with KILL.

With RPN's GTO, one could develop "spaghetti code". I suppose that
RPL's program structures are intended to prevent developers from
writing such truly "convoluted" code. Some sort of GOTO or BREAK
would indeed be handy in RPL, but offhand, it seems to me that it
would have to be restricted to "jumps" within the same structure
clause, and perhaps to only "forward" jumps, and a GOTO would
require a label or line number, neither of which RPL has. I'm not
against GOTO, but it can be used to make very complicated code.

Quote:
Finally, the RPL calcs are more advanced than their RPN
progenitors. This means that stuff you store on the stack can have
an arbitrary amount of internal structure, further obscuring what
a particular operation does. For instance subtraction in the
example code composes a symbolic expression of the difference of
two functions of X, not a simple arithmetic difference.

Well, whether subtraction returns a number or an algebraic object
depends on what the arguments were, and the state of system flags
for the modes.

But indeed, there are various object types, and a single object
may be a list or program (or other composite) which may itself
contain any other objects. An algebraic object is very similar to
a program object, but is more restricted; it's contents must be
logically equivalent to a valid (for the calculator) algebraic
expression. Arrays aren't composite, as they don't hold objects
complete in themselves, but they might be thought of as containing
(among other information) "object bodies".

Quote:
A fourth reason RPL is harder to read is not due to anything
inherent in the language. It's the culture of RPL programmers who
code it without regard for readibility.

There's some truth to this. What may be obvious to the programmer
may be very obscure to others, particularly to beginners. A public
discussion among "experts" may well be impenetrable to those who
don't have the knowledge required to understand it. When answering
a question, it may be difficult to guess how much the person
asking already knows, and tailor the response appropriately.

Some will just post a compiled program or library on hpcalc.org
for example, without bothering to include source code or explain
how it works internally. Presumably, these are meant to be
"useful" rather then "educational". Of course, others may
decompile it back to source code if they know how, and nothing can
document the code as accurately as the code itself, although it
may indeed be very difficult to understand without comments or at
least the original source code.

In "challenges", the object is usually to develop the smallest or
fastest program to accomplish a desired objective, so obscure
"tricks" are often used without any regard for readability or
explanation of just why it works.

Quote:
You can code with comments and nice indentation in a PC file.

And in the command line editor, for that matter.
Quote:
Unfortunately, both niceties are lost when the text is transferred
to the calculator.

As you probably know, these niceties are discarded because source
code is compiled to an object (or objects). Compiling discards all
source code delimiters, comments, separators, and indeed even the
source code "words" are replaced in most cases. Every object
begins with a prologue (actually, a prologue address), a location
pointer to the system code (the actual prologue) that tells the
system what type of object it is, how to handle it, and how to
find its end. That said, as implemented so far, the end of any
composite object is delimited with an object pointer to the
system's primitive code object SEMI.

RPL source code is largely "free form", except that a Line Feed
code (but not other separators) ends any comment (which can also
be ended with another "@" character). A comment also functions as
a separator. Separators (or series of separators) are otherwise
logically equivalent. One could use a separate line for every
"word" or comment, with indenting optional, or could make the
entire source code a single line, as long as it doesn't contain a
character string with an embedded Line Feed code. Even a Line Feed
within a string in a source code file may be written as the
character translation sequence \010, as long as translation mode 2
or 3 is used.

Programmers use a variety of styles for their source code. There's
no one "right" way to do it; it's rather a matter of what the
programmer considers readable. The calculators' command line
editor decompilers choose to start an indented new line for every
structure word or embedded program, but then continue the line up
to the display width and start subsequent lines at the left margin
until the next structure word, presumably to fit more information
into the calculator's limited display area while still giving some
idea of the structure. Sometimes source code is posted online
exactly as the calculator decompiles it, or the poster writes it
on the PC and doesn't bother formatting it for easy readability.

On a calculator, I mostly follow the decompiler's example, except
that I usually put any structure word or program delimiter on its
own line, except for putting the index name on the same line as
FOR. In a source code file on the PC, I tend to use "multi-line"
source code and indent the contents of a clause for the entire
clause, but sometimes put a short program structure or subprogram
on a single line. I tend to put things that seem to logically go
together, such as arguments and the operator, on the same line, if
I don't want separate comments for them. Just how I format and
comment source code depends on who I intend to have read it. For
my own use, I may well consider the source code to be
self-documenting with no or very little need for comments. For
posting online, I may well go to the trouble of extensive
commenting. For projects that seem as if they're going to be
complicated, I sometimes write comments as an outline before
writing any source code.

If you really want to preserve your nice indentation and comments,
you can write the source code within a character string. That way
the calculator compiles it to a character string object,
preserving the source code as written (or in the case of a "text"
transfer, optionally "as translated").

You can't very well have an unescaped " within a quoted-delimited
string, but a counted string form may be used for this. NUL marks
the end of the command line, so the calculators (mostly) prevent
an actual NUL from being used within the command line. For the 49
series, within a quote-delimited string, \00 can be used instead
of NUL, \" is used for ", and \\ is used for \. The 49 series
still compiles counted strings exactly as the 48 series does, but
never decompiles to the counted string form, instead using the new
"escaped" forms for decompiling NUL, ", and \. Note that 49G ROM
versions prior to 1.19-6 incorrectly compile the \00 to 00 instead
of NUL. Within a quote-delimited string, all characters except (on
the 49 series) the \00, \", and \\ sequences and \ are treated as
literal. Within a counted string, all characters are treated as
literal. Note that Conn4x has its own rules for these characters,
and can be "confused" by a \ character outside of a
quote-delimited string, mistaking it for the beginning of a
character translation sequence.

To "execute" the source code string, put it on the stack and
execute STR\-> or OBJ\->, which compiles it to an object. If it's
a "quoted" object, for example with program delimiters, you'll
need to use EVAL to pop it off the stack and actually execute its
contents. For convenient viewing on a calculator, you'd probably
want to adjust the style to fit the display, without any
horizontal scrolling to see a whole line.

So why is source code compiled? I suppose for one thing, the
compiled object nearly always uses less memory than the source
code. Then too, at run-time, the calculator doesn't have to parse
stored code from a form that's easy for a human to read to a form
that's easier for the system to execute. For source code in the
command line, compiling is a step in the execution sequence. To be
sure, the calculator does have to decompile objects for display,
\->STR. printing, and text transfers.

The developers also probably expected the users to be writing
mostly short programs, and perhaps calling other short programs by
name. Having a set of "utility" programs for other programs to
call may indeed make sense, but that introduces a dependency tree;
purging a program or changing what it uses for arguments or what
it returns affects anything else that calls it, directly or
indirectly. For an online example, any program that the example
depends on has to be included (or at least its inputs and outputs
described) for the source code to make sense to others.

RPL is indeed somewhat "different" from classic RPN. It uses a
variable depth stack instead of a 4-register stack, execution
control is restricted to "program structures" instead of jumping
just anywhere with GTO, and they have various other differences.

What I can't see is that RPL is necessarily "complicated" to use.

Regards,
James

#93

Arnaud,

you just proved that you got lost:

Quote:
Note the this example uses a maximum of 4 stack levels

Here is the Problem:

Quote:
OVER             @Stack is 3:'F-G' 2:Root1 1:'F-G'
'X' 3 ROOT @Stack is 3:'F-G' 2:Root1 1:Root2

Just before the command ROOT is executed, the stack holds the following items:

5:'F-G' 
4:Root1
3:'F-G'
2:'X'
1:3

It's not a problem of your code because the RPL stack has enough levels, but your reasoning that 4 levels were sufficient is certainly wrong.

Marcus


#94

Quote:

Just before the command ROOT is executed, the stack holds the following items:

5:'F-G' 
4:Root1
3:'F-G'
2:'X'
1:3


Oops! That renders my RPN translation invalid too.

I suppose Arnaud can be forgiven for missing a 4-item stack limit. His platform doesn't enforce such a limit. I on the other hand have no such excuse.

On the other hand, missing the stack overflow doesn't invalidate my main point, which is that RPN and RPL really are similar at a certain level. Many common RPL stack manipulations have direct RPN equivilants.

Edited: 18 Nov 2005, 5:12 p.m.

#95

Quote:
you just proved that you got lost:

Oops!!!

As I said above, I NEVER argued that RPN was straightforward and that quickly keeping stack diagram become necessary. But I also keep stack diagrams in RPN (maybe a bad habit I got from RPL)

Arnaud

#96

Karl,

Quote:

Your first indented multi-line RPL program is indeed clearer that
the one-liner, in my view. Of course, the Fortran '77 program can
also be written using multiple lines (and would have to be, if
there were an ELSE clause):

IF (A .LT. B)  THEN
A = A + 360.0
ENDIF

And that's clearer to me than the Fortran '77 one-liner.
Quote:
Now, James, would you care to try my RPL challenge from last year,
and provide a solution different from those posted by Arnaud Amiel
and Raymond Del Tondo? I'd like to see an RPL program that makes
sense to non-RPL'ers as to what exactly is taking place. The
structure of the HP-71B solution posted by Valentin was evident, I
think, even to those who are not familiar with that machine but
have learned any high-level data-oriented language.

I thought the examples posted before demonstrated that RPL was
easiest to understand, but why not?

First off, the way you described the challenge isn't entirely
clear to me. Should the two expression be defined separately, and
should they be "user-defined functions"? I chose to combine them
into one expression. Also, should there be three separate
programs, one that finds the lower limit, one that finds the upper
limit, and finally one that calls the other two and finds the
area, or should it all be combined into a single program? I chose
the single program,

An assumption: It's already known that there's exactly one
intersection point between X=0 and X=1, there's exactly one
intersection point between X=2 and X=3, and there are no
intersection points between these two. This can be verified easily
enough by plotting.

My examples are slightly "unfriendly" in that they purge global
variables named 'X' and 'IERR' without restoring the originals. I
don't like to do that, but in this case, restoring them would be
more likely to mislead the user than to be useful.

They are "friendly" in that they follow good practice and restore
modes that they may change, and also, they label the results. They
also show the "Error of integration", an estimate of how far the
result may differ from the true value. Commenting may well be to a
ridiculous degree, but that's for the benefit of those who are
less familiar with RPL.

In case anyone wants to try them out, copy the source code
(starting with the Kermit ASCII transfer headers) to files, and
simply transfer the files to any 48/49 series calculator. They
should still work on the 49 series if you download them in
approximate load, but the results from the BYTES command will be
different.

For all models, both programs return the following:

In 6 FIX mode:

X lower: 0.343717
X upper: 2.696175
Area: 3.110575
Err Int: 0.000003

In STD mode:

X lower: .343717423063
X upper: 2.69617505788
Area: 3.11057476957
Err Int: 3.11076465583E-11

This first program doesn't use local variables. It uses only a few
stack levels, so it's easy to see where everything is.
%%HP: T(3)A(D)F(.);
@ Note: Will purge variables X and IERR from current directory!
@ For 49 series, download with calculator in exact mode.
@ Results from BYTES command:
@ 49g+ Checksum: D86h
@ 49g+ Size: 221.
@ 49G Checksum: D86h
@ 49G Size: 221.
@ 48GX Checksum: 9A2Eh
@ 48GX Size: 221
@ 48SX Checksum: 9A2Eh
@ 48SX Size: 221
\<< @ Begin Program.
RCLF @ Get current flags.
RAD @ Force radians mode.
-3 SF @ Force numerical integration.
'SIN(X)-((X-1.5)^2-1)' @ Expression.
'X' @ Global variable name.
DUP2 @ Make copies.
{1 0} @ Guesses for lower limit.
ROOT @ Find lower limit.
3 PICK @ Expression.
3 PICK @ Global variable name.
{2 3} @ Guesses for upper limit.
ROOT @ Find upper limit.
DUP2 @ copy limits.
6 ROLL @ Expression.
6 ROLL @ Global variable name.
\.S @ Integrate.
ROT @ Lower limit.
"X lower" \->TAG @ Label Result.
ROT @ Upper limit.
"X upper" \->TAG @ Label Result.
ROT @ Area.
"Area" \->TAG @ Label Result.
IERR @ Error of integration.
"Err Int" \->TAG @ Label Result.
{ X IERR } PURGE @ Clean up global variables.
5 ROLL @ Original flags.
STOF @ Restore flags.
\>> @ End program.
On the 49 series, "3 PICK" could be replaced with "PICK3".

Some approximate timings, in seconds:

Model 6 FIX mode STD mode

48SX 12.72 20.54
48GX 8.84 13.20
49G 15.98 26.45
49g+ 6.80 11.52

Some interesting things about the timings:
  • As should be expected because its processor speed is higher, the
    48GX is faster than the 48SX.
  • The 49G is even slower than the 48SX. Maybe this is because of the
    CAS? Well, that's progress.
  • The 49g+ is fastest, but not by as much as might be expected;
    remember that the Saturn processor is emulated (simulated?) in
    firmware.
This second program doesn't use any stack manipulation commands at
all, using local variables instead. But I didn't attempt to
restrict the stack use to any particular number of levels, so it
wouldn't work with a 4-level stack.
%%HP: T(3)A(D)F(.);
@ Note: Will purge variables X and IERR from current directory!
@ For 49 series download with calculator in exact mode.
@ Results from BYTES command:
@ 49g+ Checksum: 3C8Bh
@ 49g+ Size: 316.5
@ 49G Checksum: 3C8Bh
@ 49G Size: 316.5
@ 48GX Checksum: CFC9h
@ 48GX Size: 316.5
@ 48SX Checksum: CFC9h
@ 48SX Size: 316.5
\<< @ Begin program.
RCLF @ Get current flags.
'SIN(X)-((X-1.5)^2-1)' @ Expression.
0 @ dummy value for l.
0 @ dummy value for u.
0 @ Dummy value for a.
\-> @ bind local variables.
f @ Original flags.
b @ Expression.
l @ Lower limit.
u @ Upper limit.
a @ Area.
\<< @ begin defining procedure for
@ local environment,
RAD @ Force radians mode.
-3 SF @ Force numerical integration.
b @ Expression.
'X' @ Global variable name.
{1 0} @ Guesses for lower limit.
ROOT @ Find lower limit.
'l' STO @ Save lower limit.
b @ Expression.
'X' @ Global variable name.
{2 3} @ Guesses for upper limit.
ROOT @ Find upper limit.
'u' STO @ Save upper limit.
l @ Lower limit.
u @ Upper limit.
b @ Expression.
'X' @ Global variable name.
\.S @ Integrate.
'a' STO @ Save area.
l @ Lower limit.
"X lower" \->TAG @ Label Result.
u @ Upper limit.
"X upper" \->TAG @ Label Result.
a @ Area.
"Area" \->TAG @ Label Result.
IERR @ Error of integration.
"Err Int" \->TAG @ Label Result.
{ X IERR } PURGE @ Clean up global variables.
f @ Original flags
STOF @ Restore flags.
\>> @ Abandon local environment.
\>> @ End Program.
Some approximate timings, in seconds:
Model   6 FIX mode      STD mode

48SX 12.76 20.58
48GX 8.95 13.32
49G 16.04 26.51
49g+ 6.81 11.50

This program is slightly slower than the first program in most
cases, but actually slightly faster for the 49g+ in STD mode.

Regards,
James


#97

...James and Howard for your responses.

James Prange's documented programs and benchmarking were quite an endeavor, and should be recognized. I did find the second one (with minimal stack manipulation) easier to follow.

Howard Owen's program is a bit closer to what I was looking for -- a concise but "followable" method of obtaining the answer.

I'll try both after I figure out what the "\" is representing...

Regards,

-- KS


#98

That's how the HP-48G renders "special" characters when programs are translated to ASCII. The most common ones are:

  ASCII     48G character
--------------------------------------------------------------------
\<< The "start program" sigil. It looks like "<<" but it's one character.
\>> The "end program" sigil. As above.
\-> The arrow operator. You see it alone marking a local variable
list. It also shows up in things like "\->LIST",
(the to list" operator) and "LIST\->" (the "from list"
operator.)

There are others, Like \=/ is the "not equal" sign, I believe.

I used the escape symbol inconsistently in my example, whereas James was consistent throughout his. Although my solution may have been more succinct, I will look back on his for coding examples!

Regards,
Howard

Edited: 20 Nov 2005, 4:19 p.m.

#99

Quote:
I'll try both after I figure out what the "\" is representing...

Actually, if you paste the source code, beginning with the

%%HP: T(3)A(D)F(.);
Kermit ASCII transfer header, to a file and download the file to
your calculator, then the calculator (or Conn4x, if you use that)
will know what they represent.

The header also specifies the unit for angular values in vectors
and complex numbers in CYLIN and SPHERE modes, and how the period
and comma characters should be compiled.

As Howard noted, the "\" represents the beginning of a translation
sequence for certain "special" characters; more specifically, for
non-ASCII characters, and the ASCII character "\" itself would be
represented as "\\". These are often referred to as "backslash
digraph" or "trigraph" codes. With translation mode 3, the
decompiled (source code string) form of an object is "translated"
to "pure ASCII" code for transfer to the PC. If you do much
writing of calculator source code in text files on the PC, then
you'll probably soon memorize the ones that you use frequently.

An alternative is to use an editor that uses a special character
set matching the calculator's, and presents you with a pick-table
of characters, or even a pick-table of commands, but I find it
easiest to just type in the translation sequences.

I suppose that one could memorize how the non-ASCII characters map
between the calculator's and text editor's character sets,
memorize their numeric values, and type them in with the Alt
numeric keypad method. Or one could have the character set tables
at hand for reference, instead of memorizing them. I'd rather not
even attempt this.

If one were to use non-ASCII characters literally in a source code
file, then it would be a problem posting them online, although
I've seen this done. It's unlikely that the reader would be using
the same character set for these, and MS Windows (or the
newsreader or other internet software?) seems to apply some
translations of its own. With "pure US ASCII" code, it's a good
bet that anyone else will see the same thing.

"\<<" and "\>>" represent the characters for the UserRPL program
delimiters, "\->" the "right arrow" character, and "\.S" the
character for the integrate command.

I use these, first off, because it's easier for me to type these
characters in source code as mode 3 translations, and second,
because it makes it easier for others to download the source code
to a calculator with no need for "fixing up" these characters.

I believe you have a 48G series? For this model, the character
translations are described in the User's Guide; see pages 27-15
and 27-16. For the 48S series, see the single-volume Owner's
Manual pages 33-6 and 33-7 or the two-volume Owner's Manual pages
626 and 627. Unless it's in the new AUR, the 49 series
documentation seems to lack this information, see
http://holyjoe.net/hp/tiotable.png for codes 128-255.

There are 4 translation modes, set with the TRANSIO command or by
editing the last element of the reserved variable IOPAR. For the
49 series, note that the numbers in IOPAR and PRTPAR must be "real
numbers", not "exact integers". Mode 0 doesn't translate anything.
Mode 1 translates Line Feed codes (used as "New Line" codes on the
calculator). Mode 2 adds translation of non-ECMA 94 codes 128-159
and \ itself, and for transfers back to the calculator, \nnn codes
\000-\159. Mode 3 adds translation of the rest of the non-ASCII
codes (160-255), and for transfers back to the calculator, can use
all \nnn codes \000-\255.

For generating a character string that shows the translations for
non-ASCII characters in the current translation mode on a
calculator, you could try one of these UserRPL programs. The
"binary" values will be in the current mode, BIN, OCT, DEC, or
HEX. "\010" represents a string containing the Line Feed (New
Line) character.

Approximate timings, in seconds:

48SX: 23.45
48GX: 16.87
49G: 17.26
49g+: 6.25

Be sure to choose the right program for your model. The wrong
address for SYSEVAL is likely to be disastrous!

%%HP: T(3)A(D)F(.);
@ For 49 series only!
@ Download with calculator in exact mode.
@ Results from BYTES command:
@ Checksum: # A162h
@ Size: 116.5
\<<
"" @ Start with an empty string.
128 255 @ For each non-ASCII value.
FOR n
"\010" @ Start a new line.
n @ The decimal value.
" " @ A space.
OVER @ The value from level 2.
R\->B @ Convert value to "binary".
OVER @ The space from level 2.
+ @ Concatenate levels 1 and 2.
PICK3 @ Decimal value from level 3.
CHR @ Convert value to string.
PICK3 @ Space from level 3.
OVER @ String from level 2.
# 2F34Eh SYSEVAL @ KVIS for 49 series only!.
+ + + + + + + @ Concatenate levels 1-8.
NEXT @ Loop for next value.
"\010" @ End with a new line.
+ @ Concatenate the new line.
\>>

Note that if you view the decompiled form of the string (by using
LeftShift CursorDown), then each \ will be doubled.

%%HP: T(3)A(D)F(.);
@ For 48 series only!
@ Results from BYTES command:
@ Checksum: # 58A5h
@ Size: 128.5
\<<
"" @ Start with an empty string.
128 255 @ For each non-ASCII value.
FOR n
"\010" @ Start a new line.
n @ The decimal value.
" " @ A space.
OVER @ The value from level 2.
R\->B @ Convert value to "binary".
OVER @ The space from level 2.
+ @ Concatenate levels 1 and 2.
3 PICK @ Decimal value from level 3.
CHR @ Convert value to string.
3 PICK @ Space from level 3.
OVER @ String from level 2.
# 2FEDDh SYSEVAL @ KVIS for 48 series only!
+ + + + + + + @ Concatenate levels 1-8.
NEXT @ Loop for next value.
"\010" @ End with a new line.
+ @ Concatenate the new line.
\>>

If the 48 series was in BIN mode while generating the string, then
you'll have to scroll right to see the end of the translation
sequence for characters converted to the \nnn form, but nnn will
be the same as the decimal value anyway.

Viewing the string in the 48 series' command line editor seems
annoyingly slow.

Once generated, the string could be stored in a variable.

Of course, the above programs are optimized for size and speed,
not for readability. I used KVIS, which the calculators use for
printing "via wire", but I could as well have used KVISLF. which
the calculators use for Kermit ASCII transfers. The program goes
back to when the 48SX was current, and I really don't recall why I
wrote it exactly as I did, but it works.

The documentation is wrong about control code <LF>. <LF> is
translated to a <CR><LF> pair, not to a <LF><CR> pair. Here <LF>
means Life Feed, ASCII 10 (decimal), and <CR> means Carriage
Return, ASCII 13.

What's more, the Kermit translation is buggy for <CR><LF>.
Although <LF> is translated to Kermit's canonic <CR><LF> line
termination string, a <CR><LF> pair is left as is instead of being
translated to <CR><CR><LF>. That is, both <LF> and <CR><LF> are
sent to the PC as <CR><LF>, and when sent back to the calculator,
both are translated to <LF>. Of course, text editors may change
the "end-of-line" codes too. To make these unambiguous in a
character string in a text file, you can use \010 for <LF> and
\013 for <CR>. This isn't a problem unless you really do, for
whatever reason, want a <CR><LF> pair within a character string on
the calculator. As far as I've been able to determine, this is the
only bug in the Kermit translations.

With Kermit, for transfers to a calculator, a \ that isn't the
beginning of a valid translation sequence is left as is. For that
matter, anything that isn't a valid translation sequence is left
as is.

An additional consideration on the 49 series is that NUL (ASCII
control code 0, the "null character"), ", and \ within a character
string are decompiled to \00, \", and \\, so after the Kermit
translation, show up in the file as \\00, \\", and \\\\. But
Conn4x handles these differently; see the Conn4x Help for the
differences, and for information on how it translates between
global variable names and MS Windows file names.

Also note that with 49G ROM revisions prior to 1.19-6, \00 within
a source code character string is incorrectly compiled to 00
instead of to NUL.

The 49 series compiler simply discards a \ within in a character
string if it isn't immediately followed by 00, ", or another \.

Conn4x doesn't use the calculators' built-in translation routines,
instead doing the translations in the Conn4x application on the
PC. It doesn't have Kermit's problem with <CR><LF>, and optionally
translates ASCII control codes 0-9, 11-31, and 127 to \nnn
sequences, but apparently in attempting to "simplify" the
translations of the decompiler's \00, \", and \\, it introduces a
new bug. Outside of a quote-delimited string, Conn4x leaves \ as
is, instead of translating it to \\. For transfers back to the
calculator, Conn4x may mistake an untranslated \ for the beginning
of a valid translation sequence. To work around this bug, change
any \ in the file that could be misinterpreted to \092, which
Conn4x correctly translate back to \. Note that the 48 series use
a counted string form for decompiling strings with an embedded ",
and the \ could occur in these, and \ is perfectly valid in a
name.

To be sure, these bugs should rarely be a problem, but they've all
"bitten" me.

<plug>
You could also see my "ASCII on SD" programs for converting
between a compiled object and a decompiled (and optionally
translated) source code string on a 49 series. Converting a
commented source code string returns both a translated but still
commented source code string and the compiled object. They're
available
here.
These are intended for the 49g+ specifically, and wouldn't work on
the 48 series as written. I prefer to use the card and these
programs for the 49g+ instead of using Conn4x.
</plug>


Regards,
James

Hi, James:

James posted:

"I thought the examples posted before demonstrated that RPL was easiest to understand, but why not ?"

    Are you serious ?
"This first program doesn't use local variables. It uses only a few stack levels, so it's easy to see where everything is.
[...] DUP2 [...] 3 PICK  3 PICK [...] DUP2 6 ROLL 6 ROLL  
[...] ROT [...] ROT [...] ROT [...] 5 ROLL [...]
"

    Again, are you serious ?
"This second program doesn't use any stack manipulation commands at all, using local variables instead."
<< RCLF 'SIN(X)-((X-1.5)^2-1)'  0   0   0   \->   
f b l u a << RAD -3 SF b 'X' {1 0} ROOT 'l'
STO b 'X' {2 3} ROOT 'u' STO l u b 'X' \.S
'a' STO l "X lower" \->TAG u "X upper" \->TAG
a "Area" \->TAG IERR "Err Int" \->TAG { X IERR } PURGE
f STOF \>> \>>

    So, even without using obfuscating stack manipulations, are you
    suggesting that that load of gibberish above is clearer than:
     10 DEF FNF(X) = SIN(X) - (X-1.5)^2 + 1 
    20 PRINT INTEGRAL( FNROOT(0,1, FNF(FVAR)), FNROOT(2,3, FNF(FVAR)), 1E-5, FNF(IVAR))
    which essentially is:
     Define  f(x) = Sin(x)-(x-1.5)2 +1 
    Print Integral( Root(0,1, f(x)), Root(2,3, f(x)), precision, f(x))
    so that your non-stack-based RPL version is equally clear or even clearer to a non-RPL (or even RPL) programmer than the one for the 71B ? (notice that it doesn't even use variables at all, local or not, except for the dummy, placeholder variable in the definition of f(x) itself).

    If you're stating this and you're serious, then it's clear to me we have significant differences about what "clarity" means, to the point that mutual understanding seems not possible.

Best regards from V.

Edited: 21 Nov 2005, 5:40 a.m.


Yes, I am indeed quite serious. As for why, I suppose first
because my examples use postfix notation, which I'm accustomed to
using on a calculator, and second, because I'm used to seeing a
few stack levels in my mind. I suppose it depends on who's looking
at the code, though.

I could simplify them by not restoring modes, returning the
limits, labeling results, or cleaning up the global variables.

%%HP: T(3)A(D)F(.);
\<< @ Begin Program.
RAD @ Force radians mode.
-3 SF @ Force numerical integration.
6 FIX @ Force precision for integration.
'SIN(X)-((X-1.5)^2-1)' @ Expression.
'X' @ Global variable name.
DUP2 @ Make copies.
{1 0} @ Guesses for lower limit.
ROOT @ Find lower limit.
3 PICK @ Expression.
3 PICK @ Global variable name.
{2 3} @ Guesses for upper limit.
ROOT @ Find upper limit.
4 ROLL @ Expression.
4 ROLL @ Global variable name.
\.S @ Integrate.
\>> @ End program.
Or using a local variable for the expression to avoid using any
stack manipulations at all:
%%HP: T(3)A(D)F(.);
\<< @ Begin program.
'SIN(X)-((X-1.5)^2-1)' @ Expression.
\-> @ bind local variables.
b @ Expression.
\<< @ begin defining procedure for
@ local environment,
RAD @ Force radians mode.
-3 SF @ Force numerical integration.
6 FIX @ Force precision for integration.
b @ Expression.
'X' @ Global variable name.
{1 0} @ Guesses for lower limit.
ROOT @ Find lower limit.
b @ Expression.
'X' @ Global variable name.
{2 3} @ Guesses for upper limit.
ROOT @ Find upper limit.
b @ Expression.
'X' @ Global variable name.
\.S @ Integrate.
\>> @ Abandon local environment.
\>> @ End Program.
Consider your BASIC program:
10 DEF FNF(X) = SIN(X) - (X-1.5)^2 + 1
20 PRINT INTEGRAL( FNROOT(0,1, FNF(FVAR)), FNROOT(2,3, FNF(FVAR)), 1E-5, FNF(IVAR))
Line 10 defines f(x) clearly enough.

In line 20, we're going to find the integral of something, with
the arguments following. But the first argument isn't a number,
it's another function,

FNROOT(0,1, FNF(FVAR))
with the arguments following again, apparently 2 guesses and then
a nested function,
FNF(FVAR)
again with the argument following, What could the arcane-looking
FVAR represent? Well, that more or less takes care of the first
argument, and the second argument is like the first argument
except with different guesses.

The third argument is simply a number for the precision.

The fourth argument looks like another function,

FNF(IVAR)
again with the argument following. What could IVAR mean, and how
does it differ from FVAR?

Okay, now that I've muddled through the arguments, I can recall
that they were supposed to be integrated.

Granted, part of my problem with all this is not being familair
with the keywords, but are you seriously saying that all those
nested parentheses are clearer than straight-forward postfix
notation? If I found that clearer, then I'd probably be using the
49 series in ALG mode.

Regards,
James

Edited: 21 Nov 2005, 5:09 p.m.


Hi, James:

James posted:

"Consider your BASIC program: ..."

    Ok, let's.
"What could the arcane-looking FVAR represent?"
    FNROOT (FiNd ROOT) can call itself to solve a non-linear system of several unknowns. As such, you need a formal variable to stand for the particular variable you're solving for. You can't name it "X", say, because perhaps you're solving for "Y" or for "E7", say, and perhaps you already do have a local or global variable called "X".

    That being so, FVAR (Function VARiable) stands for the variable you're solving for.

"What could IVAR mean, and how does it differ from FVAR?"
    INTEGRAL (Integral) can call itself to compute a multiple integral over several variables. As such, you need a formal variable to stand for the particular variable you're integrating over. You can't name it "X", say, because perhaps you're integrating over "Y" or over "E7", say, and perhaps you already do have a local or global variable called "X".

    That being so, IVAR (Integration VARiable) stands for the variable you're integrating over.

    As you can Integrate a function being Solved or Solve a function being Integrated, their respective formal variables *must* differ, so that's why one is called FVAR, and the other, consistently enough, is called IVAR, so as not to get confused in an integral being solved, say.

"Granted, part of my problem with all this is not being familair with the keywords, but are you seriously saying that all
those nested parentheses are clearer than straight-forward postfix notation?"

    There's no such thing as "straight-forward postfix notation", that's actually a contradiction of terms. That's why the vast majority of people find RPL "RePeLent" and wouldn't touch it with a ten-feet pole.

    That being so in the mind of most people, yes, I'm serious when I state that all your code posted above, commented and optimized several times, in several flavors, is much less clearer that my one-and-only, uncommented, never optimized BASIC line, which I wrote down without even thinking about it for a moment, that automatic and straightforward the task at hand is.

    Nay, it's too simple to be considered a *program*, I gave it a line number because the original challenge asked for a program, but actually it's an immediate command-line expresion, in the same league as 2+2, say.

    And I notice that you refrained from commenting several key features of both solutions, probably because you were on the losing side, namely:

    • My 71B BASIC version uses *no* local or global variables at all, so it's that much easier to set up and no chance for variable-related conflicts. No need to change or set up environments, etc.

    • I notice in your code that you "Force precision for integration.", and that consists in changing the display mode. Now, why on earth should you have to do the wholly unrelated task of changing the display mode just in order to specify some precision for your integration process ? and with the side effect of changing the display mode to the user, no less ?

      If you want to specify a particular precision, why, just do it, include the desired precision as a parameter to the integration process, which is just what my BASIC version does. Remember, we're talking about someone who's trying to fathom what the code does, and changing display modes instead of explicitly specifying a desired accuracy seems much more obscure, arbitrary, and less clean to me.

Anyway, entering this kind of threads is mostly a waste of time, because there's no way I (or anyone else) can convince you with arguments or examples, no matter how obvious or clear. If you, subjectively, find your code or RPL in general clearer, that's the way it's going to be to you, and nothing will change that.

Fine with me, to each his own. But then don't be surprised if you find that the vast majority doesn't agree with your concepts.

(Oh, and by the way, replicating the top register in classic 4-level RPN is not a bug or quirkiness or anything like that. It was done on purpose, by design, because thanks to that valuable feature you can evaluate polynomials of arbitrary degree extremely efficiently (Horner's rule), which you couldn't were it not for it. And, as you know, these advanced RPN calculators were originally designed for engineers by engineers, and at the time, real engineers found themselves evaluating polynomials constantly, and needed to do it fast, simply, and efficiently, even if they had a non-programmable model. That's why.)

Best regards from V.

Edited: 22 Nov 2005, 7:56 a.m.


Hi Valentin,

I really didn't want to get in a flame war over this. I perceived
your posts as particularly hostile and responded in kind. I'm
sorry that I didn't restrain myself.

I'm not claiming that RPL is perfect, it does have flaws and
quirks. Even more so in the 49 series, although they did add some
nice features there.

And I rather like BASIC too, but when the argument list has nested
parentheses, it looks obfuscated to me.

Quote:
FNROOT (FiNd ROOT) can call itself to solve a
non-linear system of several unknowns. As such, you need a formal
variable to stand for the particular variable you're solving for.

Agreed.
Quote:
You can't name it "X", say, because perhaps you're solving for "Y"
or for "E7", say, and perhaps you already do have a local or
global variable called "X".

Other than the problem of possibly overwriting a variable with the
same name, I don't see any reason why whatever name I'm solving
for couldn't be used. I've never particularly liked RPL's
root-finding methods potentially overwriting a global variable,
but it goes back to the RPL solver, where the user sees the
variable names in the menu, and knows that they'll be used as
global variable names. It has the advantage that the values will
be persistent, (until purged or overwritten) and I don't see it as
especially harmful.
Quote:
That being so, FVAR (Function VARiable) stands for
the variable you're solving for.

I gather that FVAR represents the X in your FNF(X)? Sort of like a
reserved variable in RPL?
Quote:
As you can Integrate a function being Solved or Solve a function
being Integrated, their respective formal variables *must* differ,
so that's why one is called FVAR, and the other, consistently
enough, is called IVAR, so as not to get confused in an integral
being solved, say.

You're saying that solving and integrating are occurring at the
same time? Yes, I know within the same "outer" function, but in
your program for example, I'd think that both limits must be
completely solved before integration could proceed.

But whatever your 71B needs is fine with me. In RPL, ROOT isn't a
function, so couldn't be used in an algebraic form of the integral
function even if I wanted to do so.

Quote:
There's no such thing as "straight-forward postfix
notation"
, that's actually a contradiction of terms.
That's why the vast majority of people find RPL
"RePeLent" and wouldn't
touch it with a ten-feet pole.

Isn't RPN (mostly) postfix too? How do the vast majority of people
find that?
Quote:
That being so in the mind of most people, yes, I'm
serious
when I state that all your code posted above,
commented and optimized several times, in several flavors, is
much less clearer that my one-and-only, uncommented, never
optimized
BASIC line, which I wrote down without even
thinking about it for a moment, that automatic and straightforward
the task at hand is.

Good for you! I'm glad that you're so familiar with your
calculator!

The comments are intended as a courtesy to anyone who doesn't
immediately recognize the keywords, know the syntax of the
commands, or has trouble picturing the stack. I certainly don't
need them for myself.

Since some seem to have trouble seeing a stack of over four
levels, I chose to write one program the way I prefer, using just
the stack, and another using no stack commands, but local
variables instead. Then, of course, you expressed your opinion, so
I edited them down to simplified versions just for you.

Karl's "challenge" isn't very clear to me as posted, but I decided
to have the program return more than was actually required, since
it was already available, and tag the results.

I did have some problems. First off, I seldom integrate anything,
so I had to look up the syntax for the integral function. I tried
that out on the 48GX, and it worked just fine, I solve for roots
and intersections often enough, but I normally use the solver for
that, so I also had to look up the syntax for ROOT, and that too
worked fine on the 48GX. Okay, everything seemed clear enough, so
I wrote the program in the text editor on the PC, commented it,
and transferred it to the 49g+. But it didn't work. It gave me a
"Bad Argument Type" error for the integral function. Looking over
the program, everything seemed right. Well, sometimes the 49
series doesn't behave the same as the 48 series. Maybe because it
was trying symbolic integration? So I stuck in the -3 SF, which
didn't help, and I forgot to remove it. Maybe something else about
that blasted CAS mucking things up? So I transferred it to the
48GX and tried it there, and it still didn't work. Double-checked
the syntax for the integral function and single-stepped the
program in the debugger. Sure enough, that's exactly where it
failed, although the arguments on the stack sure looked right to
me. Fooled around with the integral function by itself, and
finally realized that although it works fine with real numbers for
the limits, it fails with tagged real numbers there! Now that's
really out of the ordinary; I don't think I've ever seen another
case where a command didn't work correctly with a tagged argument.
It sure seems like a bug to me. Well, that pretty well meant that
there was no use tagging the limits until the integration was
finished, so back to the text editor to rewrite the source code.
This time, it worked perfectly on the first try on all of my 48
and 49 models. So I edited a copy to the version using local
variables, and that worked perfectly the first time. When I edited
copies down to the "special" versions, they worked the first time.

So are they "optimized several times"? Debugged and edited, yes,
definitely, and I did look them over carefully before posting, but
didn't see where I could improve them, so I wouldn't say
"optimized" at all.

By the way, now that I've thought a bit more about that -3 SF, I
tried taking it out and clearing flag -3, and find that it does
serve a purpose after all. With the flag clear (Function -> symb),
IERR is left as a name instead of its value being returned.

Quote:
Nay, it's too simple to be considered a *program*, I gave it a
line number because the original challenge asked for a program,
but actually it's an immediate command-line expression, in the
same league as 2+2, say.

Well, my programs aren't quite as simple as 2+2, but interestingly
enough, if I edit out the program delimiters, they'll run just
fine from the command line too. The one without local variables
could be just keyed in one thing at a time too, but with the local
variable, everything from the \-> to the \>> ending the defining
procedure would have to be on the command line at the same time.
Quote:
And I notice that you refrained from commenting several key
features of both solutions, probably because you were on the
losing side, namely:

Key features? Actually, I didn't think the following were
relevant.
Quote:
My 71B BASIC version uses *no* local or global variables at all,
so it's that much easier to set up and no chance for
variable-related conflicts. No need to change or set up
environments, etc.

My programs do use the global variable X because the ROOT command
and integral function on these models require that. I'm not
ambitious enough to try to write my own versions of those. Come to
think of it, the integral function use the global variable IERR
too. So what?
My "stack-based" program doesn't use any local variable either. In
the program that does use local variables, there's no chance of a
conflict because they're local and the defining procedure doesn't
try to use anything else with those names.

What kind of variables are your FVAR and IVAR? Do your FNROOT and
INTEGRAL functions use any other variables?

True, I do force modes. And as first written, the programs restord
the original modes. Again, so what?

Quote:
I notice in your code that you "Force precision for
integration."
, and that consists in changing the display
mode. Now, why on earth should you have to do the wholly unrelated
task of changing the display mode just in order to specify some
precision for your integration process ? and with the side effect
of changing the display mode to the user, no less ?

If you want to specify a particular precision, why, just do it,
include the desired precision as a parameter to the integration
process, which is just what my BASIC version does. Remember, we're
talking about someone who's trying to fathom what the code does,
and changing display modes instead of explicitly specifying a
desired accuracy seems much more obscure, arbitrary, and less
clean to me.


Now there's a point that I heartily agree with you on! Assuming
any association between the current display mode and the desired
accuracy is pure nonsense to me.

Interestingly, in the 28 series, the accuracy is a parameter for
the integral function, and even the order of the parameters makes
more sense to me. What ever possessed them to change this for the
48 series is beyond me.

Quote:
Anyway, entering this kind of threads is mostly a waste of time,
because there's no way I (or anyone else) can convince
you with arguments or examples, no matter how
obvious or clear. If you, subjectively, find your code or RPL in
general clearer, that's the way it's going to be to you, and
nothing will change that.

Probably so.
Quote:
Fine with me, to each his own. But then don't be surprised if you
find that the vast majority doesn't agree with your concepts.

I can live with that.
Quote:
(Oh, and by the way, replicating the top register in classic
4-level RPN is not a bug or quirkiness or anything
like that. It was done on purpose, by design, because thanks to
that valuable feature you can evaluate
polynomials of arbitrary degree extremely efficiently

(Horner's rule), which you couldn't were it not for it. And, as
you know, these advanced RPN calculators were originally
designed for engineers by engineers, and at the time,
real engineers found themselves evaluating polynomials constantly,
and needed to do it fast, simply, and efficiently, even if they
had a non-programmable model. That's why.)

Thank you for the history lesson; it does help me to understand
how that came about. And yes, I do realize that back in those
days, calculators were designed for "real world" use, not for
students or gamers.

That use of "Horner's rule" rather sparked sparked my interest.
These fancy calculators have rather spoiled me, but I do recall it
as a method of factoring polynomials such as
a+b*x+c*x^2+d*x^3+e*x^4 to the form a+x*(b+x*(c+x*(d+x*e))). That
does eliminate all exponentiation, but converted to an RPN
sequence is:

a x b x c x d x e * + * + * + * +
which couldn't even be used with a 4-register stack. Okay, I
re-arranged it to (((e*x+d)*x+c)*x+b)*x+a. That's a little better;
converted to an RPN sequence, this is:
e x * d + x * c + x * b + x * a +
so it would need only two registers. But to take advantage of the
"replicate downward" feature, I want all of the x'es first. Okay,
rearranged it to x*(x*(x*(x*e+d)+c)+b)+a, which converts to the RPN
sequence:
x x x x e * d + * c + * b + * a +
which, with an infinite supply of x values available in the stack,
would be considerably easier to key in, especially with a
higher-degree polynomial.

I surmise that this, or something quite similar, was what they
were using. Very neat, and even on an RPL model, might be easier
than keying in the polynomial as an algebraic.

Just for a check, that last RPN sequence, after being executed and
COLLECTed on a 49g+ with flag -114 set (Disp x+1 -> 1+x), shows up
exactly as the expression that I started out with.

Regards,
James

Edited: 23 Nov 2005, 8:50 p.m.


Hello, James --

James Prange posted,

Quote:
Karl's "challenge" isn't very clear to me as posted...

And yet you were able to provide a working RPL-based solution that met my specifications, as did Arnaud Amiel and Raymond Del Tondo before you, and as did Valentin for HP-71B BASIC. I take some mild umbrage at the suggestion that I didn't describe the task clearly.

However, lack of specificity in every detail does not equate to lack of clarity. The task was simply to prepare an RPL-based program that would automatically and correctly calculate three numerical answers: the two limits of integration and the area over those limits. Purposely, no other requirements were imposed; the approach was left to the user's discretion. I even provided working RPN-based code and the correct answers.

Quote:

I did have some problems. First off, I seldom integrate anything, so I had to look up the syntax for the integral function. I tried that out on the 48GX, and it worked just fine, I solve for roots and intersections often enough, but I normally use the solver for that, so I also had to look up the syntax for ROOT,

13 lines of narrative describing James' trials and tribulations snipped...


Hmm... maybe it was a real challenge after all! :-)

Quote:
That use of "Horner's rule" rather sparked sparked my interest. These fancy calculators have rather spoiled me, but I do recall it as a method of factoring polynomials such as a+b*x+c*x^2+d*x^3+e*x^4 to the form a+x*(b+x*(c+x*(d+x*e))). That does eliminate all exponentiation, but converted to an RPN sequence is:

lengthy narrative describing an application of Horner's Method snipped...


Well, upon re-reading of your narrative, it seems that you did, in fact, understand the point. But, I'd already submitted my write-up:

Horner's Method was described in the HP-15C manual, and probably others that preceded it. The idea is that the polynomial

f(x) = an(xn) + an-1(xn-1) + an-2(xn-2) + ... + a0

is to be factored into terms based on addition of each coefficient ak, and subsequent multiplication by the variable x, in order to avoid use of computationally-slow exponentials.

To do this on an HP RPN-based calculator, arrange the polynomial in descending order of terms, and load the stack with values of x, so that x can be replicated infinitely in the t-register.

For example, to evaluate

f(x) = 5x4 + 2x3 - x2 + 7 at x = -2.0:

2 
[+/-]
[ENTER]
[ENTER]
[ENTER]
5
* 5x
2
+ 5x + 2
* 5x2 + 2x
1
- 5x2 + 2x - 1
* 5x3 + 2x2 - x
* 5x4 + 2x3 - x2
7
+ 5x4 + 2x3 - x2 + 7

Answer: 67.0

Horner's method is noticeably faster on an older RPN calc. I even employed it for a Fortran mainframe program in the 1980's that required calculation of a low (5th?)-order polynomial at thousands of data points. This might not have substantially reduced the computational burden, if the object code for the power function "**" performed a multiplication-loop (instead of logarithms and ex) for small positive-integer exponents. However, Horner's Method would still require fewer operations.

-- KS

Edited: 24 Nov 2005, 1:33 a.m.


Hello Karl,

Quote:
James Prange posted,
Quote:
Karl's "challenge" isn't very clear to me as posted...

And yet you were able to provide a working RPL-based solution that
met my specifications, as did Arnaud Amiel and Raymond Del Tondo
before you, and as did Valentin for HP-71B BASIC. I take some mild
umbrage at the suggestion that I didn't describe the task clearly.

However, lack of specificity in every detail does not equate to
lack of clarity. The task was simply to prepare an RPL-based
program that would automatically and correctly calculate three
numerical answers: the two limits of integration and the area over
those limits. Purposely, no other requirements were imposed; the
approach was left to the user's discretion. I even provided
working RPN-based code and the correct answers.


Okay, I'm quite willing to take any blame for not immediately
understanding exactly what you expected. Perhaps part of my
confusion was because you seemed to be asking for the limits to be
returned, yet solutions deemed correct, although they do find the
limits for use in finding the integral, do not seem to return the
limits used.
Quote:
Hmm... maybe it was a real challenge after all! :-)

Indeed, more than it should've been.
Quote:
Well, upon re-reading of your narrative, it seems that you did, in
fact, understand the point. But, I'd already submitted my
write-up:

Okay, I don't always read posts (or documentation) that don't seem
to be relevant to models that I actually own or expect to own in
the future.
Quote:
Horner's method is noticeably faster on an older RPN calc. I even
employed it for a Fortran mainframe program in the 1980's that
required calculation of a low (5th?)-order polynomial at thousands
of data points. This might not have substantially reduced the
computational burden, if the object code for the power function
"**" performed a multiplication-loop (instead of logarithms and
ex) for small positive-integer exponents. However, Horner's Method
would still require fewer operations.

Indeed, depending on how the power function is implemented in a
particular language, I expect that Horner's method can be an
advantage.

Some languages, for example, Saturn assembler for the RPL models,
don't even provide a power function. In assembler, if I wanted to
implement a power funtion, I'd either have to iterate
multiplication, or else call an RPL routine. Offhand, if I chose
to work with a polynomial in assembler, Horner's method offers a
way to avoid using up the limited number of processor registers.

My conclusion is that when working with polynomials, Horner's
method is well worth considering.

Regards,
James


6+ years ago I was writing DSP modelling software (on PC) for a custom voice compresion algorithm.

Multiple 5th-degree polynomials needed to be evaluated as part of an interleaved rootfinding algorithm to convert LPC coefficients to line spectra.

Horner's method really sped things up!

Bill Wiese

San Jose, CA USA

Hi, James:

James wrote:

"I really didn't want to get in a flame war over this. I perceived your posts as particularly hostile and responded in kind."

    Nah, no hostility at all, it's just that my attitude is easily interpreted as 'hostile', while the proper adjective would be 'intense' or perhaps 'passionate'. But don't get me wrong, frequent posters here do know that this is just a problem in understanding my attitude, not a problematic attitude on my part; in other words, I may bark but I mean no harm and usually don't resort to name calling, most specially with polite and educated posters like yourself.
"Other than the problem of possibly overwriting a variable with the same name, I don't see any reason why whatever name
I'm solving for couldn't be used."

    It has to do with nesting. Both FNROOT and INTEGRAL can be nested, i.e., an FNROOT can solve a function which itself calls FNROOT, and INTEGRAL can integrate a function which itself calls INTEGRAL, and further FNROOT can solve INTEGRALs and INTEGRAL can integrate FNROOTs.

    That being so, were you to use a normal variable, say "X", that "X" would have different meanings and would hold different values depending on the level of nesting where it was used. That cannot be accomodated with a single, normal user variable, which is a unique location in memory, while FVAR is actually a *keyword* which holds the value of your solved or integrated variable at any and *all* levels of nesting, transparently to the user.

    So, if you were to single-step your function while being solved or integrated by a nested call, you'd see that FVAR isn't the same value from one level of nesting to another, while the keyword (i.e.: formal variable in this case) is one and the same to you: FVAR.

"I gather that FVAR represents the X in your FNF(X)? Sort of like a reserved variable in RPL?"
    That's correct, FVAR is the X in FNF(X), the Y in FNF(Y), in other words, the formal variable. But internally it's not a variable but a keyword which holds a set of values, one for each level of nesting.
    I don't know if that corresponds to a reserved variable in RPL but seems unlikely.
"You're saying that solving and integrating are occurring at the same time?"
    Why, yes. In Karl's particular example, that's not the case, you're actually integrating a function which isn't being solved, the solving procedure is only performed twice to compute the limits of integration and it's completely over before the integration process proper starts.

    But have a look at this example (already published at this Forum as part of a Test Suite for advanced HP models, search the archives for "Turtle and Hare"), where you're solving for a root of a function that itself is an integral of an implicit function (!), i.e.: you're
    Solving an Integral whose integrand requires Solve:

        Test 7: Solving a definite integral of an implicit function

    /X
    |
    Find X in [0,1] such that | y(x).dx = 1/3,
    |
    /0
    where y(x) is the implicit function defined by:

    y5 + y = x

    using a precision of 1E-3 for the integral. HP-71B code:

    FNROOT(0,1, INTEGRAL(O, FVAR,1E-3, FNROOT(0,1, FVAR^5+FVAR-IVAR))-1/3)

    gives 0.854136725005 (precision = 1E-3)
    or 0.854138746461 (precision = 1E-6)

    As you may see, solving and integrating are absolutely intertwined in this example. You can also see that the first FVAR appearing in that expression corresponds to the variable being solved by the outer FNROOT, while the 2nd and 3rd FVAR correspond to the variable being solved by the inner FNROOT. You wouldn't be able to do that using a regular, user variable like 'X', say, because in this case both 'X' would have different meanings. Of cousrse, IVAR is the formal integration variable and you can see as well that it has to be different from FVAR because they refer to wholly unrelated values.

    By the way, the above expression is a command-line expression, not a program, and uses no local/global variables at all, flags, modes, or whatever. So, it will work as-is, no need to change modes, be aware of the status of some flags, or keep care that you don't overwrite some variable.

"Isn't RPN (mostly) postfix too? How do the vast majority of people find that?"
    Repelent, of course. The difference is that while most people find RPN repelent except those few that do like it, RPL is found repelent almost universally, even among RPN fans.

    As for prefix-postfix, RPN is indeed postfix for all the parts that need to be postfix, namely mathematical operations. Utility operations such as changing flags, modes, or storing/recalling numbers which have no mathematical nature have no reason to be postfix and they aren't.

    To make them postfix as well is perverting the original intent of the elegant RPN's postfix notation, cluttering up the stack with all kinds of non-mathematical 'operands' and 'arguments' which are nothing but control parameters which don't belong in the stack to begin with. Doing that, in the name of 'consistency', only results in unnatural, unreadable code, unnecessary and constant growth and shrinking of the stack, and redundant stack manipulations, throwing out the window the innately elegant paradigm so well served by classic RPN.

"Good for you! I'm glad that you're so familiar with your calculator!"
    James, please ... there's no need to be 'so familiar' with my calculator to write down:
         Print Integrate( FindLimit1, FindLimit2, Precision, Function )
    I can do it in my dreams, and you probably could, too !! Does it actually feel so difficult or unfathomable to you !?
"So are they "optimized several times"? Debugged and edited, yes, definitely, and I did look them over carefully before
posting, but didn't see where I could improve them, so I wouldn't say "optimized" at all."

    As you wish. On the other hand, I simply wrote down my expression immediately, never gave it a second thought nor did I have to remember any syntax or whatever as it's so obvious. And of course, it ran first time, no complaints, quirks, special modes, or bugs.
"What kind of variables are your FVAR and IVAR? Do your FNROOT and INTEGRAL functions use any other variables?"
    That's been fully answered above and no, no other 'variables' are used. As FVAR and IVAR aren't actually variables but keywords that stand for formal variables and transparently take care of the different values at different levels of nesting, the inescapable conclusion is that my version uses no variables, at all.
"True, I do force modes. And as first written, the programs restord the original modes. Again, so what?"
    James, please, be serious. If I point out some illogical and undesirable effect in your proceedings and you come and say "True, but so what ?" you'll merely reinforce my impression that this kind of exchanges are useless and a waste of time, at least for me.
"Now there's a point that I heartily agree with you on! Assuming any association between the current display mode and the
desired accuracy is pure nonsense to me."

    That's better, now we're making progress. But then, I now understand your previous "True [...] so what ?" even less.
"Thank you for the history lesson; it does help me to understand how that came about."
    You're welcome.
"A method of factoring polynomials such as a+b*x+c*x^2+d*x^3+e*x^4 to the form a+x*(b+x*(c+x*(d+x*e))).
That does eliminate all exponentiation, but converted to an RPN sequence is:
         a x b x c x d x e * + * + * + * +
which couldn't even be used with a 4-register stack."

    You're right, your constant using of RPL has really spoiled you if you can come up with that particularly inefficient, multi-level scheme.
"Okay, I re-arranged it to (((e*x+d)*x+c)*x+b)*x+a. That's a little better"
    Wrong, it's much better, because now you can do it using the classic 4-level stack, no matter how large the degree of the polynomial, and you're reducing significantly the chance of making a mistake. As you now know, the correct sequence is like this example:
        Evaluate a5*x^5 + a4*x^4 + a3*x^3 + a2*x^2 + a1*x + a0

    x
    ENTER
    ENTER
    ENTER
    a5
    *
    a4
    +
    *
    a3
    +
    *
    a2
    +
    *
    a1
    +
    *
    a0
    +

    where you always begin by ENTER, ENTER, ENTER, no matter the degree of the polynomial, and you can easily detect and correct errors, while never needing more than classic-RPN 4 levels. This procedure is extremely easy do to manually on a non-programmable RPN calc, and can be made into an extremely short program, even the HP-25 included it using 10 steps or less
Best regards from V.

Hi Valentin,

Quote:

"Other than the problem of possibly overwriting a variable with
the same name, I don't see any reason why whatever name I'm
solving for couldn't be used."

It has to do with nesting. Both FNROOT and INTEGRAL can be nested,
i.e., an FNROOT can solve a function which itself calls FNROOT,
and INTEGRAL can integrate a function which itself calls INTEGRAL,
and further FNROOT can solve INTEGRALs and INTEGRAL can integrate
FNROOTs.

That being so, were you to use a normal variable, say "X", that
"X" would have different meanings and would hold
different values depending on the level of nesting where
it was used. That cannot be accomodated with a single, normal user
variable, which is a unique location in memory, while FVAR is
actually a *keyword* which holds the value of your solved or
integrated variable at any and *all* levels of nesting,
transparently to the user.

So, if you were to single-step your function while being solved or
integrated by a nested call, you'd see that FVAR isn't the same
value from one level of nesting to another, while the keyword
(i.e.: formal variable in this case) is one and the same to you:
FVAR.


"I gather that FVAR represents the X in your FNF(X)? Sort of like
a reserved variable in RPL?"

That's correct, FVAR is the X in FNF(X), the Y in FNF(Y), in other
words, the formal variable. But internally it's not a variable but
a keyword which holds a set of values, one for each level
of nesting. I don't know if that corresponds to a reserved
variable in RPL but seems unlikely.


I had a look at FNROOT and INTEGRAL in the Math Pak
Owner's Manual
, and it looks to me as if FVAR and IVAR
are more like RPL's variable of integration and variable for
plotting. "Formal variable" does seem like a good name for them.
The FVALUE and FGUESS stored by FNROOT, and IVALUE and IBOUND
stored by INTEGRAL, are examples of what I'd call "reserved
variables" in RPL.
Quote:

"You're saying that solving and integrating are occurring at the
same time?"

Why, yes. In Karl's particular example, that's
not the case, you're actually integrating a
function which isn't being solved, the solving procedure is only
performed twice to compute the limits of integration and it's
completely over before the integration process proper starts.

But have a look at this example (already published at this Forum
as part of a Test Suite for advanced HP models, search the
archives for "Turtle and Hare"), where you're solving for a root
of a function that itself is an integral of an implicit function
(!), i.e.: you're Solving an Integral whose integrand requires
Solve:

    Test 7: Solving a definite integral of an implicit function

/X
|
Find X in [0,1] such that | y(x).dx = 1/3,
|
/0
where y(x) is the implicit function defined by:

y5 + y = x

using a precision of 1E-3 for the integral. HP-71B code:

FNROOT(0,1, INTEGRAL(O, FVAR,1E-3, FNROOT(0,1, FVAR^5+FVAR-IVAR))-1/3)

gives 0.854136725005 (precision = 1E-3)
or 0.854138746461 (precision = 1E-6)

As you may see, solving and integrating are absolutely intertwined
in this example. You can also see that the first FVAR appearing in
that expression corresponds to the variable being solved by the
outer FNROOT, while the 2nd and 3rd FVAR correspond to
the variable being solved by the inner FNROOT. You
wouldn't be able to do that using a regular, user variable like
'X', say, because in this case both 'X' would have different
meanings. Of cousrse, IVAR is the formal integration variable and
you can see as well that it has to be different from FVAR because
they refer to wholly unrelated values.

Actually, it took me a while to see what was going on in that
example.

Anyway, in the first program following, I use only two distinct
names, and the 48 and 49 series manage to keep track of what they
mean. Of course this makes for truly obfuscated code, so normally
I use distinct names for distinct variables. Not only does using
distinct names make things clearer to me, but it avoids any
possible problem with the calculator getting them mixed up.

%%HP: T(3)A(D)F(.);
@ Overwrites any 'X' or 'IERR' in current directory!
@ Takes a number argument to set an error tolerance;
@ for example, 3 specifies an error tolerance of 10-3.
@ Sets display mode to FIX while running, but normally restores
@ original mode.
@ Results from the BYTES command:
@ 48 series checksum: # B2BCh
@ 49 series checksum: # B3E6h
@ Size: 197
\<<
RCLF SWAP FIX
'X' PURGE
\<<
\-> x
\<<
'X^5.+X-x'
'X'
{ 0. 1. }
ROOT
\>>
\>>
\-> x
\<<
\<<
0. X
'x(X)'
'X'
\.S
1. 3. / -
\>>
'X'
{ 0. 1. }
ROOT
\>>
SWAP STOF
\>>
With an error tolerance of 10-3, this returns
.854136725005, with 3.33478395859E-4 stored as IERR.

With an error tolerance of 10-6, this returns
.85413874646, with 3.33369684455E-7 stored as IERR.

In case anyone's interested, here are some approximate timings, in
seconds:

Error tolerance 10-3   Error tolerance 10-6
48SX: 267 48SX: 548
48GX: 181 48GX: 376
49G: 223 49G: 455
49g+: 81.2 49g+: 166
Maybe this next example will look a bit clearer (but maybe not):
%%HP: T(3)A(D)F(.);
@ Overwrites any 'X', 'Z', or 'IERR' in current directory!
@ Takes a number argument to set an error tolerance;
@ for example, 3 specifies an error tolerance of 10-3.
@ Sets display mode to FIX while running, but normally restores
@ original mode.
@ Results from the BYTES command:
@ 48 series checksum: # 2FB6h
@ 49 series checksum: # 2EECh
@ Size: 197
\<<
RCLF SWAP FIX
\<<
\-> a
\<<
'Z^5.+Z-a'
'Z'
{ 0. 1. }
ROOT
\>>
\>>
\-> f
\<<
\<<
0. X
'f(Y)'
'Y'
\.S
1. 3. / -
\>>
'X'
{ 0. 1. }
ROOT
\>>
SWAP STOF
\>>
This returns the same as the previous program, except of course
that the "inner" root 'Z' doesn't get overwritten by the "outer"
root 'X'.
Quote:
By the way, the above expression is a command-line expression, not
a program,

Okay, I wrote mine on the PC, originally as two separate programs,
but I decided that I may as well just combine them into one.

Maybe you do this sort of thing frequently, but it strikes me as
an unusual case. Ordinarily, I use the solver instead of the ROOT
command to find roots and intersections. I don't use integration
often, but I've always just typed the arguments into the command
line and pressed the integrate key. For this case, it seems
especially unfortunate that ROOT isn't a function, because the
integrate function on the 48/49 series requires the integrand to
be an algebraic.

Quote:
and uses no local/global variables at all, flags, modes, or
whatever. So, it will work as-is, no need to change modes, be
aware of the status of some flags, or keep care that you don't
overwrite some variable.

I see very little problem with using local variables; they're
local to the defining procedure and are abandoned when
the procedure finishes. A local variable will definitely never
overwrite any other variable. The only thing to be careful of with
them is that while a local variable exists, there's no way to
access anything else (including a previously bound local variable)
with the same name. For example, if you're going to use e or i, or
for that matter, SIN, in the procedure, then don't use it for a
local name.

Hmm, on second thought, there is another possible problem with
local names. Consider the sequence:

0 \-> x \<< 'x' \>> [ENTER]
That briefly stores 0 in the local variable x, puts the quoted
local name 'x' on the stack, and abandons the variable. Any
attempt to evaluate this 'x' while no local variable named 'x' is
defined results in an "Undefined Local Name" error. Note however,
that if I key in another 'x', then this new x is compiled as a
global name, so evaluating the new 'x' doesn't error out.

Although the variable of integration can be either a global or
local name, I believe that the system changes it to a new local
name to store values with, so any existing variable with the same
name is ignored, and is not overwritten by the integration. I
suppose that it could be called a "formal variable", rather like
your FVAR and IVAR, except that I can use whatever name I choose.

Yes, sometimes global variables are used (and possibly
overwritten), as with ROOT and the solver. I typically use
one-letter names for these, and have never had any problem with
confusing them with the names of variables that I really do want
to keep long-term.

"Reserved variables" are global variables such as IERR that the
system uses for its own purposes. There are quite a few of these,
so there's some danger that the user could inadvertently choose a
reserved name for his own variable, but I've never found it to be
a problem. Rather like you wouldn't usually store anything with
the names FVALUE, FGUESS, IVALUE, or IBOUND, knowing that the
system would overwrite them the next time FNROOT and INTEGRAL were
used.

Using global variables has a possible advantage that they're saved
until overwritten or purged, and of course that there's a name to
go with each value. For the solvers, there may be several
variables, some with values set by the user, and some solved by
the calculator. The solution is placed on the stack, tagged with
its name, but having them all stored as global variables with
their names displayed in the menu seems useful to me. In the case
of the ROOT command, the result is stored in the variable as well
as being pushed onto the stack; I suspect that they had the solver
in mind when they designed ROOT. For the integrate function, IERR
is a supplementary result; it very likely won't be used in
subsequent calculations, so there wouldn't be much sense in
pushing it onto the stack, but it may be worth checking.

Regarding modes, as long as you don't have any modes that could
affect the result, or can safely assume that they're already in
the state you need, fine. I'm in the habit of forcing (and
restoring, of course) modes when I know they'll make a difference,
and even sometimes when I'm not absolutely sure but suspect that
they will. Of course, when I'm not writing a program and I'm
reasonably sure that a mode is already the way I need it, there's
no need to force it.

Quote:

"Isn't RPN (mostly) postfix too? How do the vast majority of
people find that?"

Repelent, of course. The difference is that while most people find
RPN repelent except those few that do like it, RPL is found
repelent almost universally, even among RPN fans.


Or maybe the difference is that while most people find RPL
repellent except for those few who do like it, "Classic RPN" is
found repellent almost universally, even among RPL fans?

But I really don't know which of RPL or Classic RPN has more fans.
I do expect that there are a lot of 12C users out there.

Quote:
As for prefix-postfix, RPN is indeed postfix for all the parts
that need to be postfix, namely mathematical operations. Utility
operations such as changing flags, modes, or storing/recalling
numbers which have no mathematical nature have no reason to be
postfix and they aren't.

I think that the idea is that any result should be available as an
argument to subsequent operations. For a stack-based system,
putting all results on the stack and using all postfix operations
strikes me as the most elegant method to achieve this (as long as
the stack can be deep enough).
Quote:
To make them postfix as well is perverting the original intent of
the elegant RPN's postfix notation, cluttering up the stack with
all kinds of non-mathematical 'operands' and 'arguments' which are
nothing but control parameters which don't belong in the stack to
begin with.

Note that RPL operations can take "symbolic" arguments and return
"symbolic" results, which are just RPN sequences of a special
type, very similar to SysRPL programs. The start and stop values
of FOR loops, for example, often depend on previous calculations.
In my program above, I expect the user to have the value for FIX
in the command line or on the stack, where FIX in the program can
find it, saving the user the slight trouble of switching to alpha
mode and keying in FIX. Sure, we could store anything deemed
non-mathematical in a named variable (for use with prefix
operations) instead of putting it on the stack, but
having to do it that way strikes me as a lot of extra
bother.
Quote:
Doing that, in the name of 'consistency', only results in
unnatural, unreadable code, unnecessary and constant growth and
shrinking of the stack, and redundant stack manipulations,
throwing out the window the innately elegant paradigm so well
served by classic RPN.

Ah well, I expect that we'll never agree on this. To me, it seems
more like it's for functionality, not just for consistency. Is
keeping track of a growing and shrinking stack all that difficult?
It's true, although to a much lesser extent, of Classic RPN too.
What's so hard about using, for example, 3 FIX instead of FIX 3? I
put 3 on the stack and it grows one level, but FIX takes the 3 off
so it's right back where it was. The consistency helps too; I
always know where any operation will take its argument from
(though not always which order is needed for multi-argument
operations that I seldom use). As long as the hardware to make a
very deep stack is available, why not take advantage of it? With
RPL, the user is free to choose to take results off of the stack
for storage in named variables, leave the results on the stack for
as long as they're needed, or whatever mixture of these he's
comfortable with.
Quote:

"Good for you! I'm glad that you're so familiar with your
calculator!"

James, please ... there's no need to be 'so familiar' with my
calculator to write down:

     Print Integrate( FindLimit1, FindLimit2, Precision, Function )
I can do it in my dreams, and you probably could, too !! Does it
actually feel so difficult or unfathomable to you !?

Well, I suppose that if I were familiar with the keywords and
which order the arguments needed to be in, I'd catch on soon
enough. It looks as if functions can't be used as postfix
commands, and everything is either prefix or algebraic notation.
Now that I've glanced at the owners manuals, I wouldn't mind
having a 71B to play around with, although I'll stick with the 48
series for "real work". Besides, having a 71B available while I
read the HP-71B Hardware Internal Design
Specification
might be handy. But I expect that a 71B
would cost more than I could justify to myself.

But it always amazes me that so many seem to find RPL difficult.
After playing with a display sample of the 28S in the store for a
few minutes, I knew that it was a lot easier for me than switching
between "CAL", "PRO", and "RUN" on my Sharp or using short
algebraic "keystroke" programs on my little Radio Shack model. To
me, RPL has seemed so very intuitive right from day one that it's
hard for me to imagine how anyone could find it overly
complicated.

But I can understand that if someone has a Classic RPN model that
does everything he wants from a calculator and he's quite familiar
with it, then getting an RPL model and getting used to the
differences would probably be a mistake, except perhaps as a
hobby.

Actually, I sometimes get irritated with some of the changes in
the 49 series. To be sure, some of the new features are nice, and
I can happily ignore a new command when I don't have the foggiest
notion of what it's good for, but when the 49 series return
something that looks a lot more complicated to me than what the 48
series returns for the same commands, it makes me wonder what they
were thinking of with this new CAS stuff.

Quote:
         a x b x c x d x e * + * + * + * +
which couldn't even be used with a 4-register stack."[/italic]

You're right, your constant using of RPL has really spoiled you if
you can come up with that particularly inefficient, multi-level
scheme.


Sure; with RPL, I can enter a polynomial as an algebraic. Why
would I bother factoring it? Anyway, all I remembered of Horner's
method was that it was factoring a polynomial to eliminate all
powers; I didn't remember what use it had beyond that, until you
pointed it out. Leaving it in ascending order, then factoring it
and converting it from an algebraic expression to an RPN sequence
was just an exploratory first step in my seeing what else Horner's
method would be useful for on an RPN calculator.

Regards,
James


Hi James!

You wrote: "But it always amazes me that so many seem to find RPL difficult. ... To me, RPL has seemed so very intuitive right from day one that it's hard for me to imagine how anyone could find it overly complicated."

Gene: I agree. I have never found RPL particularly vexing, and I'm one of the few people here who cut their teeth on an algebraic model (the SR-51A, the SR-56 and the SR-52). I then spent nearly 10 years with the HP41 getting used to 4-level RPN. RPL has an infinite stack? So what? The HP28S and 48SX weren't really a problem for me.

You wrote: "Actually, I sometimes get irritated with some of the changes in the 49 series. To be sure, some of the new features are nice, and I can happily ignore a new command when I don't have the foggiest notion of what it's good for..."

Gene: Hopefully, now that there is a real AUR out for the 49g+, you won't have to ignore any new commands, since they're documented. :-)


Quote:
Gene: Hopefully, now that there is a real AUR out for the 49g+, you won't have to ignore any new commands, since they're documented. :-)

Yes, they are documented, but I just don't have the mathematics background to understand, for example, the command CHINREM. To make all of the commands useful to me, the documentation would have to include several volumes on mathematics, which wouldn't be appropriate. For the foreseeable future, I'll ignore any commands relating to mathematics that I don't understand.

Regards,
James

Nice exercise in programming.

It is incredible that the 49G+, being praised as a "speed demon", is actually not so much faster than the 48GX ???

That's really disappointing.

On the debate RPN vs RPL, I must stress the fact that the 48/49 screens are too narrow for proper code reading, and the poor editor effectively obfuscate the code by (almost always) improper line breaks and indenting.

On the other hand, I wonder why no one ever issued a BASIC (the real thing), graphical machine (with grapher, scrollable history or stack... I sure would love this combination.


Hi, GE:

GE posted:

"On the other hand, I wonder why no one ever issued a BASIC (the real thing), graphical machine (with grapher, scrollable history or stack... I sure would love this
combination. "

    The HP-71B itself can be connected to HP-IL displays or even plotters by using the proper interfaces to accomplish most any graphic needs.

    As for built-in graphics display, there are many SHARP BASIC-language handhelds that do have large graphical screens, recall of past command lines, and some even admit small but capable 4-colour pen plotters, to produce your graphics on paper.

    Typical BASIC commands supported for graphics and graphic text output:

    CIRCLE, COLOR, CROTATE, CSIZE, CURSOR, GCURSOR, GLCURSOR, 
    GPRINT, GRAPH, LF, LINE, LLINE, LPRINT, LTEXT, PAINT, POINT,
    PSET, PRESET, PRINT, RLINE, TEXT
    most of them are multi-function commands, i.e.: CIRCLE can draw a whole circle or a sector, circles proper or ellipses, just the outline or filled-in, solid lines or dots, dashes, etc, black or some given color, etc., depending on the particular models.
Best regards from V.

Edited: 21 Nov 2005, 7:23 a.m.

Quote:
It is incredible that the 49G+, being praised as a "speed demon",
is actually not so much faster than the 48GX ???
That's really
disappointing.

Perhaps those who praised the 49g+ as a "speed demon" were
comparing it to the 49G?

Other than that, just how fast any model is depends on what it's
doing.

Quote:
On the debate RPN vs RPL, I must stress the fact that the 48/49
screens are too narrow for proper code reading,

Well, it's a calculator; how wide would you expect the screen to
be? How much of the code can you see at one time on any
calculator?

But it might've been nice to use a "landscape" layout instead of a
"portrait" layout,

On the 49 series, you can use the VIEW operation to see the code
displayed in a mini-font, so more can be seen at one time,
although I don't find it easier to read that way.

Quote:
and the poor editor effectively obfuscate the code by (almost
always) improper line breaks and indenting.

Well, the line breaks may look improper to you or me, but any
separator is logically equivalent to any other separator or series
of separators to the compiler, and the decompiler simply inserts a
Line Feed code instead of a space character wherever it needs to
wordwrap a line or start an indented line for a structure word or
UserRPL program delimiter.

Maybe it would be more readable to you or me if each "word" were
on its own line, but that would mean a lot of vertical scrolling
for editing, and we'd see less of the code at one time. I suppose
that the decompiler's formatting style for the editor was a
compromise between using much of the display area and indenting to
indicate structure,

Regards,
James

Quote:
Some approximate timings, in seconds:
Model   6 FIX mode   STD mode

48SX 12.72 20.54
48GX 8.84 13.20
49G 15.98 26.45
49g+ 6.80 11.52

Some interesting things about the timings:

  • As should be expected because its processor speed is higher, the 48GX is faster than the 48SX.
  • The 49G is even slower than the 48SX. Maybe this is because of the CAS? Well, that's progress.
  • The 49g+ is fastest, but not by as much as might be expected; remember that the Saturn processor is emulated (simulated?) in firmware.

I always find it unfair when people simply transfers a program from a 48 to a 49 without modifications.
Do you use numbers? Then make'em REALs.

Just add a fraction mark, dot or comma (as is my case), after each and every number in your program.

My timings, for your first program, on a 49G are:

Unmodified: 26,41 sec  (STD)
REAL-ized: 15,50 sec (STD)
REAL-ized: 10,48 sec (6 FIX)

I am no big fan of RPL but let's use each calc as it is meant to be used.
Still no winner vs a 48GX, maybe I'll make some benchmarks on my hardware if I'll find some spare time.

Greetings,
Massimo


Thanks Massimo,

Good catch. I don't know why I wrote it using exacts; I really do
know better.

Quote:
Quote:
Some approximate timings, in seconds:
Model   6 FIX mode   STD mode

48SX 12.72 20.54
48GX 8.84 13.20
49G 15.98 26.45
49g+ 6.80 11.52

Some interesting things about the timings:

As should be expected because its processor speed is higher, the
48GX is faster than the 48SX.

The 49G is even slower than the 48SX. Maybe this is because of the
CAS? Well, that's progress.

The 49g+ is fastest, but not by as much as might be expected;
remember that the Saturn processor is emulated (simulated?) in
firmware.


I always find it unfair when people simply transfers a program
from a 48 to a 49 without modifications.

Actually, the programs were transfered from a PC.
Quote:
Do you use numbers? Then make'em REALs. Just add a fraction mark,
dot or comma (as is my case), after each and every number in your
program.

Easier than editing every exact in the program to a real is: Put
the calculator in approximate mode, RCL the program to the stack
"edit" the program by pressing the down arrow, press ENTER, STO
the changed program.
Quote:
My timings, for your first program, on a 49G are:
Unmodified: 26,41 sec  (STD)
REAL-ized: 15,50 sec (STD)
REAL-ized: 10,48 sec (6 FIX)
I am no big fan of RPL but let's use each calc as it is meant to
be used. Still no winner vs a 48GX, maybe I'll make some
benchmarks on my hardware if I'll find some spare time.

My new timings:
Model   6 FIX mode   STD mode

49G 10.22 15.02
49g+ 4.70 7.33

Regards,
James

Hello James,

Quote:
Easier than editing every exact in the program to a real is: Put the calculator in approximate mode, RCL the program to the stack "edit" the program by pressing the down arrow, press ENTER, STO the changed program.

You're right, of course. :-)
The fact is that I began editing the program by changing the integration limits and verified an improvement; what I didn't expect was increasing speed as I went on changing parameters in stack manipulation commands.

Greetings,
Massimo

All --

Based on the solution provided by Howard Owen, and using some enhancements from the other RPL solutions submitted, this would be my "favored" RPL solution for my RPL challenge:

'SIN(X)' 'F' STO
'(x-1.5)^2-1' 'G' STO

<< RAD F G - -> d
<< d 'X' { 0 1 } ROOT
'll' STO
d 'X' { 2 3 } ROOT
'ul' STO
ll ul d 'X' {integ} ->NUM
'I' STO
ll ul I
>>
>>

'CHAL' STO
execution:

5 FIX
CHAL [ENTER]

(10 seconds elapse)

0.34372 (lower limit, also in variable "ll")
2.69618 (upper limit, also in variable "ul")
3.11057 (the area between the curves, also in variable "I")

Here is the solution I developed for the HP-32SII, which should run just fine on the HP-32S and HP-33S. It closely parallels the structure of the solution for the HP-15C and HP-34C.

L01 LBL L F01 LBL F
L02 RAD F02 RCL X
L03 0 F03 SIN
L04 STO X F04 RCL X
L05 1 F05 1.5
L06 FN= F F06 -
L07 SOLVE X F07 x2
L08 STO L F08 1
L09 2 F09 -
L10 STO X F10 -
L11 3 F11 RTN
L12 SOLVE X
L13 STO U
L14 RCL L
L15 RCL U
L16 {S}FN d X
L17 STO I
L18 RTN

Execution:

FIX 5
XEQ L

(10 seconds elapse)

3.11057 (the area between the curves, also in register I)
Rdown
0.00001 (estimated solution error, rounded; use SHOW or ALL)
Rdown
2.69618 (upper limit, also in register U)
Rdown
0.34372 (lower limit, also in register L)

Both of these solutions are functionally-equivalent, in that they provide two values guess that bound each SOLVE or ROOT, in order to guarantee the correct solutions. They also store each result into variables or storage registers, and display the results on the stack, as well.

Thanks to all. In keeping with Valentin's recent post regarding nested execution of INTEG and SOLVE, I might release another simple challenge on that topic.

-- KS


Edited: 24 Nov 2005, 4:52 p.m.

Quote:
Karl,


You've really lost me in that paragraph. What I take away from all
of this is:

  • You don't like to see postfix non-mathematical operations because
    it seems counterintuitive to you.
  • I've given myself a good review of just why postfix operations are
    so important to making a stack-based language easy to use.
  • You find RPL program structures hard to read.
  • In general, you don't like RPL.
Actually, that last point I figured out a long time ago.

Regards,
James



Did you have something to add to that, Abbas?

-- KS

Edited: 24 Nov 2005, 2:17 a.m.

Hi James,

An important distinction between RPL machines and RPN comes out from this discussion.

RPN allows *only* one datatype on the stack: "real".

RPL has multiple datatypes.

RPL is an operating system and a language--one might in fact even talk about RPL language and RPL operating system differently?

RPN is not a language. It is a parser, or something more low-level.


The language aspect, combined with multiple datatypes and the need for parameter passing with a stack system, leads very logically to the total postfix logic that is RPN.

Ultimately the discussion, viz between Valentin and others regarding "readablility" is rather unimportant. The fact is that anyone can trip over the syntax of *any* language, if he does not know it.


The value in this dicsussion lies not in finding the "flaw" but rather in illuminating the "paradigms" (what an abused word:) . --From this illumination can come understanding--and the ability to learn the RPL language if one (me for instance, or Karl etc) is an RPN keystroke guy.

Regards,

Bill


Hi, Bill:

Bill posted:

"RPN allows *only* one datatype on the stack: "real"."

    Bill, pleeeease ! ... The 41C's RPN does admit ALPHA strings on the stack, HP-15C's RPN does admit complex numbers and matrices on the stack, HP42S's RPN does admit complex numbers, matrices, and ALPHA strings on the stack, ... Besides, it has nothing to do with RPN itself per se but with the particular data types implemented in a particular model, man !
"RPN is not a language. It is a parser, or something more low-level."
    If you say so ... but I must confess I know accepted programming languages that are lower level than RPN. My guess is that you won't consider anything a proper language unless it includes structured programming and such. That would exclude programming languages in widespread use before the concept of structured programming made its appearance. Reiventing history, we could say ...
"The language aspect, combined with multiple datatypes and the need for parameter passing with a stack system, leads very logically to the total postfix logic that is RPN."
    Great statement ! I fully agree !! Oh, but wait ... you meant "RPL" instead, right ? :-)
"Ultimately the discussion, viz between Valentin and others regarding "readablility" is rather unimportant. The fact is that anyone can trip over the syntax of *any*
language, if he does not know it."

    And !? ...
"The value in this dicsussion lies not in finding the "flaw" but rather in illuminating the "paradigms" (what an abused word:) . --From this illumination can come
understanding--and the ability to learn the RPL language if one (me for instance, or Karl etc) is an RPN keystroke guy."

    Give the man a cigar ! :-)
Best regards from V.

Quote:
"RPN is not a language. It is a parser, or something more low-level."

If you say so ... but I must confess I know accepted programming languages that are lower level than RPN. My guess is that you won't consider anything a proper language unless it includes structured programming and such. That would exclude programming languages in widespread use before the concept of structured programming made its appearance. Reiventing history, we could say ...


And that would indeed exclude Assemblers, Fortran, various Basics and a host of others. If we don't call those languages, what term should we invent when we want to speak of them as a group?


Well, glad I got your attention :-)

I guess what I am getting at is that the *RPN* aspect is merely describing the parsing order. The "language" of an hp 67 or 97 or 32sii etc is not the *RPN" part of it. In fact the "programming language" is a steadily evolving set--but it is not the RPN that makes the language. RPN is the operating paradigm under which the language operates.

For example, RPN can essentially be boiled down to the following:

Put stuff on the stack
operate on the last one or two things on the stack
put the result back on the stack

The "programming language" functions within this paradigm, but includes all sorts of other stuff--control stuff--"verbs" if you will such as DSE, PSE, XEQ, GTO, GSB, RTN, and uses some of the "direct calculations" verbs as well such as SWAP, ROT, etc.

Notice that the programming "language" of the 20s is not fundamentally different from the 11c except for the RPN aspect and more branching structures--they are both "keystroke" systems that act directly on a "stack" or a "calculator line" and that commands are run from a special logical space called a "program".

RPL is a different situation. What it retained is the stack. What is different is that commands or "verbs" *themselves* can be parsed onto the stack to be executed later. That is the real change in thinking.

Edited: 23 Nov 2005, 12:29 p.m.


Quote:
RPL is a different situation. What it retained is the stack. What is different is that commands or "verbs" *themselves* can be parsed onto the stack to be executed later. That is the real change in thinking.

= Good old Forth :)

Quote:
Bill, pleeeease ! ... The 41C's RPN does admit ALPHA strings on the stack, HP-15C's RPN does admit complex numbers and matrices on the stack, HP42S's RPN does admit complex numbers, matrices, and ALPHA strings on the stack, ... Besides, it has nothing to do with RPN itself per se but with the particular data types implemented in a particular model, man !

Well, I forgot about the alpha (I don't use the 41 very often) but as far as numbers go on the 15c---even though you have "logical" complex numbers, they are in fact "real" *on the stack* when you enter them. They are processed as complex because of the complex mode. Perhaps this is splitting hairs, but it seems quite different to me than the RPL case where putting parens around numbers and putting them on the stack declares to the parser that they are complex, whereas in the 15c, you have to first tell the parser that you are now in complex mode, then do something, then tell it you are now out of complex mode. In the RPL model, it isn't a "mode change" but a different data type. The matrix business again--each entry is a "real" and it is only by 1st telling the parser that the "reals" you are typing are to be parsed into a matrix, that it ends up that way.

Edited: 23 Nov 2005, 12:28 p.m.


Hi again, Bill:

Bill posted:

"[...] as far as numbers go on the 15c---even though you have "logical" complex numbers, they are in fact "real" *on the stack* when you enter them."

    Am I supposed to take this 'explanation' of yours seriously !? C'mon !!
"The matrix business again--each entry is a "real" and it is only by 1st telling the parser that the "reals" you are typing are to be parsed into a matrix, that it ends up that way."
    Bill, I can see you mean well, but seems to me you either have no idea what you're talking about, or else are not very knowledgeable about just how the HP-15C works.
Just to refresh your mind, if you want to add matrix A to matrix B and then subtract matrix C, with the final result stored in A (i.e.: A = A + B - C), you do this in the HP-15C's RPN flavor:
    RESULT A
RCL MATRIX A
RCL MATRIX B
+
RCL MATRIX C
-
Does this seem RPN enough to you ? With matrices on the stack, being manipulated as if they were simple numbers, though each one is operated upon as a whole ?

That you can do because, in HP-15C's RPN, the stack registers can hold and operate with whole matrices, including all stack manipulations, ENTER, X<>Y, Roll down & up, STO, RCL, LASTX, the works.

That you can do because each stack register holds a matrix descriptor, which is nothing but a pointer to where the matrix elements are actually stored, which is no different from the pointers to various objects held by RPL stack registers.

Think about it a little and then re-read your statements and judge if they make sense.

Best regards from V.


[sheepishly...] You're right, Valentin.

[sorry excuse for an explanation...] I was thinking of the "input" side of the matrix operations--essentially loading the stack, one element at a time. I conveniently forgot to think the operating part through.

Actually this 15c matrix functionality really is a huge departure from all the previous keystroke programmables in that sense, it seems to me. Really is a pinnacle in terms of development...but you can see how the input side, and the "reading or viewing the elements" of an array side is so dramatically different from an RPL machine, where you can see the whole matrix at once (well, as long as it ins't really large....)...you can see how the movement to RPL seemed an attractive idea.


Hello, Bill --

You posted,

Quote:
...the "reading or viewing the elements" of an array side is so dramatically different (on an HP-15C) from an RPL machine, where you can see the whole matrix at once (well, as long as it ins't really large....)...you can see how the movement to RPL seemed an attractive idea.

Well, the matrix-editing capabilities on the HP-15C had to be possible on its one-line 7-segment LCD, and I think HP did a thorough and thoughtful job.

On models with a free-form dot-matrix display, I prefer the HP-42S matrix-editing and display to that of RPL-based 28/48/49. On the 42S, one sees only one element at a time, but generally with at least five significant digits for each component if it is complex-valued. One can scroll up or down, left or right, using cursor softkeys.

The 28/48/49 try to display as much as possible, but it's a real mess if the matrix elements are floating-point or complex (as they often are in real-world applications). It helps somewhat to use the matrix editor on the 48 and 49, which eliminates the brackets.

On the other stuff, Valentin expressed my own thoughts, and there's no need to re-hash. You can take some consolation in that, strictly speaking, you are correct that the HP-15C does not put complex-valued elements on the dedicated stack. Instead, it borrows five registers from the free pool of user RAM to create a "four level plus LASTx" stack for the imaginary-valued components of complex arguments.

-- KS


Edited: 24 Nov 2005, 2:14 a.m.

If you're going to compare RPL and RPN programming, it would be fairer to look at the more evolved RPN models. The 16C and 12C were never top programmables; they were just specialized calculators with some limited programmability slapped on.

The HP-41C, and its successor, the HP-42S, have alphanumeric displays so you don't need to decipher key codes; they have label addressing and subroutines, insert/delete of program lines, and ISG/DSE loop counters without the limitations of the silly ISZ/DSZ. They do have four-level stacks, though.

Those two machines are what most RPN enthusiasts are thinking about when comparing RPN to RPL. (Well, I am, anyway. :-) )

- Thomas

A year or two ago, I was able to write simple programs in RPL on my 48G's to find the average, median, maximum, and minimum of a set of numbers. They work. I'm not a professional programmer, only an occasional one (only 'cuz I gotta), so I cannot attest to their elegance, not even in a wild drunken boast.

But the one I tried for finding the mode still doesn't work and haven't had the time to troubleshoot it.

I wrote one to index a x-ray powder pattern and it does work, but I fear it's a bit clunky and may even be a little bloated.

Incidentally, if anyone wants, I could post that diffraction program to the museum, not because it's such a work of art (a good programmer or even another scientist might laugh), but there aren't too many programs on HP calculators for basic scientific work aside from the usual college freshman chemistry stuff.


Indexing diffraction patterns was my first evolved sysRPL program! Once it was fully working with graphics and all, I demonstrated it to my classmates and during the IR upload something went terribly wrong and I lost everything. Since then I bought a RAM card (which regularly failed anyway :-() and always backup

Now I am interested in statistics as well and am writing a random numbers generator for different distributions...

But this is on hold due to Valentin new challenge

Arnaud


Graphics??!!!

Wow!

All mine does is to give the ratios of sums of the Miller indices and you'd still have to use your head to determine the actual Miller indices from these reduced sums! (I mean what's complex for me is simple to most others!)

I did think about some way of doing that using the 48G and 49G+ RPL, but I chickened because it looked like it would take too long. Well, maybe this holiday weekend...

... maybe!

And I'm very sorry to hear that after all that hard work, you lost it. Maybe the first upload should be to a PC, so that you can keep a copy for just that reason... if it doesn't screw up during THAT transmission.

I have one 48G and one 48G+; when I put something I need (a program, some data, etc.) on one, I try to remember (but not always) to beam it to the other, just for safekeeping.

Edited: 23 Nov 2005, 11:06 p.m.

I've read those threads, but for me, RPL is indeed "intuitive and practical", and easier to use than RPN.

Regards,
James


I like Bill's theory that one's attitude toward RPL and RPN are conditioned mainly by which style one was exposed to first. If there is such a thing as an objective truth about these two, perhaps defined as the opinion of someone who has no opinion, it may be something like "they are both ugly and hard."

But I find I can break through surface ugliness to get at a tool, as long as I'm sufficiently motivated. And frequently I find hidden beauty when I do that. When I learned RPN, the motive was to figure out what this "programming" thing was all about. The fact that the 41C was the first machine I ever programmed had a big impact on my later career as a student and as a professional. Today, I'm motivated to learn RPL because it's cool. That has a slightly less urgent edge to it than the motive that drove me to learn the 41C. But I'm getting to the point where I'm having some success in writing code that doesn't strike me as pure gobbledygook when I look at it later. That's a lot of fun. In fact, that sort of thing is 80% of the fun of collecting computing devices, for me.

I still think that RPL is oddball, and that the 48 is very complicated. But I don't seriously hold that against either. 8)

Oh, I don't want to start any war. It's just that I keep seeing RPL referred to as "complicated" compared to "Classic RPN", and I just can't see it that way.

To me, it's the "Classic RPN" programming that seems more complicated; sort of like having to write an assembly language program for something that could be accomplished very simply in UserRPL.

Of course, the RPL models are capable of things that the 16C and 12C just aren't capable of, so using them adds complexity, but I mean just the basic things that the more basic models are capable of.

I learned UserRPL first, and it all seemed pretty straight-forward and logical to me. A few different object types, arguments and operators using RPN syntax, a few stack manipulation commands, global and local variables, a few programs structures, name resolution, and realizing that any command line can be the contents of a program (and is made into one by ENTER) and that the contents of any program can be executed from the command line editor. Of course, you don't have to use all of the capabilities of RPL; a lot can be accomplished with a relatively simple program.

I'm beginning to feel that SysRPL is, in some ways, even easier, because the "magic" going on internally isn't quite so hidden behind the "smoke and mirrors" of UserRPL. Of course, with SysRPL, the command set is much larger and there are even more ways to accomplish the same thing, and it doesn't automatically check the arguments to protect the user from his own mistakes. The main advantages of SysRPL are that the programs are, as a general rule, smaller and much faster. Still, for fast development of "ad hoc" programs, UserRPL has the advantage that it's difficult to get a TTRM with it.

Of course, I suppose that it could be argued that assembly language gives me the penultimate "peek behind the curtain". There are relatively few instructions available, but remembering which operations are possible with which registers is a challenge, and it generally requires what seems like a lot of instructions to accomplish something that seems pretty basic. Note that the emulated (simulated?) Saturn processor on the 49g+ includes a lot of instructions "missing" from the physical Saturn of earlier models, although I haven't experimented with the new ones yet. The advantage of assembly language is that these programs can be amazingly fast.

Now with the 16C and 12C, trying to write any non-trivial program just seems too complicated. Why go to all that trouble when it's so simple to write a UserRPL program?

Regards
James

Edited: 10 Nov 2005, 6:11 a.m.


Quote:
UserRPL has the advantage that it's difficult to get a TTRM with it.
I have been looking for a UserRPL program (excluding SYSEVAL and LIBEVAL and Dev Library commands) that would TTRM.
Any example?

Arnaud


Quote:
I have been looking for a UserRPL program (excluding SYSEVAL and
LIBEVAL and Dev Library commands) that would TTRM. Any example?

Or in the 49 series, FLASHEVAL.

Of course, this includes calling any program that uses the above
commands improperly, or calling buggy SysRPL or assembly language
programs or external library commands.

In some cases, the problem may not be immediately apparent, but
may corrupt memory so that later perfectly normal operations will
end up with a TTRM.

Of course, the [ON]+[A]+[F] operation is supposed to cause a TTRM.

Other than those, any UserRPL operation that causes a TTRM is
caused by a bug in the operating system; it's just not supposed to
happen. A buggy UserRPL program may well return "unexpected"
results or error out, but it should never cause a warmstart or
TTRM.

That said, if I recall correctly, it's not that hard to write a
"circular reference" program that requires a warmstart to break
out of.

Using the filer to rename a global variable to an invalid name (as
can also be done with S~N) can cause some problems, but I rather
doubt anything that would cause a TTRM.

For some examples, see
this
search
. Some of these may well have been fixed in later ROM
revisions.

Overall, it seems to be pretty rare to stumble across an operating
system bug that causes a warmstart or TTRM in normal "pure
UserRPL" operations, but I wouldn't entirely rule it out.

Regards,
James

Hi James,

Point 1: please compare the 15c or 32sii etc to the 48 series. The 12c is a crippled programming environment.

Point 2: as I rather suspected, if someone (and you are an example) is exposed to RPL before RPN keystroke programming, then RPL is "easier".

Perhaps we aught to take a real poll, and ask the questions:

1. Which is easier to use, RPN or RPL programming?
2. Which do you learn first?


Quote:
Point 1: please compare the 15c or 32sii etc to the 48 series.

I'd like to, but I don't happen to have one of those, and I'm not
likely to get one. I'd love to have a "pocket-sized" RPN
calculator, but considering the current prices, I'll "make do"
with the RPL models, and struggle with a cheap "Brand X" model on
those occasions when I feel a need to carry a calculator in my
pocket.
Quote:
The 12c is a crippled programming environment.

It seems that way to me. How about the 16C? Maybe I should look
into what advantages the 15C and 32sII might have.
Quote:
Point 2: as I rather suspected, if someone (and you are an
example) is exposed to RPL before RPN keystroke programming, then
RPL is "easier".

I expect that that's very much the usual case. With RPL so easy to
use, I personally don't have much incentive to try getting
familiar with programming a "True RPN" model.

That's not to say that I have anything particular against "True
RPN" models. I can program them, but it just seems like too much
bother.

For someone who's already comfortable with programming an RPN
model and finds that it suffices for his purposes, there's
probably not much incentive to learn to work with RPL.

Quote:
Perhaps we aught to take a real poll, and ask the questions:

1. Which is easier to use, RPN or RPL programming?
2. Which do you learn first?


I expect that in this forum, the usual would be "1: RPN, 2: RPN"
with a few "1: RPL, 2:RPL", with just a very few "1: RPN, 2: RPL"
and "1: RPL, 2: RPN".

Of course, if asked in comp.sys.hp48, first off, it would require
some explanation of what was meant by "RPN" as distinguished from
"RPL", and there you'd find relatively few who either peferred RPN
or had learnt it first (if at all).

Regards,
James


Quote:
Quote: The 12c is a crippled programming environment.

It seems that way to me. How about the 16C? Maybe I should look into what advantages the 15C and 32sII might have.


They all three have more programming power than the 12C. As noted previously in this thread, the 16C leaves out a lot of the standard scientific fuctions, replacing them with bit fiddling operations.

The 33S is very similar to the 32SII, and it goes for 50 bucks or so. You want to be sure to get a recent one, as noted in this thread, and elsewhere in the archives. But if you have time and inclination to play, I'd get the Free42 simulator. The consensus here is that the 42S represented the pinnacle of the pure RPN programmable calculator. Free42 will only cost you the time required to set it up. And at least you won't be turned off by arbitrary and silly limits like those the 33S and 32SII suffer under. The other models mentioned also lack alphanumeric capability to a greater or lesser degree, whereas the 42S is fully alphanumeric.

Quote:

I expect that in this forum, the usual would be "1: RPN, 2: RPN"
with a few "1: RPL, 2:RPL", with just a very few "1: RPN, 2: RPL"
and "1: RPL, 2: RPN".

Of course, if asked in comp.sys.hp48, first off, it would require
some explanation of what was meant by "RPN" as distinguished from
"RPL", and there you'd find relatively few who either peferred RPN
or had learnt it first (if at all).

Regards,
James


Yes, by cracky, us old uns is gettin' scarce in these latter, decadent days! Why, when I was a youth, I'd walk three miles through snow just to get enough "N" cells to keep my 41C working with the card reader! Nowadays these youngsters have standard batteries. Bah! Them triple-A's is a dime a dozen!

8) 8)


The 16C does indeed lack such vital (to me) cababilites as trig
and statistical functions, so although it's great for what it's
designed for, it doesn't suit my usual needs at all. The 48/49
series doesn't have all of the "binary" capabilites of the 16C
built-in, but I'm confident that I could write programs for them
if I felt the need; it does seem a bit of a shame that they aren't
all built-in.

I've been thinking of the 33S, but it still doesn't look as if it
would fit very comfortably in my shirt pocket, and doesn't seem as
if I could do anywhere near with it what I can do with the 48SX,
so what would be the advantage over the 48 series? $50 is still
$50, and I don't want to waste it on something that I have no use
for. Now they've come out with the improved version, but since it
still has the same model name, it would seem to be a bit difficult
to know which version one is buying online. It's not as if I could
walk into a store and look at the calculator or its serial number.
Of course, that keyboard is about as ugly as I can imagine,
although I could live with that if there were a good reason for my
owning one.

Maybe I'll look into Free42, but still, what advantage would that
have over the 48 series? On the other hand, at least it's free,
and might be fun to play around with.

Regarding the N cells, I still need them for the 28 series. To be
sure, I don't use the 28S very much since the 48SX came out, but
the 28S is still a very useful calculator, with some advantages
over the 48/49 series. The thing that really put me off on the 28S
was that the first time I got a "low battery" annunciator, I
promptly bought a new set, installed them, and pressed ON, only to
have the 28S turn back off immediately. It turned out that the
"new" N cells were almost completely dead, and the memory had been
cleared. Of course, with no way to input anything other than with
the keyboard, my only backups were printouts. Since then, I just
don't trust the 28 series for storing any object that I really
don't want to key in all over again.

By the way, I expect that the "three miles through snow" was
"uphill both ways"?

With the 49 series, they might better have used AA instead of AAA
cells. The 49g+ in particular goes through them faster than I'd
like.

Regards,
James

You know, I learned FORTRAN (my only REAL programming language outside of calculators; never had the gumption to fully learn anything else) before I ever got a RPN machine and of course, I used HP's RPN beauties for a long time before RPL was ever introduced and finally obtained a RPL unit myself.

I find the order of ease to be RPN > FORTRAN > RPL.

But what I didn't say was that due to my own circumstances, I've had more experience programming a scientific programmable (34C, 32SII, 33S) than FORTRAN on any sized machine, and this more than RPL (48G, 48G+, 49G+)

But I think from the experience of the three for me that RPN is MORE INTUITIVE, as essentially, you are helped by the language being laid out right there for you, right on the keyboard you are pressing on! It did not take me long to figure out programming in RPN on a programmable scientific (though that wonderful old HP-34C manual helped greatly) ; RPL I'm still trying to master and FORTRAN... well, I rub the bumps on my head every time I pass by that guy...

... this stupid comment being said now, I would like to state that I wish schools, from the high school level on, would offer as an alternative (at the start, and make it a fixed part of the curriculum years later) programming a 33S (or better, a 34C if they can manage to get any, so there goes THAT idea... ) as a "starter language" or "pre-programming" (in the same spirit as "pre-calculus", which is how they seem to be packaging some essential algebra and trigonometry for the kids in many U.S. schools these days).

This is because I think programming in the program space of a RPN machine is *SO* easy to pick up for a teenager starting out. It is easier, really than something even little grade school kids (who are still struggling with the multiplication table) can do- use HTML and create a knockout webpage better than some pros.

RPN is better than HTML because you are not concentrating on cosmetics, but calculations and true math, from basic to (acidic... okay, bad joke... ) incredibly advanced (see some of the programs archived here on this very site).

Even though I still do it for my 33S and less now, my 32SII, I still dream wispy-eyed about programming and using my 34C.

Norm Hill, I think, once said to me on this forum that the best thing for an adolescent math student was a HP 33E (no continuous memory means no stored data and thus no... um, less cheating on tests). This is because this rather powerful (and even at the time) affordable calculator had all the basic mathematical functions that anyone in high school to even some scientific research might ever need and is programmable with enough memory for short, useful programs, but not for games or other such waylaying stuff for schoolkids.

* * *

The take home message of this long winded post? RPN is easier. ;)

Quote:
Perhaps we aught to take a real poll, and ask the questions:

1. Which is easier to use, RPN or RPL programming? 2. Which do you learn first?


I think RPN is easier to use, and I learned RPN first. But perhaps I should add that I learned Fortran, BASIC, 6502 assembly, C, Pascal, Forth, COBOL, Natural and Unix shell programming before either RPN or RPL. I still like RPN better even though I think RPL is more like the other languages with which I've worked.

(I also should mention that I needed -- and achieved -- only a minimal amount of proficiency in all but a few of the afore-mentioned languages.)

James posted,

Quote:
To me, it's the "Classic RPN" programming that seems more complicated; sort of like having to write an assembly language program for something that could be accomplished very simply in UserRPL... I learned UserRPL first, and it all seemed pretty straight-forward and logical to me.

...

Now with the 16C and 12C, trying to write any non-trivial program just seems too complicated. Why go to all that trouble when it's so simple to write a UserRPL program?


Yes, and there are those to whom a Rubik's Cube is simple and straightforward, and who can solve it for any initial state in only a few minutes. That's probably not like most people, though...

I agree with Bill Platt: Please use the 15C, 32S/SII, 41S, or 42S as a good example of the RPN programming paradigm. The 12C's programming is primitive; the 16C has a limited set of mathematical operations.

I'll quote several examples from the three earlier threads I linked in a post earlier in this thread. First, my RPL programming challenge, which was to develop a complete program to determine the area between two function curves

f(x) = sin(x)  (x in radians)
g(x) = (x-1.5)^2 - 1

using SOLVE to find the limits of integration where f(x) = g(x), and then INTEG to compute the area between those limits.

My RPN program for the 15C and 34C:

x_lower = 0.343717
x_upper = 2.696175
Area = 3.110575

LBL "A" LBL "B" (execution)
0 SIN RAD
ENTER X<>Y FIX 5
1 1 GSB "A"
SOLVE "B" .
STO 0 5
2 -
ENTER X^2
3 1
SOLVE "B" -
STO 1 -
RCL 0 RTN
X<>Y
INTEG "B"
STO 2
RTN

The approach is quite direct:

  1. Program the driver routine under label "A" and program the routine to calculate f(x)-g(x) under label "B".
  2. SOLVE for x at the first crossing of f(x) and g(x) between 0 and 1 on the stack; store the result in register 0.
  3. SOLVE for x at the second crossing of f(x) and g(x) between 2 and 3 on the stack; store the result in register 1.
  4. INTEGrate f(x)-g(x) over the two solved limits placed on the stack; store to register 2.

Here are the RPL programs the respondents provided:

(store 'SIN(X)' in 'F'; store 'SQ(X-1.5)-1' in 'G')
<< RAD F G - DUP 'X' 0 ROOT OVER 'X' 3 ROOT ROT 'X' (INTEG) >>

(with 'SIN(X)-SQ(X-1.5)-1' on the stack)
<< 'X' DUP2 0 ROOT 3 PICK 3 PICK 3 ROOT 4 ROLL 4 ROLL (INTEG) >NUM >>

Good grief! How would the typical, logical engineering/scientific person read and interpret the respective procedures of those programs? They certainly don't make much sense to me.

How about this program statement:

"IF (A .LT. B)  A = A + 360.0"             (Fortran '77)
"<< IF A B < THEN A 360 + 'A' STO END >>" (RPL)

To read substantial material regarding RPL, RPN, and BASIC discussed last year at length by Valentin Albillo and Vincent Weber, just follow the link to the "RPN vs. RPL" thread I provided. David Ramsey also had some good, clear insights in the "leisure suit" thread.

-- KS


Edited: 10 Nov 2005, 11:31 p.m.


I've just put my finger on what I think is the principal problem I have with RPL. I'm continuing to explore the graphics on the 48G, and I just wrote a program to REPL a list of GROBs into a larger GROB so I can make sure I have the dimensions right and so forth. Here's my very rough, not completely correct work in progress:

<< # 131d # 64d BLANK @ Create a GROB the size of the display
'DICE' RCL @ Get the list of 6 dice images
1 @ Starting index into the list
WHILE DUP 6 <= @ 6 dice images
REPEAT
DUP 1 -
20 * R->B # 30d @ Point in large GROB to REPL the small GROB
2 ->LIST
3 ROLLD GETI @ Pick the current die out o the list
3 ROLLD 5 ROLLD
5 ROLLD @ Set up the stack for the REPL
REPL
3 ROLLD @ Set up the stack for the while loop
END
>>

Now, I could probably be more efficient and logical in my use of the stack. But why the heck should I have to worry about it? But here's a second version that's a little more general, and uses named local variables to clarify what is going on:

<< # 131d # 64d BLANK @ Create a GROB the size of the display
'DICE' RCL @ Get the list of dice images
DUP SIZE -> big dice top @ names!
<< 1 1 top @ The first 1 is a dummy for our return val
FOR idx DROP @ Index named. DROP the dummy (but not the last time)
idx 1 -
20 * R->B # 30d @ Point in large GROB to REPL the small GROB
2 ->LIST -> loc @ name our location.
<<
big loc
dice idx GET
REPL @ MUCH better
>> DUP 'big' STO @ use the same big GROB each time!
@ Also, the DUPd value will stay on the stack
@ the last time only
NEXT
>>
>>

This one is actually completely correct, too.

Why do I have to worry about the stack so much, even in this version? I think it's because Prof. Wickes and colleagues were just coming out of an era in which memory constraints were quite painful in handheld devices. I base this of an analysis of why FORTH's stack oriented quality was perceived as a benefit to many in the 80's, and particularly in the 70's. Stacks are efficient Stack oriented systems can be designed so that limits on stack size aren't arbitrary. That is, you can get pretty close to the ideal maximum of memory usage with stacks. Microcomputers in the 1980s had one or two letter variable names, and a limited number of these. The hassle of keeping track of deep stacks of variables was part of the price you paid to get to use all the memory as efficiently as possible.

But memory no longer needs to be the limiting factor in what are now called "embedded systems." One of my Zaurii has 64MB of SDRAM, and 128MB of flash built in. I can run a version of Linux on that machine that isn't stripped down. The performance is pretty close to a PII/300 or so. The battery life is suprisingly good for all that.

My point is that there is no necessary virtue in using stacks to the extent they are used on the HP48G[X+]. The HP48SX had only 32K to start, which was a lot for the day. But I'm sure that System RPL allowed for a much more capable machine within the RAM constraints. And I'll bet stack usage was a big part of the story. But the 48GX shipped with 128K standard, and expandibility up to 4MB. Suddenly we were looking over the crest of a hill into the era of abundant RAM. And just as suddenly, the need for a stack oriented machine became less pressing.

And what's the tradeoff? Stack diagrams on paper while you are developing a solution. And these tend to disappear ater the initial development, so you get to come back later and figure it out all over again.


Edited: 11 Nov 2005, 4:16 p.m.


I don't see where you're worrying about the stack much in your
second version. You use DUP twice and DROP once, the only stack
manipulation commands that I see in the program. Surely anyone who
programs in RPN should find those simple enough?

Yes, RPL's unlimited (well, limited only by available memory)
variable depth stack does require some complications over a fixed
stack size. Such commands as ROLL, ROLLD, PICK, and UNPICK,
require an argument for which stack level is to be used, and for
DUPN and DROPN how many levels, and there's a need for such
commands as DEPTH and CLEAR. In particular, when the stack gets
"too deep", it gets hard to keep track of just where things are.
Of course, "too deep" varies with the individual user, and for a
given user, such matters as how tired he is and what distractions
he's dealing with. To make it easier to deal with a deep stack,
the stack can be managed by making objects on the stack into a
list, or even easier in many cases, by temporarily storing stack
objects into named local variables.

Note that dealing with lists in temporary memory (never stored as
a global variable, that is) has a disadvantage in that it's
difficult to deal with for "garbage collection" (really, "memory
packing" describes it better). Any element "extracted" from a list
is referenced by a pointer into the still existing (even if it's
no longer on the stack) list until the element is either stored
into a global variable or a NEWOB is done on it. Now, the size of
the list is unknown, so the garbage collection routine has to
examine every object in the list to find the end of it, needed for
deciding how much of temporary memory needs to be kept (and
usually, moved) or can be overwritten. In the case of a large list
that's been "exploded" unto the stack, for example, garbage
collection can take a very long time.

I expect that there will be objections that it's a hassle to
create a new local environment every time you want to store
another object into a local variable. But you can "initialize" all
of the local variables that you're going to use with a dummy value
right at the beginning of a program. For example, by storing the
object 0 into each of them, and then using STO to replace the
dummy object with the desired object as it becomes available. If
you discover that you want another local variable, it's easy
enough to edit the program to add another dummy object and name at
the beginning. If you decide that you don't need a local variable
after all, you can edit out the dummy object and name, or you can
just leave them there; they'll do no harm other than using up a
little memory.

So why have a stack in the first place? Well, first off, how would
you implement an RPN system without one? As long as you already
have a stack, why not have the stack manipulation commands
available to the user, in case he chooses to use them?

I doubt that using the stack is all that much more memory
efficient than using local variables. Either way, the object
exists in memory in only one place. Using the stack, it's
referenced by a pointer on the stack (having objects "on the
stack" is a bit of an illusion by the "smoke and mirrors" of RPL
to make things easy for the user). Using a local variable, it's
referenced by a name in the local environment.

It seems to me that the advantage (or disadvantage) of keeping
objects on the stack and using the stack manipulation commands is
mostly a matter of speed. If you have plenty of time to develop a
faster program using just the stack, you can do that, but if you
need to develop something quickly, or want it to be easy to debug
or modify, you can use local variables, with a bit of an execution
speed penalty. With both local variables and stack manipulation
commands available, it's up to the individual user to choose which
method, or, perhaps more likely, mixture of methods, to use. Where
would you rather spend extra time, in developing the program, or
in running the program? For a fairly complicated program, if
you're going to run the program, say, only a few hundred times,
it's probably going to be difficult to accumulate enough saved
execution time to make up for the extra development time. If
you're going to be using the program frequently for the
foreseeable future, or intend to distribute it, or are just
refining your skills, then it may be worthwhile to spend extra
time on development.

Actually, I suspect that having so many ways to accomplish things
may be a large part of the reason so many seem to find RPL overly
"complicated". It's difficult to teach how to use RPL because
there's no one "right way" to accomplish much of anything in RPL.

Regards,
James


Interesting comments, James. Thanks.

Quote:
I don't see where you're worrying about the stack much in your second version. You use DUP twice and DROP once, the only stack manipulation commands that I see in the program. Surely anyone who programs in RPN should find those simple enough?

Yes, as I've remarked elsewhere, I'm beginning to find ways to code RPL that scan better for me. The names are the key, of course.

There's one other stack oriented oddity in that second example. The "1" placed on the stack before the range of the FOR statement, only to be immediately DROPped off. As the comment states, that's a place holder for the return value of the inner function.

Quote:
Yes, RPL's unlimited (well, limited only by available memory) variable depth stack does require some complications over a fixed stack size. Such commands as ROLL, ROLLD, PICK, and UNPICK, require an argument for which stack level is to be used, and for DUPN and DROPN how many levels, and there's a need for such commands as DEPTH and CLEAR. In particular, when the stack gets "too deep", it gets hard to keep track of just where things are. Of course, "too deep" varies with the individual user, and for a given user, such matters as how tired he is and what distractions he's dealing with. To make it easier to deal with a deep stack, the stack can be managed by making objects on the stack into a list, or even easier in many cases, by temporarily storing stack objects into named local variables.

I prefer the latter. My contention is that large gobs of anonymous data floating on a stack is broken My first attempt shows why I think this is so, not that I hold that up as a prime example of that approach to using an unlimited stack. It's not just an issue of how many things you can juggle in your head via a stack metaphor, either. Source code has a way of creeping away from its author. If someone else ever needs to read that sort of code, the first thing they'll do, once they stop crying, is to start graphing out the anonymous data, assigning temporary names so they can track the stack manipulations on paper. The third thing they'll do is start poking pins in a voodoo doll with your name on it. 8)
Quote:
Note that dealing with lists in temporary memory (never stored as a global variable, that is) has a disadvantage in that it's difficult to deal with for "garbage collection" (really, "memory packing" describes it better). Any element "extracted" from a list is referenced by a pointer into the still existing (even if it's no longer on the stack) list until the element is either stored into a global variable or a NEWOB is done on it. Now, the size of the list is unknown, so the garbage collection routine has to examine every object in the list to find the end of it, needed for deciding how much of temporary memory needs to be kept (and usually, moved) or can be overwritten. In the case of a large list that's been "exploded" unto the stack, for example, garbage collection can take a very long time.

That's interesting. So there's a reference to the element in the list which is the only one, so it doesn't get cleared until the object it references either gains another reference or is explicitly destroyed. That means that the list also hangs around, meaning a reference is kept somewhere to its storage. And GC has to walk the list to see how many and how large the objects it contains are. Because .. why? Because that information isn't kept anywhere else? Must be it.

So anonymous data on the stack is hard for machines and humans both? 8)

Quote:
I expect that there will be objections that it's a hassle to create a new local environment every time you want to store another object into a local variable.

Not from me. I find not having the name to be more of a hassle.

Quote:
So why have a stack in the first place? Well, first off, how would you implement an RPN system without one? As long as you already have a stack, why not have the stack manipulation commands available to the user, in case he chooses to use them?

Anonymous stack data: just say "no!" 8)

C'mon, the unlimited stack isn't just provided, it's a central feature of the machine's architecture.

Quote:
I doubt that using the stack is all that much more memory efficient than using local variables. Either way, the object exists in memory in only one place. Using the stack, it's referenced by a pointer on the stack (having objects "on the stack" is a bit of an illusion by the "smoke and mirrors" of RPL to make things easy for the user). Using a local variable, it's referenced by a name in the local environment.

The names themselves take up space, even if you are hashing them. An 8 character variable name is nothing on a machine with 128K, or even 32K. But User RPL debuted on the HP-28C, with, what was it, 2K?

But, point taken. The major difference between stack oriented and variable oriented processing on the 48G must be the time it takes to create those local variables.

Quote:
Actually, I suspect that having so many ways to accomplish things may be a large part of the reason so many seem to find RPL overly "complicated". It's difficult to teach how to use RPL because there's no one "right way" to accomplish much of anything in RPL.

I think so too. But there is also the counter-example I offered elsewhere of Perl. Perl can be quite a mess because of the variety of ways in which you can do practically everything in the language. But, as I also stated, Perl offers idioms that match the way I think. I find no such easy idiom in RPL. RPL, like RPN, is weird to the rest of the world. I mean, it's an infix world out there, by and large. RPL is even weirder since it carries the postfix notion and stack orientation beyond where the RPN models left off.

To give some idea of what I view as "normal" coding, here's how I would code the GROB example in Perl:

But first, a word about curly braces. ({}). See those nice braces? I can't get them into the [pre] section below. Not only that, but when I type them here, they echo as "|" and "]" in the editor. But they render just fine in the HTML. Have I offended the HP Calculator gods by calling RPN "weird?" Will my calculator collection get up in the middle of the night to give me a good talking to? Let's hope not! 8)

open IN, "blank.grob" or die $!; # No native GROBs, of course.
my @grob_data=(<IN>); # slurp all the data in the file into (named) memory
for (my $i=1;$i<7;$i++){ # Very "C" like iterator
open IN, "die$i" or die $! # no need to close in Perl
push @dice_images, [(<IN>)] # semi-anonymous data, Perl style
# The brackets [] create an anonymous array reference whose
# content is the lines of the file currently open under the IN
# file handle. This array ref gets pushed into the @dice_images
# array, which is a LIFO stack. But in this case there's a name
# associated with the stack. So the third die image is
# $dice_images[2] (0 based arrays) and so forth.
}
for (my $i=1;$i<=@dice_images;$i++){ # an array in scalar context returns its length
my $x=20*($i-1)+1;
replace_grob(
grob_data => \@grob_data,
replace_loc => [$x,30],
repl_grob => $dice_images[$i]
);
}
open OUT ">out.grob" or die $!
print OUT @grob_data;
close OUT; # This flushes buffers on output, but so does ending the program.


Before starting let me say that how you do things is a matter of taste, and programming style. No-one can presume to tell you how to do things.

Quote:
The names themselves take up space, even if you are hashing them.

If you hash the names then you are left with the hash, how are you going to display the name? Also, how will you know you have the correct variable if two names produce the same hash.

Hashing is used to speed up searches not to save memory.


Quote:
Anonymous stack data: just say "no!" 8)

You are confusing variables with objects. In programming languages you can use variables for temporary values, and they will go away once you exit their scope. In RPL these variables are objects that exist in non-volatile memory until you delete them. This is where the garbage collection issue comes in. Its not the computer that will have to do the GC, its the user.

If the program creates variables and then makes sure they are destroyed, then the programmer is burdened with the GC.

If you use the stack, then the computer does the GC without having you to worry about it. Even if you leave garbage on the stack (bad practice, anyway), the user may have to clear the stack, but he will not have to wonder whether to delete that object or not, anything on the stack is assumed to be temporary.

So, as I said aerlier, its a matter of taste, and programming style. Use whatever style you like and feel comfortable with.

**vp

Quote:
There's one other stack oriented oddity in that second example.
The "1" placed on the stack before the range of the FOR statement,
only to be immediately DROPped off. As the comment states, that's
a place holder for the return value of the inner function.

Yes, I do find that rather "odd". My suggestion is to remove that
1, the DROP, and the DUP right after your "inner" program, and
insert a "big" (but unquoted) right after your NEXT. Not only does
that simplify things and make your program smaller, but there's a
speed and run-time memory usage advantage to keeping operations
outside of any loop where feasible, so they don't have to be
executed in every iteration of the loop.

The "unlimited" stack can indeed be difficult to deal with. Of
course, dealing with any program code gets worse if you want to
debug or modify code that you wrote quite a while ago, and worse
yet if trying to understand someone else's source code. Using
local variables can help a lot, as can careful commenting of the
source code. Retaining any comments and the source code formatting
requires that the source code is within a character string or a
file on another device, such as your PC.

On the other hand, even in "True RPN", one has to be careful of
where things are on the stack, although with only four stack
registers and the LAST X register available, it's arguably less of
a chore. But being careful not to try to use more than the
available stack can be a bit of a chore too. If storage registers
are used, the burden is shifted to keeping track of which storage
registers are used, somewhat like keeping track of variables.

The original RPL is what we now call "SysRPL", intended to ease
the development of new "operating system" code as calculators
became more complicated. Using assembler to develop new ROM code
was thought to be too complicated, and apparently none of the
existing "higher-level" languages was considered quite right for
the calculators, so the new language was developed. UserRPL makes
a useful subset of SysRPL available to the ordinary user, with the
built-in compilers checking syntax and run-time argument checking
of UserRPL operations to protect the user from his own mistakes,
as well as checking for a press of the ATTN (or now, CANCEL) key
and such details as occasionally checking the battery condition.
Perhaps some of the perceived "problems" with UserRPL stem from it
being an adaptation of a language not intended for the "ordinary
user".

A problem now is that the original developers are no longer
available, and HP "rested on its laurels" for a long time, with no
development of new calculators or training of new developers. Of
course now even most of the developers of the 49G are no longer
available "in-house", and the in-house "development team" is very
small indeed, with most development (such as the "emulated Saturn
processor" and hardware design) presumably out-sourced. I suspect
that the developers of the 49G sometimes didn't quite understand
the 48GX as a whole, and worked on the areas that they were most
interested in, without enough of a look at how changes affected
the system as a whole, or due consideration of what "ordinary
users" would find most useful. In particular, sometimes the "CAS"
causes the 49 series to return results that look far more
complicated to me than what the 48 series returns, although they
may perhaps make more sense to a "pure mathematician", so may be
better for educational mathematics. Sometimes the CAS rather
cavalierly uses variables in a "higher-level" directory that it
has no business tinkering with, and of course, the CAS routinely
fails to restore any modes that it's changed. And now we have such
niceties as "styles" (bold, italic, underlined, or inverse) and
user-definable fonts, which, while interesting and arguably even
useful, may seem a bit out of place on a "calculator". Is it
intended to be a calculator with rudimentary character string
processing capabilities, or is it supposed to be also a "word
processor"? It seems to me that the distinction between
"calculator" and "computer" has shifted again. That said, I don't
have to use styles or user-defined fonts, but I do pretty well
have to put up with the wonderful CAS if I choose to use a 49
series as a "calculator".

But I confess, I actually do use my own custom font, to make ASCII
control codes 0-9 and 11-27 distinguishable instead of the same
little black square, and make such characters as 0, 7, Z, and z
more to my liking. But I consider the user-defined fonts to be a
frill, rather than essential to a calculator.

Quote:
That's interesting. So there's a reference to the element in the
list which is the only one, so it doesn't get cleared until the
object it references either gains another reference or is
explicitly destroyed. That means that the list also hangs around,
meaning a reference is kept somewhere to its storage. And GC has
to walk the list to see how many and how large the objects it
contains are. Because .. why? Because that information isn't kept
anywhere else? Must be it.

It's complicated, at least to me. Mercifully, a good deal of the
"magic" of RPL (even SysRPL) is hidden from the user by "smoke and
mirrors" (well, perhaps "multiple layers of indirection" would be
more technically correct). Most of the time, the details of
exactly how memory is managed are important only to assembly
language programmers, and perhaps not all that much to them. With
the "internal" languages, it's mostly a matter of knowing under
what circumstances a GC may occur, and being careful that a GC
isn't going to conflict with the execution of the code. But
sometimes, knowing a bit about what really goes on "behind the
scenes" can be interesting, and even useful, to even "ordinary"
UserRPL programmers.

Although I'm fairly experienced in UserRPL, I'm not qualified to
explain the details what goes on what goes on "behind the
curtains", particularly where it gets into assembler.

I'm tempted to explain more of what I do understand, but it would
be very complicated, very lengthy, and mostly irrelevant in this
forum. If you really want to know more about the "internals" of
RPL, I suggest looking in the "usual places" such as
http://www.hpcalc.org/,
http://m.webring.com/hub?ring=hp48, searching the newsgroup
archive at http://groups.google.com/group/comp.sys.hp48?,
and the information available in the MoHPC CD set/DVD. If you
still have a question, ask on the newsgroup.

Quote:
So anonymous data on the stack is hard for machines and humans
both? 8)

I don't understand what you mean by "anonymous" in this context.

Nothing simply appears on the stack without a reason, and every
object contains the information to identify which type of object
it is.

Anyway, for composites and GC, the problem isn't so much what's on
the stack as it is skipping through composites in TEMPOB, although
what pointers are on the stack certainly determines whether GC has
to do this, and how many times it has to be done.

Notably, don't keep anything that you no longer need on the stack.
Among other considerations, a GC has to look at every pointer on
the stack.

Quote:
C'mon, the unlimited stack isn't just provided, it's a central
feature of the machine's architecture.

Okay, the operating system does use the stack a lot, but that's
mostly hidden from the user. For the user, it may well be
convenient to use a few more than the four levels available on a
"True RPN" calculator. In some cases, a large meta-object may be
used on the stack (and usually, combined into a new composite or
array after it's been operated on), but I doubt that many users
keep even a dozen objects on the stack as a general rule. A
4-level stack for the user may suffice in many cases, but that's
up to the individual user with RPL.
Quote:
The names themselves take up space, even if you are hashing them.

Huh? Names aren't hashed. And yes, of course they take up space.
Quote:
An 8 character variable name is nothing on a machine with 128K, or
even 32K.

Well, let me see now, an 8-character name takes up 11.5 bytes
unquoted, or 16.5 bytes quoted. But for local variables, I usually
just use 1-character names, which each use 4.5 bytes unquoted, or
9.5 bytes quoted. After all, it's not likely that I'll be using
all that many local variables in a program, so that's enough to
tell me what it's for. I do know a SysRPL programmer who would be
very happy to find a way to shave 14 nibbles off of his programs,
but for me, saving keystrokes is the main reason, although saving
bytes helps.

Of course, the code for setting up each local environment uses 7.5
bytes too.

And the local environment must use up some memory too, while it
exists, but I don't know how much.

Each stack pointer to an object uses 2.5 bytes. While it exists in
TEMPOB, an object takes up an extra 3 bytes beyond its own size.
Each stack manipulation command uses 2.5 bytes.

I expect that, at least in most cases, using local variables will
indeed use more memory than keeping objects on the stack, but as
you note, the extra memory requirements may be considered
negligible in all RPL models except the 28C.

Quote:
But User RPL debuted on the HP-28C, with, what was it, 2K?

Perhaps 2KB, but only about 1700 bytes are actually available to
the user, and that's with last command lines, arguments, and stack
saves diabled.

I think we can agree that the 28C is rather crippled by it low
memory capacity. I guess that releasing it with so little memory
could be considered a "marketing experiment".

Quote:
But, point taken. The major difference between stack oriented and
variable oriented processing on the 48G must be the time it takes
to create those local variables.

And the time for retrieving or replacing the contents of local
variables (these entail a "search by name"), and abandoning the
local environment at the end.

And of course, "ease of use" and individual preferences.

But don't assume that stack oriented programs will necessarily be
faster. Any operation does take some time. For example, ROLL or
ROLLD, particularly with a high stack level and iterated in a
loop, take an appreciable time, and accessing a local variable is
reasonably fast, as is accessing a global variable at the
beginning of the current directory.

Since any local variable requires a "defining procedure" (a
program or algebraic, or FOR or START loops with their index local
variable) it would be unusual to use one outside of a program,
although one can do so from the command line, which is in fact
compiled to a secondary (the SysRPL version of a program) by
ENTER.

Each style of programming has its advantages and disadvantages. It
may well be that the choice of "variable-oriented" or
"stack-oriented" programming, or which mixture of styles, is
mostly simply a matter of individual preference.

Regards,
James


James,

Thanks again for a thoughtful response.

Quote:
My suggestion is to remove that 1, the DROP, and the DUP right after your "inner" program, and insert a "big" (but unquoted) right after your NEXT.

Thanks. I'll do that in the current version, which retains the kludge.

Quote:
Quote: So anonymous data on the stack is hard for machines and humans both? 8)

I don't understand what you mean by "anonymous" in this context.


I mean "unnamed," which I believe is the dictionary definition of "anonymous." Data on the stack has no name, but is addressed by the user by its position on the stack.

Quote:
Each style of programming has its advantages and disadvantages. It may well be that the choice of "variable-oriented" or "stack-oriented" programming, or which mixture of styles, is mostly simply a matter of individual preference.

If you like, hop on over to this thread, where we are discussing what a fusion of RPN and RPL might look like. We could use the perspective of an RPL fan.

Regards,
Howard

RPL is simpler than TI-Basic. I progam my 49 a lot, also have a TI89. Programs that have the same function are almost always shorter and faster in RPL on the 49 than the 89, neglecting processor speed differences.

TI definitely won the calculator war, but not on programming merits. I've never seen any math/science/engineering professor teaching calculator programming, by the way. Bright kids who are inclined to program will do so on their own, learning from a variety of sources.

The reasons TI dominates the market are: their machines are good quality, easy to use right out of the box, and TI did a great job of selling to educators.


Or in other words, 99 44/100 % of graphing calculator buyers have no intention of programming anything--the programmability is not in their minds *at all* wit hregards to purchasing.


I think you're right here. It's another reason why TI calcs are so popular: they're so easy to use and do most everything right out of the box.

TI's are fairly easily programmed in TI-basic, though, and thousands of programs have been written for them from kids to pros. Check out the immensive archive at www.ticalc.org Sad part is half of them seem to be games.

Is Linux better than *BSD?

Is Windows superior to Linux?

Is RPL better than RPN?

--------------------------


Come on, stop wasting everybody's time with silly questions like these.

Don't like it don't use. That's my rule.

So anything *anybody* says in this forum is not going to change this.

=> the discussion is pointless

**vp


Hi Vassilis,

I don't think this discussion has been pointless. Rather than arguing "mine's better" or something, we have been making some progress towards understanding *why* we feel one is more difficult.

That may be boring to you (you may have already figured it out!) but not to some of us--me included.

BTW as you are a person with considerable interest in outer space, I thought I'd relay a story I told the other day:

The press go all excited about the X-prize for a little while, and Bert Rutan even started to let it get to his head enough to change his mind and start considering an orbital mission as being within the cards sooner rather than later.

So I took a piece of paper, drew a circle on it, and drew a 60 mile high "prick" on the circle. Then I completed the "orbit" that they made--pretending the earth was not in the way. It is of course a very elliptical orbit--looks like a straight line on a piece of paper.

Then I drew a picture of the 1st Mercury orbit. A big circle more or less, only slightly bigger than the earth.

The reaction was pretty dramatic. The visual nature of the difference in energy is striking. In other words Rutan did something great, but even by his own earlier admission, nowhere near the big leagues yet.

Another method of explanation that I used on somebody who did not really get the picture part: "Throw a ball 50 feet in the air. Dfficult? Not really. Now, throw it 50 feet in the air while also getting it to go 385 feet horizontally. Now how difficult was it?"

The light-bulb came on. It is sort of fun figuring out how to de-mystify some of these problems "for the masses".

To some extent, this discussion about RPN/RPL is a delf-directed group "demystification exersize".

Regards,

Bill

Edited: 11 Nov 2005, 9:06 a.m.

As another point of reference, the local Walmart had 3 HP33S units. Two were the older, smaller and harder to read decimal point. They had a serial numbe in the CNA 4xx range. One of the units had a much nicer display - bigger comma and DP and just generally much easier to read. Some of the major bugs seemed to have been fixed (I only tried the cNr and polar conversion but I assume other issues were fixed). This much better 33S had a serial number that started with CNA 532 (which places it mid-2005-ish). Fortunately, HP puts the SN on the back of the blister pack. I never used an older poor-display 33S other than the display model and didn't buy one because of that issue (the bugs were unknown to me at the time). The newer unit seems much improved.


Yay!

Now maybe my original pre-issue buggy version will become a collector's item ;-)


Possibly Related Threads...
Thread Author Replies Views Last Post
  latest prime software release? Geoff Quickfall 3 104 10-12-2013, 03:53 PM
Last Post: Tim Wessman
  So, latest 41CL / Library 4 config is... Gene Wright 4 125 09-22-2013, 02:59 AM
Last Post: Ángel Martin
  Latest 50G Update...? Matt Agajanian 1 67 09-03-2013, 05:00 AM
Last Post: Pier Aiello
  Latest HP Prime "emulator" software available :) Adrien Bertrand 46 703 08-21-2013, 10:48 PM
Last Post: Joe Horn
  SVN command to get latest realbuild Barry Mead 3 110 07-19-2013, 12:59 PM
Last Post: Didier Lachieze
  Latest & Last SandMath is released Ángel Martin 0 68 07-02-2013, 12:44 AM
Last Post: Ángel Martin
  Improved debugger on WP34s Qt Emulator pascal_meheut 0 48 04-15-2013, 03:52 PM
Last Post: pascal_meheut
  [WP 34s] How to get the latest version of file xyz Walter B 3 108 03-17-2013, 05:52 AM
Last Post: Alexander Oestert
  Latest Clonix/NoV's SW update. Diego Diaz 5 106 02-15-2013, 12:12 PM
Last Post: Ángel Martin
  HP-32S/33S/35S emulator with Stack Overflow sensing/Stack display x34 3 106 10-26-2012, 04:56 PM
Last Post: x34

Forum Jump: