# HG changeset patch
# User Niles Johnson <nilesj@gmail.com>
# Date 1282565172 14400
# Node ID 801877d649b277fa789afde5083821bb3867652c
# Parent  6e7354d7f97de2b6d5fb5eea6214f56cd1a64680
#3893 *args and **kwds for random_element methods

diff -r 6e7354d7f97d -r 801877d649b2 sage/coding/linear_code.py
--- a/sage/coding/linear_code.py	Tue Sep 21 10:30:35 2010 -0700
+++ b/sage/coding/linear_code.py	Mon Aug 23 08:06:12 2010 -0400
@@ -160,6 +160,8 @@
 - Kwankyu Lee (2010-01): added methods gen_mat_systematic, information_set, and 
   magma interface for linear codes.
 
+- Niles Johnson (2010-08): Trac #3893: ``random_element()`` should pass on ``*args`` and ``**kwds``.
+
 TESTS::
 
     sage: MS = MatrixSpace(GF(2),4,7)
@@ -2019,9 +2021,10 @@
         GL2 = MS2(list(B))
         return LinearCode(GL2)
 
-    def random_element(self):
+    def random_element(self, *args, **kwds):
         """
-        Returns a random codeword.
+        Returns a random codeword; passes other positional and keyword
+        arguments to ``random_element()`` method of vector space.
         
         OUTPUT:
         
@@ -2038,10 +2041,20 @@
             False
             sage: c2 in Cc
             True
+
+        ::
+
+            sage: C.random_element()
+            (1, 0, 0, a + 1, 1, a, a, a + 1, a + 1, 1, 1, 0, a + 1, a, 0, a, a, 0, a, a, 1)
+
+        Passes extra positional or keyword arguments through::
+        
+            sage: C.random_element(prob=.5, distribution='1/n')
+            (1, 0, a, 0, 0, 0, 0, a + 1, 0, 0, 0, 0, 0, 0, 0, 0, a + 1, a + 1, 1, 0, 0)
         """
         V = self.ambient_space()
         S = V.subspace(self.basis())
-        return S.random_element()
+        return S.random_element(*args, **kwds)
     
     def redundancy_matrix(C):
         """
diff -r 6e7354d7f97d -r 801877d649b2 sage/crypto/mq/sr.py
--- a/sage/crypto/mq/sr.py	Tue Sep 21 10:30:35 2010 -0700
+++ b/sage/crypto/mq/sr.py	Mon Aug 23 08:06:12 2010 -0400
@@ -19,6 +19,8 @@
 
 - Martin Albrecht (2007-09): initial version
 
+- Niles Johnson (2010-08): Trac #3893: ``random_element()`` should pass on ``*args`` and ``**kwds``.
+
 EXAMPLES:
 
 We construct SR(1,1,1,4) and study its properties.
@@ -1040,7 +1042,7 @@
                d.ncols() == self.c and \
                d.base_ring() == self.base_ring()
 
-    def random_state_array(self):
+    def random_state_array(self, *args, **kwds):
         r"""
         Return a random element in ``MatrixSpace(self.base_ring(),
         self.r, self.c)``.
@@ -1052,9 +1054,9 @@
             [a^3 + a + 1       a + 1]
             [      a + 1         a^2]
         """
-        return random_matrix(self.base_ring(), self._r, self._c)
+        return random_matrix(self.base_ring(), self._r, self._c, *args, **kwds)
 
-    def random_vector(self):
+    def random_vector(self, *args, **kwds):
         """
         Return a random vector as it might appear in the algebraic
         expression of self.
@@ -1084,11 +1086,12 @@
 
            `\phi` was already applied to the result.
         """
-        return self.vector( self.random_state_array() )
+        return self.vector(self.random_state_array(*args, **kwds))
 
-    def random_element(self, elem_type = "vector"):
+    def random_element(self, elem_type = "vector", *args, **kwds):
         """
-        Return a random element for self.
+        Return a random element for self.  Other arguments and keywords are
+        passed to random_* methods.
         
         INPUT:
         
@@ -1107,11 +1110,19 @@
             [a^3 + a^2 + a]
             sage: sr.random_element('state_array')
             [a + 1]
