# HG changeset patch
# User Marco Streng
# Date 1279625403 7200
# Node ID 4c87bd2ae96911b58dffe93aeefda6cf498072b5
# Parent d8f792fb37aa5db2c4b0d7023dc775da4684dfdc
Trac 727: Corrected indentation of documentation. Correctec qfsolve for nonternary forms
diff r d8f792fb37aa r 4c87bd2ae969 doc/en/reference/quadratic_forms.rst
 a/doc/en/reference/quadratic_forms.rst Sun Jul 18 23:47:44 2010 +0200
+++ b/doc/en/reference/quadratic_forms.rst Tue Jul 20 13:30:03 2010 +0200
@@ 1,4 +1,4 @@
.. _ch:schemes:
+.. _ch:quadraticforms:
Quadratic Forms
===============
@@ 6,5 +6,5 @@
.. toctree::
:maxdepth: 2
 sage/quadratic_forms/fsolve.py
+ sage/quadratic_forms/qfsolve
diff r d8f792fb37aa r 4c87bd2ae969 sage/quadratic_forms/qfsolve.py
 a/sage/quadratic_forms/qfsolve.py Sun Jul 18 23:47:44 2010 +0200
+++ b/sage/quadratic_forms/qfsolve.py Tue Jul 20 13:30:03 2010 +0200
@@ 3,13 +3,15 @@
Interface to the GP quadratic forms code of Denis Simon.
AUTHOR:
 Denis Simon (GP code)
 Nick Alexander (Sage interface)
+AUTHORS:
+
+ * Denis Simon (GP code)
+
+ * Nick Alexander (Sage interface)
"""
#*****************************************************************************
# Copyright (C) 2008 William Stein
+# Copyright (C) 2008 Nick Alexander
#
# Distributed under the terms of the GNU General Public License (GPL)
#
@@ 57,62 +59,86 @@
# \\ quadratique ternaire G, en utilisant la solution particuliere sol.
# \\ si fl>0, la 'fl'eme forme quadratique est reduite.
def Qfsolve(G, factD=None):
 r"""Find a solution to (x,y,z)^t*G*(x,y,z) = 0.
+def qfsolve(G, factD=None):
+ r"""
+ Find a solution `x = (x_0,...,x_n)` to `x G x^t = 0` for an
+ `n \times n`matrix ``G`` over `\QQ`.
 If successful, returns a triple of rational numbers (x0, y0, z0).
 If unsuccessful, returns 1 if no solutions exists over the reals and a
 prime p if no solution exists over the padic field Q_p.
+ If a solution exists, returns a tuple of rational numbers `x`.
+ Otherwise, returns `1` if no solutions exists over the reals and a
+ prime `p` if no solution exists over the `p`adic field `\QQ_p`.
 EXAMPLES:
 sage: from sage.quadratic_forms.qfsolve import Qfsolve
+ EXAMPLES::
+
+ sage: from sage.quadratic_forms.qfsolve import qfsolve
sage: M = Matrix(QQ, [[0, 0, 12], [0, 12, 0], [12, 0, 1]]); M
[ 0 0 12]
[ 0 12 0]
[12 0 1]
 sage: sol = Qfsolve(M); sol
+ sage: sol = qfsolve(M); sol
(1, 0, 0)
sage: sol[0].parent() is QQ
True
sage: M = Matrix(QQ, [[1, 0, 0], [0, 1, 0], [0, 0, 1]])
 sage: ret = Qfsolve(M); ret
+ sage: ret = qfsolve(M); ret
1
sage: ret.parent() is ZZ
True
sage: M = Matrix(QQ, [[1, 0, 0], [0, 1, 0], [0, 0, 7]])
 sage: Qfsolve(M)
+ sage: qfsolve(M)
7
+
+ sage: M = Matrix(QQ, [[3, 0, 0, 0], [0, 5, 0, 0], [0, 0, 7, 0], [0, 0, 0, 11]])
+ sage: qfsolve(M)
+ (3, 4, 3, 2)
"""
gp = _gp_for_simon()
if factD is not None:
 raise NotImplementedError
