| 1 | """ |
| 2 | Finite Prime Fields |
| 3 | |
| 4 | AUTHORS: |
| 5 | -- William Stein: initial version |
| 6 | -- Martin Albrecht (2008-01): refactoring |
| 7 | """ |
| 8 | |
| 9 | #***************************************************************************** |
| 10 | # Copyright (C) 2006 William Stein <wstein@gmail.com> |
| 11 | # Copyright (C) 2008 Martin Albrecht <malb@informatik.uni-bremen.de> |
| 12 | # |
| 13 | # Distributed under the terms of the GNU General Public License (GPL) |
| 14 | # |
| 15 | # This code is distributed in the hope that it will be useful, |
| 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 18 | # General Public License for more details. |
| 19 | # |
| 20 | # The full text of the GPL is available at: |
| 21 | # |
| 22 | # http://www.gnu.org/licenses/ |
| 23 | #***************************************************************************** |
| 24 | |
| 25 | from ring import FiniteField as FiniteField_generic |
| 26 | from sage.structure.parent_gens import normalize_names, ParentWithGens |
| 27 | |
| 28 | import polynomial.polynomial_ring as polynomial_ring |
| 29 | import integer_mod_ring |
| 30 | import integer |
| 31 | import rational |
| 32 | import integer_mod |
| 33 | import arith |
| 34 | |
| 35 | |
| 36 | class FiniteField_prime_modn(FiniteField_generic, integer_mod_ring.IntegerModRing_generic): |
| 37 | def __init__(self, p, name=None): |
| 38 | """ |
| 39 | Return a new finite field of order $p$ where $p$ is prime. |
| 40 | |
| 41 | INPUT: |
| 42 | p -- an integer >= 2 |
| 43 | name -- ignored |
| 44 | |
| 45 | EXAMPLES: |
| 46 | sage: FiniteField(3) |
| 47 | Finite Field of size 3 |
| 48 | |
| 49 | sage: FiniteField(next_prime(1000)) |
| 50 | Finite Field of size 1009 |
| 51 | """ |
| 52 | p = integer.Integer(p) |
| 53 | if not arith.is_prime(p): |
| 54 | raise ArithmeticError, "p must be prime" |
| 55 | integer_mod_ring.IntegerModRing_generic.__init__(self, p) |
| 56 | self._kwargs = {} |
| 57 | self.__char = p |
| 58 | self.__gen = self(1) # self(int(pari.pari(p).znprimroot().lift())) |
| 59 | ParentWithGens.__init__(self, self, ('x',), normalize=False) |
| 60 | |
| 61 | def __cmp__(self, other): |
| 62 | r""" |
| 63 | Compare \code{self} with \code{other}. Two finite prime fields |
| 64 | are considered equal if their characteristic is equal. |
| 65 | |
| 66 | EXAMPLE: |
| 67 | sage: K = FiniteField(3) |
| 68 | sage: copy(K) == K |
| 69 | True |
| 70 | sage: copy(K) is K |
| 71 | False |
| 72 | """ |
| 73 | if not isinstance(other, FiniteField_prime_modn): |
| 74 | return cmp(type(self), type(other)) |
| 75 | return cmp(self.__char, other.__char) |
| 76 | |
| 77 | def _is_valid_homomorphism_(self, codomain, im_gens): |
| 78 | """ |
| 79 | This is called implicitly by the hom constructor. |
| 80 | |
| 81 | EXAMPLES: |
| 82 | sage: k = GF(73^2,'a') |
| 83 | sage: f = k.modulus() |
| 84 | sage: r = f.change_ring(k).roots() |
| 85 | sage: k.hom([r[0][0]]) # indirect doctest |
| 86 | Ring endomorphism of Finite Field in a of size 73^2 |
| 87 | Defn: a |--> 72*a + 3 |
| 88 | """ |
| 89 | try: |
| 90 | return im_gens[0] == codomain._coerce_(self.gen(0)) |
| 91 | except TypeError: |
| 92 | return False |
| 93 | |
| 94 | def _coerce_impl(self, x): |
| 95 | """ |
| 96 | This is called implicitly by arithmetic methods. |
| 97 | |
| 98 | EXAMPLES: |
| 99 | sage: k = GF(7) |
| 100 | sage: e = k(6) |
| 101 | sage: e * 2 # indirect doctest |
| 102 | 5 |
| 103 | sage: 12 % 7 |
| 104 | 5 |
| 105 | """ |
| 106 | if isinstance(x, (int, long, integer.Integer)): |
| 107 | return self(x) |
| 108 | if isinstance(x, integer_mod.IntegerMod_abstract) and \ |
| 109 | x.parent().characteristic() == self.characteristic(): |
| 110 | return self(x) |
| 111 | raise TypeError, "no canonical coercion of x" |
| 112 | |
| 113 | def characteristic(self): |
| 114 | r""" |
| 115 | Return the characteristic of \code{self}. |
| 116 | |
| 117 | EXAMPLE: |
| 118 | sage: k = GF(7) |
| 119 | sage: k.characteristic() |
| 120 | 7 |
| 121 | """ |
| 122 | return self.__char |
| 123 | |
| 124 | def modulus(self): |
| 125 | """ |
| 126 | Return the minimal polynomial of self, which is allways $x - 1$. |
| 127 | |
| 128 | EXAMPLE: |
| 129 | sage: k = GF(199) |
| 130 | sage: k.modulus() |
| 131 | x + 198 |
| 132 | """ |
| 133 | try: |
| 134 | return self.__modulus |
| 135 | except AttributeError: |
| 136 | x = polynomial_ring.PolynomialRing(self, 'x').gen() |
| 137 | self.__modulus = x - 1 |
| 138 | return self.__modulus |
| 139 | |
| 140 | def is_prime_field(self): |
| 141 | """ |
| 142 | Return True |
| 143 | |
| 144 | EXAMPLE: |
| 145 | sage: k.<a> = GF(3) |
| 146 | sage: k.is_prime_field() |
| 147 | True |
| 148 | |
| 149 | sage: k.<a> = GF(3^2) |
| 150 | sage: k.is_prime_field() |
| 151 | False |
| 152 | """ |
| 153 | return True |
| 154 | |
| 155 | def polynomial(self, name=None): |
| 156 | """ |
| 157 | |
| 158 | """ |
| 159 | if name is None: |
| 160 | name = self.variable_name() |
| 161 | try: |
| 162 | return self.__polynomial[name] |
| 163 | except AttributeError: |
| 164 | from sage.rings.finite_field import FiniteField |
| 165 | R = polynomial_ring.PolynomialRing(FiniteField(self.characteristic()), name) |
| 166 | f = polynomial_ring.PolynomialRing(self, name)([0,1]) |
| 167 | try: |
| 168 | self.__polynomial[name] = f |
| 169 | except (KeyError, AttributeError): |
| 170 | self.__polynomial = {} |
| 171 | self.__polynomial[name] = f |
| 172 | return f |
| 173 | |
| 174 | def order(self): |
| 175 | """ |
| 176 | Return the order of this finite field. |
| 177 | |
| 178 | EXAMPLE: |
| 179 | sage: k = GF(5) |
| 180 | sage: k.order() |
| 181 | 5 |
| 182 | """ |
| 183 | return self.__char |
| 184 | |
| 185 | def gen(self, n=0): |
| 186 | """ |
| 187 | Return generator of this finite field. |
| 188 | |
| 189 | EXAMPLES: |
| 190 | sage: k = GF(13) |
| 191 | sage: k.gen() |
| 192 | 1 |
| 193 | sage: k.gen(1) |
| 194 | Traceback (most recent call last): |
| 195 | ... |
| 196 | IndexError: only one generator |
| 197 | """ |
| 198 | if n != 0: |
| 199 | raise IndexError, "only one generator" |
| 200 | return self.__gen |
| 201 | |
| 202 | def __iter__(self): |
| 203 | """ |
| 204 | EXAMPLE: |
| 205 | sage: for a in GF(5): |
| 206 | ... print a |
| 207 | 0 |
| 208 | 1 |
| 209 | 2 |
| 210 | 3 |
| 211 | 4 |
| 212 | """ |
| 213 | for i in xrange(self.order()): |
| 214 | yield self(i) |
| 215 | |
| 216 | def degree(self): |
| 217 | """ |
| 218 | Returns the degree of the finite field, which is a positive |
| 219 | integer. |
| 220 | |
| 221 | EXAMPLES: |
| 222 | sage: FiniteField(3).degree() |
| 223 | 1 |
| 224 | """ |
| 225 | return 1 |