+
+        Passes extra positional or keyword arguments through::
+
+            sage: sr.random_element(density=0)
+            [0]
+            [0]
+            [0]
+            [0]           
         """
         if elem_type == "vector":
-            return self.random_vector()
+            return self.random_vector(*args, **kwds)
         elif elem_type == "state_array":
-            return self.random_state_array()
+            return self.random_state_array(*args, **kwds)
         else:
             raise TypeError, "parameter type not understood"
 
diff -r 6e7354d7f97d -r 801877d649b2 sage/modular/arithgroup/congroup_sl2z.py
--- a/sage/modular/arithgroup/congroup_sl2z.py	Tue Sep 21 10:30:35 2010 -0700
+++ b/sage/modular/arithgroup/congroup_sl2z.py	Mon Aug 23 08:06:12 2010 -0400
@@ -1,5 +1,10 @@
 r"""
 The modular group `{\rm SL}_2(\ZZ)`
+
+AUTHORS:
+
+- Niles Johnson (2010-08): Trac #3893: ``random_element()`` should pass on ``*args`` and ``**kwds``.
+
 """
 
 ################################################################################
@@ -139,10 +144,12 @@
         """
         return Cusp(1,0)
 
-    def random_element(self, bound=100):
+    def random_element(self, bound=100, *args, **kwds):
         r"""
         Return a random element of `{\rm SL}_2(\ZZ)` with entries whose
         absolute value is strictly less than bound (default 100).
+        Additional arguments and keywords are passed to the random_element
+        method of ZZ.
 
         (Algorithm: Generate a random pair of integers at most bound. If they
         are not coprime, throw them away and start again. If they are, find an
@@ -157,13 +164,23 @@
 
         EXAMPLES::
 
-            sage: SL2Z.random_element() # random
-            sage: SL2Z.random_element(5) # still random
+            sage: SL2Z.random_element()
+            [60 13]
+            [83 18]
+            sage: SL2Z.random_element(5)
+            [-1  3]
+            [ 1 -4]
+
+        Passes extra positional or keyword arguments through::
+            
+            sage: SL2Z.random_element(5, distribution='1/n')
+            [ 1 -1]
+            [ 0  1]
+
         """
-
-        if bound <= 1: raise ValueError, "Don't be silly"
-        c = ZZ.random_element(1-bound, bound)
-        d = ZZ.random_element(1-bound, bound)
+        if bound <= 1: raise ValueError, "bound must be greater than 1"
+        c = ZZ.random_element(1-bound, bound, *args, **kwds)
+        d = ZZ.random_element(1-bound, bound, *args, **kwds)
         if gcd(c,d) != 1: # try again
             return self.random_element(bound)
         else:
diff -r 6e7354d7f97d -r 801877d649b2 sage/modules/free_module.py
--- a/sage/modules/free_module.py	Tue Sep 21 10:30:35 2010 -0700
+++ b/sage/modules/free_module.py	Mon Aug 23 08:06:12 2010 -0400
@@ -133,6 +133,9 @@
 - William Stein (2005, 2007)
 
 - David Kohel (2007, 2008)
+
+- Niles Johnson (2010-08): Trac #3893: ``random_element()`` should pass on ``*args`` and ``**kwds``.
+
 """
 
 ###########################################################################
@@ -1707,17 +1710,18 @@
         """
         return FreeModule(self.base_ring(), self.rank())
 
-    def random_element(self, prob=1.0, **kwds):
+    def random_element(self, prob=1.0, *args, **kwds):
         """
         Returns a random element of self.
         
         INPUT:
         
         
-        -  ``prob`` - float; probability that given coefficient
-           is nonzero.
-        
-        -  ``**kwds`` - passed on to random_element function
+        -- ``prob`` - float. Each coefficient will be set to zero with
+           probability `1-prob`. Otherwise coefficients will be chosen
+           randomly from base ring (and may be zero).
+        
+        -- ``*args, **kwds`` - passed on to ``random_element()`` function
            of base ring.
         
         
@@ -1730,11 +1734,18 @@
             (2, 2)
             sage: M.random_element()
             (1, 1)
+
+        Passes extra positional or keyword arguments through::
+
+            sage: M.random_element(5,10)
+            (9, 9)
+
+        
         """
         rand = current_randstate().python_random().random
         R = self.base_ring()
         prob = float(prob)
