From 1cdd3fe5428e1e88bfad9b1ca18c4c4ea2f61c48 Mon Sep 17 00:00:00 2001
From: kwsamarasinghe <kwsamarasinghe@gmail.com>
Date: Sun, 18 Apr 2010 21:41:17 +0200
Subject: [PATCH] Prime Field Implementation

---
 sympy/abstractalgebra/__init__.py        |    1 +
 sympy/abstractalgebra/finitefield.py     |  121 ++++++++++++++++++++++++++++++
 sympy/abstractalgebra/test_primefield.py |   77 +++++++++++++++++++
 3 files changed, 199 insertions(+), 0 deletions(-)
 create mode 100644 sympy/abstractalgebra/__init__.py
 create mode 100644 sympy/abstractalgebra/finitefield.py
 create mode 100644 sympy/abstractalgebra/test_primefield.py

diff --git a/sympy/abstractalgebra/__init__.py b/sympy/abstractalgebra/__init__.py
new file mode 100644
index 0000000..7983d66
--- /dev/null
+++ b/sympy/abstractalgebra/__init__.py
@@ -0,0 +1 @@
+from finitefield import PrimeField
diff --git a/sympy/abstractalgebra/finitefield.py b/sympy/abstractalgebra/finitefield.py
new file mode 100644
index 0000000..42a0eb2
--- /dev/null
+++ b/sympy/abstractalgebra/finitefield.py
@@ -0,0 +1,121 @@
+"""Finite Field (Galois Field) Module for sympy"""
+from sympy.ntheory.primetest import isprime
+from sympy.core.numbers import igcdex
+
+class PrimeField():
+    """PrimeField object object which represents GF(p)
+
+    Examples:
+        >>> from sympy.abstractalgebra.finitefield import PrimeField
+        >>> gf2 = PrimeField(2)
+    """
+
+    def __init__(self, p):
+        if isprime(p) == True:
+            self.p = p
+        else:
+            raise ValueError('Argument should be a prime number')
+
+    def elements(self):
+        """Returns the elements of the finite field
+
+        Examples:
+	>>> from sympy.abstractalgebra.finitefield import  PrimeField
+        >>> gf2=PrimeField(2)
+        >>> print gf2.elements()
+        [0, 1]
+        """
+
+        elements = range(0, self.p, 1)
+        return elements
+
+    def add(self,x1,x2):
+        """Returns the addition of the two arguements in modulo p
+
+        Examples:
+	>>> from sympy.abstractalgebra.finitefield import PrimeField
+        >>> gf7 = PrimeField(7)
+        >>> gf7.add(4,5)
+        2
+        """
+
+        if x1 <= self.p -1 and x2 <= self.p -1:
+            return (x1+x2)%self.p
+        else:
+            raise ValueError('Arguments must be elements of prime field ')
+
+    def additive_inverse(self,x):
+        """Returns the additive inverse of the element
+
+        Examples:
+	>>> from sympy.abstractalgebra.finitefield import PrimeField
+        >>> gf7 = PrimeField(7)
+        >>> gf7.additive_inverse(5)
+        2
+        """
+        return self.p-x
+
+    def multiply(self,x1,x2):
+        """Returns the multiplication of arguements in modulo p
+
+        Examples:
+	>>> from sympy.abstractalgebra.finitefield import PrimeField
+        >>> gf7 = PrimeField(7)
+        >>> gf7.multiply(4,5)
+        6
+        """
+
+        if x1 <= self.p -1 and x2 <= self.p -1:
+            return (x1*x2)%self.p
+        else:
+            raise ValueError('Arguments must be elements of prime field ')
+
+    def multiplicative_inverse(self,x):
+        """Returns the multiplicative inverse of the element
+
+        Uses the extended euclid algorithm,
+        Inverse is y, such that xy+qp=1 iff gcd of x and p is 1.
+
+        Examples:
+	>>> from sympy.abstractalgebra.finitefield import PrimeField
+        >>> gf7 = PrimeField(7)
+        >>> gf7.multiplicative_inverse(4)
+        2
+        """
+        if x < self.p and x > -1:
+            return igcdex(x,self.p)[0]%self.p
+        else:
+            raise ValueError('Argument must be an element of prime field ')
+
+    def power(self,x,power):
+        """Raises the element to the given power in modulo p
+
+        Uses repeated squaring
+
+        Examples:
+	>>> from sympy.abstractalgebra.finitefield import PrimeField
+        >>> gf7 = PrimeField(7)
+        >>> gf7.power(3,3)
+        6
+        """
+
+        if x < self.p and x > -1:
+            if power%2 == 0:
+                limit = power/2
+                ans = 1
+            else:
+                limit = (power - 1)/2
+                ans = x
+
+            i=0
+            while i<limit:
+                ans = ans * x**2
+                i=i+1
+            return ans%self.p
+        else:
+            raise ValueError('Argument must be an element of prime field')
+
+    def __repr__(gf):
+	elements = gf.elements()
+	return str(elements)
+    
diff --git a/sympy/abstractalgebra/test_primefield.py b/sympy/abstractalgebra/test_primefield.py
new file mode 100644
index 0000000..a66e309
--- /dev/null
+++ b/sympy/abstractalgebra/test_primefield.py
@@ -0,0 +1,77 @@
+from sympy.abstractalgebra.finitefield import PrimeField
+
+def test_elements():
+    """Test Elements in the prime field"""
+    #In GF(2)
+    gf2=PrimeField(2)
+    assert gf2.elements() == [0,1]
+    #In GF(7)
+    gf7=PrimeField(7)
+    assert gf7.elements() == [0,1,2,3,4,5,6]
+
+def test_add():
+    """Test addition of two elements' in the prime field"""
+    #In GF(2)
+    gf2 = PrimeField(2)
+    assert gf2.add(1, 0) == 1
+    #In GF(3)
+    gf3 = PrimeField(3)
+    assert gf3.add(1,2) == 0
+    #In GF(7)
+    gf7=PrimeField(7)
+    assert gf7.add(4,5) == 2
+
+def test_additive_inverse():
+    """Test additive inverse of an element in the prime field"""
+    #In GF(2)
+    gf2 = PrimeField(2)
+    assert gf2.additive_inverse(1) == 1
+    #In GF(3)
+    gf3 = PrimeField(3)
+    assert gf3.additive_inverse(2) == 1
+    #In GF(7)
+    gf7=PrimeField(7)
+    assert gf7.additive_inverse(5) == 2
+
+
+def test_multiply():
+    """Test multiplication of two elements in the prime field"""
+    #In GF(2)
+    gf2 = PrimeField(2)
+    assert gf2.multiply(1, 0) == 0
+    #In GF(3)
+    gf3 = PrimeField(3)
+    assert gf3.multiply(1, 2) == 2
+    #In GF(7)
+    gf7=PrimeField(7)
+    assert gf7.multiply(4,5) == 6
+    assert gf7.multiply(3,6) == 4
+
+
+
+def test_multiplicative_inverse():
+    """Test multiplicative inverse of an element in the prime field"""
+    #In GF(2)
+    gf2 = PrimeField(2)
+    assert gf2.multiplicative_inverse(1) == 1
+    #In GF(3)
+    gf3 = PrimeField(3)
+    assert gf3.multiplicative_inverse(1) == 1
+    #In GF(7)
+    gf7=PrimeField(7)
+    assert gf7.multiplicative_inverse(4) == 2
+    assert gf7.multiplicative_inverse(5) == 3
+
+
+def test_power():
+    """Test exponentiation of an element in the prime field"""
+    #In GF(2)
+    gf2 = PrimeField(2)
+    assert gf2.power(1, 2) == 1
+    #In GF(7)
+    gf7 = PrimeField(7)
+    assert gf7.power(3, 3) == 6
+    assert gf7.power(4, 2) == 2
+    assert gf7.power(2, 5) == 4
+
+
-- 
1.7.0.2.msysgit.0

