RosettaCodeData/Task/Hailstone-sequence/EDSAC-order-code/hailstone-sequence.edsac

261 lines
10 KiB
Plaintext

[Hailstone (or Collatz) task for Rosetta Code.
EDSAC program, Initial Orders 2.]
[This program shows how subroutines can be called via the
phi, H, N, ..., V parameters, so that the code doesn't have
to be changed if the subroutines are moved about in store.
See Wilkes, Wheeler and Gill, 1951 edition, page 18.]
[Library subroutine P7, prints long strictly positive integer;
10 characters, right justified, padded left with spaces.
Input: 0D = integer to be printed.
Closed, even; 35 storage locations; working position 4D.]
T 55 K [call subroutine via V parameter]
P 56 F [address of subroutine]
E 25 K
T V
GKA3FT26@H28#@NDYFLDT4DS27@TFH8@S8@T1FV4DAFG31@SFLDUFOFFFSFL4F
T4DA1FA27@G11@XFT28#ZPFT27ZP1024FP610D@524D!FO30@SFL8FE22@
[Subroutine to print a string placed after the subroutine call.
One location per character, with character in top 5 bits.
Last character flagged by having bit 0 set.
17 locations, workspace 0F.]
T 54 K [call subroutine via C parameter]
P 91 F [address of subroutine]
E 25 K
T C
GKH16@A2FG4@A6@A2FT6@AFTFOFCFSFE3@A6@A3FT15@EFV2047F
[************ Rosetta Code task ************
Subroutine to generate and optionally store the hailstone
(Collatz) sequence for the passed-in initial term n.
Input: 4D = n, 35-bit positive integer
6F = start address of sequence if stored;
must be even; 0 = don't store
Output: 7F = number of terms in sequence, or -1 if error
Workspace: 0D (general), 8D (term of sequence)
Must be loaded at an even address.]
T 45 K [call subroutine via H parameter]
P 108 F [address of subroutine]
E 25 K
T H
G K
A 3 F
T 46 @
H 54#@ [mult reg := 1 to test odd/even]
A 4 D [load n passed in by caller]
T 8 D [term := n]
A 54 @ [load 1 (single)]
T 7 F [include initial term in count]
A 6 F [load address for store]
S 56 @ [test for 0; allow for pre-inc]
G 11 @ [skip next if storing not wanted]
A 12 @ [make 'T addr D' order]
[11] T 21 @ [plant T order, or -ve value if not storing
(note that a T order is +ve as an integer)]
[Loop: deal with current term in sequence
First store it, if user requested that]
[12] T D [clear acc; also serves to make 'T addr D' order]
A 21 @ [load T order to store term]
G 22 @ [jump if caller doesn't want store]
A 56 @ [pre-inc the address]
U 21 @ [update T order]
S 51 @ [check not gone beyond max EDSAC address]
E 47 @ [error exit if it has]
T F [clear acc]
A 8 D [load term]
[21] T D [store]
[22] T F [clear acc]
A 54#@ [load 1 (double)]
S 8 D [1 - term]
E 46 @ [if term = 1, jump out with acc = 0]
T F [clear acc]
C 8 D [acc := term AND 1]
S 54#@ [test whether 0 or 1]
G 38 @ [jump if term is even]
[Here if term is odd; acc = 0]
A 8 D [load term]
S 52#@ [guard against numeric overflow]
E 47 @ [jump if overflow]
A 52#@ [restore term after test]
L D [term*2]
A 8 D [term*3]
A 54#@ [plus 1]
E 41 @ [join common code]
[Here if term is even]
[38] T F [clear acc]
A 8 D [load term]
R D [term/2]
[Common code, acc = new term]
[41] T 8 D [store new term]
A 7 F [load count]
A 54 @ [add 1]
T 7 F [update count]
E 12 @ [loop back]
[Here when sequence has reached 1
Assume jump here with acc = 0]
[46] E F [return with acc = 0]
[47] T F [here on error]
S 54 F [acc := -1]
T 7 F [return that as count]
E 46 @
[Arrange the following to ensure even addresses for 35-bit values]
[51] T 1024 F [for checking valid address]
[52] H 682 DT 682 D [(2^34 - 1)/3]
[54] P DP F [1]
[56] P 2 F [to change addresses by 2]
[Program to demonstrate Rosetta Code subroutine]
T 180 K
G K
[Double constants]
[P 500 F P F] [maximum n = 1000"]
[0] & 848 F PF [maximum n = 100000]
[2] P 13 D PF [n = 27 as demo of sequence]
[4] P D PF [1]
[Double variables]
[6] P F P F [n, start of Collatz sequence]
[8] P F P F [n with maximum count]
[Single constants]
[10] P 400 F [where to store sequence]
[11] P 2 F [to change addresses by 2]
[12] @ F [carriage return]
[13] & F [line feed]
[14] K 4096 F [null char]
[15] A D [used for maiking 'A addr D' order]
[16] P 8 F [ used for adding 8 to address]
[Single variables]
[17] P F [maximum number of terms]
[18] P F [temporary store]
[19] P F [marks end of printing]
[Subroutine to print 4 numbers starting at address in 6F.
Prints new line (CR, LF) at end.]
[20] A 3 F [plant link for return]
T 40 @
A 6 F [load start address]
A 15 @ [make 'A addr D' order]
A 16 @ [inc address by 8 (4 double values)]
U 19 @ [store as test for end]
S 16 @ [restore 'A addr D' order for start]
[27] U 31 @ [plant 'A addr D' order in code]
S 19 @ [test for end]
E 38 @ [out if so]
T F [clear acc]
[31] A D [load number]
T D [to 0D for printing]
[33] A 33 @ [call print subroutine]
G V
A 31 @ [load 'A addr D' order]
A 11 @ [inc address to next double value]
G 27 @ [loop back]
[38] O 12 @ [here when done, print CR LF]
O 13 @
[40] E F [return]
[Enter with acc = 0]
[PART 1]
[41] A 2#@ [load demo value of n]
T 4 D [to 4D for subroutine]
A 10 @ [address to store sequence]
T 6 F [to 6F for subroutine]
[45] A 45 @ [call subroutine to generate sequence]
G H
A 7 F [load length of sequence]
G 198 @ [out if error]
T 18 @
[Print result]
[50] A 50 @ [print 'start' message]
G C
K2048F SF TF AF RF TF !F !F #D
A 2#@ [load demo value of n]
T D [to 0D for printing]
[63] A 63 @ [print demo n]
G V
[65] A 65 @ [print 'length' string]
G C
K2048F @F &F LF EF NF GF TF HF !F #D
T D [ensure 1F and sandwich bit are 0]
A 18 @ [load length]
T F [to 0F (effectively 0D) for printing]
[81] A 81 @
G V
[83] A 83 @ [print 'first and last four' string]
G C
K2048F @F &F FF IF RF SF TF !F AF NF DF !F LF AF SF TF !F FF OF UF RF @F &F #D
A 18 @ [load length of sequence]
L 1 F [times 4]
A 6 F [make address of last 4]
S 16 @
T 18 @ [store address of last 4]
[115] A 115 @ [print first 4 terms]
G 20 @
A 18 @ [retrieve address of last 4]
T 6 F [pass as parameter]
[119] A 119 @ [print last 4 terms]
G 20 @
[PART 2]
T F
T 17 @ [max count := 0]
T 6#@ [n := 0]
[Loop: update n, start new sequence]
[124] T F [clear acc]
A 6#@ [load n]
A 4#@ [add 1 (double)]
U 6#@ [update n]
T 4 D [n to 4D for subroutine]
T 6 F [say no store]
[130] A 130 @ [call subroutine to generate sequence]
G H
A 7 F [load count returned by subroutine]
G 198 @ [out if error]
S 17 @ [compare with max count so far]
G 140 @ [skip if less]
A 17 @ [restore count after test]
T 17 @ [update max count]
A 6#@ [load n]
T 8#@ [remember n that gave max count]
[140] T F [clear acc]
A 6#@ [load n just done]
S #@ [compare with max(n)]
G 124 @ [loop back if n < max(n)
else fall through with acc = 0]
[Here whan reached maximum n. Print result.]
[144] A 144 @ [print 'max n' message]
G C
K2048F MF AF XF !F NF !F !F #D
A #@ [load maximum n]
T D [to 0D for printing]
[157] A 157 @ [call print subroutine]
G V
[159] A 159 @ [print 'max len' message]
G C
K2048F @F &F MF AF XF !F LF EF NF #D
T D [clear 1F and sandwich bit]
A 17 @ [load max count (single)]
T F [to 0F, effectively to 0D]
[175] A 175 @ [call print subroutine]
G V
[177] A 177 @ [print 'at n =' message]
G C
K2048F @F &F AF TF !F NF !F #F VF !D
A 8#@ [load n for which max count occurred]
T D [to 0D for printing]
[192] A 192 @ [call print subroutine]
G V
[194] O 12 @ [print CR, LF]
O 13 @
O 14 @ [print null to flush teleprinter buffer]
Z F [stop]
[Here if term would overflow EDSAC 35-bit value.
With a maximum n of 100,000 this doesn't happen.]
[198] A 198 @ [print 'overflow' message]
G C
K2048F @F &F OF VF EF RF FF LF OF WD
E 194 @ [jump to exit]
E 41 Z [define entry point]
P F [acc = 0 on entry]