-        c = [0 if rand() > prob else R.random_element(**kwds) for _ in range(self.rank())]
+        c = [0 if rand() > prob else R.random_element(*args, **kwds) for _ in range(self.rank())]
         return self.linear_combination_of_basis(c)
 
     def rank(self):
@@ -4144,18 +4155,19 @@
         """
         return self.coordinates(v, check=check)
 
-    def random_element(self, prob=1.0, **kwds):
+    def random_element(self, prob=1.0, *args, **kwds):
         """
         Returns a random element of self.
         
         INPUT:
         
         
-        -  ``prob`` - float; probability that given coefficient
-           is nonzero.
-        
-        -  ``**kwds`` - passed on to random_element function
-           of base ring.
+        - ``prob`` - float. Each coefficient will be set to zero with
+           probability `1-prob`. Otherwise coefficients will be chosen
+           randomly from base ring (and may be zero).
+        
+        - ``*args, **kwds`` - passed on to random_element function of base
+           ring.
         
         
         EXAMPLES::
@@ -4167,14 +4179,20 @@
             (-95, -1, -2)
             sage: M.random_element()
             (-12, 0, 0)
+
+        Passes extra positional or keyword arguments through::
+
+            sage: M.random_element(5,10)
+            (5, 5, 5)
+
         
         ::
         
             sage: M = FreeModule(ZZ, 16)
             sage: M.random_element()
-            (1, -1, 1, -1, -2, -1, 4, -4, -6, 5, 0, 0, -2, 0, 1, -4)
+            (-6, 5, 0, 0, -2, 0, 1, -4, -6, 1, -1, 1, 1, -1, 1, -1)
             sage: M.random_element(prob=0.3)
-            (0, 0, 0, 0, 0, 0, 0, -6, 1, -1, 1, 0, 1, 0, 0, 0)
+            (0, 0, 0, 0, -3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, -3)
         """
         rand = current_randstate().python_random().random
         R = self.base_ring()
@@ -4182,7 +4200,7 @@
         prob = float(prob)
         for i in range(self.rank()):
             if rand() <= prob:
-                v[i] = R.random_element(**kwds)
+                v[i] = R.random_element(*args, **kwds)
         return v
 
     
diff -r 6e7354d7f97d -r 801877d649b2 sage/rings/complex_double.pyx
--- a/sage/rings/complex_double.pyx	Tue Sep 21 10:30:35 2010 -0700
+++ b/sage/rings/complex_double.pyx	Mon Aug 23 08:06:12 2010 -0400
@@ -213,7 +213,7 @@
 
     def random_element(self, double xmin=-1, double xmax=1, double ymin=-1, double ymax=1):
         """
-        Return a random element this complex double field with real and
+        Return a random element of this complex double field with real and
         imaginary part bounded by xmin, xmax, ymin, ymax.
         
         EXAMPLES::
diff -r 6e7354d7f97d -r 801877d649b2 sage/rings/complex_field.py
--- a/sage/rings/complex_field.py	Tue Sep 21 10:30:35 2010 -0700
+++ b/sage/rings/complex_field.py	Mon Aug 23 08:06:12 2010 -0400
@@ -4,6 +4,9 @@
 AUTHORS:
 
 - William Stein (2006-01-26): complete rewrite
+
+- Niles Johnson (2010-08): Trac #3893: ``random_element()`` should pass on ``*args`` and ``**kwds``.
+
 """
 
 #################################################################################
@@ -418,10 +421,11 @@
         return (AlgebraicClosureFunctor(), self._real_field())
 
 
-    def random_element(self, component_max=1):
+    def random_element(self, component_max=1, *args, **kwds):
         r"""
         Returns a uniformly distributed random number inside a square
         centered on the origin (by default, the square [-1,1]x[-1,1]).
+        Passes additional arguments and keywords to underlying real field.
         
         EXAMPLES::
         