+ raise NotImplementedError, "qfsolve not implemented with parameter factD"
ret = pari(gp('Qfsolve(%s)' % G._pari_()))
if ret.type() == 't_COL':
 return (QQ(ret[0]), QQ(ret[1]), QQ(ret[2]))
+ return tuple([QQ(r) for r in ret])
return ZZ(ret)
def Qfparam(G, sol):
+def qfparam(G, sol):
r"""
+ Parametrizes the conic defined by the matrix ``G``.
 EXAMPLES:
 sage: from sage.quadratic_forms.qfsolve import Qfsolve, Qfparam
+ INPUT:
+
+  ``G``  a `3 \times 3`matrix over `\QQ`.
+
+  ``sol``  a triple of rational numbers providing a solution
+ to sol*G*sol^t = 0.
+
+ OUTPUT:
+
+ A triple of polynomials that parametrizes all solutions of
+ x*G*x^t = 0 up to scaling.
+
+ ALGORITHM:
+
+ Uses Denis Simon's pari script Qfparam.
+
+ EXAMPLES::
+
+ sage: from sage.quadratic_forms.qfsolve import qfsolve, qfparam
sage: M = Matrix(QQ, [[0, 0, 12], [0, 12, 0], [12, 0, 1]]); M
[ 0 0 12]
[ 0 12 0]
[12 0 1]
 sage: sol = Qfsolve(M);
 sage: ret = Qfparam(M, sol); ret
+ sage: sol = qfsolve(M);
+ sage: ret = qfparam(M, sol); ret
(t^2  12, 24*t, 24*t^2)
sage: ret[0].parent() is QQ['t']
True
"""
gp = _gp_for_simon()
R = QQ['t']
 str = 'Qfparam(%s, (%s)~)*[t^2,t,1]~' % (G._pari_(), pari(gp(sol))._pari_())
 ret = pari(gp(str))
 return (R(ret[0]), R(ret[1]), R(ret[2]))
+ t = R.gen()
+ s = 'Qfparam(%s, (%s)~)*[t^2,t,1]~' % (G._pari_(), pari(gp(sol))._pari_())
+ ret = pari(gp(s))
+ return tuple([R(r) for r in ret])
qfsolve = Qfsolve
qfparam = Qfparam
diff r d8f792fb37aa r 4c87bd2ae969 sage/schemes/plane_conics/con_field.py
 a/sage/schemes/plane_conics/con_field.py Sun Jul 18 23:47:44 2010 +0200
+++ b/sage/schemes/plane_conics/con_field.py Tue Jul 20 13:30:03 2010 +0200
@@ 519,9 +519,9 @@
sage: c.hom(Matrix([[0, 0, 1/2], [0, 1, 0], [1, 0, 0]]), d)
Scheme morphism:
From: Projective Conic Curve over Rational Field defined by x^2 + y^2 + z^2
 To: Projective Conic Curve over Rational Field defined by 4*x^2 + y^2  z^2
 Defn: Defined on coordinates by sending (x : y : z) to
 (1/2*z : y : x)
+ To: Projective Conic Curve over Rational Field defined by 4*x^2 + y^2  z^2
+ Defn: Defined on coordinates by sending (x : y : z) to
+ (1/2*z : y : x)
``ValueError`` is raised if the wrong codomain ``Y`` is specified:
@@ 970,6 +970,3 @@
return self.defining_polynomial().parent().variable_names()



diff r d8f792fb37aa r 4c87bd2ae969 sage/schemes/plane_conics/con_number_field.py
 a/sage/schemes/plane_conics/con_number_field.py Sun Jul 18 23:47:44 2010 +0200
+++ b/sage/schemes/plane_conics/con_number_field.py Tue Jul 20 13:30:03 2010 +0200
@@ 71,47 +71,55 @@
Returns ``True`` if and only if ``self`` has a point
defined over its base field `B`.
 If ``point`` or ``obstruction`` is True, then returns
 a second output ``S``:
  if ``point`` is True and ``self`` has a rational point,
 then ``S`` is a rational point;
  if ``obstruction`` is True, ``self`` has no rational point,
 then ``S`` is a prime or infinite place of `B` such that no
 rational point exists over the completion at ``S``.

