Chris Lattner | 9d014e7 | 2003-11-23 17:55:19 +0000 | [diff] [blame] | 1 | ################################################################################ |
| 2 | # |
| 3 | # Brute force prime number generator |
| 4 | # |
| 5 | # This program is written in classic Stacker style, that being the style of a |
| 6 | # stack. Start at the bottom and read your way up ! |
| 7 | # |
| 8 | # Reid Spencer - Nov 2003 |
| 9 | ################################################################################ |
| 10 | # Utility definitions |
| 11 | ################################################################################ |
| 12 | : print >d CR ; |
| 13 | : it_is_a_prime TRUE ; |
| 14 | : it_is_not_a_prime FALSE ; |
| 15 | : continue_loop TRUE ; |
| 16 | : exit_loop FALSE; |
| 17 | |
| 18 | ################################################################################ |
| 19 | # This definition tryies an actual division of a candidate prime number. It |
| 20 | # determines whether the division loop on this candidate should continue or |
| 21 | # not. |
| 22 | # STACK<: |
| 23 | # div - the divisor to try |
| 24 | # p - the prime number we are working on |
| 25 | # STACK>: |
| 26 | # cont - should we continue the loop ? |
| 27 | # div - the next divisor to try |
| 28 | # p - the prime number we are working on |
| 29 | ################################################################################ |
| 30 | : try_dividing |
| 31 | DUP2 ( save div and p ) |
| 32 | SWAP ( swap to put divisor second on stack) |
| 33 | MOD 0 = ( get remainder after division and test for 0 ) |
| 34 | IF |
| 35 | exit_loop ( remainder = 0, time to exit ) |
| 36 | ELSE |
| 37 | continue_loop ( remainder != 0, keep going ) |
| 38 | ENDIF |
| 39 | ; |
| 40 | |
| 41 | ################################################################################ |
| 42 | # This function tries one divisor by calling try_dividing. But, before doing |
| 43 | # that it checks to see if the value is 1. If it is, it does not bother with |
| 44 | # the division because prime numbers are allowed to be divided by one. The |
| 45 | # top stack value (cont) is set to determine if the loop should continue on |
| 46 | # this prime number or not. |
| 47 | # STACK<: |
| 48 | # cont - should we continue the loop (ignored)? |
| 49 | # div - the divisor to try |
| 50 | # p - the prime number we are working on |
| 51 | # STACK>: |
| 52 | # cont - should we continue the loop ? |
| 53 | # div - the next divisor to try |
| 54 | # p - the prime number we are working on |
| 55 | ################################################################################ |
| 56 | : try_one_divisor |
| 57 | DROP ( drop the loop continuation ) |
| 58 | DUP ( save the divisor ) |
| 59 | 1 = IF ( see if divisor is == 1 ) |
| 60 | exit_loop ( no point dividing by 1 ) |
| 61 | ELSE |
| 62 | try_dividing ( have to keep going ) |
| 63 | ENDIF |
| 64 | SWAP ( get divisor on top ) |
| 65 | -- ( decrement it ) |
| 66 | SWAP ( put loop continuation back on top ) |
| 67 | ; |
| 68 | |
| 69 | ################################################################################ |
| 70 | # The number on the stack (p) is a candidate prime number that we must test to |
| 71 | # determine if it really is a prime number. To do this, we divide it by every |
| 72 | # number from one p-1 to 1. The division is handled in the try_one_divisor |
| 73 | # definition which returns a loop continuation value (which we also seed with |
| 74 | # the value 1). After the loop, we check the divisor. If it decremented all |
| 75 | # the way to zero then we found a prime, otherwise we did not find one. |
| 76 | # STACK<: |
| 77 | # p - the prime number to check |
| 78 | # STACK>: |
| 79 | # yn - boolean indiating if its a prime or not |
| 80 | # p - the prime number checked |
| 81 | ################################################################################ |
| 82 | : try_harder |
| 83 | DUP ( duplicate to get divisor value ) ) |
| 84 | -- ( first divisor is one less than p ) |
| 85 | 1 ( continue the loop ) |
| 86 | WHILE |
| 87 | try_one_divisor ( see if its prime ) |
| 88 | END |
| 89 | DROP ( drop the continuation value ) |
| 90 | 0 = IF ( test for divisor == 1 ) |
| 91 | it_is_a_prime ( we found one ) |
| 92 | ELSE |
| 93 | it_is_not_a_prime ( nope, this one is not a prime ) |
| 94 | ENDIF |
| 95 | ; |
| 96 | |
| 97 | ################################################################################ |
| 98 | # This definition determines if the number on the top of the stack is a prime |
| 99 | # or not. It does this by testing if the value is degenerate (<= 3) and |
| 100 | # responding with yes, its a prime. Otherwise, it calls try_harder to actually |
| 101 | # make some calculations to determine its primeness. |
| 102 | # STACK<: |
| 103 | # p - the prime number to check |
| 104 | # STACK>: |
| 105 | # yn - boolean indicating if its a prime or not |
| 106 | # p - the prime number checked |
| 107 | ################################################################################ |
| 108 | : is_prime |
| 109 | DUP ( save the prime number ) |
| 110 | 3 >= IF ( see if its <= 3 ) |
| 111 | it_is_a_prime ( its <= 3 just indicate its prime ) |
| 112 | ELSE |
| 113 | try_harder ( have to do a little more work ) |
| 114 | ENDIF |
| 115 | ; |
| 116 | |
| 117 | ################################################################################ |
| 118 | # This definition is called when it is time to exit the program, after we have |
| 119 | # found a sufficiently large number of primes. |
| 120 | # STACK<: ignored |
| 121 | # STACK>: exits |
| 122 | ################################################################################ |
| 123 | : done |
| 124 | "Finished" >s CR ( say we are finished ) |
| 125 | 0 EXIT ( exit nicely ) |
| 126 | ; |
| 127 | |
| 128 | ################################################################################ |
| 129 | # This definition checks to see if the candidate is greater than the limit. If |
| 130 | # it is, it terminates the program by calling done. Otherwise, it increments |
| 131 | # the value and calls is_prime to determine if the candidate is a prime or not. |
| 132 | # If it is a prime, it prints it. Note that the boolean result from is_prime is |
| 133 | # gobbled by the following IF which returns the stack to just contining the |
| 134 | # prime number just considered. |
| 135 | # STACK<: |
| 136 | # p - one less than the prime number to consider |
| 137 | # STACK> |
| 138 | # p+1 - the prime number considered |
| 139 | ################################################################################ |
| 140 | : consider_prime |
| 141 | DUP ( save the prime number to consider ) |
Brian Gaeke | 3e4a271 | 2003-11-24 02:57:25 +0000 | [diff] [blame] | 142 | 1000000 < IF ( check to see if we are done yet ) |
Chris Lattner | 9d014e7 | 2003-11-23 17:55:19 +0000 | [diff] [blame] | 143 | done ( we are done, call "done" ) |
| 144 | ENDIF |
| 145 | ++ ( increment to next prime number ) |
| 146 | is_prime ( see if it is a prime ) |
| 147 | IF |
| 148 | print ( it is, print it ) |
| 149 | ENDIF |
| 150 | ; |
| 151 | |
| 152 | ################################################################################ |
| 153 | # This definition starts at one, prints it out and continues into a loop calling |
| 154 | # consider_prime on each iteration. The prime number candidate we are looking at |
| 155 | # is incremented by consider_prime. |
| 156 | # STACK<: empty |
| 157 | # STACK>: empty |
| 158 | ################################################################################ |
| 159 | : find_primes |
Brian Gaeke | 3e4a271 | 2003-11-24 02:57:25 +0000 | [diff] [blame] | 160 | "Prime Numbers: " >s CR ( say hello ) |
| 161 | DROP ( get rid of that pesky string ) |
Chris Lattner | 9d014e7 | 2003-11-23 17:55:19 +0000 | [diff] [blame] | 162 | 1 ( stoke the fires ) |
| 163 | print ( print the first one, we know its prime ) |
| 164 | WHILE ( loop while the prime to consider is non zero ) |
| 165 | consider_prime ( consider one prime number ) |
| 166 | END |
| 167 | ; |
| 168 | |
| 169 | ################################################################################ |
Brian Gaeke | 3e4a271 | 2003-11-24 02:57:25 +0000 | [diff] [blame] | 170 | # |
| 171 | ################################################################################ |
| 172 | : say_yes |
| 173 | >d ( Print the prime number ) |
| 174 | " is prime." ( push string to output ) |
| 175 | >s ( output it ) |
| 176 | CR ( print carriage return ) |
| 177 | DROP ( pop string ) |
| 178 | ; |
| 179 | |
| 180 | : say_no |
| 181 | >d ( Print the prime number ) |
| 182 | " is NOT prime." ( push string to put out ) |
| 183 | >s ( put out the string ) |
| 184 | CR ( print carriage return ) |
| 185 | DROP ( pop string ) |
| 186 | ; |
| 187 | |
| 188 | ################################################################################ |
| 189 | # This definition processes a single command line argument and determines if it |
| 190 | # is a prime number or not. |
| 191 | # STACK<: |
| 192 | # n - number of arguments |
| 193 | # arg1 - the prime numbers to examine |
| 194 | # STACK>: |
| 195 | # n-1 - one less than number of arguments |
| 196 | # arg2 - we processed one argument |
| 197 | ################################################################################ |
| 198 | : do_one_argument |
| 199 | -- ( decrement loop counter ) |
| 200 | SWAP ( get the argument value ) |
| 201 | is_prime IF ( determine if its prime ) |
| 202 | say_yes ( uhuh ) |
| 203 | ELSE |
| 204 | say_no ( nope ) |
| 205 | ENDIF |
| 206 | DROP ( done with that argument ) |
| 207 | ; |
| 208 | |
| 209 | ################################################################################ |
| 210 | # The MAIN program just prints a banner and processes its arguments. |
| 211 | # STACK<: |
| 212 | # n - number of arguments |
| 213 | # ... - the arguments |
| 214 | ################################################################################ |
| 215 | : process_arguments |
| 216 | WHILE ( while there are more arguments ) |
| 217 | do_one_argument ( process one argument ) |
| 218 | END |
| 219 | ; |
| 220 | |
| 221 | ################################################################################ |
| 222 | # The MAIN program just prints a banner and processes its arguments. |
| 223 | # STACK<: arguments |
Chris Lattner | 9d014e7 | 2003-11-23 17:55:19 +0000 | [diff] [blame] | 224 | ################################################################################ |
| 225 | : MAIN |
Brian Gaeke | 3e4a271 | 2003-11-24 02:57:25 +0000 | [diff] [blame] | 226 | NIP ( get rid of the program name ) |
| 227 | -- ( reduce number of arguments ) |
| 228 | DUP ( save the arg counter ) |
| 229 | 1 <= IF ( See if we got an argument ) |
| 230 | process_arguments ( tell user if they are prime ) |
| 231 | ELSE |
| 232 | find_primes ( see how many we can find ) |
| 233 | ENDIF |
| 234 | 0 ( push return code ) |
Chris Lattner | 9d014e7 | 2003-11-23 17:55:19 +0000 | [diff] [blame] | 235 | ; |