@@ -432,10 +436,16 @@
             [-5.7e-7 + 5.4e-7*I, 8.6e-7 + 9.2e-7*I, -5.7e-7 + 6.9e-7*I, -1.2e-7 - 6.9e-7*I, 2.7e-7 + 8.3e-7*I]
             sage: [CC6.random_element(pi^20) for _ in range(5)]
             [-5.0e9*I, 2.8e9 - 5.1e9*I, 2.7e8 + 6.3e9*I, 2.7e8 - 6.4e9*I, 6.7e8 + 1.7e9*I]
+
+        Passes extra positional or keyword arguments through::
+
+            sage: [CC.random_element(distribution='1/n') for _ in range(5)]
+            [-0.227352360839242 + 0.589094456851554*I, 0.0750329809397750 + 0.590691975700246*I, -0.128454377918593 + 0.131058245507370*I, -0.409592358398239 - 0.141913124504965*I, -0.998326992750827 + 0.250548278995221*I]
+
         """
         size = self._real_field()(component_max)
-        re = self._real_field().random_element(-size, size)
-        im = self._real_field().random_element(-size, size)
+        re = self._real_field().random_element(-size, size, *args, **kwds)
+        im = self._real_field().random_element(-size, size, *args, **kwds)
         return self(re, im)
 
     def pi(self):
diff -r 6e7354d7f97d -r 801877d649b2 sage/rings/complex_interval_field.py
--- a/sage/rings/complex_interval_field.py	Tue Sep 21 10:30:35 2010 -0700
+++ b/sage/rings/complex_interval_field.py	Mon Aug 23 08:06:12 2010 -0400
@@ -1,12 +1,16 @@
 r"""
 Field of Arbitrary Precision Complex Intervals
 
-AUTHOR:
-  William Stein wrote complex_field.py.
+AUTHORS:
+
+- William Stein wrote complex_field.py.
     -- William Stein (2006-01-26): complete rewrite
   Then complex_field.py was copied to complex_interval_field.py and
   heavily modified:
     -- Carl Witty (2007-10-24): rewrite for intervals
+
+    -- Niles Johnson (2010-08): Trac #3893: ``random_element()`` should pass on ``*args`` and ``**kwds``.
+
 """
 
 #################################################################################
@@ -331,11 +335,11 @@
             raise IndexError, "n must be 0"
         return complex_interval.ComplexIntervalFieldElement(self, 0, 1)
 
-    def random_element(self, *args):
+    def random_element(self, *args, **kwds):
         """
-        Create a random element of self. Simply chooses the real and 
-        imaginary part randomly, passing arguments to the underlying 
-        real interval field. 
+        Create a random element of self. Simply chooses the real and
+        imaginary part randomly, passing arguments and keywords to the
+        underlying real interval field.
 
         EXAMPLES::
         
@@ -343,9 +347,14 @@
             -0.30607732607725314? - 0.075929193054320221?*I
             sage: CIF.random_element(10, 20)
             10.809593725498833? + 13.964968616713041?*I
+
+        Passes extra positional or keyword arguments through::
+        
+            sage: CIF.random_element(max=0, min=-5)
+            -4.3945698326594416? - 3.8270855512644575?*I            
         """
-        return self._real_field().random_element(*args) \
-            + self.gen() * self._real_field().random_element(*args)
+        return self._real_field().random_element(*args, **kwds) \
+            + self.gen() * self._real_field().random_element(*args, **kwds)
      
     def is_field(self, proof = True):
         """
diff -r 6e7354d7f97d -r 801877d649b2 sage/rings/contfrac.py
--- a/sage/rings/contfrac.py	Tue Sep 21 10:30:35 2010 -0700
+++ b/sage/rings/contfrac.py	Mon Aug 23 08:06:12 2010 -0400
@@ -38,13 +38,13 @@
 
     sage: a = random_matrix(CFF, 4)
     sage: a
-    [[0, 2]    [1]    [1] [0, 2]]
-    [  [-1]    [1]   [-1]   [-2]]
-    [   [2]    [1]   [-1]    [1]]
-    [  [-1]    [1]   [-2] [0, 2]]
+    [    [-1, 2] [-1, 1, 94]      [0, 2]       [-12]]
+    [       [-1]      [0, 2]  [-1, 1, 3]   [0, 1, 2]]
+    [    [-3, 2]   [0, 1, 2]        [-1]         [1]]
+    [       [-1]      [0, 3]         [1]        [-1]]
     sage: f = a.charpoly()
     sage: f
