factor/extra/math/miller-rabin/miller-rabin.factor

73 lines
2.0 KiB
Factor
Raw Normal View History

2008-04-25 16:56:15 -04:00
USING: combinators combinators.lib io locals kernel math
2008-01-26 22:44:00 -05:00
math.functions math.ranges namespaces random sequences
2008-04-14 03:40:32 -04:00
hashtables sets ;
2007-09-20 18:09:08 -04:00
IN: math.miller-rabin
: >even ( n -- int ) dup even? [ 1- ] unless ; foldable
: >odd ( n -- int ) dup even? [ 1+ ] when ; foldable
: next-odd ( m -- n ) dup even? [ 1+ ] [ 2 + ] if ;
2007-09-20 18:09:08 -04:00
TUPLE: positive-even-expected n ;
: (factor-2s) ( r s -- r s )
dup even? [ -1 shift >r 1+ r> (factor-2s) ] when ;
: factor-2s ( n -- r s )
#! factor an integer into s * 2^r
0 swap (factor-2s) ;
2007-09-20 18:09:08 -04:00
:: (miller-rabin) ( n trials -- ? )
[let | r [ n 1- factor-2s drop ]
s [ n 1- factor-2s nip ]
prime?! [ t ]
a! [ 0 ]
count! [ 0 ] |
trials [
n 1- [1,b] random a!
a s n ^mod 1 = [
0 count!
r [
2^ s * a swap n ^mod n - -1 =
[ count 1+ count! r + ] when
] each
count zero? [ f prime?! trials + ] when
] unless drop
] each prime? ] ;
2007-09-20 18:09:08 -04:00
: miller-rabin* ( n numtrials -- ? )
over {
{ [ dup 1 <= ] [ 3drop f ] }
{ [ dup 2 = ] [ 3drop t ] }
2008-01-13 01:07:49 -05:00
{ [ dup even? ] [ 3drop f ] }
[ [ drop (miller-rabin) ] with-scope ]
2007-09-20 18:09:08 -04:00
} cond ;
: miller-rabin ( n -- ? ) 10 miller-rabin* ;
: next-prime ( n -- p )
next-odd dup miller-rabin [ next-prime ] unless ;
: random-prime ( numbits -- p )
random-bits next-prime ;
ERROR: no-relative-prime n ;
2007-09-20 18:09:08 -04:00
: (find-relative-prime) ( n guess -- p )
over 1 <= [ over no-relative-prime ] when
dup 1 <= [ drop 3 ] when
2007-09-20 18:09:08 -04:00
2dup gcd nip 1 > [ 2 + (find-relative-prime) ] [ nip ] if ;
: find-relative-prime* ( n guess -- p )
#! find a prime relative to n with initial guess
>odd (find-relative-prime) ;
: find-relative-prime ( n -- p )
2008-01-13 15:09:59 -05:00
dup random find-relative-prime* ;
2007-09-20 18:09:08 -04:00
2008-04-25 01:25:37 -04:00
ERROR: too-few-primes ;
2007-09-20 18:09:08 -04:00
: unique-primes ( numbits n -- seq )
#! generate two primes
2008-04-25 01:25:37 -04:00
over 5 < [ too-few-primes ] when
2008-01-09 17:36:30 -05:00
[ [ drop random-prime ] with map ] [ all-unique? ] generate ;