# HG changeset patch
# User Maarten Derickx <m.derickx.student@gmail.com>
# Date 1284288712 -7200
# Node ID b5ecf7f27964d43965fa5cd406ff0a0ebb7b7948
# Parent  35297cc2620b7e81805e0f3a529c30af30575149
#9652 Unnecesary and buggy code in arith.py


diff -r 35297cc2620b -r b5ecf7f27964 sage/rings/arith.py
--- a/sage/rings/arith.py	Tue Jul 20 22:37:51 2010 +0200
+++ b/sage/rings/arith.py	Sun Sep 12 12:51:52 2010 +0200
@@ -554,17 +554,18 @@
     """
     return ZZ(n).is_prime_power(flag=flag)
 
-def valuation(m, p):
-    """
-    The exact power of p that divides m.
-    
-    m should be an integer or rational (but maybe other types work
-    too.)
-    
-    This actually just calls the m.valuation() method.
-    
-    If m is 0, this function returns rings.infinity.
-    
+def valuation(m,*args1, **args2):
+    """    
+    This actually just calls the m.valuation() method. 
+    See the documentation of m.valuation() for a more precise description. 
+    Use of this function by developers is discouraged. Use m.valuation() instead.
+    
+    .. NOTE::
+
+        This is not always a valuation in the mathematical sense.
+        For more information see:
+        sage.rings.finite_rings.integer_mod.IntegerMod_int.valuation
+
     EXAMPLES::
     
         sage: valuation(512,2)
@@ -595,20 +596,18 @@
         5
         sage: valuation(243*10007,10007)
         1
-    """
-    if hasattr(m, 'valuation'):
-        return m.valuation(p)
-    if m == 0:
-        import sage.rings.all
-        return sage.rings.all.infinity
-    if is_FractionFieldElement(m):
-        return valuation(m.numerator()) - valuation(m.denominator())
-    r = 0
-    power = p
-    while not (m % power): # m % power == 0
-        r += 1
-        power *= p
-    return r
+        sage: y = QQ['y'].gen()
+        sage: valuation(y^3, y)
+        3
+        sage: x = QQ[['x']].gen()
+        sage: valuation((x^3-x^2)/(x-4))
+        2
+        sage: valuation(4r,2r)
+        2
+    """
+    if isinstance(m,(int,long)):
+        m=ZZ(m)
+    return m.valuation(*args1, **args2)
 
 def prime_powers(start, stop=None):
     r"""
diff -r 35297cc2620b -r b5ecf7f27964 sage/rings/finite_rings/integer_mod.pyx
--- a/sage/rings/finite_rings/integer_mod.pyx	Tue Jul 20 22:37:51 2010 +0200
+++ b/sage/rings/finite_rings/integer_mod.pyx	Sun Sep 12 12:51:52 2010 +0200
@@ -42,6 +42,9 @@
 
 -  William Stein: sqrt
 
+-  Maarten Derickx: moved the valuation code from the global
+   valuation function to here
+
 
 TESTS::
 
@@ -1141,6 +1144,66 @@
             raise ArithmeticError, "multiplicative order of %s not defined since it is not a unit modulo %s"%(
                 self, self.__modulus.sageInteger)
 
+    def valuation(self, p):
+        """
+        The largest power r such that m is in the ideal generated by p^r or infinity if there is not a largest such power.
+        However it is an error to take the valuation with respect to a unit.
+
+        .. NOTE::
+        
+            This is not a valuation in the mathematical sense. As shown with the examples below.
+
+        EXAMPLES:
+       
+        This example shows that the (a*b).valuation(n) is not always the same as a.valuation(n) + b.valuation(n)
+ 
+        ::
+
+            sage: R=ZZ.quo(9)
+            sage: a=R(3)
+            sage: b=R(6)
+            sage: a.valuation(3)
+            1
+            sage: a.valuation(3) + b.valuation(3)
+            2
+            sage: (a*b).valuation(3)
+            +Infinity
+
+        The valuation with respect to a unit is an error
+
+        ::
+
+            sage: a.valuation(4)
+            Traceback (most recent call last):
+            ...
+            ValueError: Valuation with respect to a unit is not defined.
+
+        TESTS::
+
+            sage: R=ZZ.quo(12)
+            sage: a=R(2)
+            sage: b=R(4)
+            sage: a.valuation(2)
+            1
+            sage: b.valuation(2)
+            +Infinity
+            sage: ZZ.quo(1024)(16).valuation(4)
+            2
+      
+        """
+        p=self.__modulus.sageInteger.gcd(p)
+        if p==1:
+            raise ValueError("Valuation with respect to a unit is not defined.")
+        r = 0
+        power = p
+        while not (self % power): # self % power == 0
+            r += 1
+            power *= p
+            if not power.divides(self.__modulus.sageInteger):
+                from sage.rings.all import infinity
+                return infinity
+        return r
+
     def __floordiv__(self, other):
         """
         Exact division for prime moduli, for compatibility with other fields.
