For Version 1.06 the the chief aim is to enable the calculator to store the argument (or arguments) of the most recent calculation so that the user can recall them when necessary and push them onto the stack. Version 1.06 implements two new stack functions: **la** ("Last Argument(s)"), and **dr** ("Drop"), the latter of which just pops the top element of the stack. In certain circumstances use of both functions can eliminate much of the pressure of assigning to variables in a program, and thus minimize the risks of wrongly overwriting previously established variables.

Creating the capacity to store and recall last arguments seems straightforward on its face, but is actually fairly complicated, because (1) some math functions are *unary* (i.e., they take only one argument) while others are *binary* (these take two); and (2) there are five operators and 32 math functions through which we must distribute the effect of recording the argument (or arguments) of the most recent computation. The challenge is to find an economical way to achieve this distribution. It all begins with encapsulating the arguments and their associated functions within a brand new class called Arguments. This is a simple class that contains private fields of type *double*, called *value1* and *value2*, to hold either or both arguments of the most recent math operation or function; and another field of type *int* called *arity*, which behaves like a flag, signalling whether the most recent operation took one or two arguments. The Arguments class contains two public methods that effect storage and retrieval of the argument(s) respectively. An instance of Arguments, called *lastArguments*, is made a member of the Calculator class. When the method Calculator::DeployStackFunction() encounters the **la** command, it calls the method Arguments:: Restore(), which first monitors *arity* to determine whether to push onto the stack either *value1* alone, or both of *value1* and *value2*. So far, simple enough.