-    [1]*x^4 + ([-1])*x^3 + [3, 1, 3]*x^2 + [3]*x + [-18]
+    [1]*x^4 + [2]*x^3 + ([-12, 1, 14, 7, 1, 1, 7])*x^2 + ([-40, 2, 32, 2, 1, 1, 2])*x + [8, 1, 5, 2, 14, 1, 1, 3]
     sage: f(a)
     [[0] [0] [0] [0]]
     [[0] [0] [0] [0]]
@@ -52,6 +52,11 @@
     [[0] [0] [0] [0]]
     sage: vector(CFF, [1/2, 2/3, 3/4, 4/5])
     ([0, 2], [0, 1, 2], [0, 1, 3], [0, 1, 4])
+
+AUTHORS:
+
+- Niles Johnson (2010-08): Trac #3893: ``random_element()`` should pass on ``*args`` and ``**kwds``.
+
 """
 from sage.structure.element         import FieldElement
 from sage.structure.parent_gens     import ParentWithGens
@@ -335,14 +340,22 @@
         """
         return infinity
 
-    def random_element(self, num_bound=2, den_bound=2):
+    def random_element(self, *args, **kwds):
         """
         EXAMPLES::
         
            sage: CFF.random_element(10,10)
            [0, 4]
+
+        Passes extra positional or keyword arguments through::
+        
+           sage: [CFF.random_element(den_bound=10, num_bound=2) for x in range(4)]
+           [[-1, 1, 3], [0, 7], [0, 3], [0, 4]]
+
+
+           
         """
-        return self(QQ.random_element(num_bound = num_bound, den_bound = den_bound))
+        return self(QQ.random_element(*args, **kwds))
     
 
 class ContinuedFraction(FieldElement):
diff -r 6e7354d7f97d -r 801877d649b2 sage/rings/finite_rings/finite_field_base.pyx
--- a/sage/rings/finite_rings/finite_field_base.pyx	Tue Sep 21 10:30:35 2010 -0700
+++ b/sage/rings/finite_rings/finite_field_base.pyx	Mon Aug 23 08:06:12 2010 -0400
@@ -566,24 +566,26 @@
         return self.order() - 1
     
 
-    def random_element(self, bound=None):
+    def random_element(self, *args, **kwds):
         r"""
-        A random element of the finite field.
-
-        INPUT:
-
-        - ``bound`` -- ignored (exists for consistency with other
-          ``random_element`` methods, e.g. for `\ZZ`)
+        A random element of the finite field.  Passes arguments to
+        ``random_element()`` function of underlying vector space.
 
         EXAMPLES::
 
-            sage: k = GF(2^10, 'a')
-            sage: k.random_element() # random output
-            a^9 + a
+            sage: k = GF(19^4, 'a')
+            sage: k.random_element()
+            a^3 + 3*a^2 + 6*a + 9
+
+        Passes extra positional or keyword arguments through::
+
+            sage: k.random_element(prob=0)
+            0
+
         """
         if self.degree() == 1:
             return self(randrange(self.order()))
-        v = self.vector_space().random_element()
+        v = self.vector_space().random_element(*args, **kwds)
         return self(v)
 
     def polynomial(self):
diff -r 6e7354d7f97d -r 801877d649b2 sage/rings/integer_ring.pyx
--- a/sage/rings/integer_ring.pyx	Tue Sep 21 10:30:35 2010 -0700
+++ b/sage/rings/integer_ring.pyx	Mon Aug 23 08:06:12 2010 -0400
@@ -551,25 +551,30 @@
         The default uniform distribution is integers between -2 and 2
         inclusive::
         
-            sage: [ZZ.random_element(distribution="uniform") \
-                    for _ in range(10)]
+            sage: [ZZ.random_element(distribution="uniform") for _ in range(10)]
             [2, -2, 2, -2, -1, 1, -1, 2, 1, 0]
+
+        Here we use the distribution `1/n`::
+
+            sage: [ZZ.random_element(distribution="1/n") for _ in range(10)]
+            [-6, 1, -1, 1, 1, -1, 1, -1, -3, 1]
+
         
         If a range is given, the distribution is uniform in that range::
         
             sage: ZZ.random_element(-10,10)
