***** *** * * **** ***** ***** *** * * * ** * * * * * * * * * * * * * * * * * **** * **** * * * * * * *** *** * * * * * * * * * * * * * ** * * * * * * **** ***** * * **** * ****** *** Volume 3 Number 2 48/39 February 1978 Newsletter of the SR-52 Users Club published at 9459 Taylorsville Road Dayton, OH 45424 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Practical Application of Obscure but Powerful Programming FeaturesIn asking the question: has anyone found a practical use for having a subroutine call itself? Cliff DeJong (290) suggests a broad topic for membership exploration: Given one of the more powerful but seldom-used machine capabilities, show how it can enhance the solution of a practical programming problem. Several somewhat obscure 58/59 capabilities come to mind: 1) Use of all 6 subroutine levels; 2) Use of both an indirect conditional and its indirect transfer together, i.e. Dsz*ab*cd; 3) Use of the list, trace, and Op 8 functions under program control; and 4) Use of HIR operations to alter stacked operands before pending arithmetic is executed. Members are invited to address these and to suggest other related topics covering any of the TI PPCs. I'll lead off with some thoughts concerning Cliff's question. Given the architecture of the TI PPCs, I can't think of a practical application where having a subroutine call itself is an advantage. Seq- uences of the form: ...Lbl a ...b ...Lbl b ...rtn are indeed useful (see the V2N5p5 program), but amount to 2 routines sharing some common code, not one routine calling itself. A routine of the form: ...Lbl a ... a ...rtn calls itself, but without further specification, would not terminate. It could be made to terminate by writing something of the form:Lbl aseq1 ifflgx b stflgx aLbl bseq2 rtn. Calling it with Flag x unset would cause the code designated by seq1 and seq2 to be executed as: seq1 seq1 seq2 seq2; calling with Flag x set would produce: seq1 seq2. More flags could be introduced to produce more variations, but I suspect the overhead of flag testing and setting would make straight forward calls to separate subroutines more attrac- tive. Anyone else care to address Cliff's question?Efficient Print Code StorageClive Durbin (618) has found a HIR application which significantly minimizes data storage and processing requirements in many cases. His approach takes advantage of the differences in how Op 4 and HIR 08 treat display values during transfer to the print buffer. While Op 4 copies the 8 LSDs of the integer part of the display into the 8 LDSs of the print buffer (HIR 8), the HIR 08 function copies an entire real, as formatted in the display register. Thus only the print code con- tained in the integer part of the displayed mantissa is used to gen- erate a character string with an Op 4, while as many as 8 LSDs (regard- less of decimal point position) are used with HIR 08 storage. Using Op 4 to prepare one character string for printing, and HIR 08 on the - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

