; FILE: gg:src/own/primc/fprim.ASM REV: 3 --- quickly check if number is prime ; History ; 0 Started 9th Feb 2001: Implemented simple SPRP version using ; 2-, 7- and 61-SPRP. ; 1 11th Feb 2001: Wrote 68060 mulmod routine and optimized SPRP ; to use it. ; 2 14th Feb 2001: Implemented '2- and 59-SPRP + hash' optimization ; and 'modulo check' optimization by ArtDent. When both are enabled ; the routine is about %131 faster on my 060. Huh. :) ; 3 15th Feb 2001: Added 7 & 13 modulo check to get the 68060 ; version fit the 1024 byte limit. Tested with all 32bit 2-SPRP ; pseudoprimes, and fixed the bugs. Currently my 68060@50 does ; over 37Kchecks/sec with compo setup. This is 3.7 times my fastest ; wheel factoring, and that routine goes dead slow with bss ; clearing... :) The 060 FPU optimized routine does over 73Kchecks/ ; sec, even withough unrolling. ; ; This routine was written for the #amycoders prime number speed optimizing ; competition. The algorithm used is based on `strong probable primes'. ; ; Reference : D. M. Bressoud, Factorization and Primality Testing, ; Undergraduate Texts in Mathematics, Springer-Verlag, ; New York, 1989 (QA161.F3B73, ISBN 3-540-97040-1). ; Algorithm 3.3 p.34 & 6.1 p.77 ; ; The algorithm was further optimized by Marko "ArtDent" Nippula and I ; (Harry "Piru" Sintonen) ported it to 68K assembler. So this entry is our ; joint effort to the compo, even though I must admit that Art did most of ; the hard work. ;-) ; ; Basically the biggest work for me was implementing the routine in ; relatively fast 68k assembler. Especially the 68060 optimized mulmod ; routine was quite tricky. ; ; Unfortunately the fully optimized 68060 version get a bit over compo ; rules limited maximum code size (it's 1110 bytes), but a sligthly less ; optimized - but still very fast - routine is 994 bytes. ; ; The source compiles with PhxAss and DevPac's GenAm. ; ; For 68020-68040 CPUs disable USE_060CODE. Enable USE_MODCHECK, ; USE_MC_7_11_13 and USE_2SPRPHASH. ; ; For 68060 CPU enable USE_060CODE, USE_MODCHECK and USE_2SPRPHASH. ; Disable USE_MC_7_11_13. For even faster, but oversized routine, ; enable USE_MC_7_11_13. Also, enabling USE_060FPU give 100% speedup, ; but according to compo rules FPU cannot be used. ; ; - Harry "Piru" Sintonen ; ;TESTSPSP EQU 1 TIME EQU 2*65536 USE_060CODE EQU 1 ; avoid 64bit divu.l and mulu.l ? USE_MODCHECK EQU 1 ; use quick modulo check ? ;USE_MC_7_11_13 EQU 1 ; use 7, 11 & 13 -check or 7 & 11 -check ? USE_2SPRPHASH EQU 1 ; use 2- and 59-SPRP + hash or 2-, 7- and 61-SPRP ? ; don't touch these, unless you know what you're doing USE_HASH_OLAY EQU 1 ; overlay hashtables ? USE_OPTMODU32 EQU 1 ; use optimized MODU32 macro ? USE_UNROLLED EQU 1 ; use unrolled SPRP loop ? USE_NEWFIND EQU 1 ; move preparations out of SPRP ? USE_SMARTMC EQU 1 ; use smart MODU32 in MODCHECK ? USE_FASTMM060 EQU 1 ; use fast mulmod for 060 ? ;USE_060FPU EQU 1 ; use 68060 FPU for 64bit math ? Main IFD TESTSPSP pea (test_spsp,pc) .loop move.l ([sp]),d0 beq.b .done bsr PrimeNumber tst.l d0 beq.b .ok move.l ([sp]),d0 trap #1 .ok addq.l #4,(sp) bra.b .loop .done addq.l #4,sp rts ENDC IFD TIME pea TIME .lope move.l (sp),d0 bsr PrimeNumber move.l (sp),d0 swap d0 bsr PrimeNumber moveq #-1,d0 add.l (sp),d0 bsr PrimeNumber move.l #$7fffffff,d0 add.l (sp),d0 bsr PrimeNumber move.l #$7fffffff,d0 sub.l (sp),d0 bsr PrimeNumber subq.l #1,(sp) bne.b .lope addq.l #4,sp ELSE IFGT 1 moveq #-3,d0 ; not bsr PrimeNumber moveq #-5,d0 ; prime bsr PrimeNumber moveq #-17,d0 ; prime bsr PrimeNumber moveq #-19,d0 ; not bsr PrimeNumber move.l #44477921,d0 ; prime bsr PrimeNumber moveq #3,d0 bsr PrimeNumber moveq #4,d0 bsr PrimeNumber moveq #5,d0 bsr PrimeNumber moveq #6,d0 bsr PrimeNumber moveq #13,d0 bsr PrimeNumber moveq #17,d0 bsr PrimeNumber moveq #97,d0 bsr PrimeNumber moveq #101,d0 bsr PrimeNumber moveq #103,d0 bsr PrimeNumber moveq #107,d0 bsr PrimeNumber ENDC move.l #10000001,d0 ; not bsr PrimeNumber move.l #110202021,d0 ; not bsr PrimeNumber move.l #44477921,d0 bsr PrimeNumber move.l #44478053,d0 bsr PrimeNumber move.l #44478061,d0 bsr PrimeNumber moveq #0,d0 bsr PrimeNumber moveq #10,d0 bsr PrimeNumber moveq #1,d0 bsr PrimeNumber moveq #2,d0 bsr PrimeNumber moveq #3,d0 bsr PrimeNumber moveq #4,d0 bsr PrimeNumber moveq #5,d0 bsr PrimeNumber moveq #6,d0 bsr PrimeNumber moveq #13,d0 bsr PrimeNumber moveq #17,d0 bsr PrimeNumber ENDC moveq #0,d0 rts IFD USE_OPTMODU32 ; optimized 32:32->32 modulo calculation macro ; MODU32 MACRO *divisor, dividend(result), tmp cmp.l \2,\1 bhi.b .MODU32nodiv\@ divul.l \1,\3:\2 move.l \3,\2 .MODU32nodiv\@ ENDM ELSE MODU32 MACRO *divisor, dividend(result), tmp divul.l \1,\3:\2 move.l \3,\2 ENDM ENDC HEADER MACRO move.l d0,d2 subq.l #1,d0 ; if (n == 1) return 0; beq.b .exit IFD USE_NEWFIND move.l d0,a0 ; nMinus1 = n - 1; ENDC lsr.l #1,d0 ; if ((n & 1) == 0) return (n == 2) bcc.b .odd .test_dif2 subq.l #2,d2 .isprime2 beq .isprime .notprime moveq #0,d0 .exit rts .odd ENDM IFD USE_MODCHECK MODCHECK MACRO ; 3*5 == 15 bit mask: ; ;3322 2222 2222 1111 1111 1100 0000 0000 ;1098 7654 3210 9876 5432 1098 7654 3210 ; ;0000 0000 0000 0000 1001 0110 0110 1001 moveq #3*5,d1 move.l d2,d3 move.w #$9669,d4 ; or 0x1669 which ever fits better IFD USE_SMARTMC divul.l d1,d7:d3 btst d7,d4 ELSE MODU32 d1,d3,d7 btst d3,d4 ENDC beq.b .not_3_5 subq.l #3,d2 .test_11_13 beq.b .isprime2 bra.b .test_dif2 .not_3_5 IFD USE_MC_7_11_13 move.w #7*11*13,d1 ; d1 upper word is zero! move.l d2,d3 IFD USE_SMARTMC divul.l d1,d7:d3 move.l d7,d1 lsr.l #3,d1 btst d7,(tab_7_11_13,pc,d1.l) ELSE MODU32 d1,d3,d7 move.l d3,d1 lsr.l #3,d3 btst d1,(tab_7_11_13,pc,d3.l) ENDC beq.b .not_7_11_13 subq.l #7,d2 beq.b .isprime2 subq.l #11-7,d2 bra.b .test_11_13 .not_7_11_13 ELSE moveq #7*11,d1 move.l d2,d3 IFD USE_SMARTMC divul.l d1,d7:d3 move.l d7,d1 lsr.l #3,d1 btst d7,(tab_7_11,pc,d1.l) ELSE MODU32 d1,d3,d7 move.l d3,d1 lsr.l #3,d3 btst d1,(tab_7_11,pc,d3.l) ENDC beq.b .not_7_11 subq.l #7,d2 beq.b .isprime2 subq.l #11-7,d2 bra.b .isprime2 .not_7_11 ENDC ENDM ELSE MODTABLE_7_11 MACRO ENDM MODCHECK MACRO ENDM ENDC IFD USE_NEWFIND FINDPREP MACRO sub.l a1,a1 ; a = 0 .find lsr.l #1,d0 addq.l #1,a1 bcc.b .find move.l d0,a2 ENDM ELSE FINDPREP MACRO ENDM ENDC IFD USE_2SPRPHASH SPRPCHECK MACRO *basereg moveq #2,\1 bsr.b .S_SPRP beq.b .exit moveq #59,\1 bsr.b .S_SPRP beq.b .exit ; check from error_hash table moveq #23,d3 move.l d2,d4 move.l d2,d1 lsr.l #8,d4 lsr.l d3,d1 lsr.l #2,d4 add.l d1,d1 moveq #127,d3 sub.l d1,d4 and.l d3,d4 lea (error_hash,pc,d4.l*4),a0 cmp.l (a0)+,d2 beq.b .notprime ; optimizer make these cmp.l (a0),d2 beq.b .notprime ; branches short... ; d0.l = 1 rts ENDM ELSE SPRPCHECK MACRO *basereg moveq #2,\1 bsr.b .S_SPRP beq.b .exit moveq #7,\1 bsr.b .S_SPRP beq.b .exit moveq #61,\1 ; [FALL THRU] ENDM ENDC IFD USE_060CODE CNOP 0,4 PrimeNumber HEADER MODCHECK FINDPREP SPRPCHECK d5 ; [FALL THRU] ; IN: d2.l = n ; d5.l = b ; a1.l = a (USE_NEWFIND) ; a2.l = t (USE_NEWFIND) .S_SPRP move.l d5,d1 IFD USE_NEWFIND move.l a2,d3 ELSE move.l d2,a0 subq.l #1,a0 ; nMinus1 = n - 1; move.w #-1,a1 ; a = -1 move.l a0,d3 ; t = n - 1 .find lsr.l #1,d3 addq.l #1,a1 bcc.b .find ENDC ; modexpo ;; move.l d5,d1 ; moved above MODU32 d2,d1,d0 ; r = b % n; mulu.w d5,d5 ; 16x16 = 32 MODU32 d2,d5,d0 ; b = (b * b) % n; lsr.l #1,d3 bcc.b .me_skip1 mulu.w d5,d1 ; 16x16 = 32 MODU32 d2,d1,d0 ; r = (b * r) % n; .me_skip1 tst.l d3 beq.b .me_done mulu.w d5,d5 ; 16x16 = 32 MODU32 d2,d5,d0 ; b = (b * b) % n; .me_loop move.l d5,d0 lsr.l #1,d3 ; t >>= 1; IFND USE_060FPU move.l d3,a3 ; save d3 ENDC bcc.b .me_skip bsr.b mulmod060 ; r = (b * r) % n; move.l d5,d0 .me_skip exg d5,d1 bsr.b mulmod060 ; b = (b * b) % n; exg d5,d1 IFND USE_060FPU move.l a3,d3 ; restore d3 ELSE tst.l d3 ENDC bne.b .me_loop .me_done ; t = r = d1 subq.l #1,d1 beq.b .isprime ; if (t == 1) return 1; move.l a1,d5 addq.l #1,d1 bra.b .goloop .loop subq.l #1,d5 IFD USE_2SPRPHASH beq .notprime ELSE IFD USE_MODCHECK beq .notprime ELSE beq.b .notprime ENDC ENDC move.l d1,d0 bsr.b mulmod060 ; t = (t * t) % n; .goloop cmp.l a0,d1 ; if (t == nMinus1) return 1; bne.b .loop .isprime moveq #1,d0 rts ELSE CNOP 0,4 PrimeNumber HEADER MODCHECK FINDPREP SPRPCHECK d1 ; [FALL THRU] ; IN: d2.l = n ; d1.l = b ; a1.l = a (USE_NEWFIND) ; a2.l = t (USE_NEWFIND) .S_SPRP IFD USE_NEWFIND move.l a1,d0 move.l a2,d3 ELSE move.l d2,a0 subq.l #1,a0 ; nMinus1 = n - 1; moveq #-1,d0 ; a = -1 move.l a0,d3 ; t = n - 1 .find addq.l #1,d0 lsr.l #1,d3 bcc.b .find ENDC IFD USE_UNROLLED ; modexpo move.l d1,d6 MODU32 d2,d6,d5 ; r = b % n; mulu.w d1,d1 ; 16x16 = 32 MODU32 d2,d1,d5 ; b = (b * b) % n; lsr.l #1,d3 bcc.b .me_skip1 mulu.w d1,d6 ; 16x16 = 32 MODU32 d2,d6,d5 ; r = (r * a) % n; .me_skip1 tst.l d3 beq.b .me_done mulu.w d1,d1 ; 16x16 = 32 MODU32 d2,d1,d5 ; b = (b * b) % n; .me_loop lsr.l #1,d3 ; t >>= 1; bcc.b .me_skip mulu.l d1,d5:d6 ; 32x32 = 64 divu.l d2,d5:d6 ; 64/32 = 32r:32q move.l d5,d6 ; r = (r * a) % n; .me_skip mulu.l d1,d5:d1 ; 32x32 = 64 divu.l d2,d5:d1 ; 64/32 = 32r:32q move.l d5,d1 ; b = (b * b) % n; tst.l d3 bne.b .me_loop .me_done ELSE ; modexpo move.l d1,d5 divul.l d2,d6:d5 ; r = b % n; bra.b .me_skip .me_loop move.l d5,d1 ; r = tmp; lsr.l #1,d3 ; t >>= 1; bcc.b .me_skip mulu.l d1,d5:d6 divu.l d2,d5:d6 move.l d5,d6 ; r = (r * a) % n; .me_skip mulu.l d1,d5:d1 divu.l d2,d5:d1 ; tmp = (r * r) % n; tst.l d3 bne.b .me_loop .me_done ENDC ; t = d6 subq.l #1,d6 beq.b .isprime ; if (t == 1) return 1; addq.l #1,d6 bra.b .goloop .loop subq.l #1,d0 beq.b .notprime2 mulu.l d6,d5:d6 ; 32x32 = 64 divu.l d2,d5:d6 ; 64/32 = 32r:32q move.l d5,d6 ; t = (t * t) % n; .goloop cmp.l a0,d6 ; if (t == nMinus1) return 1; bne.b .loop .isprime moveq #1,d0 .notprime2 rts ENDC IFD USE_060CODE IFD USE_060FPU CNOP 0,4 ; IN: d0.l = x (rarely zero) ; d1.l = y (rarely zero) ; d2.l = z (*never* zero) ; OUT: d1.l = x * y % z mulmod060 fabs.l d0,fp0 fabs.l d1,fp1 fabs.l d2,fp2 fmul.x fp1,fp0 fmove.x fp0,fp1 fdiv.x fp2,fp0 fintrz.x fp0,fp0 fmul.x fp2,fp0 fsub.x fp0,fp1 fmove.l fp1,d1 rts ELSE IFD USE_FASTMM060 ; optimized 32 * 32 -> 64 multiplication macro ; IN: d7.l % 64 = 16 ; OUT: d6.l = 0 ;NOTE: d3/d4 trashed MULU64 MACRO ; multiplier(result upper 32bits),multiplicand(result lower 32bits) move.l \1,d6 move.l \2,d3 move.l \2,d4 ror.l d7,d6 ; swap ror.l d7,d4 ; swap mulu.w \1,\2 ; bd = m2_l × m1_l mulu.w d4,\1 ; ad = m1_h × m2_l mulu.w d6,d3 ; bc = m2_h × m1_l mulu.w d6,d4 ; ac = m2_h × m1_h ror.l d7,\2 ; (=swap) moveq #0,d6 add.w \1,\2 ; Add ad to bd's most significant word addx.l d6,d4 ; Add the potential carry to ac add.w d3,\2 ; Add bc to bd's most significant word addx.l d6,d4 ; Add the potential carry to ac lsr.l d7,\1 lsr.l d7,d3 add.l d4,\1 ror.l d7,\2 ;swap add.l d3,\1 ;= Most significant longword. ENDM CNOP 0,4 ; IN: d0.l = x (rarely zero) ; d1.l = y (rarely zero) ; d2.l = z (*never* zero) ; OUT: d1.l = x * y % z ;NOTE: d0/d3/d4/d6/d7/a3-a6 trashed mulmod060 moveq #16,d7 ; term = 0 (in bit 6) MULU64 d1,d0 ; is dividend_hi zero? ;tst.l d1 ; from mulu64 above! bne.b .full64bit ; ok. it is a 32bit only operation ; if divisor > dividend then remainder is dividend cmp.l d2,d0 bls .exit2 ; .exit2 does or.l d0,d1 (d1 = 0) ; use 32bit : 32bit divide divul.l d2,d1:d0 .exit rts .full64bit ; ok the dividend is full 64bit value, we need to do more ; work. ; note: I do not check for overflow here, as it should ; never happen. ; if divisor < 65536 we can use simple math cmp.l #$ffff,d2 bhi.b .fullthing lsl.l d7,d1 ; <<16 lsr.l d7,d0 ; >>16 move.w d0,d1 divu.w d2,d1 ; (dividend_hi << 16 | dividend_lo >> 16) % (uint16) divisor) move.w d0,d1 ; | (dividend_lo & 0x0000ffff) divu.w d2,d1 ; % (uint16) divisor; lsr.l d7,d1 rts .fullthing ; in this case there is no shortcut, we need to do ; the full thing. ; pre-adjust the values move.l d2,d6 ; divisor & 0x80000000 set ? sub.l a6,a6 ; shift = 0; bmi.b .pa_done .pa_loop add.l d0,d0 addx.l d1,d1 ; dividend <<= 1; add.l d6,d6 ; divisor <<= 1; addq.l #1,a6 ; shift++; bpl.b .pa_loop .pa_done move.l d6,-(sp) ; push work register move.l d5,a5 ; save d5 move.l d2,a4 ; save d2 .mloop ; determine the count move.l d1,d3 lsr.l d7,d3 ; dividend_hi >> 16 moveq #-1,d5 ; cnt = 0xffff; cmp.w (sp),d3 beq.b .equ move.l d1,d5 divu.w (sp),d5 ; cnt = dividend_hi / ((uint16) (divisor >> 16)); .equ ; adjust the count ror.l d7,d0 ; swap dividend_lo .adjustcnt move.w (sp),d3 mulu.w d5,d3 ; (divisor >> 16)) * cnt move.l d1,d6 sub.l d3,d6 ; diff = dividend_hi - ((uint16) (divisor >> 16)) * cnt; move.l (sp),d3 ror.l d7,d6 ; swap mulu.w d5,d3 ; ((uint16) divisor) * cnt tst.w d6 ; if (diff >> 16) break; bne.b .adjustdone move.w d0,d6 ; diff = diff << 16 | dividend_lo >> 16; cmp.l d3,d6 ; if (diff >= (((uint16) divisor) * cnt)) break; bhs.b .adjustdone subq.w #1,d5 ; cnt--; bra.b .adjustcnt .adjustdone ror.l d7,d0 ; restore dividend_lo lsl.l d7,d5 move.l (sp),d2 MULU64 d5,d2 ; delta = mulu64(cnt << 16, divisor) ; decrement the delta sub.l d2,d0 subx.l d5,d1 bcc.b .nocarry ; add due to carry ;moveq #0,d6 ; zeroed by MULU64 above! move.l (sp),d4 lsl.l d7,d4 move.w (sp),d6 add.l d4,d0 ; dividend_lo += divisor << 16 addx.l d6,d1 ; dividend_hi += divisor >> 16 + carry .nocarry bset #6,d7 ; if (term) break; term = 1; bne.b .mdone ror.l d7,d0 ; swap dividend_lo lsl.l d7,d1 ; dividend_hi << 16 move.w d0,d1 ; | dividend_lo >> 16 clr.w d0 ; dividend_lo <<= 16; bra.b .mloop .mdone addq.l #4,sp ; pop work storage IFGT 1 ;trap #0 move.w d1,d0 ; dividend_lo = (dividend_lo & 0xffff0000) | (dividend_hi & 0xffff); move.l a6,d3 ; get shift count ror.l d7,d0 ; swap dividend_lo move.l a4,d2 ; restore d2 lsr.l d3,d0 ; shift the result back move.l a5,d5 ; restore d5 .exit2 move.l d0,d1 ; return result rts ELSE move.l a6,d3 ; get shift count moveq #-1,d6 ; mask move.w d1,d0 ; dividend_lo = (dividend_lo & 0xffff0000) | (dividend_hi & 0xffff); lsl.l d3,d6 ; shift mask ror.l d7,d1 ; swap dividend_hi ror.l d7,d0 ; swap dividend_lo and.l d6,d1 ; dividend_hi &= mask; move.l a4,d2 ; restore d2 lsr.l d3,d0 ; shift the result back lsr.l d3,d1 move.l a5,d5 ; restore d5 .exit2 or.l d0,d1 ; join the result rts ENDC ELSE ; This mulmod060 routine seems simpler, but it can ; get VERY VERY slow. CNOP 0,4 ; IN: d0.l = x (rarely zero) ; d1.l = y (rarely zero) ; d2.l = z (*never* zero) ; OUT: d1.l = x * y % z ;NOTE: d0/d6/d7/a4-a5 trashed mulmod060 moveq #16,d7 cmp.l d0,d2 bhi.b .nodiv1 move.l d0,d6 divul.l d2,d0:d6 ; x %= z; .nodiv1 cmp.l d1,d2 bhi.b .nodiv2 move.l d1,d6 divul.l d2,d1:d6 ; y %= z; .nodiv2 move.l d0,d6 move.l d4,a4 ; save d4 move.l d1,d4 lsr.l d7,d6 ; hx = x >> 16; lsr.l d7,d4 ; hy = y >> 16; tst.w d6 bne.b .big tst.w d4 bne.b .big mulu.w d0,d1 ; l_xy = x * y; bra.b .exit .big ; x &= 0x0000ffff; ; y &= 0x0000ffff; move.l d5,a5 ; save d5 move.w d0,d5 mulu.w d1,d5 mulu.w d4,d0 ; lxhy = lx * hy; mulu.w d6,d4 ; hxhy = hx * hy; mulu.w d1,d6 ; lyhx = hx * ly; move.l d5,d1 lsr.l d7,d5 ;move.l d1,d1 ; l_xy = (lx * ly) & 0x0000ffff; ror.l d7,d1 ; swap l_xy add.l d6,d5 ; c = (c >> 16) + lyhx; move.l d5,d6 and.l #$0000ffff,d5 lsr.l d7,d6 ; h_xy = c >> 16; add.l d0,d5 ; c = (c & 0x0000ffff) + lxhy; move.w d5,d1 ; l_xy |= ((c & 0x0000ffff) << 16); lsr.l d7,d5 ror.l d7,d1 ; swap l_xy add.l d5,d6 move.l a5,d5 ; restore d5 add.l d4,d6 ; h_xy += (c >> 16) + hxhy; beq.b .exit .adjust MODU32 d2,d1,d0 sub.l d2,d1 ; lxy = (lxy % z) - z; subq.l #1,d6 bne.b .adjust .exit move.l a4,d4 ; restore d4 MODU32 d2,d1,d0 ; ret = l_xy % z; rts ENDC ENDC ENDC IFD USE_MODCHECK ; align the table beginning IFD USE_2SPRPHASH IFD USE_HASH_OLAY IFD _PHXASS_ CNOP 2,4 ELSE IFEQ (*-PrimeNumber)&2 dc.w 0 ENDC ENDC ENDC ENDC IFD USE_MC_7_11_13 ; 7*11*13 == 1001 bit mask: ; tab_7_11_13 dc.l $81686014,$8A149281,$46601009,$0C43A142 dc.l $34900814,$22834128,$58080732,$8144A430 dc.l $18050AC1,$402A1089,$2406A5C0,$21184806 dc.l $4291C820,$15280407,$89403012,$1AC4028D dc.l $60213108,$44828350,$A0124C24,$0A814960 dc.l $100E9482,$91082250,$090C4281,$62309488 dc.l $04328143,$68500806,$13A14024,$B008150A dc.l $C3402218,$880526A1,$44A11858 dc.w $0400 ELSE ; 7*11 == 77 bit mask: ; ;7777 7777 7766 6666 6666 5555 5555 5544 4444 4444 3333 3333 3322 2222 2222 1111 1111 1100 0000 0000 ;9876 5432 1098 7654 3210 9876 5432 1098 7654 3210 9876 5432 1098 7654 3210 9876 5432 1098 7654 3210 ; ;0010 0000 0100 0100 1000 0001 1000 0010 0001 0100 0000 1010 0001 0000 0110 0000 0100 1000 1000 0001 tab_7_11 dc.b %10000001 dc.b %01001000 dc.b %01100000 dc.b %00010000 dc.b %00001010 dc.b %00010100 dc.b %10000010 dc.b %10000001 dc.b %01000100 dc.b %00100000 ENDC ENDC ; ; This table contain hash lookup table for the 'wrongly' calculated ; base-2 strong probable primes within 4gig area (base-2 pseudoprimes). ; The 59-SPRP doesn't rule out all pseudoprimes, so this hash is needed. ; It's much faster to have this hashtable than doing third SPRP call. ; ; Optimal table was generated by finding base that removed most of the ; base-2 pseudoprimes (59) and then generating the hashtable of the ; remaining ones. ; IFD USE_2SPRPHASH IFD USE_MODCHECK IFD USE_HASH_OLAY error_hash EQU *-16 ELSE CNOP 0,4 error_hash dc.l 0,0,0,0 ENDC ELSE CNOP 0,4 error_hash dc.l 0,0,0,0 ENDC dc.l $1249,0,$11f73289,$a1cbd59 dc.l 0,0,0,0 dc.l $11841d9,$7e1c1521,$1a852cf,$81aba79 dc.l 0,0,$b76f829,$264ee9 dc.l $346392a1,$3d4222c5,$bdfc2f95,0 dc.l 0,0,$8a7369,0 dc.l $729d,0,$3347a8dd,0 dc.l $3241a11f,$833eb2f5,$cb213929,0 dc.l 0,$2d8bec1,$668fb25,0 dc.l $6e70955,0,0,0 dc.l 0,$99d4dc1,$b8f6fc9,0 dc.l $baf7b25,0,0,$4cdc5 dc.l 0,$3223f675,$c226fb0d,0 dc.l 0,0,$40f29f1,$d0f729 dc.l $8c37821,$14f5d5,0,$ff01 dc.l $37ee7bf5,$ab3db661,0,$9f14a7 dc.l $4774c39,$2ee9fa21,0,0 dc.l 0,$1db8fca1,$4c1721b,0 dc.l 0,0,$24d5b29,$c61d9bb1 dc.l 0,0,$90e85361,0 dc.l 0,0,0,0 dc.l 0,0,0,$9e405dd dc.l 0,0,0,0 dc.l 0,$bfa17dc7,0,$2f8c4b dc.l 0,$148cde6d,$d2a6a41,$e353cadd dc.l 0,$42d3cd95,$8e0323d,$42f5d0df dc.l $2fb021,$d2e4da05,$e7c24d,$93f6f78d dc.l $6d029a1,0,$2219e981,$46642da7 dc.l 0,$45a22fb9,$7d98f,0 dc.l $8086231,$46884f01,0,$9100ff21 dc.l 0,0,0,$378f741d dc.l 0 ENDC IFD TESTSPSP test_spsp dc.l 2047,3277,4033,4681,8321,15841,29341,42799 dc.l 49141,52633,65281,74665,80581,85489,88357,90751 dc.l 104653,130561,196093,220729,233017,252601,253241,256999 dc.l 271951,280601,314821,357761,390937,458989,476971,486737 dc.l 489997,514447,580337,635401,647089,741751,800605,818201 dc.l 838861,873181,877099,916327,976873,983401,1004653,1016801 dc.l 1023121,1082401,1145257,1194649,1207361,1251949,1252697,1302451 dc.l 1325843,1357441,1373653,1397419,1441091,1493857,1507963,1509709 dc.l 1530787,1678541,1730977,1811573,1876393,1907851,1909001,1969417 dc.l 1987021,2004403,2081713,2181961,2205967,2264369,2269093,2284453 dc.l 2304167,2387797,2419385,2510569,2746477,2748023,2757241,2811271 dc.l 2909197,2953711,2976487,3090091,3116107,3125281,3375041,3400013 dc.l 3429037,3539101,3567481,3581761,3605429,3898129,4181921,4188889 dc.l 4335241,4360621,4469471,4502485,4513841,4682833,4835209,4863127 dc.l 5016191,5044033,5049001,5173169,5173601,5256091,5310721,5444489 dc.l 5489641,5590621,5599765,5672041,5681809,5919187,6140161,6226193 dc.l 6233977,6334351,6368689,6386993,6787327,6836233,6952037,7177105 dc.l 7306261,7306561,7462001,7674967,7759937,7820201,7883731,8036033 dc.l 8095447,8384513,8388607,8534233,8725753,8727391,9006401,9056501 dc.l 9069229,9073513,9371251,9564169,9567673,9588151,9729301,9774181 dc.l 9863461,9995671,10323769,10386241,10425511,10610063,10655905,10712857 dc.l 10763653,10974881,11081459,11335501,11473885,11541307,11585293,11777599 dc.l 12263131,12327121,13057787,13216141,13338371,13421773,13446253,13500313 dc.l 13635289,13694761,13747361,14179537,14324473,14709241,14794081,14865121 dc.l 15101893,15139199,15188557,15220951,15247621,15479777,15510041,15603391 dc.l 15698431,15802681,15976747,15978007,16070429,16132321,16324001,16360381 dc.l 16705021,16773121,16822081,16853077,16879501,17116837,17134043,17208601 dc.l 17327773,17375249,17509501,17585969,18073817,18366937,18443701,18454921 dc.l 18535177,18653353,18740971,19328653,19404139,19471033,19607561,20261251 dc.l 20417311,20647621,21303343,21306157,21359521,21400481,21417991,21623659 dc.l 22075579,22087477,22564081,22591301,22669501,22849481,22953673,23464033 dc.l 23577497,23734901,23828017,23872213,23963869,24214051,25080101,25326001 dc.l 25629913,26254801,26377921,26758057,26821601,26840269,26877421,27108397 dc.l 27118601,27219697,27271151,27279409,27331921,27380831,27392041,27509653 dc.l 27664033,27798461,27808463,27966709,28325881,28527049,28572961,29111881 dc.l 29214541,29581501,29878381,30022129,30185569,30219757,30295141,30388753 dc.l 30418957,30576151,30662497,30740417,30881551,30894307,31166803,31436123 dc.l 33627301,33704101,34003061,34856167,35576599,35703361,35820937,35851037 dc.l 36307981,36338653,36765901,36861901,36919681,37109467,37439201,37769887 dc.l 38010307,38046817,38118763,38210323,38342071,38624041,39465091,39655153 dc.l 40629601,40782589,40827473,40987201,41121433,41604109,41642681,41662297 dc.l 41840809,42485119,42623017,42984589,43363601,43397551,43661257,44314129 dc.l 44963029,45100177,45414433,45485881,45769645,45819541,46325029,46517857 dc.l 46679761,47220367,47349373,47759041,47903701,47918581,48191653,48269761 dc.l 48316969,48369727,48448661,48551161,49303801,49411801,50155733,51129781 dc.l 51302353,51340807,51500521,52072021,52119289,52204237,53399449,53656021 dc.l 53675623,53695721,53711113,54029741,54449431,54468001,55109401,55318957 dc.l 55729957,56420033,57561085,58422409,58449847,58509977,59631211,59840537 dc.l 59913157,60155201,60352921,60547831,60566431,60581401,60696661,60738257 dc.l 61201009,61219789,61377109,61755751,61832377,63001801,63065281,63167743 dc.l 63318169,63346999,63388033,64605041,65254393,65301013,65359477,66096253 dc.l 66977281,67194401,67642513,68102641,68154001,68165761,68512867,69030901 dc.l 69128641,69176647,69228967,69231061,69485281,69885649,70030501,70149631 dc.l 70593931,70728121,71572957,71734417,72498253,72543547,73562833,73645001 dc.l 74329399,74411131,74927161,75140137,75565873,76725091,76745101,77533123 dc.l 77576401,77812153,77817979,78939089,79398901,79417801,79786523,80375707 dc.l 80556337,80687881,81433591,81445585,82273201,82506439,82870517,83204801 dc.l 84421081,84487457,84998503,85519337,86027329,86067241,86530621,86999837 dc.l 87499651,87694261,88368853,89308771,90626185,91433281,91659283,93431521 dc.l 93541537,94316401,94502701,95451361,95452781,96618397,96904081,96925921 dc.l 97496449,97796953,97863529,97924217,99036001,99115297,99486889,99789673 dc.l 100463443,100618933,100943201,101270251,101276579,101649241,102004421,102678031 dc.l 102690677,104078857,104852881,104857391,105305443,105919633,106485121,106743073 dc.l 106775761,107543333,108596953,109118791,109437751,110139499,110312773,110717861 dc.l 111654401,112402981,112792519,112828801,114305441,114701341,115007581,115039081 dc.l 115174681,115804501,115873801,116090081,116617289,117987841,119204809,119558011 dc.l 120296677,120517021,121472359,122166307,123671671,123987793,124145473,126132553 dc.l 127050067,128079409,128124151,128665319,128987429,129256273,129357061,131567929 dc.l 131938561,132332201,132338881,132575071,133216381,133302781,133467517,133800661 dc.l 134696801,134767153,135263269,135308881,135969401,136043641,136661201,137415821 dc.l 137763037,138030721,139487041,140197051,143168581,145348529,146156617,146884393 dc.l 147028001,147287141,148087801,148109473,148910653,149389633,150960239,150988753 dc.l 151533377,152486551,152716537,153369061,153754873,153928133,154287451,155102221 dc.l 156114061,156532799,157069189,157405249,157725829,158068153,158192317,158397247 dc.l 158496911,158895281,160348189,160491329,160587841,160672201,161035057,161304001 dc.l 162026869,162067441,162690481,163442551,165224321,165938653,166082309,166827943 dc.l 167579497,167692141,167881121,168566501,169655641,170782921,172116181,172290241 dc.l 174479729,174769621,176030977,176597821,177927641,177951973,178956971,179285137 dc.l 179820257,180497633,180703451,181285537,181542601,181647497,182383111,183677341 dc.l 184411567,185365141,186183469,187667969,187761241,189714193,189738361,190382161 dc.l 190913297,191233813,191981609,192346153,192857761,193298365,193330237,193949641 dc.l 194556451,196035001,196049701,198982759,199674721,200143351,202130197,203505697 dc.l 204582457,205057561,206304961,206504033,206529737,207008569,207030541,207477001 dc.l 207618781,208051201,208096681,208969223,210842113,213035761,214852609,214858717 dc.l 215436241,215878531,217875571,218642029,218947121,220531501,220883521,221368153 dc.l 222630193,223449463,223625851,223782263,225853633,226359547,226450297,227444101 dc.l 227475481,228549565,228652201,229589413,230357761,231383461,232771501,234420481 dc.l 235426913,235928071,237791143,238001653,238244041,240068041,240785047,242650717 dc.l 244883981,245006623,245950561,246099317,246282511,246434761,246658441,247318957 dc.l 247416101,247800709,250958401,251663837,251737993,252853921,253610281,253893397 dc.l 255318001,255416897,257590661,258020473,258043229,259765747,260156101,260518801 dc.l 260963389,261703417,262979501,264269449,265020001,266811169,270525737,271272569 dc.l 271763467,271950829,273480637,274701913,274919401,275619961,276131137,276638321 dc.l 280885153,282471853,282769771,284166877,284301751,284736091,284834299,287160301 dc.l 287449091,288099001,288117721,288735277,290643601,290953921,292153681,292902481 dc.l 293609485,293847721,295419097,297411661,298212601,299736181,301413001,302635351 dc.l 303373801,305897131,307694323,307972801,310978027,311177213,311411629,311655829 dc.l 311671361,312408113,312614021,313748611,314184487,315034513,315351521,317365933 dc.l 317641171,317796119,319440769,319726177,320326003,320819941,321324589,322469701 dc.l 322941881,324171541,324477697,325352101,325546873,326266051,326405713,326695141 dc.l 327398009,328302901,329153653,330198331,331658081,331934989,337135501,337420679 dc.l 337665901,338125537,338458807,339492169,341958121,341994131,343017529,344201441 dc.l 344255551,344776301,346080391,348989101,349752913,350031973,351058753,352802803 dc.l 356836819,357348601,357872971,358416577,359394751,359727073,360145633,360787771 dc.l 361312337,363170837,365077373,366487201,367559501,368016949,369269551,369667561 dc.l 371011801,371611153,372167101,373533617,373669453,373906513,374988661,376957153 dc.l 377192353,377334497,377806687,377869031,382536001,385319089,385454161,390612221 dc.l 392679737,393513121,393611653,394723177,395900557,396899581,399156661,399302581 dc.l 399647221,403095967,405739681,405782623,407889161,410613809,410680357,412836689 dc.l 413429801,414216461,414368641,415204501,415476343,415878541,417779909,418044563 dc.l 418226581,418616161,418617281,418667401,419184481,420468481,421942951,422928101 dc.l 423465001,424411501,425967301,426770437,426783811,427294141,428180191,428373401 dc.l 429135841,429509837,430046857,430646401,430733701,435016187,435993301,437462101 dc.l 437866087,439309261,440707345,441650591,441758461,442050577,442181291,446414621 dc.l 450807481,450866021,453366029,453967739,455198563,460251733,461151121,461272267 dc.l 462587329,462639409,464012033,464955857,466290949,466758181,467100937,470268137 dc.l 470644021,471535373,473581057,474983881,475723849,478614067,480668347,482488393 dc.l 483006889,483029821,486902929,487896601,488585521,489994201,490950461,493108481 dc.l 494288677,495909871,496560349,497148599,497285713,498662561,498706651,500747293 dc.l 501172241,504870241,505473263,505532773,505798213,506349421,507142567,508606771 dc.l 509302873,509551201,510925609,511215521,511611673,514738981,516764063,517662001 dc.l 518216201,518548801,522758233,523756711,528220117,531681281,533429881,534782293 dc.l 535252867,535428577,536114197,536342419,536870911,540621181,540654409,540680141 dc.l 541935901,544861633,545550433,546117301,546322201,548989561,550132741,550230409 dc.l 550635373,550853137,551313001,553027201,554487121,554599051,555321007,556069849 dc.l 556095433,556114609,558235109,558900821,561448487,562367821,564298489,564689381 dc.l 565664761,567358513,568902001,570941881,572123521,572228929,572567353,572936869 dc.l 574998841,576724219,577210181,577352641,577613261,579606301,579956653,581618143 dc.l 582799951,585261637,586706821,587343541,588049001,592467451,592468777,593682169 dc.l 593728489,597537361,599135767,600893921,601606487,602379181,606057985,606338185 dc.l 609361567,609813781,611146861,611770513,611812321,612006253,613849601,615361183 dc.l 616280897,617087701,619239457,620544961,620755537,621769669,626717471,627886657 dc.l 628868467,629134081,630811513,631767943,631974613,633289807,635155291,635291077 dc.l 635319361,636337073,636936697,638837761,639807781,640650931,640977373,643036321 dc.l 643552909,644457551,644731357,645556481,651151801,651514753,653260633,660095641 dc.l 660754117,661122881,661207177,661896145,662134201,663760681,672103001,673778827 dc.l 676359391,678481693,678981871,680983817,681124207,682528687,687741401,692597647 dc.l 693456521,696998251,698192041,698819711,702683101,704934361,705303457,705351583 dc.l 707691601,709409993,710721001,711374401,714490481,714663139,716652001,717096641 dc.l 717653129,717831211,722955773,724160251,724969087,725508241,731276521,732805681 dc.l 739444021,740988151,741214237,742017181,745493761,745745461,746331041,747406801 dc.l 750632137,751705597,753233717,753532781,753574537,753594001,756205633,756271909 dc.l 758581651,758687581,758901701,759252367,763907741,764033999,764240611,765378241 dc.l 766823797,770909107,770937931,771337891,773131927,773807401,775368901,775896181 dc.l 776443769,777218989,781471001,782823281,784450393,784777393,784783477,784966297 dc.l 787085857,787209277,788046901,790453049,791118043,794201333,796072003,796200901 dc.l 796560703,797834017,799630753,799898833,799916101,801093011,801227269,801866647 dc.l 804978721,805771501,809790881,811607777,811730923,816024161,816215401,818391211 dc.l 819466201,822018961,826004467,830664451,831807145,831933901,832048447,833610751 dc.l 839268139,839280691,839908217,840749761,841217653,842785841,842824981,843161887 dc.l 844545271,846961321,848090377,849548671,854094781,858687103,858895921,859096477 dc.l 860334301,862678081,867022747,867110501,867638201,868111597,868691401,870248821 dc.l 870985223,871157233,878940833,879995689,880870513,880922657,883276549,884304037 dc.l 884701441,888868441,893692819,894264337,899019353,900736411,902566501,903108821 dc.l 903390643,905040953,907378669,907670501,910202509,914255785,914906539,921858631 dc.l 923437213,925265551,926756881,927106561,929159941,932148253,936421141,938376181 dc.l 946034057,947878081,949317217,949697233,952893881,954924013,955718345,956422657 dc.l 958131157,958970545,960946321,962489557,962491237,962523169,965501857,967266451 dc.l 967287751,967714021,968283247,970586713,971975071,974113601,974471243,977483449 dc.l 979363153,980056507,981484561,994133479,995586373,998489017,998590601,998596741 dc.l 998724481,999828727,1002261781,1005833971,1006800829,1008839999,1009025263,1009140161 dc.l 1011319501,1011333061,1011570457,1011909271,1012438391,1013833153,1015626151,1020515761 dc.l 1022336611,1027744453,1028494429,1034958601,1039224121,1040234231,1054999441,1056121453 dc.l 1057426651,1065602281,1069388497,1070941987,1072898711,1073288581,1073484823,1078467589 dc.l 1081798061,1084241341,1084444481,1087190371,1094042321,1097416321,1098743563,1100624857 dc.l 1102573501,1104194521,1105038871,1106529761,1106595493,1108135381,1109304913,1110582947 dc.l 1111205873,1111939201,1112671603,1116379301,1117202557,1117828001,1117890019,1119412321 dc.l 1120981021,1121176981,1123406047,1123625501,1124396521,1125038377,1130933429,1134367777 dc.l 1139137057,1140573601,1142466151,1147434289,1151670001,1153164097,1153997885,1154987209 dc.l 1156761911,1157839381,1160844821,1163227759,1165717129,1166598217,1168221121,1168256953 dc.l 1171525681,1180970407,1181566219,1183338241,1184554801,1186325981,1187235193,1191153937 dc.l 1192314817,1192903531,1193557093,1196852273,1202142061,1204205449,1205772499,1209998077 dc.l 1210393801,1210653541,1213619761,1217823517,1217924159,1220114377,1221127013,1222861271 dc.l 1223531677,1223941657,1226855293,1227133513,1229491063,1229751667,1230446653,1231362793 dc.l 1232445677,1235188597,1236313501,1236442421,1238825569,1242171349,1242958501,1254277909 dc.l 1255665613,1260404821,1265477791,1267345081,1270489621,1270667353,1272558739,1272866167 dc.l 1281100549,1282568741,1285445305,1286298263,1296613501,1297443913,1301926081,1302607801 dc.l 1302745481,1307823661,1308998741,1309983901,1310329567,1312332001,1312573123,1313396221 dc.l 1318717531,1319992181,1320793813,1321058213,1323668917,1325172421,1325329297,1328256247 dc.l 1331973329,1344597577,1344975721,1345514101,1350685001,1352453257,1356328121,1356661711 dc.l 1357459183,1361355751,1362463807,1362515701,1366608377,1368769681,1375322101,1378646179 dc.l 1383283129,1385656829,1386705433,1391890033,1394640941,1397357851,1398883201,1400859847 dc.l 1404008369,1404253369,1406826241,1409372779,1414154827,1414529533,1421475031,1424503849 dc.l 1425860101,1426319563,1427771089,1438648993,1440922891,1441678411,1442945689,1443388481 dc.l 1446818651,1448921633,1454282449,1456527461,1457378449,1461307717,1463030101,1463065501 dc.l 1463178817,1464568381,1465908193,1465945417,1468540477,1468824787,1469960377,1470080501 dc.l 1470650851,1481626513,1483873861,1485061471,1486564301,1493114149,1495190699,1497965713 dc.l 1499971457,1499989177,1500142001,1502171117,1502403121,1503240559,1503705601,1504832033 dc.l 1509156013,1515175087,1517039371,1518290707,1521221473,1526732803,1529648231,1529819971 dc.l 1530495289,1532419099,1532569681,1532755369,1534063081,1535020133,1536251047,1537433899 dc.l 1537641691,1538012449,1539583921,1541955409,1545019813,1545177581,1546106773,1546508057 dc.l 1547140841,1547712601,1554270481,1565893201,1566594551,1567830241,1568916311,1574362441 dc.l 1577983489,1578009401,1581576641,1582783777,1583230241,1584443341,1586436193,1593706201 dc.l 1595647351,1597330813,1603765021,1603810561,1603994701,1609916491,1614508267,1617795181 dc.l 1617921667,1620646177,1630062253,1631314609,1633044241,1637434657,1637930893,1638294661 dc.l 1639846391,1641971701,1644637051,1647225529,1648076041,1649430889,1649684401,1650265549 dc.l 1650682153,1656229921,1661202113,1663998337,1668037621,1671603667,1672125131,1675978193 dc.l 1678274581,1679130641,1685433413,1686001861,1692605041,1695158921,1700250049,1709909293 dc.l 1714322377,1716774481,1718013133,1718088301,1720630759,1721061497,1721290741,1721986313 dc.l 1722703501,1725675451,1726372441,1731048937,1734059291,1735071913,1740214841,1743166441 dc.l 1746721681,1750412161,1760014561,1769267761,1770236893,1773582977,1776820033,1779649381 dc.l 1784638309,1785843547,1787934881,1790023861,1791426787,1792442737,1792588813,1794814103 dc.l 1802510669,1803768091,1804906517,1805947313,1809888967,1816408273,1816572745,1819829749 dc.l 1835114401,1844028961,1846171781,1850233897,1850598961,1854940231,1856689453,1860373241 dc.l 1862880401,1867165249,1868951881,1873177693,1878691753,1879111697,1879775501,1888407781 dc.l 1894909141,1894955311,1899081757,1905958891,1909566073,1910134309,1911197947,1912950241 dc.l 1914303841,1916987593,1917397637,1920301951,1921309633,1922092567,1922687293,1923224689 dc.l 1923311317,1923845801,1928903971,1930534453,1930915169,1934350351,1938264241,1943951041 dc.l 1950987193,1957705177,1959659857,1960708261,1964958805,1965007601,1968002149,1970065681 dc.l 1988965861,1990822961,1991063449,1995830761,1996231189,1996339649,1997844157,1999053601 dc.l 1999111801,2007646961,2013554869,2013655645,2016481477,2017021333,2017509601,2021392369 dc.l 2021884343,2028279793,2028812399,2029830409,2036224321,2046320701,2049293401,2049791185 dc.l 2050617713,2052149221,2055634561,2057835781,2062612033,2068867841,2076192007,2081039297 dc.l 2081551753,2082146617,2086645009,2093300401,2095627153,2096046457,2100292841,2101744837 dc.l 2104994449,2105594401,2107148761,2112030361,2114643217,2115769633,2116483027,2116541221 dc.l 2117031263,2117555641,2118621097,2120096161,2123601751,2124691213,2127197489,2129304997 dc.l 2129331241,2131811501,2139155051,2140771609,2141340833,2141744221,2144961253,2147418113 dc.l 2152627801,2155046141,2155416251,2172155819,2173540951,2173579801,2175126601,2175406201 dc.l 2177374321,2177645557,2185362233,2187717761,2200115713,2201924341,2202205897,2203649197 dc.l 2206095589,2210578759,2213431729,2216960929,2217879901,2229468697,2231332357,2241880033 dc.l 2241982009,2246762899,2249509159,2251732033,2256748777,2256751837,2262861901,2269307587 dc.l 2274584089,2283289681,2284416181,2284660351,2289251669,2290910257,2292068143,2295209281 dc.l 2296995121,2300795353,2309241601,2311558021,2311575001,2315137261,2320527613,2321591371 dc.l 2323147201,2324867399,2330569541,2331181621,2335341601,2338157597,2340460487,2345907961 dc.l 2347597981,2352371251,2354453561,2355230749,2355320101,2355622721,2355735089,2370928337 dc.l 2372976563,2375415841,2381782597,2382364601,2382678101,2385574201,2389544977,2394311233 dc.l 2395916965,2398393661,2401166041,2405599561,2411128441,2412172153,2413973071,2428648967 dc.l 2430697513,2431144801,2432761633,2432860273,2433791593,2434974433,2435091221,2437907779 dc.l 2438778413,2443708961,2448039497,2454285751,2471205361,2473120961,2473189441,2474676949 dc.l 2476283239,2477814193,2478643907,2480147521,2482435981,2482682131,2484408301,2488420801 dc.l 2492480233,2494660033,2495834329,2499327041,2501012599,2502525637,2506733189,2507121037 dc.l 2508178843,2513230891,2519297089,2526566041,2528291341,2529827821,2530351561,2532630787 dc.l 2533465661,2533797017,2537105761,2539406281,2541660367,2542479481,2545934077,2550780277 dc.l 2551365769,2555391481,2561945401,2565186137,2571180247,2575060949,2582952769,2584460701 dc.l 2588582089,2597289241,2597294701,2602343521,2602378721,2604803701,2611122229,2611461529 dc.l 2617563031,2621080741,2621977627,2622124597,2625903601,2626783921,2627284987,2632605049 dc.l 2634284801,2634804481,2634820813,2639099233,2642159809,2642582251,2646751249,2648662777 dc.l 2649907201,2651507713,2656494271,2658696301,2668469431,2672605657,2672651521,2681041843 dc.l 2682823681,2683742491,2684284441,2687655169,2688124001,2693739751,2695115473,2700818017 dc.l 2700891839,2701479001,2701878941,2704957909,2706863833,2707661501,2708826841,2716157989 dc.l 2716275007,2717428033,2721721939,2725357249,2736316301,2738184697,2753333227,2759392633 dc.l 2765323397,2766006253,2767672189,2769080161,2769602333,2777887297,2778304273,2781117721 dc.l 2800352011,2809635901,2823570433,2824256377,2824804693,2828205397,2832743713,2837917633 dc.l 2840634109,2840871041,2847894377,2848466281,2848722131,2855512909,2866005139,2866527841 dc.l 2871536561,2872948321,2874382853,2877769501,2881429741,2882370481,2885594497,2890316801 dc.l 2890414873,2895004927,2899294889,2903776129,2907393385,2916247819,2918295451,2920691161 dc.l 2929106753,2930831641,2931708097,2932327549,2936227603,2936958181,2941343633,2944555681 dc.l 2945208001,2951136343,2956724317,2957320351,2965700233,2968206601,2974506841,2986025677 dc.l 2993462713,2994098281,2994415201,2998202353,3004443679,3014101261,3015502181,3016957381 dc.l 3018147217,3018576689,3025350343,3028586471,3035375047,3036079729,3037295801,3037781251 dc.l 3038880473,3039681457,3041984353,3050190163,3056100623,3057886591,3058670677,3059397793 dc.l 3063685633,3065998717,3079496551,3082054697,3083053387,3083537689,3083884651,3094763851 dc.l 3103800701,3114125071,3118762921,3120445697,3122287981,3133899409,3145410761,3150972917 dc.l 3156599161,3156643141,3166504273,3172658653,3175204531,3175255717,3181356263,3182606857 dc.l 3182655361,3185571181,3187035113,3187421077,3187939921,3197565001,3197911001,3199164901 dc.l 3199264201,3207297773,3208902491,3211036165,3215031751,3219808411,3222693421,3227082823 dc.l 3227209057,3237992101,3242533897,3246238801,3248236309,3250348417,3252148621,3257334541 dc.l 3258647809,3261114601,3263097641,3263626957,3265122451,3267417677,3268506541,3274264033 dc.l 3275671969,3278640289,3282974857,3287174129,3288757249,3295362727,3296403601,3299246833 dc.l 3302322241,3305829073,3306686659,3306957593,3312536569,3315139717,3320669437,3323590463 dc.l 3323829169,3328354801,3334350781,3340214413,3344191241,3346172189,3349218881,3352091557 dc.l 3355382857,3369139201,3371024521,3371693063,3374360965,3381052177,3385842877,3386603221 dc.l 3387487351,3389030261,3395091311,3399205591,3402234749,3407772817,3407952169,3408135121 dc.l 3411829693,3415379701,3415832137,3417522841,3420143941,3423580481,3427050673,3428133103 dc.l 3429982081,3430804297,3432695921,3433458073,3434575327,3435973837,3443704261,3449768513 dc.l 3450717901,3458257741,3464236901,3466158361,3470716657,3482161261,3492178873,3492883081 dc.l 3504132113,3512291021,3513604657,3519318721,3524086333,3525088961,3529119361,3529864391 dc.l 3533662129,3533856913,3538213381,3542303047,3548378341,3552158521,3553567057,3557646401 dc.l 3562963973,3563340457,3566428301,3571451677,3574891757,3579288691,3583249921,3583604161 dc.l 3586833253,3587553971,3590409439,3594110081,3596491907,3596815169,3605151241,3612298321 dc.l 3614770573,3628526287,3630596257,3651572609,3662387977,3662503093,3663084541,3669587533 dc.l 3672754633,3673078513,3679657997,3685775741,3692307161,3695628133,3697278427,3697673959 dc.l 3700801861,3705582073,3708123301,3708905341,3709626961,3712887289,3713287801,3723699373 dc.l 3725016749,3729097633,3733761739,3746101189,3749383681,3751782737,3754680403,3756668401 dc.l 3760622689,3762110881,3767640601,3798040471,3798626833,3800084401,3805699501,3807112123 dc.l 3807308269,3807749821,3809018947,3813919453,3817706621,3827035237,3844074781,3846174151 dc.l 3846532801,3847106803,3852800033,3863326897,3865604023,3867183937,3874471147,3874523017 dc.l 3875096893,3886515361,3887423437,3891892421,3894053311,3897241129,3897869201,3900327241 dc.l 3903711841,3905533721,3907577521,3907752241,3914864773,3914880337,3914923211,3918227437 dc.l 3922321561,3924718057,3926912669,3935864017,3947383201,3953408801,3958930441,3959578801 dc.l 3966350203,3979485931,3987528793,3987960913,3991124341,3992697997,3997536427,4005660961 dc.l 4011996871,4015548769,4034969401,4034993269,4036395581,4042538497,4044601751,4048493983 dc.l 4058433931,4060942381,4061009971,4064633821,4067039461,4071644893,4076009857,4079665633 dc.l 4079682361,4083376067,4098258707,4099303297,4100934241,4103745689,4108970251,4109400127 dc.l 4109461709,4109711581,4110320663,4113013141,4115891893,4117058221,4117447441,4121286907 dc.l 4127050621,4129914673,4139015987,4155375349,4157008813,4166032873,4183664101,4186561633 dc.l 4187360341,4191864013,4192060699,4195843037,4196323561,4201014949,4204344601,4206006229 dc.l 4206295433,4212105409,4218900001,4232966251,4234224601,4237212061,4244022301,4244663651 dc.l 4247990917,4250920459,4251904273,4255695013,4271267333,4275011401,4277526901,4278305651 dc.l 4282867213,4294901761 dc.l 0 ENDC