-            -5
+            -2
             sage: ZZ.random_element(10)
-            7
+            2
             sage: ZZ.random_element(10^50)
-            62498971546782665598023036522931234266801185891699
+            9531604786291536727294723328622110901973365898988
             sage: [ZZ.random_element(5) for _ in range(10)]
-            [1, 3, 4, 0, 3, 4, 0, 3, 0, 1]
+            [3, 1, 2, 3, 0, 0, 3, 4, 0, 3]
         
         Notice that the right endpoint is not included::
         
             sage: [ZZ.random_element(-2,2) for _ in range(10)]
-            [-1, -2, 0, -2, 1, -1, -1, -2, -2, 1]
+            [1, -2, -2, -1, -2, -1, -1, -2, 0, -2]
         
         We compute a histogram over 1000 samples of the default
         distribution::
@@ -579,8 +584,9 @@
             sage: for _ in range(1000): 
             ...       samp = ZZ.random_element()
             ...       d[samp] = d[samp] + 1
+
             sage: sorted(d.items())
-            [(-1026, 1), (-248, 1), (-145, 1), (-81, 1), (-80, 1), (-79, 1), (-75, 1), (-69, 1), (-68, 1), (-63, 2), (-61, 1), (-57, 1), (-50, 1), (-37, 1), (-35, 1), (-33, 1), (-29, 2), (-27, 2), (-25, 1), (-23, 2), (-22, 2), (-20, 1), (-19, 1), (-18, 1), (-16, 4), (-15, 3), (-14, 1), (-13, 2), (-12, 2), (-11, 2), (-10, 7), (-9, 3), (-8, 3), (-7, 7), (-6, 8), (-5, 13), (-4, 24), (-3, 34), (-2, 75), (-1, 207), (0, 209), (1, 189), (2, 64), (3, 35), (4, 13), (5, 11), (6, 10), (7, 4), (8, 4), (10, 1), (11, 1), (12, 1), (13, 1), (14, 1), (16, 3), (18, 1), (19, 1), (26, 2), (27, 1), (28, 1), (29, 1), (30, 1), (32, 1), (33, 2), (35, 1), (37, 1), (39, 1), (41, 1), (42, 1), (52, 1), (91, 1), (94, 1), (106, 1), (111, 1), (113, 2), (132, 1), (134, 1), (232, 1), (240, 1), (2133, 1), (3636, 1)]
+            [(-1955, 1), (-1026, 1), (-357, 1), (-248, 1), (-145, 1), (-81, 1), (-80, 1), (-79, 1), (-75, 1), (-69, 1), (-68, 1), (-63, 2), (-61, 1), (-57, 1), (-50, 1), (-37, 1), (-35, 1), (-33, 1), (-29, 2), (-27, 1), (-25, 1), (-23, 2), (-22, 3), (-20, 1), (-19, 1), (-18, 1), (-16, 4), (-15, 3), (-14, 1), (-13, 2), (-12, 2), (-11, 2), (-10, 7), (-9, 3), (-8, 3), (-7, 7), (-6, 8), (-5, 13), (-4, 24), (-3, 34), (-2, 75), (-1, 206), (0, 208), (1, 189), (2, 63), (3, 35), (4, 13), (5, 11), (6, 10), (7, 4), (8, 3), (10, 1), (11, 1), (12, 1), (13, 1), (14, 1), (16, 3), (18, 2), (19, 1), (26, 2), (27, 1), (28, 2), (29, 1), (30, 1), (32, 1), (33, 2), (35, 1), (37, 1), (39, 1), (41, 1), (42, 1), (52, 1), (91, 1), (94, 1), (106, 1), (111, 1), (113, 2), (132, 1), (134, 1), (232, 1), (240, 1), (2133, 1), (3636, 1)]
         """
         cdef integer.Integer z
         z = <integer.Integer>PY_NEW(integer.Integer)
@@ -615,6 +621,8 @@
                 mpz_urandomm(value, rstate.gmp_state, n_width.value)
                 mpz_add(value, value, n_min.value)
         elif distribution == "mpz_rrandomb":
+            if x is None:
+                raise ValueError("must specify x to use 'distribution=mpz_rrandomb'")
             mpz_rrandomb(value, rstate.gmp_state, int(x))
         else:
             raise ValueError, "Unknown distribution for the integers: %s"%distribution
diff -r 6e7354d7f97d -r 801877d649b2 sage/rings/rational_field.py
--- a/sage/rings/rational_field.py	Tue Sep 21 10:30:35 2010 -0700
+++ b/sage/rings/rational_field.py	Mon Aug 23 08:06:12 2010 -0400
@@ -44,6 +44,11 @@
     True
     sage: RationalField() is RationalField()
     True
+
+AUTHORS:
+
+- Niles Johnson (2010-08): Trac #3893: ``random_element()`` should pass on ``*args`` and ``**kwds``.
+
 """
 
 import random