same number for another not only saves the unpacking required in the V2N11p6 approach, but allows for overlapping that can enable one real to prepare 2 strings of up to 4 characters each. For example, Op 4 Op 6 on 916323117.4437 produces the tag DONE, while HIR 08 Op 6 on the same number produces NEXT. Note that the leading 9 serves as a dummy filler to force right justification within the 13 mantissa places, and that because of the odd number of mantissa places, overlapping with Op 5 printing would be difficult at best. However, there may be useful strings of characters some of whose print codes can be split and re- paired to form other useful strings. For example, 1624222437.253 produces DIGIT with Op 1 Op 5, but VGW÷π with HIR 05 Op 5 (sorry, I couldn't think of a more useful example!). Members are invited to share their best (most practical) Op 4/Hir 08 Op 6 and Op 1-4/ HIR 05- 08 Op 5 creations.Recording Current Machine States (52,59)In many practical applications it would be helpful to be able to record on mag cards such things as flag status, display format, angle mode, partitioning, printer connection, CROM module number, the con- tents of the HIRs and the T register ... prevailing conditions which the user might need to manually reinitialize every time he reads a particular card. Converting such information into recordable data is, for most of the above, a fairly straight forward exercise, but doing it efficiently may be somewhat challenging. For example, 10 registers could be designated to hold flag status: each stored with a 1 for set, 0 for not set, but this might be unacceptably wasteful of data registers. So it is attractive to consider data packing as an alternative. The following sequence stores the status of all 10 flags in Reg 1, taking advantage of the machine interpretation of flag 10 as flag 0 (TI-59): ... 0 S01 10 S00 1 S2L1'CLR INV Ifflg*0 2' 1 L2' X R2 = SUM01 10 Prd2 Dsz0 1' ... and the following takes the value in Reg 1 and sets all 10 flags accordingly: ... CP 10 S0L3'R1 ÷ 10 - Int S1 = x=t 4' Stflg*0L4'Dsz0 3' ... . See V1N5p6 for a display- format determining routine, V2N11p6 for angle mode indicator, and V2N9p2 and V2N10p3,4 for printer connection sensing. Partitioning can be decoded with: ... Op 16 INV Int X 10 + 1 = Int S1 ... and set with:... R1 Op 17 ... . Picking a suitable approach to saving the contents of the HIRs is somewhat frustrating: There ought to be a straight forward way to loop through a basic sequence 8 times, but there doesn't seem to be since the HIRs are not indirectly addressable under program con- trol. The following sequence will transfer the contents of the HIRs to Reg 1-8 by an iterative process, requiring dynamic code modifica- tion (V1N2p3), but not efficiently: ... 10 Op 17 10.82 S99 8 S0L1'10 Op17 1 SUM99 6 Op17 GTO 166 ... 168: S*0 Dsz0 1' ... . The straight forward: ... H11 S1 H12 S2 H13 S3 H14 s4 H15 S5 H16 S6 H17 S7 H18 S8 ... is both shorter and faster. Members are invited to find and share better approaches, and to suggest other things worth recording; efficient recording utilities will be valuable to many users. 52-NOTES V3N2p2

Sorting and Searching: Some Popular Applications (59)While member feedback on the V2N8p1 and V2N11p2,3 articles has so far been slight, there is growing interest in developing efficient approaches to 2 related topics: 1) Addressing block-stored data by arbitrary tags, and 2) Sorting data by magnitude. Mechanization of both topics reveals machine as well as data dependency, and since practical implementation concerns more than just a few data, the dis- cussion which follows centers on the TI-59/PC-100a.Addressing Block-Stored Data by Arbitrary Tags:Bob Anderson (506) poses a common business problem, whose efficient solution should be of considerable interest to many users: A collection of entities, which I refer to here as records (machine-represented by specified numerical values), is to be stored in a specified block of data regis- ters, each record identified by a unique tag or key (also machine- represented by a specified number) such that the required code and the execution time required to address each record from its key are mini- mized. The special case where keys match one for one the addresses of allocated data registers is simple enough to mechanize efficiently via indirect addressing, but it precludes the user from choosing "natural" keys: numbers and numerical representations of characters directly associated with the stored records. So let's look at a real- world situation which Bob poses: 20 departments in an organisation are identified by the numbers (keys): 2,4,6,8,9,10,13,17,18,22,23,25, 29,31,32,33,34,51,72, and 73, each of which is associated with a labor rate (record). The records are to be stored in a concise block of data registers (not scattered throughout the Reg 2-Reg 73 range), and be efficiently addressable by their keys. A straight forward approach would be to compare an input key with all stored keys, one at a time until it is matched, at which time processing is diverted to appro- priately initialize a pointer. But this would be prohibitively costly in both code and execution time. Another approach might be to try something along the lines of Ordered Hashing (V2N8p1), which Bob experi- mented with, using the ML-15 random number generator to serve as the hash function. This is an improvement, but is still a bit slow, and requires handling quite a few "collisions" (2 or more keys produce the same hash (register) address)... a problem not likely to be solved by trying to find a better hash function. But assuming that the keys are not to be changed, in some cases advantage can be taken of the pattern they form. In this example, all but 3 of the 20 keys can be matched one for one with a register in the 1-34 address range, which might be an acceptably concise block. Each of the remaining keys: 51,72,73 should then be matched with one of the 14 unassigned registers in the 1-34 address range, and use made of the remaining 11 for program scratch. But what's the best way to match the remaining keys? It is tempting to look for a special no-collision hash function, which might be mechanized along the lines of the following algorithm: If K ≥ 51 set h(K) ← (K mod M) + 1 Else set h(K) ← K which will do the job with M=47, and in English says: If an input key (K) is greater than or equal to 51, evaluate a hash function h(K) by adding 1 to the remainder modulo M (the remainder in integer form 52-NOTES V3N2p3

resulting from the division of K by M) of K. If K is less than 51, use K itself as the hash function value. In either case, the value h(K) points to the desired register. The number 47 was found by trial and error to satisfy the relations h(51)≠h(72)≠h(73), all in the 1-34 range of unassigned registers. The routine:LAS1 x:t 50 x≥t 1' R1 ÷ 47 = INV Int X 47 = fix 0 EE INC EE S1 Op21L1'rtn accepts one of the 20 keys in the display, and following a call to A, produced the corresponding h(K) in Reg 1. Incidently, the fix 0 EE INV EE is required for rounding, and although fix 0 D.MS works just as well, it takes about 4 times as long to execute. The fox 0 can be eliminated if this routine is always called with a fix 0 display. But it turns out that for only 3 keys, a straight forward match- and-process approach is considerably faster, and not much longer:LAS1 x:t 50 x≥t 1' 51 x=t 2' 72 x=t 3' 26 S1 rtnL2'5 S1 rtnL3'27 S1L1'rtn. This exercise illustrates an important programming precept: Don't let exotic schemes close your mind to simpler ones that are better (unless your objective is to make an exotic scheme work!). One more thing to keep in mind when approaching the problem of how to best process arbitrary keys: It may pay off to spend a fair amount of effort looking for patterns which can be matched by simple non- or low-collision hash functions. There is a straight forward mathematical procedure for fitting n-1 data points with an nth degree polynomial, and while such an approach is impractical for large n, it suggests a compromise: Try out various combinations of simple mathematical functions: trig, log, arithmetic, etc; with per- severance and a little luck you may be able to solve the collision problem.Sorting Data By Magnitude:In the previous problem, the user doesn't care where each record is stored, so long as it is readily accessible by an arbitrary key. Sorting data by magnitude is a different kind of problem, and arises any time the user wishes to start with an unordered sequential set of records and put them into ascending (or descending) order. While these records could also have arbitrary keys, such are not necessary to illustrate the sorting techniques discussed here, and in the interests of simplicity a record's key will be considered identical with the address of the register in which it resides. There are a few data dependencies to keep in mind when choosing an approach: 1) The initial ordering, 2) The number of repeated values, and 3) The number of data. These combined with machine idiosyncrasies make the choice of approach consequential. With no packing, about 100 data is a practical limit for the 59 to process, and for quantities in this neighborhood a variant of the so-called Shell Sort method does reasonably well. The program that follows was mechanized from an algorithm appearing inPopular Computing(Jan 78 p5). Members wishing to examine Donald Shell's method in detail will find a technical discussion in Vol III pp 84-95 of Knuth's"The Art of Computer Programming". Use is made of the HIR operations (V2N9) to maximize data capacity, and as you may have noticed earlier in this issue, the mnemonic HIR has been short- ened to H. A reverse-order input of 99 records takes about 21½ minutes to sort; a sample of 99 random numbers produced by ML-15 took 26½ minutes 52-NOTES V3N2p4

