comparison scripts/specfun/isprime.m @ 19242:2f117c4b5cb0

isprime.m: Document negative and complex inputs. Simplify Gaussian prime test in 3rd case where x^2 + y^2 is prime. * isprime.m: Document negative and complex inputs. Simplify Gaussian prime test in 3rd case where x^2 + y^2 is prime.
author Rik <rik@octave.org>
date Mon, 25 Aug 2014 21:30:23 -0700
parents 89e275a4f6f6
children bb0c5e182c12
comparison
equal deleted inserted replaced
19241:c573d9c70ae5 19242:2f117c4b5cb0
20 ## -*- texinfo -*- 20 ## -*- texinfo -*-
21 ## @deftypefn {Function File} {} isprime (@var{x}) 21 ## @deftypefn {Function File} {} isprime (@var{x})
22 ## Return a logical array which is true where the elements of @var{x} are 22 ## Return a logical array which is true where the elements of @var{x} are
23 ## prime numbers and false where they are not. 23 ## prime numbers and false where they are not.
24 ## 24 ##
25 ## @code{isprime} is appropriate if the maximum value in @var{x} is not too 25 ## A prime number is conventionally defined as a positive integer (1, 2, 3,
26 ## large (< 1e15). For larger values special purpose factorization code 26 ## @dots{}) which is divisible only by itself and 1. Octave extends this
27 ## should be used. 27 ## definition to include both negative integers and complex values. A
28 ## negative integer is prime if its positive counterpart is prime. This is
29 ## equivalent to @code{isprime (abs (x))}.
30 ##
31 ## If @code{class (@var{x})} is complex, then primality is tested in the domain
32 ## of Gaussian integers (@url{http://en.wikipedia.org/wiki/Gaussian_integer}).
33 ## Some non-complex integers are prime in the ordinary sense, but not in the
34 ## domain of Gaussian integers. For example, @math{5 = (1+2i)*(1-2i)} shows
35 ## that 5 is not prime because it has a factor other than itself and 1.
36 ## Exercise caution when testing complex and real values together in the same
37 ## matrix.
38 ##
39 ## Examples:
28 ## 40 ##
29 ## @example 41 ## @example
30 ## @group 42 ## @group
31 ## isprime (1:6) 43 ## isprime (1:6)
32 ## @result{} [0, 1, 1, 0, 1, 0] 44 ## @result{} [0, 1, 1, 0, 1, 0]
33 ## @end group 45 ## @end group
34 ## @end example 46 ## @end example
35 ## 47 ##
36 ## If @code{class (@var{x})} is complex, then primality will be tested
37 ## in the domain of Gaussian integers. This means that some real prime
38 ## numbers will fail the primality test in this case. For example, 5 =
39 ## (1+2i)*(1-2i) and 2 = i*(1-i)^2.
40 ##
41 ## @example 48 ## @example
42 ## @group 49 ## @group
43 ## isprime ([i, 2, 3, 5]) 50 ## isprime ([i, 2, 3, 5])
44 ## @result{} [0, 0, 1, 0] 51 ## @result{} [0, 0, 1, 0]
45 ## @end group 52 ## @end group
46 ## @end example 53 ## @end example
54 ##
55 ## Programming Note: @code{isprime} is appropriate if the maximum value in
56 ## @var{x} is not too large (< 1e15). For larger values special purpose
57 ## factorization code should be used.
58 ##
59 ## Compatibility Note: @var{matlab} does not extend the definition of prime
60 ## numbers and will produce an error if given negative or complex inputs.
47 ## @seealso{primes, factor, gcd, lcm} 61 ## @seealso{primes, factor, gcd, lcm}
48 ## @end deftypefn 62 ## @end deftypefn
49 63
50 function t = isprime (x) 64 function t = isprime (x)
51 65
63 if (iscomplex (x)) 77 if (iscomplex (x))
64 t = isgaussianprime (x); 78 t = isgaussianprime (x);
65 return; 79 return;
66 endif 80 endif
67 81
68 ## Handle negative entries 82 ## Code strategy is to build a table with the list of possible primes
69 x = abs (x); 83 ## and then quickly compare entries in x with the table of primes using
84 ## lookup(). The table size is limited to save memory and computation
85 ## time during its creation. All entries larger than the maximum in the
86 ## table are checked by straightforward division.
70 87
88 x = abs (x); # handle negative entries
71 maxn = max (x(:)); 89 maxn = max (x(:));
72 ## generate prime table of suitable length. 90 ## generate prime table of suitable length.
73 maxp = min (maxn, max (sqrt (maxn), 1e7)); # FIXME: threshold not optimized. 91 ## 1e7 threshold requires ~0.15 seconds of computation, 1e8 requires 1.8.
92 maxp = min (maxn, max (sqrt (maxn), 1e7));
74 pr = primes (maxp); 93 pr = primes (maxp);
75 ## quick search for table matches. 94 t = lookup (pr, x, "b"); # quick search for table matches.
76 t = lookup (pr, x, "b"); 95
77 ## take the rest. 96 ## process any remaining large entries
78 m = x(x > maxp); 97 m = x(x > maxp);
79 if (! isempty (m)) 98 if (! isempty (m))
80 ## there are still possible primes. filter them out by division.
81 if (maxn <= intmax ("uint32")) 99 if (maxn <= intmax ("uint32"))
82 m = uint32 (m); 100 m = uint32 (m);
83 elseif (maxn <= intmax ("uint64")) 101 elseif (maxn <= intmax ("uint64"))
84 m = uint64 (m); 102 m = uint64 (m);
85 else 103 else
86 warning ("isprime: X contains integers too large to be tested"); 104 warning ("isprime: X contains integers too large to be tested");
87 endif 105 endif
106
107 ## Start by dividing through by the small primes until the remaining
108 ## list of entries is small (and most likely prime themselves).
88 pr = cast (pr(pr <= sqrt (maxn)), class (m)); 109 pr = cast (pr(pr <= sqrt (maxn)), class (m));
89 for p = pr 110 for p = pr
90 m = m(rem (m, p) != 0); 111 m = m(rem (m, p) != 0);
91 if (length (m) < length (pr) / 10) 112 if (numel (m) < numel (pr) / 10)
92 break; 113 break;
93 endif 114 endif
94 endfor 115 endfor
116
117 ## Check the remaining list of possible primes against the
118 ## remaining prime factors which were not tested in the for loop.
119 ## This is just an optimization to use arrayfun over for loo
95 pr = pr(pr > p); 120 pr = pr(pr > p);
96 mm = arrayfun (@(x) all (rem (x, pr)), m); 121 mm = arrayfun (@(x) all (rem (x, pr)), m);
97 m = m(mm); 122 m = m(mm);
123
124 ## Add any remaining entries, which are truly prime, to the results.
98 if (! isempty (m)) 125 if (! isempty (m))
99 m = cast (sort (m), class (x)); 126 m = cast (sort (m), class (x));
100 t |= lookup (m, x, "b"); 127 t |= lookup (m, x, "b");
101 endif 128 endif
102 endif 129 endif
103 130
104 endfunction 131 endfunction
105 132
106 function t = isgaussianprime (z) 133 function t = isgaussianprime (z)
107 ## Assumed prime unless proven otherwise 134 ## Assume prime unless proven otherwise
108 t = true (size (z)); 135 t = true (size (z));
109 136
110 x = real (z); 137 x = real (z);
111 y = imag (z); 138 y = imag (z);
112 139
116 yidx = x==0 & mod (y, 4) == 3; 143 yidx = x==0 & mod (y, 4) == 3;
117 144
118 t(xidx) &= isprime (x(xidx)); 145 t(xidx) &= isprime (x(xidx));
119 t(yidx) &= isprime (y(yidx)); 146 t(yidx) &= isprime (y(yidx));
120 147
121 ## Otherwise, prime if x^2 + y^2 is prime and NOT 3 mod 4. 148 ## Otherwise, prime if x^2 + y^2 is prime
122 zabs = x.^2 + y.^2; 149 zidx = ! (xidx | yidx); # Skip entries that were already evaluated
123 zidx = mod (zabs, 4) != 3 & !xidx & !yidx; 150 zabs = x(zidx).^2 + y(zidx).^2;
124 151 t(zidx) &= isprime (zabs);
125 t(zidx) &= isprime (zabs (zidx));
126 endfunction 152 endfunction
127
128 153
129 154
130 %!assert (isprime (3), true) 155 %!assert (isprime (3), true)
131 %!assert (isprime (4), false) 156 %!assert (isprime (4), false)
132 %!assert (isprime (5i), false) 157 %!assert (isprime (5i), false)
142 %% Test input validation 167 %% Test input validation
143 %!error isprime () 168 %!error isprime ()
144 %!error isprime (1, 2) 169 %!error isprime (1, 2)
145 %!error <X contains non-integer entries> isprime (0.5i) 170 %!error <X contains non-integer entries> isprime (0.5i)
146 %!error <X contains non-integer entries> isprime (0.5) 171 %!error <X contains non-integer entries> isprime (0.5)
172