Moving data from the HP 48 to a desktop computer is easy with Kermit and a serial cable. The problem, however, is the format or usability of the data once it is moved to the desktop. One of the most common formats used to share data among programs is comma delimited data to be used in a spreadsheet.
An array is a very efficient form to store purely numeric data on the HP 48 series machines. An HP 48 Array is of two types. A vector, for example, [ 1 2 3 ] or a Matrix, for example, [[ 4 5 6 ][ 7 8 9 ]]. If the OBJ-> command is applied to either form the array is disassembled and the elements of the array are exploaded onto the stack with a list containing the number of rows and columns on stack level one. The vector above produces { 3 }, and the Matrix produces { 2 3 }, two rows of three elements.
For maximum flexability either form is to be converted to a string in row order. The first step is to process each of the OBJ-> list possibilities so that either works. This is done by adding 1 to the list to insure that there is a minimum of two elements in the list. If the elements of the list are multiplied with the HP 48 G series list command, ãLIST, the number of elements in the array is produced. The short program 'NEA', Number of Elements in Array, produces the number of elements given the array on level one. If the input is ALWAYS a vector the, 1 + ãLIST commands may be omitted.
'NEA' << OBJ-> 1 + ãLIST >>
The next step is to reassemble the elements into a vector (or list) and convert to a string. OBJ-> allows either a list or an array to be used as the input. Once the array or list is assembled it is converted to a string with ->STR. Using the Matrix example the result is:
We want a string of the elements without brackets (or curly braces if a LIST is used), leading or training spaces. This is accomplished by SUBing the 3rd thru SIZE minus 2 characters. A program that takes the result of 'NEA' and makes a string is Stack to String, 'S2S'.
'S2S' << ->ARRY ->STR 3 OVER SIZE 2 - SUB >>
The example matrix now looks like:
Now all that is left is to replace the spaces with comas and we have the desired format. This is done with the position, POS, command. POS returns the first postion that matches the input string. Once the space position is known REPL is used to replace it with a comma. 'S->C' does this.
'S->C' << DUP " " POS "," REPL >>
This program will replace each space with a comma until POS doesn't find a space. With the program in the menu you need to press the key five times to remove all the spaces.
The next step is to automate the process with a loop. The WHILE, REPEAT, END looping structure is used. It looks like this:
'AS->C' << WHILE DUP " " POS DUP REPEAT "," REPL REPEAT END >>
Auto Space to Commas, 'AS->C', works well. A zero, however, remains on the stack because the last POS returns a zero when no space is found. This is what stops the loop. Add a DROP at the end and the program is complete. Array to String with Commas, 'A2SC', combines all of the above.
'A2SC' << OBJ-> 1 + ãLIST ->ARRY ->STR 3 OVER SIZE 2 - SUB WHILE DUP " " POS DUP REPEAT "," REPL END DROP >>
100 6 digit Numbers in a vector converts to a comma delimited string in 8.86 seconds. Using ->LIST instead of ->ARRY is slower at 11.05 seconds.
The string (text) form takes 704 bytes compared to the original array at 812 bytes resulting in a 13% improvement in memory usage. The last step is to send the string out the serial port. If the array is very large memory will be a consideration and this program should be examined for memory usage as well as speed. While reasonable programming techniques are used no claim is made for this program being optimum. The HP 48 keeps copies of objects in memory while certain commands are executed. If memory is a problem it may be better to process the array element by element and add a comma while sending it out the serial port. This approach would be slower. The choice of OBJ-> and ->ARRY are based on the timing of a random 6 digit 100 element ARRAY and the same elements as a list. The values are in the following table.
Disassemble | Reassemble | Array | List |
OBJ-> | ->ARRY | 8.863 | 8.870 |
OBJ-> | ->LIST | 11.047 | 10.944 |
ARRY-> | ->ARRY | 8.868 | * |
ARRY-> | ->LIST | 11.043 | * |
LIST-> | ->ARRY | * | 8.638 |
LIST-> | ->LIST | * | 10.963 |
The approach above works. There is another approach. The first step is the same using 'NEA'.
The next step is to reassemble the elements into a string adding commas after each element as they are taken from the stack. The stack contains the number of elements in the array on level one. To combine them one less operation is required than the total. A START NEXT loop is used starting with two. 'A2SC1' is the complete program.
'A2SC1' << OBJ-> 1 + ãLIST 2 SWAP START "," SWAP + + NEXT >>
This program is for G series machines only because it uses ãLIST. Array or list data may be used. If the data is in vector form, the program may be simplified to:
'A2SC2' << OBJ-> EVAL 2 SWAP START "," SWAP + + NEXT >>
A universal program for HP 48 S and G machines, arrays (vector or matrix) or lists is shown in the box below. It is fast and does not use list processing commands. Good HP 48 operating practice suggests that last argument is kept active - system flag -55 is clear. The LASTARG command is used in the program. The timing for 100 data is given. The time for larger arrays or lists increases. Doubling the size nearly triples the time. This is not a major problem because the conversion is usually done only once to move the data to the PC.
'A2S' << OBJ-> EVAL LASTARG SIZE 1 - { * } IFT 2 SWAP START "," SWAP + + NEXT >> |
When the text string is transfered to the PC a header will be added. This will have to be deleted using a text editor. It is usually less than the first dozen (obvious) characters.
The inverse of 'A2S', Array To String, converts a comma delimited string to a vector. The program String To Array, 'S2A', is listed in the box below. The program must run with whatever is on the stack above the input string. The DEPTH commands are used to assemble what is on the stack into a list so the string may be exploaded onto the stack with OBJ-> and reassembled into an array.
'S2A' << DEPTH ROLLD DEPTH 1 - ->LIST SWAP OBJ-> DEPTH 1 - ->ARRY SWAP LIST-> 1 + ROLL >> |
REV B 960430