TI-59/PC-100A Program: Shell Sorting of up to 99 Data EdUser Instructions:Key number of data (n), press E; key records (ri), press R/S, for i=1,2,... n. Execution begins following the input of rn, and when the program halts, Reg 1 - Reg n contain the input records sorted low to high, the contents of which may be displayed by successive R/Ss if a printer is not connected, or are automatically printed if it is.Program Listing:000:LEx:t 10 Op17 CMs x:t H8 H7 S0 R/S S*0 Dsz0 015 H17 ÷ 2 = Int 028: H7 CP x=t 104 1 H6 H18 - H17 = H5 H16 H4 H14 S0 R*0 x:t H17 + 059: H14 = S0 R*0 x≥t 090 x:t S*0 H14 S0 x:t S*0 H17 H54 1 x:t H14 087: x≥t 049 1 H36 H16 x:t H15 x≥t 045 GTO 022 1 INV List S0 R*0 111: R/S Op20 GTO 109 Sorting permutations of a fixed quantity of specified values by magnitude is a special case of this second type, which Lou Cargile (625) has been exploring using several of the TI/HP PPCs to effectively per- form card shuffling, dealing, and arranging for the game of Contract Bridge. His 59/100A program which follows combines a number of illus- trative approaches and techniques, and will be a tough challenge to anyone aspiring to write a better one.TI-59/PC-100A Program: Bridge Deal Lou Cargile (625)User Instructions:Key RN seed < 1, press E; (optional): key another seed < 1, press D. To print one deal, press A; to print n deals, key n, press B.Program Listing:000:LE'R*20 Op0 Op1 Op5 Op0 Op5 1 INV SUM20 rtnLAR19 SBR245 39 028: S17 1 SUM25 R25 Prt CLT INV Stflg2 R19 X R26 + R27 = INV Int 051: S19 + R16 = INV Int X 52 = Int S11 ÷ 13 = Int S12 + 1 = S0 R11 080: + 1 - R12 X 13 = S13 R*0 ÷ R13 INV log EE S13 INV EE = INV Int 106: X R13 = EE x:t CLR R13 ÷ 10 = x:t INV x≥t 036 x:t INV SUM*0 128: x:t 1 INV SUM17 4 SUM0 x:t SUM*0 R17 ÷ 13 = INV Int x:t 0 INV 150: x=t 036 x:t Stflg2 8 S0 E' 0 S24 4 S9 R*0 x=t 211 log EE Int S15 176: INV EE INV log EE INV SUM*0 CLR R9 + 61 = S21 R15 + 47 = S23 201: R*21 + R*23 X 100 = Op*9 SUM24 1 INV SUM0 Dsz9 166 R24 x=t 236 228: Op05 4 SUM0 GTO 160 Adv Ifflg2 333 Dsz"22" A R/S S19 1 EE 13 INV 252: EE ÷ 9 = S1 S2 S3 S04 3 S47 4 S48 5 S49 6 S50 7 S51 10 S52 11 285: S53 12 S54 2.01 S55 25 S56 34 S57 26 S58 13 S59 9821 S26 .211327 326: S27 69 S20 rtn R17 INV x=t 036 INV Stflg2 E' GTO 160LBS22 GTO A 352:LDS16 16 Op4 R16 GTP 395LEx:t 6 OP17 CMs 7 Op17 Op0 R60 Op2 381: R61 Op3 Op05 17 Op4 Adv x:t S19 Op6 Adv R/SPre-stored Data:60: 143524 1622170000 36000000 23000000 16000000 15000000 4317363700 67: 3632413723 1713363700 3132353723 - - - - - - - - -Tips and MiscellanyA Safe, Handy Hardware Interrupt (58/59):In cases where no CROM program is called within a loop, George Hartwig (638) has found a method paralleling the SR-52 D-R switch application (V3N1p4): A dummy call to a CROM program places at a safe position in the loop works nicely with a manual RST to cause a transfer to step 000 of user memory. 52-NOTES V3N2p5