+ If ``point`` and ``obstruction`` are both False (default),
+ then the output is boolean ``out`` saying whether ``self``
+ has a rational point.
+
+ If ``point`` or ``obstruction`` is True, then the output is
+ a pair ``(out, S)``, where ``out`` is as above and:
+
+  if ``point`` is True and ``self`` has a rational point,
+ then ``S`` is a rational point,
+
+  if ``obstruction`` is True, ``self`` has no rational point,
+ then ``S`` is a prime or infinite place of `B` such that no
+ rational point exists over the completion at ``S``.
+
Points and obstructions are cached whenever they are found.
Cached information is used for the output if available, but only
if ``read_cache`` is True.
ALGORITHM:
 The parameter ``algorithm``
 specifies the algorithm to be used:
+ The parameter ``algorithm``
+ specifies the algorithm to be used:
 ``'rnfisnorm'``  Use PARI's rnfisnorm (cannot be combined with
 ``obstruction = True``)
 ``'local'``  Check if a local solution exists for all primes
 and infinite places of `B` (cannot be combined with
 ``point = True``)
 ``'default'``  Use ``algorithm = 'local'`` first. If a rational
 point exists, then use ``algorithm = 'rnfisnorm'``
 to find one.
+  ``'rnfisnorm'``  Use PARI's rnfisnorm
+ (cannot be combined with ``obstruction = True``)
+
+  ``'local'``  Check if a local solution exists for all primes
+ and infinite places of `B` and apply the Hasse principle
+ (cannot be combined with ``point = True``)
+
+  ``'default'``  Use ``'local'`` first.
+ If a rational point exists, then use ``'rnfisnorm'``
+ to find one.
NOTE:
 Algorithms for local solubility of conics over number fields
 of degree `> 1` have not been implemented yet, so
 'rnfisnorm' is the only working algorithm.
+ Algorithms for local solubility of conics over number fields
+ of degree `> 1` have not been implemented yet, so
+ 'rnfisnorm' is the only working algorithm.
+
+ To implement algorithms for local solubility, use Hilbert symbols
+ from Trac #9334.
 To implement algorithms for local solubility, use Hilbert symbols
 from Trac #9334.

 The algorithm 'rnfisnorm' only works for small examples and
 gives the error
 ``GP/PARI ERROR: *** rnfisnorm: precision too low in isunit.``
 if the examples become to large.
 Instead of improving rnfisnorm.py, replace it by Trac #2329
 as soon as that ticket is finished.
+ The algorithm 'rnfisnorm' only works for small examples and
+ gives the error
+ ``GP/PARI ERROR: *** rnfisnorm: precision too low in isunit.``
+ if the examples become to large.
+ Instead of improving rnfisnorm.py, replace it by Trac #2329
+ as soon as that ticket is finished.
EXAMPLES:
@@ 165,8 +173,9 @@
sage: d = [C.has_rational_point(algorithm = 'rnfisnorm', point = True) for C in c] # long time: 15 seconds
sage: assert all([c[k].defining_polynomial()(Sequence(d[k][1])) == 0 for k in range(len(c)) if d[k][0]])
 Create a bunch of conics that are known to have rational points already over `\QQ`
 and check if points are found by ``has_rational_point``.
+ Create a bunch of conics that are known to have rational points
+ already over `\QQ` and check if points are found by
+ ``has_rational_point``. ::
sage: l = Sequence(cartesian_product_iterator([[1, 0, 1] for i in range(3)]))
sage: K. = QuadraticField(23)
diff r d8f792fb37aa r 4c87bd2ae969 sage/schemes/plane_conics/con_rational_field.py
 a/sage/schemes/plane_conics/con_rational_field.py Sun Jul 18 23:47:44 2010 +0200