@@ -759,21 +764,27 @@
     def _an_element_(self):
         return rational.Rational((1,2))
     
-    def random_element(self, num_bound=None, den_bound=None, distribution=None):
+    def random_element(self, num_bound=None, den_bound=None, *args, **kwds):
         """
         EXAMPLES::
         
-            sage: QQ.random_element(10,10) # random output
-            -5/3
+            sage: QQ.random_element(10,10)
+            1/4
+
+        Passes extra positional or keyword arguments through::
+        
+            sage: QQ.random_element(10,10, distribution='1/n')
+            -1
+
         """
         global ZZ
         if ZZ is None:
             import integer_ring
             ZZ = integer_ring.ZZ
         if num_bound == None:
-            num = ZZ.random_element(distribution=distribution)
-            den = ZZ.random_element(distribution=distribution)
-            while den == 0: den = ZZ.random_element(distribution=distribution)
+            num = ZZ.random_element(*args, **kwds)
+            den = ZZ.random_element(*args, **kwds)
+            while den == 0: den = ZZ.random_element(*args, **kwds)
             return self((num, den))
         else:
             if num_bound == 0:
@@ -782,8 +793,10 @@
                 den_bound = num_bound
                 if den_bound < 1:
                     den_bound = 2
-            return self((ZZ.random_element(-num_bound, num_bound+1, distribution=distribution),
-                         ZZ.random_element(1, den_bound+1, distribution=distribution)))
+            num = ZZ.random_element(-num_bound, num_bound+1, *args, **kwds)
+            den = ZZ.random_element(1, den_bound+1, *args, **kwds)
+            while den == 0: den = ZZ.random_element(1, den_bound+1, *args, **kwds)
+            return self((num,den))
     def zeta(self, n=2):
         """
         Return a root of unity in ``self``.
diff -r 6e7354d7f97d -r 801877d649b2 sage/rings/real_mpfi.pyx
--- a/sage/rings/real_mpfi.pyx	Tue Sep 21 10:30:35 2010 -0700
+++ b/sage/rings/real_mpfi.pyx	Mon Aug 23 08:06:12 2010 -0400
@@ -9,6 +9,9 @@
 - William Stein (2007-01-24): modifications and clean up and docs,
   etc.
 
+- Niles Johnson (2010-08): Trac #3893: ``random_element()`` should pass on ``*args`` and ``**kwds``.
+
+
 This is a straightforward binding to the MPFI library; it may be
 useful to refer to its documentation for more details.
 
@@ -663,10 +666,10 @@
         """
         return __create__RealIntervalField_version0, (self.__prec, self.sci_not)
 
-    def random_element(self, *args):
-        """
-        Returns a random element of self. Any arguments are passed onto
-        the random element function in real field. 
+    def random_element(self, *args, **kwds):
+        """
+        Returns a random element of self. Any arguments or keywords are
+        passed onto the random element function in real field.
 
         By default, this is uniformly distributed in `[-1, 1]`.
 
@@ -678,8 +681,15 @@
             -0.075929193054320221?
             sage: RIF.random_element(-100, 100)
             -83.808125490023344?
-        """
-        return self(self._middle_field().random_element(*args))
+
+        Passes extra positional or keyword arguments through::
+
+            sage: RIF.random_element(min=0, max=100)
+            39.649686167130405?
+            sage: RIF.random_element(min=-100, max=0)
+            -87.891396653188821?
+        """
+        return self(self._middle_field().random_element(*args, **kwds))
 
     def gen(self, i=0):
         if i == 0:
