HP-67
Section: User Commands (1)
Updated:
Index
NAME
hp67
- a scientific calculator in Reverse Polish Notation
SYNOPSIS
hp67
[-n|--noexit] [--program=program|-p program]
[--ignorercfile|-i] [--help|-h]
DESCRIPTION
This program emulates an HP-67 calculator with a few minor variations.
This calculator uses the 'Reverse Polish Notation' favoured by
Hewlett-Packard.
Reverse Polish Notation is somewhat different from the "forward"
notation available on many, probably most, handheld calculators. It is
the notation used by the Forth system of languages. Here are some
examples of how the notation works:
To evaluate: (3 + 4*7) / (2 + 8^3)
You hit the following sequence of keys:
-
3 <ENTER>
4 <ENTER>
7 *
+
2 <ENTER>
8 <ENTER>
3 y^x
+
/
The <ENTER> key is used to separate different numbers entered
consecutively. As numbers are entered they are pushed onto a LIFO
stack. The most recently entered number, at the top of the stack, is
called the 'X' value, the next most recently entered number is the 'Y'
value. On the screen the 'X' appears nearest the bottom, with 'Y'
immediately above it. Unary operations such as 'sin' pop a single
number (X) off the stack, act on that number, and push the result onto
the stack. Binary operations such as '/' pop two numbers off the stack,
and divide the first number popped (X) into the second (Y), then push
the result onto the stack. This has the effect of reducing by one the
total number of elements on the stack. Look over the above example
until it's clear. Another register, 'LSTX', is not displayed on the
stack. This holds the value which 'X' held before the last operation
was made. Not all operations will update this number. LSTX is most
commonly used in error correction, such as if you typed '*' instead
of '/', and in the implementation of automatic constants.
OPTIONS
- -n, --noexit
-
Disable the CTRL-D exit key.
This
behaviour is desirable if the program is run from within a
dedicated xterm,
such as
via
the following shell script:
-
#! /bin/sh
#
/usr/X11R6/bin/color_xterm $@ -ls -tn xterm-color \
-e hp67 --noexit &
-
This script can then be invoked, for instance, as follows:
-
hp67.sh -iconic -geometry +700+400
-
to produce a dedicated xterm window which cannot be aborted, short of
sending the program a killing signal.
- -p program, --program=program
-
Load the program space with the named program during. Equivalent to
issuing the command
r/prog program
from the keyboard immediately when the program begins.
- -i, --irnorercfile
-
Don't preload any programs.
- -h, --help
-
Issue a usage message and exit.
SPECIFICS OF THE HP-67 EMULATOR
Command entry format
Numbers must be entered alone on the line. They may be expressed in
fixed or scientific notation. Examples of valid entries on the command
line are:
-
12.493 12.4e-5 .008E4 1.2E+4
Note that it is not normally possible to enter negative numbers
directly at the command line prompt (but see the entry for '{' in the
section on "magic" keys in curses mode.)
Commands and operations may be entered alone on the command line, or
immediately after a valid number, with argument if allowed. The argument
must be separated from the command by one or more blanks or tab
characters. Examples of valid commands and operations are:
-
+
sto speedoflight
dsp 9
fix
See the list of operations for details of which commands require
operands.
If an operation pops a non-existent stack element, it is not an error,
a zero is obtained. Similarly, an attempt to read an uninitialized
memory element returns a zero.
Display layout
The calculator requires at least an 80x22 screen to work, and the
layout of buttons is most logical when the number of columns is
exactly 80. The upper portion of the screen consists of buttons
showing the currently valid commands to the calculator. The right side
has a numeric keypad, while the lower-left portion is responsible for
interaction with the user. The lower-middle portion shows the most
recently accessed memory elements, up to 15 if the number of screen
rows is large enough, and the first 8 characters of the element's
label (assuming an 80 column screen).
In immediate (interactive) mode, a number of stack elements are
displayed in this region, with X at the bottom, Y above it, and higher
elements above those.
In program mode, the current insertion and run point is shown with
an arrow to its left. Above and below it are neighbouring program
elements. New elements are inserted after the position of the arrow,
and when the calculator runs, the arrow always shows the next step
which will be executed.
A stepping mode also exists. If a program is interrupted with a
keypress, or if "step" is entered in immediate mode, then the display
shows part of the stack, and part of the program. The program window
shows the next step which will be performed, the earlier step in the
program memory (not necessarily the last step performed, if that was a
branch), and the step after the next one to be performed. Every time
"step" is entered, one program step is executed and the insertion/run
pointer is updated.
Curses magic behaviour
When operating in curses mode, hp67 performs some extra actions for
certain input sequences.
The '#' is a comment character for almost all functions. The disk
I/O functions ignore it, and so can load file names containing the
character, but all other operations consider that the argument ends
with the last non-whitespace before the '#' character appears. A
comment may not be the only content of the input line.
If a line of input begins with a character which identifies it as a
number, such as a digit or decimal point, then it continues to accept
characters until such time as one shows up which is not part of a
valid float. The valid float is passed to the interpreter, while the
remaining text waits on the input line. So, if the sequence "102s" is
typed, it is as if the number "102", then <ENTER>, then "s" were
typed. If the sequence "45e+l" is entered, it is interpreted as "45",
<ENTER>, "e+l". Note that there is at present no command which begins
"e+l", so this is likely not to appear in normal use. If the sequence
"1e4e" is typed, it is interpreted as "1e4" (10000), <ENTER>,
"e". This number watching allows one to avoid an extra keypress, it is
legal to type "30 ENTER 40 +", the result is seventy.
Note that the following sequence on the command line: "3+4" <ENTER>
may not do what you expect. This has the effect of pushing 3 onto the
stack, adding it to whatever was on the stack before, then pusing 4
onto the stack.
Now, the input line supports a few special command sequences.
In the following, the notation "M-a" means "meta (lowercase) a".
This sequence can be produced by holding down the ALT key on terminals
which support this, or prefixing the 'a' keypress with ESC.
The following are 'hot keys'. If they are entered in the first position
on a blank input line their functions will be invoked:
- <DELETE>
-
In immediate mode, invokes the "clx" function to delete
the top element of the stack. In program mode, deletes the
current program line.
- M-<SPACE>
-
In immediate mode, invokes the "step" function.
- M-<key>
-
If <key> is a printable key, in immediate mode this
invokes the command "run <key>", running a subroutine
identified by the single letter label <key>. In program
mode, this invokes the command "label <key>", creating an
entry point identified by the single letter label <key>.
- <CTRL>-D
-
In immediate mode, exits the calculator. In program mode,
returns to immediate mode.
- UP-ARROW
-
In program mode, moves the program insertion/execution
pointer back one space.
- DOWN-ARROW
-
In program mode, moves the program insertion/execution
pointer forward one space (without executing the step).
- {
-
As the first element on the line, the '{' character
disables (for the current input line) the magic
floating-point number parsing described above. This is
intended for future expansion, when input types such as
complex numbers may use different characters to mark
input. It can be used to enter negative numbers at the
command line.
- CTRL-L
-
forces curses to redraw the entire window from scratch.
Useful if the window is resized, or if some other
output to the screen intrudes.
All control keys not listed above are filtered at the keyboard read
stage and can never be embedded into labels or commands. The TAB key is
immediately translated into a blank at read time.
On terminals which support ncurses mouse events, the function list
at the top of the screen, and the keypad on the right side, are both
clickable to invoke the corresponding action. Commands which take no
arguments are sent with an implied <ENTER> following them, so simply
pressing the text of "sin" calculates the sine of the current X
value. Commands which take arguments are sent with an implied BLANK
following them, allowing the user to enter the argument. Numbers on
the keypad, of course, are sent without modification.
LIST OF COMMANDS
The following commands are available either in programming or in user
mode:
- +Addition operator X <- Y + XLSTX
-
This operator takes no arguments. It pops the top two elements of
the stack and adds them together, pushing the result on the stack.
- -Subtraction operator X <- Y - XLSTX
-
As above, but it subtracts.
- *Multiplication operator X <- Y * XLSTX
-
As above, but it multiplies.
- /Division operator X <- Y / XLSTX
-
- !Factorial operator X <- !XLSTX
-
This operator takes no arguments. It replaces the value in the X
register with the factorial of the number. The factorial is the product
of all natural numbers less than or equal to the number. If the value
in X is not an integer, it returns the real-number generalization of
the factorial, the gamma function of 'X+1'. An error occurs if X is a
negative integer, or if an overflow occurs.
- recipReciprocal operator X <- 1 / XLSTX
-
This operator takes no arguments. It replaces the value in the X
register with its reciprocal.
- chsChange sign operator X <- -XLSTX
-
This operator takes no arguments. It replaces the value in the X
register with its negative value.
- sinSine operator X <- sin(X)LSTX
-
This operator takes no arguments. It repalces the value in the X
register with its sine, where X is interpreted as an angle in the units
of the 'THETA' flag. See below for information on changing this flag.
- cosCosine operator X <- cos(X)LSTX
-
As above, but for cosine.
- tanTangent operator X <- tan(X)LSTX
-
As above, but for tangent.
- asinInverse sine operator X <- asin(X)LSTX
-
As above, but for inverse sine.
- acosInverse cosine operator X <- acos(X)LSTX
-
As above, but for inverse cosine.
- atanInverse tangent operator X <- atan(X)LSTX
-
As above, but for inverse tangent.
- sqrtSquare root operator X <- sqrt(X)LSTX
-
This operator takes no arguments. It replaces the value in the X
register with its square root. This won't work for negative numbers.
- squareSquare operator X <- X ^ 2LSTX
-
This operator takes no arguments. It replaces the value in the X
register with its square.
- lnNatural logarithm operator X <- ln(X)LSTX
-
This operator takes no arguments. It replaces the value in the X
register with its natural logarithm.
- expExponential operator X <- exp(X)LSTX
-
This operator takes no arguments. It replaces the value in the X
register with e^X.
- log10Base 10 logarithm X <- log(X)LSTX
-
This operator takes no arguments. It replaces the value in the X
register with its base 10 logarithm.
- exp10Power on 10 operator X <- 10^XLSTX
-
This operator takes no arguments. It replaces the value in the X
register with 10^X.
- y^xPower operator X <- Y ^ XLSTX
-
This operator takes no arguments. It replaces the value in the X
register with the value Y^X. This returns errors if X is negative and Y
is not an integer, or if X is zero and Y is less than or equal to zero.
- absAbsolute value operator X <- abs(X)LSTX
-
This operator takes no arguments. It replaces the value in the X
register with its absolute value.
- dspSet display precision
-
This operator takes one argument, an integer between 0 and 14
inclusive. In 'fix' and 'sci' modes this sets the number of digits to
appear to the right of the decimal point. In 'eng' mode this sets the
total number of digits to appear on the screen to 'n+1'. In other
words, changing from 'sci' to 'eng' mode does not change the precision
of the display. This operator is available with indirection. If the
argument is "(i)" it will set the number of digits to the greatest
integer value of the I register, if that value lies in the correct
range.
- fixSet fixed display mode
-
This operator takes no arguments. It sets the display of stack
elements to fixed point notation. Numbers which cannot be displayed
in this notation in the precision specified by 'dsp' will be displayed
instead in scientific notation.
- sciSet scientific notation display mode
-
This operator takes no arguments. It sets the display of stack
elements to scientific notation. In this form all numbers are written
with a single digit preceding the decimal point, and a four digit
exponent on the right of the display.
- engSet engineering notation display mode
-
As above, but between one and three digits precede the decimal point,
and the exponent is always a multiple of three.
- hexSet hexadecimal display mode
-
In hexadecimal mode, all numbers are displayed in hexadecimal
format, as the next integer closer to zero (i.e. rounding down for
positive values, and up for negative values). In hexadecimal mode the
magic input completion is disabled, and numbers can be entered as
either octal, decimal, or hexadecimal integers. A number beginning
with '0x' is interpreted as hexadecimal, otherwise a number beginning
with '0' is octal. In all other cases the number is treated as a
decimal value.
- degSet degrees mode THETA = degrees
-
This operator takes no arguments. It sets the internal 'THETA' flag
to degrees. All subsequent angles are interpreted in units of degrees,
and functions which return angles return them in degrees.
- radSet radians mode THETA = radians
-
As above, but it sets angles to radians.
- grdSet gradians mode THETA = gradians
-
As above, but it sets angles to gradians. There are 400 gradians in
a circle, and if you use this mode even once I'll be surprised.
- stoStore to memory register <label> <- X
-
This operator takes a single argument. That argument can be any
string which does not contain a '#' and does not begin with a '.'.
The current X value will be written into the memory identified by this
label. If no such memory register exists, it is created. This
operator can also use indirect addressing. If the label is "(i)", the
current value of the I register is extracted, converted to an integer,
then to a character string, and passed as if it were the argument
typed on the command line. So, if I holds the value 214.1, the X
register is stored to the memory element labelled "214".
- rclRecall from memory reg. X <- <label>
-
As above, but it recalls from memory and pushes the number obtained
onto the stack. The current X value is not lost, it is merely pushed up
with the rest of the stack.
- sto+Add to memory register <label> <- <label>+X
-
This operator takes one argument, the memory label. It acts like the
register, it adds the current X value to it. This operation is
available with indirection.
- sto-Subtract from memory reg. <label> <- <label>-X
-
As above, but it subtracts X from the memory register.
- sto*Multiply into memory reg. <label> <- <label>*X
-
As above, but it multiplies X into the memory register.
- sto/Divide into memory reg. <label> <- <label>/X
-
As above, but it divides X into the memory register.
- x<>ySwap X and Y X <--> Y
-
This operator takes no arguments. It exchanges the X and Y elements
on the stack. This is useful, for instance, if you want to evaluate
X^Y. You can first swap X and Y, then use the 'pow' operator.
- r>pRectangular to polar conversion LSTX
-
This operator takes no arguments. It converts the pair (X,Y) into
polar form.
-
X <- sqrt(X^2 + Y^2)
Y <- atan2(Y,X)
- p>rPolar to rectangular conversion LSTX
-
This operator takes no arguments. It reads the X register as a
distance and the Y register as an angle, and converts to cartesian form.
This has the effect:
-
X <- X * cos(Y)
Y <- X * sin(Y)
-
The former Y value is lost.
- d>rDegrees to radians conv. X <- X * 180/piLSTX
-
This operator takes no arguments. It converts the value in the X
register from degrees to radians. Note that it does not change the
value of the 'angmode' internal flag.
- r>dRadians to degrees X <- X * 180/piLSTX
-
This operator takes no arguments. It converts the value in the X
register from an angle in radians to one in degrees. Note that it does
not change the value of the internal 'THETA' flag.
- piNumerical value of pi X <- pi
-
This operator takes no arguments. It is shorthand for entering the
first 19 decimal places of 'pi'. It pushes 'pi' onto the stack. The X
register is not lost, it moves into the Y register, and so on down the
stack.
- h>hmsHours to hours/minutes/seconds conversion LSTX
-
This operator takes no arguments. It reads the X register as a
number of hours, and converts it to hh.mm.ssss form. See the 'hms+'
and 'hms>h' operators description for more information.
- hms>hConvert hours/minutes/seconds to hour LSTX
-
This operator takes no arguments. It reads the X register as a
number in hh.mm.ssss form and converts the result to a fraction of an
hour. So, 1.30 would become 1.5, since one hour and thirty minutes is
equal to an hour and a half.
- hms+Add in hours/min/sec fmt. X <- X + Y hmsLSTX
-
This operator takes no arguments. It adds X and Y as if they were
in the form: hh.mmssss. That is, the integer part of the number is
taken as hours, the first two digits after the decimal point are taken
as minutes, and all digits after that are interpreted as seconds. For
instance, 3.182014 would become 3 hours, 18 minutes, 20.14 seconds.
After the addition, the result is adjusted so that the seconds and
minutes fields do not equal or exceed sixty. For example:
-
1.4020 <ENTER>
1.3052
hms+
-
yields: 3.1112
- intInteger roundoff X <- (int)XLSTX
-
This operator takes no arguments. It rounds the number in the X
register to the next integer closer to zero.
- fracFractional part X <- frac(X)LSTX
-
This operator takes no arguments. It discards the integer portion of
X. If X is negative, it still discards the whole part, so that
-
frac(-1.2) = -0.2
- roundRound off to displayed value
-
This operator takes no arguments. It rounds off the value in the X
register to the actual value displayed on the screen. If the X register
holds 1.2284, and the display mode is 'fixed' and 'dsp 2', then the
screen will display the value '+1.23'. The 'rnd' function rounds off the
internal representation to match.
- rciRecall from I register
-
This operator takes no arguments. It pushes the current I value onto
the stack, pushing the rest of the stack down to accomodate it.
- stiStore in I register I <- X
-
This operator takes no arguments. It stores the current X value in
I. The former value of I is lost, nothing else is changed. Note that
this function cannot be replaced by "sto (i)" as that would invoke the
indirection behaviour of the "sto" function.
- dszDecrement; skip if zero I <- I - 1
-
This operator takes no arguments. It decrements the I register. If
a program is executing, and the I register is zero after the decrement,
then the next program step is skipped.
- dsz(i)Decrement indirect; skip if zero
-
This operator takes no arguments. It decrements the memory register
whose label matches I. If the register is zero after the decrement and a
program is executing, the next program step is skipped.
- iszIncrement; skip if zero I <- I + 1
-
As 'dsz', but it increments the register.
- isz(i)Increment indirect, skip if zero
-
As 'dsz(i)', but it decrements the register.
- x<>iExchange X and I X <--> I
-
This operator takes no arguments. It exchanges the current X and I
values.
- stat+Add statistical data pair LSTX
-
This operator takes no arguments. It takes the current X and Y
values and updates internal registers containing the sum of: X, X^2,
Y, Y^2, and X*Y. The X value is replaced by the total number of data
pairs collected. This function can also be used if you are only
processing X values, rather than X,Y pairs. Just ignore the results
from the 'Y' values. This operator updates memory elements accessible
to any running program. These are, "_stats_sumx", "_stats_sumx2",
"_stats_sumy", "_stats_sumy2", "_stats_sumxy", "_stats_n", and
contain the sum of values of X, X squared, Y, Y squared, X * Y, and
the number of points, respectively.
- stat-Subtract statistical data pair LSTX
-
As above, but it subtracts out the values from the internal
registers. This is usually used to remove erroneous data pairs entered
with 'sum+'.
- avgObtain average X and Y values LSTX
-
This operator takes no arguments. It replaces the current X and Y
values with the average values of X and of Y entered with 'sum+'.
- sdevObtain standard deviation of X and Y values LSTX
-
This operator takes no arguments. It replaces the current X and Y
values with the standard deviations of X and of Y entered with 'sum+'.
- %Percentage operator X <- Y * X/100LSTX
-
This operator takes no arguments. It multiplies the top two elements
on the stack, and then divides by 100.
- %chgPercent change operator X <- (X-Y)*100/YLSTX
-
This operator takes no arguments. It changes the value in the X
register to the percentage of Y by which X differs from Y.
- clxClear X value X <- Y
-
This operator takes no arguments. It pops the stack, discarding the X
value and promoting the former Y value to the new X value. Note that
this is subtly different from the clear operator on the HP-67, repeated
invocations of which do not clear the entire stack.
- rdownRoll stack down
-
This operator takes no arguments. It rolls the stack so that the X
value goes to the bottom of the stack, and all other registers move up
one position, making the former Y value into the new X value. This
differs from the HP-67 roll down operator in that it rolls only active
stack elements. The HP-67 has a stack size of four, and the X register
is always moved into the fourth position, even if fewer than four stack
elements were in use.
- rupRoll stack up
-
This operator takes no arguments. It rolls the stack so that the
bottom stack element moves into the X position, and all other stack
elements move one level deeper. This differs from the HP-67 operator in
the same way as 'rdown' above.
- lastx