+++ b/sage/schemes/plane_conics/con_rational_field.py Tue Jul 20 13:30:03 2010 +0200
@@ 30,7 +30,7 @@
from sage.schemes.generic.projective_space import ProjectiveSpace
from sage.matrix.constructor import Matrix
from sage.quadratic_forms.qfsolve import Qfsolve, Qfparam
+from sage.quadratic_forms.qfsolve import qfsolve, qfparam
from con_number_field import ProjectiveConic_number_field
@@ 70,13 +70,19 @@
r"""
Returns True if and only if ``self`` has a point defined over `\QQ`.
 If ``point`` or ``obstruction`` is True, then returns
 a second output ``S``:
  if ``point`` is True and ``self`` has a rational point,
 then ``S`` is a rational point;
  if ``obstruction`` is True and ``self`` has no rational point,
 then ``S`` is a prime such that no rational point exists
 over the completion at ``S`` or `1` if no point exists over `\RR`.
+ If ``point`` and ``obstruction`` are both False, then the output
+ is a boolean ``out`` saying whether ``self`` has a rational point.
+
+ If ``point`` or ``obstruction`` is True, then the output is
+ a pair ``(out, S)``, where ``out`` is as above and the following
+ holds:
+
+  if ``point`` is True and ``self`` has a rational point,
+ then ``S`` is a rational point,
+
+  if ``obstruction`` is True and ``self`` has no rational point,
+ then ``S`` is a prime such that no rational point exists
+ over the completion at ``S`` or `1` if no point exists over `\RR`.
Points and obstructions are cached, whenever they are found.
Cached information is used if and only if ``read_cache`` is True.
@@ 86,16 +92,17 @@
The parameter ``algorithm``
specifies the algorithm to be used:
  ``'qfsolve'``  Use Denis Simon's Qfsolve (only over `\QQ`)
  ``'rnfisnorm'``  Use PARI's rnfisnorm (cannot be combined with
 ``obstruction = True``)
  ``'local'``  Check if a local solution exists for all primes
 and infinite places of `\QQ` (cannot be combined with
 point = True)
  ``'default'``  Use ``'qfsolve'`` over `\QQ`. Use ``'local'`` over
 other number fields. If self has a rational point
 and ``point`` is True, then use ``'rnfisnorm'`` to find
 the point.
+  ``'qfsolve'``  Use Denis Simon's pari script Qfsolve
+ (see ``sage.quadratic_forms.qfsolve.qfsolve``)
+
+  ``'rnfisnorm'``  Use PARI's function rnfisnorm
+ (cannot be combined with ``obstruction = True``)
+
+  ``'local'``  Check if a local solution exists for all primes
+ and infinite places of `\QQ` and apply the Hasse principle
+ (cannot be combined with ``point = True``)
+
+  ``'default'``  Use ``'qfsolve'``
EXAMPLES::
@@ 154,12 +161,10 @@
if obstruction:
return True, None
return True
 if algorithm == 'default':
 algorithm = 'qfsolve'
 if algorithm == 'qfsolve':
+ if algorithm == 'default' or algorithm == 'qfsolve':
M = self.symmetric_matrix()
M *= lcm([ t.denominator() for t in M.list() ])
 pt = Qfsolve(M)
+ pt = qfsolve(M)
if pt in ZZ:
if self._local_obstruction == None:
self._local_obstruction = pt
@@ 296,7 +301,8 @@
ALGORITHM:
 Uses Denis Simon's Qfparam.
+ Uses Denis Simon's pari script Qfparam.
+ See ``sage.quadratic_forms.qfsolve.qfparam``.
EXAMPLES ::
@@ 353,7 +359,7 @@
gens = self.ambient_space().gens()
M = self.symmetric_matrix()
M *= lcm([ t.denominator() for t in M.list() ])
 par1 = Qfparam(M, point)
+ par1 = qfparam(M, point)
B = Matrix([[par1[i][j] for j in range(3)] for i in range(3)])
# self is in the image of B and does not lie on a line,
# hence B is invertible