The complexity arises when we begin to consider recording of the last argument, or arguments. The method Arguments:: Record() *sets* the flag *arity* to either 1 or 2 before popping, recording, and replacing one or two arguments as appropriate. Now we must find a way to minimize the number of calls to this function. Fortunately, the math operators **+**, **-**, *****, **/**, and **%** are all binary, so in the Calculator::DeployMathOperator() method, only one call to Arguments::Record() is required. (We simply have to avert the possibility of invoking this method when the operation is assignment instead.) But the method Calculator::DeployMathFunction() is another story altogether, because many of these functions are unary, whereas some are binary. That is the main reason why we scuttled the lengthy *if-else* block in the DeployMathFunction() method back in Version 1.02, and went with a lengthy *switch* statement instead. Had we stayed with the *if-else*, we would have had to insert a call to Arguments::Record() into the code block of each and every math function. That's 32 instances of a single function call! Much too redundant, much too messy, and quite unnecessary. Instead, we merely *group* these functions according to whether they take one or two arguments. Then we insert some simple code at the top, which determines the value of *arity* based on the index number of the math function being invoked. In so doing we need make only *one* call to Arguments::Record(). The *switch* statement thus turns out to be quite an elegant solution for storing and retrieving last argument(s).

Let's put the new functions **la** and **dr** to work. Suppose we're tasked with writing a program called **f1** to evaluate the following function: f(x, y) = (x + ln y / y) / ln x . Suppose also, for the sake of argument (no pun intended!), that we don't want to risk writing over the values stored in the variables X and Y. We could choose other variables with which to write the program, assuming they are available. However, there is another solution that is superior, because it avoids variable assignment completely. That solution is shown immediately below:

pgm Enter a name for the program: f1 Enter a sequence of program instructions; terminate by entering "end": dp ln sw / + la dr ln / ? end Program "f1" created. Save "f1" to file? (y/n) y Program "f1" saved to file "f1.pf". 47 95 f1 12.219774516 921.3 77.88 f1 134.981665094

Let's trace this chain of calculations to determine what happens at its most crucial steps. It should be clear that the sequence of instructions **dp ln sw / +** goes as far as to calculate the numerator of the function **f1**: (x + ln y / y) . But once these terms are added together, they are no longer available on the stack, and we need x to compute the function's denominator. So we *restore* the two arguments by way of the **la** command and push them back onto the stack. (Both arguments are restored because the operator **+** is binary.) Since we no longer need the argument ln y / y , we just pop it off the stack using the **dr** command. This leaves x at the top of the stack, whereupon we take its natural logarithm, divide numerator by denominator, and output the result.

Anyone who has used an HP 48G calculator, or the newer HP 50G model, will recognize at once that the Tiny RPN Calculator is no match for either of them. Nor was it intended to be. No C++ program spanning just 700 lines or so of code could accomplish what these calculators accomplish. The Tiny Calculator does not display its stack, it does not have graphic capability, it cannot be programmed with branching statements and loops, and for that matter, it only works within the real number system. What about *other* mathematical objects such as complex numbers, vectors, matrices, algebraics, ordered tuples, sets, and the like? Our calculator also falls far short in terms of the stack functions available to it. The HP calculators include at least a dozen more functions that enable users to deal with the stack interactively. (Chances are good that all of these functions could be implemented in our own calculator by applying programming acumen and some hard thinking.) And even if you have interesting applications that are restricted to computation within the real number system, it's a good bet that trying to implement some of them on the Tiny Calculator will be cumbersome at best, and futile at worst. In other words, if you desire a certain application for which the Tiny Calculator proves unsuitable, *write it.*

All that said, adding storage and recall of last arguments does point the way toward possible future development of the Tiny Calculator, if someone cared to develop it. A Version 2.00 of this calculator, if it ever came into being, should deal not just with real numbers but with all sorts of mathematical objects. These objects would very likely be descendants of a generic MathObject class, and the stack would be designed to hold elements of type MathObject. This is the real reason why recalling last arguments proves to be such a powerful and useful facility. It's difficult enough to re-enter a floating-point number; imagine trying to re-enter a *9 x 9 matrix* of floating-point numbers, or some such!

**1)** Using stack functions, write and save to file a program called **delta%2** that functions exactly like **delta%** of Version 1.05, but without assigning to variables. Your solution should contain no more than nine program instructions if it does not use strings to label outputs; somewhat more than nine if strings are used.

**2)** Using stack functions, write and save to file a program called **my%ch2** that functions exactly like the built-in function **%ch**, but without the variable assignments that complicate **my%ch** of Version 1.05. If you do this correctly, your finished program will contain no more than eight instructions.

**3)** You're already aware of the **pr** function of the calculator—the function that adjusts precision of output to a certain specified number of digits. Many times, however, when outputting decimal numbers we would like to express the fractional part of the number using a specific number of digits irrespective of the magnitude of the number's integral part. (Think here of formatting numbers in dollars-and-cents, such as we did in Version 1.01, Exercise 3—i.e., with just two digits after the decimal point.) In cases like these the **pr** function cannot help. Let us therefore add to our library of useful functions the function **fmt**. This function will take as arguments the decimal number to be formatted, and the number of desired digits to the right of the decimal point, in that order; the function will convert our decimal number accordingly. Write and save to file a program called **fmt** that accomplishes this task (at least for any number of digits that falls reasonably within our predefined scope of precision). Your program should use only stack functions; no assigning to variables. Test your program against some well-known decimal constants. (The **fmt** function is analogous to the FIX facility found in HP calculators; however, for our function the name "fmt" is preferred because it operates on only one number at a time, whereas HP's FIX facility *fixes* all outputs to the desired number of decimal places until the user de-programs it, or re-programs it.)

**4)** Think of your own applications that would be worthy of programming on the Tiny Calculator, and saving to files for future use; then implement them.

**1)** We present two solutions below. The first is a "bare-bones" implementation that does not output strings; the second employs strings to function exactly as does **delta%** of Version 1.05. (Credit for this solution belongs to the Hewlett-Packard Corporation; it's one installment of their HP 48 One Minute Marvel series.)

pgm Enter a name for the program: delta%2 Enter a sequence of program instructions; terminate by entering "end": %ch la sw %ch min ? la max ? end Program "delta%2" created. Save "delta%2" to file? (y/n) n 8 10 delta%2 -20 25 10 8 delta%2 -20 25 320.2 3.202 delta%2 -99 9900 6.77 286.5 delta%2 -97.6369982548 4131.90546529 pi e sq delta%2 -57.4831668412 135.200960586 pgm Enter a name for the program: delta%2 The program "delta%2" already exists. Do you want to overwrite it? (y/n) y Enter a sequence of program instructions; terminate by entering "end": %ch la sw %ch min $ 'percent' 'decrease' nl la max $ 'percent' 'increase' nl end Program "delta%2" created. Save "delta%2" to file? (y/n) y 8 10 delta%2 -20 percent decrease 25 percent increase 10 8 delta%2 -20 percent decrease 25 percent increase 320.2 3.202 delta%2 -99 percent decrease 9900 percent increase 6.77 286.5 delta%2 -97.6369982548 percent decrease 4131.90546529 percent increase pi e sq delta%2 -57.4831668412 percent decrease 135.200960586 percent increase

**2)** The solution is as follows:

pgm Enter a name for the program: my%ch2 Enter a sequence of program instructions; terminate by entering "end": sw - la sw dr / 100 * end Program "my%ch2" created. Save "my%ch2" to file? (y/n) y Program "my%ch2" saved to file "my%ch2.pf". 64 92 my%ch2 ? 43.75 64 92 %ch ? 43.75 92 64 my%ch2 ? -30.4347826087 92 64 %ch ? -30.4347826087 pi cb 36 7 / exp my%ch2 ? 452.159896165 pi cb 36 7 / exp %ch ? 452.159896165 36 7 / exp pi cb my%ch2 ? -81.8893040414 36 7 / exp pi cb %ch ? -81.8893040414

**3)** Note that in this solution, and in some solutions to previous exercises, we have declined to build the output instruction **?** into our program. The reason for that is to give users the option to print outputs with or without strings to label them.

pgm Enter a name for the program: fmt Enter a sequence of program instructions; terminate by entering "end": 10 sw yx * la sw dr sw round sw / end Program "fmt" created. Save "fmt" to file? (y/n) y Program "fmt" saved to file "fmt.pf". pi 2 fmt ? 3.14 pi 8 fmt ? 3.14159265 e 6 fmt ? 2.718282 2 sqrt 5 fmt ? 1.41421 2 sqrt 7 fmt ? 1.4142136 200000000 sqrt 3 fmt ? 14142.136 5 sqrt 1 + 2 / dp 5 fmt ? sw r 5 fmt ? 1.61803 0.61803 300000 7 / 2 fmt $ 'payable' 'on' 'demand' nl 42857.14 payable on demand