github.com/jflude/taocp@v0.0.0-20240210234939-99f2a91af3c2/mix/cycle_test.go (about)

     1  package mix
     2  
     3  import (
     4  	"errors"
     5  	"os"
     6  	"strings"
     7  	"testing"
     8  )
     9  
    10  func TestCycle(t *testing.T) {
    11  	c, tmpDir := newSandbox(t, "")
    12  	defer closeSandbox(t, c, tmpDir)
    13  	if testing.Verbose() {
    14  		c.Tracer = os.Stdout
    15  	}
    16  
    17  	// LDA
    18  	copy(c.Contents[mBase+0:], egCycle1)
    19  	c.Contents[mBase+2000] = NewWord(-(80<<18 | 030504))
    20  	c.next = 0
    21  	for i, v := range okCycle1 {
    22  		if err := c.Cycle(); err != nil {
    23  			t.Errorf("#%d: error: %v", i+1, err)
    24  			c.next++
    25  			continue
    26  		}
    27  		if c.Reg[A] != v {
    28  			t.Errorf("#%d: got: %#v, want: %#v",
    29  				i+1, c.Reg[A], v)
    30  		}
    31  	}
    32  
    33  	// LD[1-6]N
    34  	copy(c.Contents[mBase+0:], egCycle2)
    35  	c.Contents[mBase+2000] = NewWord(-01234)
    36  	c.next = 0
    37  	for i, v := range okCycle2 {
    38  		if err := c.Cycle(); err != nil {
    39  			t.Errorf("#%d: error: %v", i+1, err)
    40  			c.next++
    41  			continue
    42  		}
    43  		if c.Reg[I1+i] != v {
    44  			t.Errorf("#%d: got: %#v, want: %#v",
    45  				i+1, c.Reg[I1+i], v)
    46  		}
    47  	}
    48  
    49  	// STA
    50  	copy(c.Contents[mBase+0:], egCycle3)
    51  	c.Reg[A] = NewWord(0607101100)
    52  	c.next = 0
    53  	for i, v := range okCycle3 {
    54  		c.Contents[mBase+2000] = NewWord(-0102030405)
    55  		if err := c.Cycle(); err != nil {
    56  			t.Errorf("#%d: error: %v", i+1, err)
    57  			c.next++
    58  			continue
    59  		}
    60  		if c.Contents[mBase+2000] != v {
    61  			t.Errorf("#%d: got: %#v, want: %#v",
    62  				i+1, c.Contents[mBase+2000], v)
    63  		}
    64  	}
    65  
    66  	// ST1
    67  	copy(c.Contents[mBase+0:], egCycle4)
    68  	c.Reg[I1] = NewWord(01100)
    69  	c.next = 0
    70  	for i, v := range okCycle4 {
    71  		c.Contents[mBase+2000] = NewWord(-0102030405)
    72  		if err := c.Cycle(); err != nil {
    73  			t.Errorf("#%d: error: %v", i+1, err)
    74  			c.next++
    75  			continue
    76  		}
    77  		if c.Contents[mBase+2000] != v {
    78  			t.Errorf("#%d: got: %#v, want: %#v",
    79  				i+1, c.Contents[mBase+2000], v)
    80  		}
    81  	}
    82  
    83  	// ADD, SUB, MUL, DIV
    84  	for i, op := range egCycle5 {
    85  		c.Contents[mBase+0] = op[0]
    86  		c.Reg[A] = op[1]
    87  		c.Reg[X] = op[2]
    88  		c.Contents[mBase+1000] = op[3]
    89  		c.next = 0
    90  		if err := c.Cycle(); err != nil {
    91  			t.Errorf("#%d: error: %v", i+1, err)
    92  			continue
    93  		}
    94  		if c.Reg[A] != op[4] {
    95  			t.Errorf("#%d: got: A = %#v, want: A = %#v",
    96  				i+1, c.Reg[A], op[4])
    97  		}
    98  		if c.Reg[X] != op[5] {
    99  			t.Errorf("#%d: got: X = %#v, want: X = %#v",
   100  				i+1, c.Reg[X], op[5])
   101  		}
   102  	}
   103  
   104  	// SLA, SRA, SRAX, SLC, SRC, SLB, SRB
   105  	c.Reg[A] = NewWord(0102030405)
   106  	c.Reg[X] = NewWord(-0607101112)
   107  	c.next = 0
   108  	for i, op := range egCycle6 {
   109  		c.Contents[mBase+i] = op[0]
   110  		if err := c.Cycle(); err != nil {
   111  			t.Errorf("#%d: error: %v", i+1, err)
   112  			c.next++
   113  			continue
   114  		}
   115  		if c.Reg[A] != op[1] {
   116  			t.Errorf("#%d: got: A = %#v, want: A = %#v",
   117  				i+1, c.Reg[A], op[1])
   118  			c.Reg[A] = op[1]
   119  		}
   120  		if c.Reg[X] != op[2] {
   121  			t.Errorf("#%d: got: X = %#v, want: X = %#v",
   122  				i+1, c.Reg[X], op[2])
   123  			c.Reg[X] = op[2]
   124  		}
   125  	}
   126  
   127  	// NUM, INCA1, CHAR
   128  	c.Reg[A] = NewWord(-0374047)
   129  	c.Reg[X] = NewWord(04571573636)
   130  	c.next = 0
   131  	for i, op := range egCycle7 {
   132  		c.Contents[mBase+i] = op[0]
   133  		if err := c.Cycle(); err != nil {
   134  			t.Errorf("#%d: error: %v", i+1, err)
   135  			c.next++
   136  			continue
   137  		}
   138  		if c.Reg[A] != op[1] {
   139  			t.Errorf("#%d: got: A = %#v, want: A = %#v",
   140  				i+1, c.Reg[A], op[1])
   141  			c.Reg[A] = op[1]
   142  		}
   143  		if c.Reg[X] != op[2] {
   144  			t.Errorf("#%d: got: X = %#v, want: X = %#v",
   145  				i+1, c.Reg[X], op[2])
   146  			c.Reg[X] = op[2]
   147  		}
   148  	}
   149  
   150  	// NUM (overflow, etc)
   151  	c.Contents[mBase+0] = NUM
   152  	for i, op := range egCycle8 {
   153  		c.Reg[A] = op[0]
   154  		c.Reg[X] = op[1]
   155  		c.Overflow = false
   156  		c.next = 0
   157  		if err := c.Cycle(); err != nil {
   158  			t.Errorf("#%d: error: %v", i+1, err)
   159  			continue
   160  		}
   161  		if c.Overflow {
   162  			c.Reg[A] = c.Reg[A].Negate()
   163  		}
   164  		if c.Reg[A] != op[2] {
   165  			t.Errorf("#%d: got: A = %#v, want: A = %#v",
   166  				i+1, c.Reg[A], op[2])
   167  		}
   168  	}
   169  
   170  	// AND, OR, XOR
   171  	c.next = 1000
   172  	for i, op := range egCycle9 {
   173  		c.Contents[mBase+1000+i] = op[0]
   174  		c.Contents[mBase+0] = op[1]
   175  		c.Reg[A] = NewWord(-05555555555)
   176  		if err := c.Cycle(); err != nil {
   177  			t.Errorf("#%d: error: %v", i+1, err)
   178  			c.next++
   179  			continue
   180  		}
   181  		if c.Reg[A] != op[2] {
   182  			t.Errorf("#%d: got: A = %#v, want: A = %#v",
   183  				i+1, c.Reg[A], op[2])
   184  		}
   185  	}
   186  
   187  	// Program M, Section 1.3.2
   188  	copy(c.Contents[mBase+3000:], egCycle10)
   189  	c.Contents[mBase+0] = NewWord(3000<<18 | 39) // JMP 3000
   190  	c.Contents[mBase+1] = NewWord(0205)          // HLT
   191  	c.Contents[mBase+1000] = NewWord(1)
   192  	c.Contents[mBase+1001] = NewWord(7)
   193  	c.Contents[mBase+1002] = NewWord(2)
   194  	c.Contents[mBase+1003] = NewWord(7)
   195  	c.Contents[mBase+1004] = NewWord(6)
   196  	c.Contents[mBase+1005] = NewWord(3)
   197  	c.Contents[mBase+1006] = NewWord(1)
   198  	c.Contents[mBase+1007] = NewWord(4)
   199  	c.Contents[mBase+1008] = NewWord(5)
   200  	c.Contents[mBase+1009] = NewWord(2)
   201  	c.Reg[I1] = 10
   202  	c.next = 0
   203  	if err := c.resume(); !errors.Is(err, ErrHalted) {
   204  		t.Error("error:", err)
   205  	}
   206  	if c.Reg[A].Int() != 7 {
   207  		t.Errorf("got: %#o (%v), want: 7", c.Reg[A], c.Reg[A])
   208  	}
   209  	if c.Elapsed != 226 {
   210  		t.Fatalf("got: elapsed %d, want %d", c.Elapsed, 226)
   211  	}
   212  
   213  	// Program P, Section 1.3.2
   214  	c.zeroContents()
   215  	c.unlockContents()
   216  	c.Elapsed = 0
   217  	c.Idle = 0
   218  	copy(c.Contents[mBase+3000:], egCycle11a)
   219  	copy(c.Contents[mBase+0:], egCycle11b)
   220  	copy(c.Contents[mBase+1995:], egCycle11c)
   221  	copy(c.Contents[mBase+2024:], egCycle11d)
   222  	copy(c.Contents[mBase+2049:], egCycle11e)
   223  	c.next = 3000
   224  	if err := c.resume(); !errors.Is(err, ErrHalted) {
   225  		t.Error("error:", err)
   226  	}
   227  	b, err := os.ReadFile("printer.mix")
   228  	if err != nil {
   229  		t.Fatal("error:", err)
   230  	}
   231  	if strings.Compare(string(b), okCycle11) != 0 {
   232  		t.Error("got: incorrect printer output")
   233  	}
   234  	if c.Elapsed != 6100052 {
   235  		t.Fatalf("got: elapsed %d, want %d", c.Elapsed, 6100052)
   236  	}
   237  	if c.Idle != 5909153 {
   238  		t.Fatalf("got: idle %d, want %d", c.Idle, 5909153)
   239  	}
   240  }
   241  
   242  func BenchmarkProgramM(b *testing.B) {
   243  	c := NewComputer()
   244  	copy(c.Contents[mBase+3000:], egCycle10)
   245  	c.Contents[mBase+0] = NewWord(3000<<18 | 39) // JMP 3000
   246  	c.Contents[mBase+1] = NewWord(0205)          // HLT
   247  	c.Contents[mBase+1000] = NewWord(1)
   248  	c.Contents[mBase+1001] = NewWord(7)
   249  	c.Contents[mBase+1002] = NewWord(2)
   250  	c.Contents[mBase+1003] = NewWord(7)
   251  	c.Contents[mBase+1004] = NewWord(6)
   252  	c.Contents[mBase+1005] = NewWord(3)
   253  	c.Contents[mBase+1006] = NewWord(1)
   254  	c.Contents[mBase+1007] = NewWord(4)
   255  	c.Contents[mBase+1008] = NewWord(5)
   256  	c.Contents[mBase+1009] = NewWord(2)
   257  	b.ResetTimer()
   258  	for i := 0; i < b.N; i++ {
   259  		c.Reg[I1] = 10
   260  		c.next = 0
   261  		if err := c.resume(); !errors.Is(err, ErrHalted) {
   262  			b.Fatal("error:", err)
   263  		}
   264  	}
   265  }
   266  
   267  func BenchmarkProgramP(b *testing.B) {
   268  	c := NewComputer()
   269  	binding := DefaultBinding
   270  	binding[PrinterUnit] = "/dev/null"
   271  	c.Bind(binding)
   272  	copy(c.Contents[mBase+3000:], egCycle11a)
   273  	copy(c.Contents[mBase+0:], egCycle11b)
   274  	copy(c.Contents[mBase+1995:], egCycle11c)
   275  	copy(c.Contents[mBase+2024:], egCycle11d)
   276  	copy(c.Contents[mBase+2049:], egCycle11e)
   277  	b.ResetTimer()
   278  	for i := 0; i < b.N; i++ {
   279  		c.next = 3000
   280  		if err := c.resume(); !errors.Is(err, ErrHalted) {
   281  			b.Error("error:", err)
   282  		}
   283  	}
   284  }
   285  
   286  var (
   287  	egCycle1 = []Word{
   288  		NewWord(2000<<18 | 0510),  // LDA  2000
   289  		NewWord(2000<<18 | 01510), // LDA  2000(1:5)
   290  		NewWord(2000<<18 | 03510), // LDA  2000(3:5)
   291  		NewWord(2000<<18 | 0310),  // LDA  2000(0:3)
   292  		NewWord(2000<<18 | 04410), // LDA  2000(4:4)
   293  		NewWord(2000<<18 | 010),   // LDA  2000(0:0)
   294  	}
   295  	okCycle1 = []Word{
   296  		NewWord(-(80<<18 | 030504)),
   297  		NewWord(80<<18 | 030504),
   298  		NewWord(030504),
   299  		NewWord(-(80<<6 | 3)),
   300  		NewWord(5),
   301  		NewWord(0).Negate(),
   302  	}
   303  
   304  	egCycle2 = []Word{
   305  		NewWord(2000<<18 | 0521),  // LD1N 2000
   306  		NewWord(2000<<18 | 01522), // LD2N 2000(1:5)
   307  		NewWord(2000<<18 | 03523), // LD3N 2000(3:5)
   308  		NewWord(2000<<18 | 0324),  // LD4N 2000(0:3)
   309  		NewWord(2000<<18 | 04425), // LD5N 2000(4:4)
   310  		NewWord(2000<<18 | 026),   // LD6N 2000(0:0)
   311  	}
   312  	okCycle2 = []Word{
   313  		NewWord(01234),
   314  		NewWord(-01234),
   315  		NewWord(-01234),
   316  		0,
   317  		NewWord(-012),
   318  		0,
   319  	}
   320  
   321  	egCycle3 = []Word{
   322  		NewWord(2000<<18 | 0530),  // STA  2000
   323  		NewWord(2000<<18 | 01530), // STA  2000(1:5)
   324  		NewWord(2000<<18 | 05530), // STA  2000(5:5)
   325  		NewWord(2000<<18 | 02230), // STA  2000(2:2)
   326  		NewWord(2000<<18 | 02330), // STA  2000(2:3)
   327  		NewWord(2000<<18 | 0130),  // STA  2000(0:1)
   328  	}
   329  	okCycle3 = []Word{
   330  		NewWord(0607101100),
   331  		NewWord(-0607101100),
   332  		NewWord(-0102030400),
   333  		NewWord(-0100030405),
   334  		NewWord(-0111000405),
   335  		NewWord(02030405),
   336  	}
   337  
   338  	egCycle4 = []Word{
   339  		NewWord(2000<<18 | 0531),  // ST1  2000
   340  		NewWord(2000<<18 | 01531), // ST1  2000(1:5)
   341  		NewWord(2000<<18 | 05531), // ST1  2000(5:5)
   342  		NewWord(2000<<18 | 02231), // ST1  2000(2:2)
   343  		NewWord(2000<<18 | 02331), // ST1  2000(2:3)
   344  		NewWord(2000<<18 | 0131),  // ST1  2000(0:1)
   345  	}
   346  	okCycle4 = []Word{
   347  		NewWord(01100),
   348  		NewWord(-01100),
   349  		NewWord(-0102030400),
   350  		NewWord(-0100030405),
   351  		NewWord(-0111000405),
   352  		NewWord(02030405),
   353  	}
   354  
   355  	egCycle5 = [][]Word{
   356  		{ // #1
   357  			NewWord(01750000501),       // ADD  1000
   358  			NewWord(1234<<18 | 010226), // A (before)
   359  			0,                          // X (before)
   360  			NewWord(100<<18 | 050062),  // CONTENTS[1000]
   361  			NewWord(1334<<18 | 060310), // A (after)
   362  			0,                          // X (after)
   363  		},
   364  		{ // #2
   365  			NewWord(01750000502), // SUB  1000
   366  			NewWord(-(1234<<18 | 9)),
   367  			0,
   368  			NewWord(-(2000<<18 | (150 << 6))),
   369  			NewWord(766<<18 | 149<<6 | 067),
   370  			0,
   371  		},
   372  		{ // #3
   373  			NewWord(01750001103), // MUL  1000(1:1)
   374  			NewWord(-112),
   375  			0,
   376  			NewWord(0200000000),
   377  			NewWord(0).Negate(),
   378  			NewWord(-224),
   379  		},
   380  		{ // #4
   381  			NewWord(01750000503), // MUL  1000
   382  			NewWord(-(50<<24 | 112<<6 | 4)),
   383  			0,
   384  			NewWord(-0200000000),
   385  			NewWord(100<<18 | 224),
   386  			NewWord(8 << 24),
   387  		},
   388  		{ // #5
   389  			NewWord(01750000504), // DIV  1000
   390  			0,
   391  			NewWord(17),
   392  			NewWord(3),
   393  			NewWord(5),
   394  			NewWord(2),
   395  		},
   396  		{ // #6
   397  			NewWord(01750000504), // DIV  1000
   398  			NewWord(0).Negate(),
   399  			NewWord(1235<<18 | 0301),
   400  			NewWord(-0200),
   401  			NewWord(617<<12 | 04001),
   402  			NewWord(-0101),
   403  		},
   404  	}
   405  
   406  	egCycle6 = [][3]Word{
   407  		{ // #1
   408  			NewWord(01000306),    // SRAX 1
   409  			NewWord(01020304),    // A
   410  			NewWord(-0506071011), // X
   411  		},
   412  		{ // #2
   413  			NewWord(02000006), // SLA  2
   414  			NewWord(0203040000),
   415  			NewWord(-0506071011),
   416  		},
   417  		{ // #3
   418  			NewWord(04000506), // SRC  4
   419  			NewWord(0607101102),
   420  			NewWord(-0304000005),
   421  		},
   422  		{ // #4
   423  			NewWord(02000106), // SRA  2
   424  			NewWord(060710),
   425  			NewWord(-0304000005),
   426  		},
   427  		{ // #5
   428  			NewWord(0765000406), // SLC  501
   429  			NewWord(06071003),
   430  			NewWord(-0400000500),
   431  		},
   432  		{ // #6
   433  			NewWord(03000606), // SLB  3
   434  			NewWord(060710030),
   435  			NewWord(-04000005000),
   436  		},
   437  		{ // #7
   438  			NewWord(03000706), // SRB  3
   439  			NewWord(06071003),
   440  			NewWord(-0400000500),
   441  		},
   442  	}
   443  
   444  	egCycle7 = [][3]Word{
   445  		{ // #1
   446  			NewWord(05), // NUM
   447  			NewWord(-12977700),
   448  			NewWord(04571573636),
   449  		},
   450  		{ // #2
   451  			NewWord(01000060), // INCA 1
   452  			NewWord(-12977699),
   453  			NewWord(04571573636),
   454  		},
   455  		{ // #3
   456  			NewWord(0105), // CHAR
   457  			NewWord(-03636374047),
   458  			NewWord(04545444747),
   459  		},
   460  	}
   461  
   462  	egCycle8 = [][3]Word{
   463  		{ // #1
   464  			NewWord(-03736363636), // A (before)
   465  			NewWord(-03636363637), // X (before)
   466  			NewWord(-1000000001),  // A (after, negated if overflow)
   467  		},
   468  		{ // #2
   469  			NewWord(-04747474747),
   470  			NewWord(04747474747),
   471  			NewWord(02402761777),
   472  		},
   473  	}
   474  
   475  	egCycle9 = [][3]Word{
   476  		{ // #1
   477  			NewWord(0305), // AND  0
   478  			NewWord(0000777777),
   479  			NewWord(-0555555),
   480  		},
   481  		{ // #2
   482  			NewWord(0405), // OR  0
   483  			NewWord(02222222222),
   484  			NewWord(-07777777777),
   485  		},
   486  		{ // #3
   487  			NewWord(0505), // XOR  0
   488  			NewWord(07777777777),
   489  			NewWord(-02222222222),
   490  		},
   491  	}
   492  
   493  	//                                         * FIND THE MAXIMUM
   494  	//                                         X        EQU  1000
   495  	egCycle10 = []Word{ //                              ORIG 3000
   496  		NewWord(3009<<18 | 0240),       // MAXIMUM  STJ  EXIT
   497  		NewWord(010263),                // INIT     ENT3 0,1
   498  		NewWord(3005<<18 | 39),         //          JMP  CHANGEM
   499  		NewWord(1000<<18 | 030570),     // LOOP     CMPA X,3
   500  		NewWord(3007<<18 | 0700 | 39),  //          JLE  *+3
   501  		NewWord(030200 | 50),           // CHANGEM  ENT2 0,3
   502  		NewWord(1000<<18 | 030500 | 8), //          LDA  X,3
   503  		NewWord(01000100 | 51),         //          DEC3 1
   504  		NewWord(3003<<18 | 0200 | 43),  //          J3P  LOOP
   505  		NewWord(3009<<18 | 39),         // EXIT     JMP  *
   506  	}
   507  
   508  	//                                    * EXAMPLE: TABLE OF PRIMES
   509  	//                                    L         EQU  500
   510  	//                                    PRINTER   EQU  18
   511  	//                                    PRIME     EQU  -1
   512  	//                                    BUF0      EQU  2000
   513  	//                                    BUF1      EQU  BUF0+25
   514  	egCycle11a = []Word{ //                         ORIG 3000
   515  		NewWord(02243),            // START     IOC  0(PRINTER)
   516  		NewWord(2050<<18 | 0511),  //           LD1  =1-L=
   517  		NewWord(2051<<18 | 0512),  //           LD2  =3=
   518  		NewWord(01000061),         // 2H        INC1 1
   519  		NewWord(499<<18 | 010532), //           ST2  PRIME+L,1
   520  		NewWord(3016<<18 | 0151),  //           J1Z  2F
   521  		NewWord(02000062),         // 4H        INC2 2
   522  		NewWord(02000263),         //           ENT3 2
   523  		NewWord(0260),             // 6H        ENTA 0
   524  		NewWord(020267),           //           ENTX 0,2
   525  		NewWord(-01030504),        //           DIV  PRIME,3
   526  		NewWord(3006<<18 | 0157),  //           JXZ  4B
   527  		NewWord(-01030570),        //           CMPA PRIME,3
   528  		NewWord(01000063),         //           INC3 1
   529  		NewWord(3008<<18 | 0647),  //           JG   6B
   530  		NewWord(3003<<18 | 047),   //           JMP  2B
   531  		NewWord(1995<<18 | 02245), // 2H        OUT  TITLE(PRINTER)
   532  		NewWord(2035<<18 | 0264),  //           ENT4 BUF1+10
   533  		NewWord(-062000265),       //           ENT5 -50
   534  		NewWord(501<<18 | 065),    // 2H        INC5 L+1
   535  		NewWord(-01050510),        // 4H        LDA  PRIME,5
   536  		NewWord(0105),             //           CHAR
   537  		NewWord(041437),           //           STX  0,4(1:4)
   538  		NewWord(01000164),         //           DEC4 1
   539  		NewWord(062000165),        //           DEC5 50
   540  		NewWord(3020<<18 | 0255),  //           J5P  4B
   541  		NewWord(042245),           //           OUT  0,4(PRINTER)
   542  		NewWord(030040514),        //           LD4  24,4
   543  		NewWord(3019<<18 | 055),   //           J5N  2B
   544  		NewWord(0205),             //           HLT
   545  	}
   546  	//                                    * TABLES AND BUFFERS
   547  	egCycle11b = []Word{ //                         ORIG PRIME+1 (=0)
   548  		NewWord(2), //                          CON  2
   549  	}
   550  	egCycle11c = []Word{ //                         ORIG BUF0-5 (=1995)
   551  		NewWord(0611232627),  //      TITLE     ALF  FIRST
   552  		NewWord(06113105),    //                ALF   FIVE
   553  		NewWord(010301704),   //                ALF   HUND
   554  		NewWord(02305040021), //                ALF  RED P
   555  		NewWord(02311160526), //                ALF  RIMES
   556  	}
   557  	egCycle11d = []Word{ //                         ORIG BUF0+24 (=2024)
   558  		NewWord(2035), //                       CON  BUF1+10
   559  	}
   560  	egCycle11e = []Word{ //                         ORIG BUF1+24 (=2049)
   561  		NewWord(2010), //                       CON  BUF0+10
   562  		NewWord(-499), //                       CON  1-L
   563  		NewWord(3),    //                       CON  3
   564  	}
   565  
   566  	okCycle11 = "\014" + `FIRST FIVE HUNDRED PRIMES
   567       0002 0233 0547 0877 1229 1597 1993 2371 2749 3187
   568       0003 0239 0557 0881 1231 1601 1997 2377 2753 3191
   569       0005 0241 0563 0883 1237 1607 1999 2381 2767 3203
   570       0007 0251 0569 0887 1249 1609 2003 2383 2777 3209
   571       0011 0257 0571 0907 1259 1613 2011 2389 2789 3217
   572       0013 0263 0577 0911 1277 1619 2017 2393 2791 3221
   573       0017 0269 0587 0919 1279 1621 2027 2399 2797 3229
   574       0019 0271 0593 0929 1283 1627 2029 2411 2801 3251
   575       0023 0277 0599 0937 1289 1637 2039 2417 2803 3253
   576       0029 0281 0601 0941 1291 1657 2053 2423 2819 3257
   577       0031 0283 0607 0947 1297 1663 2063 2437 2833 3259
   578       0037 0293 0613 0953 1301 1667 2069 2441 2837 3271
   579       0041 0307 0617 0967 1303 1669 2081 2447 2843 3299
   580       0043 0311 0619 0971 1307 1693 2083 2459 2851 3301
   581       0047 0313 0631 0977 1319 1697 2087 2467 2857 3307
   582       0053 0317 0641 0983 1321 1699 2089 2473 2861 3313
   583       0059 0331 0643 0991 1327 1709 2099 2477 2879 3319
   584       0061 0337 0647 0997 1361 1721 2111 2503 2887 3323
   585       0067 0347 0653 1009 1367 1723 2113 2521 2897 3329
   586       0071 0349 0659 1013 1373 1733 2129 2531 2903 3331
   587       0073 0353 0661 1019 1381 1741 2131 2539 2909 3343
   588       0079 0359 0673 1021 1399 1747 2137 2543 2917 3347
   589       0083 0367 0677 1031 1409 1753 2141 2549 2927 3359
   590       0089 0373 0683 1033 1423 1759 2143 2551 2939 3361
   591       0097 0379 0691 1039 1427 1777 2153 2557 2953 3371
   592       0101 0383 0701 1049 1429 1783 2161 2579 2957 3373
   593       0103 0389 0709 1051 1433 1787 2179 2591 2963 3389
   594       0107 0397 0719 1061 1439 1789 2203 2593 2969 3391
   595       0109 0401 0727 1063 1447 1801 2207 2609 2971 3407
   596       0113 0409 0733 1069 1451 1811 2213 2617 2999 3413
   597       0127 0419 0739 1087 1453 1823 2221 2621 3001 3433
   598       0131 0421 0743 1091 1459 1831 2237 2633 3011 3449
   599       0137 0431 0751 1093 1471 1847 2239 2647 3019 3457
   600       0139 0433 0757 1097 1481 1861 2243 2657 3023 3461
   601       0149 0439 0761 1103 1483 1867 2251 2659 3037 3463
   602       0151 0443 0769 1109 1487 1871 2267 2663 3041 3467
   603       0157 0449 0773 1117 1489 1873 2269 2671 3049 3469
   604       0163 0457 0787 1123 1493 1877 2273 2677 3061 3491
   605       0167 0461 0797 1129 1499 1879 2281 2683 3067 3499
   606       0173 0463 0809 1151 1511 1889 2287 2687 3079 3511
   607       0179 0467 0811 1153 1523 1901 2293 2689 3083 3517
   608       0181 0479 0821 1163 1531 1907 2297 2693 3089 3527
   609       0191 0487 0823 1171 1543 1913 2309 2699 3109 3529
   610       0193 0491 0827 1181 1549 1931 2311 2707 3119 3533
   611       0197 0499 0829 1187 1553 1933 2333 2711 3121 3539
   612       0199 0503 0839 1193 1559 1949 2339 2713 3137 3541
   613       0211 0509 0853 1201 1567 1951 2341 2719 3163 3547
   614       0223 0521 0857 1213 1571 1973 2347 2729 3167 3557
   615       0227 0523 0859 1217 1579 1979 2351 2731 3169 3559
   616       0229 0541 0863 1223 1583 1987 2357 2741 3181 3571
   617  `
   618  )