For example, write: 000: R/SLA20 S0L1'Dsz0 1' Pgm 7 SBR005 GTO A. Press A, and after an arbitrary time interval, press and hold down RST until execution halts. No matter when the RST is pressed, the halt occurs at the step 000 R/S, following a completed Dsz cycle. It appears that is doesn't matter at what step the CROM program is called; so long as the RST is depressed during the call, no CROM code is exe- cutes. If the CROM call is to an undefined label, an error condition is set, but transfer to step 000 of user memory still occurs. But for practical application, it is best to call a CROM program at a rtn (as in the above example), since this minimizes execution time (about 200 ms) and doesn't let the CROM code do anything during times when the RST is not depressed.Use of p41 to Make Lbl Lbl Tricks Work for the 58/59:Rusty Wright (581) discovered that the SR-52 LBL LBL tricks can be made to work on the new machines if each Lbl Lbl sequence is preceded by the SST pseudo (p41). For example, Jared's flag reversal routine (V2N10p2) for the 52 can be written: ...Ifflg0 p41 Lbl Lbl INV Stflg0... for the new machines. Carl Paulson (854) has been exploring other sequen- ces with p41 executed under program control, and finds that the first R/S or any number of P31s following one or more p41s is ignored. All this added to the unorthodox manual use of SST in creating fractured digits (V3N1p6) should help to encourage further exploration for new SST/p41 uses.PC-100 to PC-100A:Mike Brown (128) reports that he turned his PC-100 into a PC-100A by positioning the 52-56 switch halfway between the 2 intended settings, effectively creating the "other" position on the PC-100A. The only problem Mike encountered was that sometimes the machine "... has trouble printing a line of 20 of the same characters", which he suggests may be due to a less robust power supply for the PC-100.56/57/58 Program Exchange:Dave Johnston (5) has a new catalog dated 1 Feb 1978 listing 26 math, 8 statistics, 9 operations research and simulation, 24 physics, 10 other physical sciences, 24 engineering and technology, 3 live and behavioral sciences, 13 games, 6 finance, and 1 general inf0-test routine... programs written for the SR-56, of which 34 have been translated for the 57, and 15 for the 58. A few more programs in scattered categories were written for only the 57 or 58. Send Dave a SASE and 15¢ for the catalog. He continues to provide program copies at the modest rate of 5¢ per page.CROM HIRs(V3N1p5):Several members have noted that T S Cox probably meant to refer to the Blackjack program (11) of the Leisure Library, and that while step 240 is a code 82, it is part of a GTO address, and was not intended to be a HIR operation. On the other hand, Roy Chardon's reported use of H8 in Pgm 13 of the Real Estate Library was intended (H8 at step 183 and H18 at step 219). In order to avoid confusion, members are asked when discussing CROM code to indicate whether a stated sequence is intended or unintended. Intended code is defined as that what the printer would list, addressed con- tinuously from start to finish; unintended as printed starting from an intermediate step which separates the elements of a composite instruc- tion. 52-NOTES V3N2p6 (end)