There may be a problem in the part of the patch that refers to the 
docs.  The last doc patch I had not stripped trailing blanks from the 
patch, this time I did. 

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"sympy-patches" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/sympy-patches?hl=en
-~----------~----~----~----~------~----~------~--~---

From cb7a77913b061e9d81438fe33a0287a0a8afc730 Mon Sep 17 00:00:00 2001
From: Alan Bromborsky <bro...@ga.(none)>
Date: Fri, 5 Jun 2009 11:50:50 -0400
Subject: [PATCH] Fixes and updates -
 1. Fixed multivector constructor option
 2. Added option to mulivector project function
 3. Added documentation for mulivector project function
 4. Added tests for multivector constructors and
    multivector project function

---
 doc/src/modules/galgebra/GA/GAsympy.txt |  150 ++++++++++++++++---------------
 sympy/galgebra/GA.py                    |   42 ++++++---
 sympy/galgebra/tests/test_GA.py         |   29 ++++++-
 3 files changed, 134 insertions(+), 87 deletions(-)

diff --git a/doc/src/modules/galgebra/GA/GAsympy.txt b/doc/src/modules/galgebra/GA/GAsympy.txt
index dc06135..bc1633a 100644
--- a/doc/src/modules/galgebra/GA/GAsympy.txt
+++ b/doc/src/modules/galgebra/GA/GAsympy.txt
@@ -1,5 +1,5 @@
 **************************************
-  Geometric Algebra Module for Sympy  
+  Geometric Algebra Module for Sympy
 **************************************
 
 :Author: Alan Bromborsky
@@ -10,7 +10,7 @@
 .. % documentation is available in ``Documenting Python'', which is part
 .. % of the standard documentation for Python.  It may be found online
 .. % at:
-.. % 
+.. %
 .. % http://www.python.org/doc/current/doc/doc.html
 .. % \lstset{language=Python}
 .. % \input{macros}
@@ -28,7 +28,7 @@
 
 .. % This makes the Abstract go on a separate page in the HTML version;
 .. % if a copyright notice is used, it should go immediately after this.
-.. % 
+.. %
 .. % \ifhtml
 .. % \chapter*{Front Matter\label{front}}
 .. % \fi
@@ -64,7 +64,7 @@ product) of any vector [Hestenes,Lasenby].  The elements of the geometric
 algebra are called multivectors and consist of the linear combination of
 scalars, vectros, and the geometric product of two or more vectors. The
 additional axioms  for the geometric algebra are that for any vectors :math:`a`,
-:math:`b`, and :math:`c` in the base vector space: 
+:math:`b`, and :math:`c` in the base vector space:
 
 .. math::
   :nowrap:
@@ -96,19 +96,19 @@ python module  :mod:`sympy`.
 
 The basic geometic algebra operations will be implemented in python by defining
 a multivector  class, MV, and overloading the python operators in Table
-:ref:`1 <table1>` where ``A`` and ``B``  are any two multivectors (In the case of 
-``+``, ``-``, ``*``, ``^``, ``|``, ``<<``, and ``>>`` the operation is also defined if ``A`` or 
+:ref:`1 <table1>` where ``A`` and ``B``  are any two multivectors (In the case of
+``+``, ``-``, ``*``, ``^``, ``|``, ``<<``, and ``>>`` the operation is also defined if ``A`` or
 ``B`` is a sympy symbol or a sympy real number).
 
 .. _table1:
 
-.. csv-table:: 
+.. csv-table::
 	:header: " Operation ", " Result "
 	:widths: 10, 40
 
 	" ``A+B`` ", " sum of multivectors "
- 	" ``A-B`` ", " difference of multivectors " 
-	" ``A*B`` ", " geometric product "  
+ 	" ``A-B`` ", " difference of multivectors "
+	" ``A*B`` ", " geometric product "
 	" ``A^B`` ", " outer product of multivectors  "
 	" ``A|B`` ", " inner product of multivectors "
 	" ``A<B`` or ``A<<B`` ", " left contraction of multivectors "
@@ -118,8 +118,8 @@ Table :ref:`1 <table1>`. Multivector operations for symbolicGA
 
 The option to use ``<`` or ``<<`` for left contraction and ``>`` or ``>>`` is given since the ``<`` and
 ``>`` operators do not have r-forms (there are no *__rlt__()* and *__rlt__()* functions to overload) while
-``<<`` and ``>>`` do have r-forms so that *x << A* and *x >> A* are allowed where *x* is a scalar (symbol or integer) 
-and *A* is a multivector. With ``<`` and ``>`` we can only have mixed modes (scalars and multivectors) if the 
+``<<`` and ``>>`` do have r-forms so that *x << A* and *x >> A* are allowed where *x* is a scalar (symbol or integer)
+and *A* is a multivector. With ``<`` and ``>`` we can only have mixed modes (scalars and multivectors) if the
 multivector is the first operand.
 
 .. note::
@@ -130,7 +130,7 @@ multivector is the first operand.
 .. warning::
 
     Note that the operator order precedence is determined by python and is not
-    neccessarily that used by  geometric algebra. It is **absolutely essential** to 
+    neccessarily that used by  geometric algebra. It is **absolutely essential** to
     use parenthesis in multivector
     expressions containing ``^``, ``|``, ``<``, ``>``, ``<<`` and/or ``>>``.  As an example let
     ``A`` and ``B`` be any two multivectors. Then ``A + A*B = A +(A*B)``, but
@@ -173,7 +173,7 @@ the following symbols
   \begin{equation*}
   g = \lbrk
   \begin{array}{ccc}
-  	a0**2 & (a0.a1)  & (a0.a2) \\ 
+  	a0**2 & (a0.a1)  & (a0.a2) \\
   	(a0.a1) & a1**2  & (a1.a2) \\
   	(a0.a2) & (a1.a2) & a2**2 \\
   \end{array}
@@ -211,7 +211,7 @@ then calling `MV.setup(basis,metric)` would initialize
   \begin{equation*}
   g = \lbrk
   \begin{array}{ccccc}
-  	a0**2 & (a0.a1)  & (a0.a2) & 0 & 0\\ 
+  	a0**2 & (a0.a1)  & (a0.a2) & 0 & 0\\
   	(a0.a1) & a1**2  & (a1.a2) & 0 & 0\\
   	(a0.a2) & (a1.a2) & a2**2 & 0 & 0 \\
   	0 & 0 & 0 & 0 & 2 \\
@@ -276,9 +276,9 @@ complete set of bases and labels are shown in Table :ref:`2 <table2>`
 
 ::
 
-   MV.basislabel = ['1', ['a0', 'a1', 'a2'], ['a0a1', 'a0a2', 'a1a2'], 
+   MV.basislabel = ['1', ['a0', 'a1', 'a2'], ['a0a1', 'a0a2', 'a1a2'],
                     ['a0a1a2']]
-   MV.basis      = [[], [[0], [1], [2]], [[0, 1], [0, 2], [1, 2]], 
+   MV.basis      = [[], [[0], [1], [2]], [[0, 1], [0, 2], [1, 2]],
                     [[0, 1, 2]]]
 
 Table :ref:`2 <table2>`. Multivector basis labels and internal basis representation.
@@ -383,7 +383,7 @@ Blade Representation of Multivectors
 
 Since we can now calculate the symbolic geometric product of any two
 multivectors we can also calculate the blades corresponding to the product of
-the symbolic basis vectors using the formula 
+the symbolic basis vectors using the formula
 
 .. math::
   :nowrap:
@@ -446,12 +446,12 @@ from one representation to the other.
 
 .. warning::
 
-    When the geometric product of two multivectors is calculated the module looks to 
+    When the geometric product of two multivectors is calculated the module looks to
     see if either multivector is in blade representation.  If either is the result of
     the geometric product is converted to a blade representation.  One result of this
     is that if either of the multivectors is a simple vector (which is automatically a
     blade) the result will be in a blade representation.  If ``a`` and ``b`` are vectors
-    then the result ``a*b`` will be ``(a.b)+a^b`` or simply ``a^b`` if ``(a.b) = 0``. 
+    then the result ``a*b`` will be ``(a.b)+a^b`` or simply ``a^b`` if ``(a.b) = 0``.
 
 
 Outer and Inner Products, Left and Right Contractions
@@ -459,7 +459,7 @@ Outer and Inner Products, Left and Right Contractions
 
 In geometric algebra any general multivector :math:`A` can be decomposed into
 pure grade  multivectors (a linear combination of blades of all the same order)
-so that in a :math:`n`-dimensional vector space 
+so that in a :math:`n`-dimensional vector space
 
 .. math::
   :nowrap:
@@ -470,7 +470,7 @@ so that in a :math:`n`-dimensional vector space
 
 
 The geometric product of two pure grade multivectors :math:`A_{r}` and
-:math:`B_{s}` has the form 
+:math:`B_{s}` has the form
 
 .. math::
   :nowrap:
@@ -482,7 +482,7 @@ The geometric product of two pure grade multivectors :math:`A_{r}` and
 
 where :math:`\proj{}{t}` projects the :math:`t` grade components of the
 multivector argument.  The   inner and outer products of :math:`A_{r}` and
-:math:`B_{s}` are then defined to be 
+:math:`B_{s}` are then defined to be
 
 .. math::
   :nowrap:
@@ -502,7 +502,7 @@ multivector argument.  The   inner and outer products of :math:`A_{r}` and
   \end{equation*}
 
 
-and 
+and
 
 .. math::
   :nowrap:
@@ -521,7 +521,7 @@ and
   \end{equation*}
 
 
-Likewise the right (:math:`\lfloor`) and left (:math:`\rfloor`) contractions are defined as 
+Likewise the right (:math:`\lfloor`) and left (:math:`\rfloor`) contractions are defined as
 
 
 .. math::
@@ -598,7 +598,7 @@ The steps for calculating the outer product are:
 
 .. warning::
 
-    In the  ``MV`` class we have overloaded the ``^`` operator to represent the outer 
+    In the  ``MV`` class we have overloaded the ``^`` operator to represent the outer
     product so that instead of calling the outer product function we can write ``mv1^ mv2``.
     Due to the precedence rules for python it is **absolutely essential** to enclose outer products
     in parenthesis.
@@ -650,8 +650,8 @@ function is  ::
 The inner product is calculated the same way as the outer product except that in
 step 4, ``i1+i2`` is replaced by ``abs(i1-i2)`` or ``i1-i2`` for the right contraction or
 ``i2-i1`` for the left contraction.  If ``i1-i2`` is less than zero there is no contribution
-to the right contraction.  If ``i2-i1`` is less than zero there is no contribution to the 
-left contraction. 
+to the right contraction.  If ``i2-i1`` is less than zero there is no contribution to the
+left contraction.
 
 .. warning::
 
@@ -668,7 +668,7 @@ left contraction.
 Reverse of Multivector
 ======================
 
-If :math:`A` is the geometric product of :math:`r` vectors 
+If :math:`A` is the geometric product of :math:`r` vectors
 
 .. math::
   :nowrap:
@@ -678,7 +678,7 @@ If :math:`A` is the geometric product of :math:`r` vectors
   \end{equation*}
 
 
-then the reverse of :math:`A` designated :math:`A^{\R}` is defined by 
+then the reverse of :math:`A` designated :math:`A^{\R}` is defined by
 
 .. math::
   :nowrap:
@@ -690,7 +690,7 @@ then the reverse of :math:`A` designated :math:`A^{\R}` is defined by
 
 The reverse is simply the product with the order of terms reversed.  The reverse
 of a sum of products is defined as the sum of the reverses so that for a general
-multivector A we have 
+multivector A we have
 
 .. math::
   :nowrap:
@@ -740,7 +740,7 @@ If we have :math:`M` linearly independent vectors (a frame),
 :math:`a_{1},\dots,a_{M}`, then the reciprocal frame is
 :math:`a^{1},\dots,a^{M}` where :math:`a_{i}\cdot a^{j} = \delta_{i}^{j}`,
 :math:`\delta_{i}^{j}` is the Kronecker delta (zero if :math:`i \ne j` and one
-if :math:`i = j`). The reciprocal frame is constructed as follows: 
+if :math:`i = j`). The reciprocal frame is constructed as follows:
 
 .. math::
   :nowrap:
@@ -760,7 +760,7 @@ if :math:`i = j`). The reciprocal frame is constructed as follows:
   \end{equation*}
 
 
-Then 
+Then
 
 .. math::
   :nowrap:
@@ -791,7 +791,7 @@ If :math:`F` is a multivector field that is a function of a vector
 :math:`x = x^{i}\bm{\gamma}_{i}` (we are using the summation convention that
 pairs of subscripts and superscripts are summed over the dimension of the vector
 space) then the geometric derivative :math:`\nabla F` is given by (in this
-section the summation convention is used): 
+section the summation convention is used):
 
 .. math::
   :nowrap:
@@ -803,7 +803,7 @@ section the summation convention is used):
 
 If :math:`F_{R}` is a grade-:math:`R` multivector and
 :math:`F_{R} = F_{R}^{i_{1}\dots i_{R}}\bm{\gamma}_{i_{1}}\W\dots\W \bm{\gamma}_{i_{R}}`
-then 
+then
 
 .. math::
   :nowrap:
@@ -829,7 +829,7 @@ also can only contain those grades. For a grade-:math:`R` multivector
   \end{equation*}
 
 
-and 
+and
 
 .. math::
   :nowrap:
@@ -848,7 +848,7 @@ Curvilinear coordinates are derived from a vector function
 :math:`\bm{\theta} = \lp\theta_{1},\dots,\theta_{N}\rp` where the number of
 coordinates is equal to the dimension of the  vector space.  In the case of
 3-dimensional spherical coordinates :math:`\bm{\theta} = \lp r,\theta,\phi \rp`
-and the coordinate generating function :math:`x(\bm{\theta})` is 
+and the coordinate generating function :math:`x(\bm{\theta})` is
 
 .. math::
   :nowrap:
@@ -860,7 +860,7 @@ and the coordinate generating function :math:`x(\bm{\theta})` is
 
 A coordinate frame is derived from :math:`x` by
 :math:`\bm{e}_{i} = \pdiff{x}{\theta^{i}}`.  The following show the frame for
-spherical coordinates. 
+spherical coordinates.
 
 .. math::
   :nowrap:
@@ -891,7 +891,7 @@ spherical coordinates.
 
 
 The coordinate frame generated in this manner is not necessarily normalized so
-define a normalized frame by 
+define a normalized frame by
 
 .. math::
   :nowrap:
@@ -903,7 +903,7 @@ define a normalized frame by
 
 This works for all :math:`\bm{e}_{i}^{2} \neq 0` since we have defined
 :math:`\abs{\bm{e}_{i}} = \sqrt{\abs{\bm{e}_{i}^{2}}}`.   For spherical
-coordinates the normalized frame vectors are 
+coordinates the normalized frame vectors are
 
 .. math::
   :nowrap:
@@ -933,7 +933,7 @@ coordinates the normalized frame vectors are
   \end{equation*}
 
 
-The geometric derivative in curvilinear coordinates is given by 
+The geometric derivative in curvilinear coordinates is given by
 
 .. math::
   :nowrap:
@@ -949,11 +949,11 @@ The geometric derivative in curvilinear coordinates is given by
                      \pdiff{}{\theta^{j}}\lp\bm{\hat{e}}_{i_{1}}\W\dots\W\bm{\hat{e}}_{i_{R}}\rp \\
                    & =   \lp\pdiff{}{\theta^{j}} F_{R}^{i_{1}\dots i_{R}}\rp
                      \bm{e^{j}}\lp\bm{\hat{e}}_{i_{1}}\W\dots\W\bm{\hat{e}}_{i_{R}}\rp+
-                     F_{R}^{i_{1}\dots i_{R}}C\lbrc \bm{\hat{e}}_{i_{1}}\W\dots\W\bm{\hat{e}}_{i_{R}}\rbrc                 
+                     F_{R}^{i_{1}\dots i_{R}}C\lbrc \bm{\hat{e}}_{i_{1}}\W\dots\W\bm{\hat{e}}_{i_{R}}\rbrc
   \end{align*}
 
 
-where 
+where
 
 .. math::
   :nowrap:
@@ -965,7 +965,7 @@ where
 
 
 are the connection multivectors for the curvilinear coordinate system. For a
-spherical coordinate system they are 
+spherical coordinate system they are
 
 .. math::
   :nowrap:
@@ -1013,7 +1013,7 @@ spherical coordinate system they are
   :nowrap:
 
   \begin{equation*}
-  C\lbrc\bm{\hat{e}}_{r}\W\bm{\hat{e}}_{\phi}\rbrc = \frac{1}{r}\bm{\hat{e}}_{{\phi}} 
+  C\lbrc\bm{\hat{e}}_{r}\W\bm{\hat{e}}_{\phi}\rbrc = \frac{1}{r}\bm{\hat{e}}_{{\phi}}
                       - \frac{\cos\left({\theta}\right)}{r \sin\left({\theta}\right)}\bm{\hat{e}}_{r}\W\bm{\hat{e}}_{{\theta}}\W\bm{\hat{e}}_{{\phi}}
   \end{equation*}
 
@@ -1059,7 +1059,7 @@ The multivector class is initialized with:
    the number of basis vectors.  These symbols are used as the arguments of a
    multivector field as a function of position and for calculating the derivatives
    of a multivector field (if *coords* is defined then *rframe* is automatically
-   set equal to *True*). *offset* is an integer that is added to the multivector 
+   set equal to *True*). *offset* is an integer that is added to the multivector
    coefficient index. For example if one wishes to start labeling vector coefficient
    indexes at one instead of zero then set *offset=1*.  Additionally, :func:`MV.setup`
    calculates the pseudo scalar, :math:`I` and its inverse, :math:`I^{-1}` and makes
@@ -1090,7 +1090,7 @@ curvilinear coordinates using:
 
 *  ``debug``: If ``True`` printout (LaTeX) all quantities required for derivative calculation
 
-*  ``debug_level``: Set to 0,1,2, or 3 to stop curvilinear calculation before all quatities are 
+*  ``debug_level``: Set to 0,1,2, or 3 to stop curvilinear calculation before all quatities are
    calculated.  This is done when debugging new curvilinear coordinate systems since simplification
    of expressions is not sufficiently automated to insure success of process of any coordinate system
    defined by vector function ``x``
@@ -1118,11 +1118,11 @@ curvilinear coordinates using:
 
 		This function directly affects the way multivectors are printed with the
 		print command since it interacts with the :func:`__str__` function for the
-		multivector class which is used by the ``print`` command. 
- 
+		multivector class which is used by the ``print`` command.
+
 
-		.. csv-table:: 
-			:header: " ``str_mode`` ", " Effect on print " 
+		.. csv-table::
+			:header: " ``str_mode`` ", " Effect on print "
 			:widths: 10, 50
 
 			" 0 ","One multivector per line"
@@ -1135,7 +1135,7 @@ Instantiating a Multivector
 Now that grades and bases have been described we can show all the ways that a
 multivector can be instantiated. As an example assume that the multivector space
 is initialized with ``MV.setup('e1 e2 e3')``. Then the vectors ``e1``, ``e2``,
-and ``e3`` are made available (broadcast) for use in the program . 
+and ``e3`` are made available (broadcast) for use in the program .
 
 .. warning::
 
@@ -1161,8 +1161,8 @@ or with the multivector class constructor:
    switch that will convert the symbolic coefficients of a multivector to functions
    if coordinate variables have been defined when :func:`MV.setup` is called:
 
-	.. csv-table:: 
-		:header: " mvtype ", " value ", " result " 
+	.. csv-table::
+		:header: " mvtype ", " value ", " result "
 		:widths: 10, 30, 30
 
 		" default ", " default ", " Zero multivector "
@@ -1192,8 +1192,8 @@ or with the multivector class constructor:
    the :mod:`latex_ex` is used to print the multivector the coefficients would print as
    :math:`A`, :math:`A^{xy}`, :math:`A^{xz}`, and :math:`A^{yz}`.
 
-   If the *fct* argrument of :func:`MV` is set to *True* and the *coords* argument in 
-   :func:`MV.setup` is defined the symbolic coefficients of the multivector are functions 
+   If the *fct* argrument of :func:`MV` is set to *True* and the *coords* argument in
+   :func:`MV.setup` is defined the symbolic coefficients of the multivector are functions
    of the coordinates.
 
 
@@ -1221,7 +1221,11 @@ Basic Multivector Class Functions
 
 .. function:: project(self,r)
 
-   Return the grade-:math:`r` components of the multivector.
+   If r is a integer return the grade-:math:`r` components of the multivector. If
+   r is a multivector return the grades of the multivector that correspond to the
+   non-zero grades of r. For example if one is projecting a general multivector and
+   r is a spinor, ``A.project(r)`` will return only the even grades of the multivector
+   A since a spinor only has even grades that are non-zero.
 
 
 .. function:: even(self)
@@ -1257,13 +1261,13 @@ Basic Multivector Class Functions
 
 .. function:: grad_ext(self)
 
-   Return the outer (curl) derivative of the multivector function. Equivalent to 
+   Return the outer (curl) derivative of the multivector function. Equivalent to
    :func:`curl`.
 
 
 .. function:: grad_int(self)
 
-   Return the inner (div) derivative of the multivector function. Equivalent to 
+   Return the inner (div) derivative of the multivector function. Equivalent to
    :func:`div`.
 
 .. warning::
@@ -1346,7 +1350,7 @@ class.
 
 	.. warning::
 
-		You can only directly use *x*, *y*, and *ab* as symbols in your program if 
+		You can only directly use *x*, *y*, and *ab* as symbols in your program if
 		the statement  ``set_main(sys.modules[__name__])`` appears immediately after
 		the ``from sympy.galgebra.GA import *`` statement.
 
@@ -1487,7 +1491,7 @@ correctly  (in our units:math:`c=1`) [Lasenby,pp229-231].
 
 ``Begin Program Output``
 
-:math:`I` Pseudo-Scalar  
+:math:`I` Pseudo-Scalar
 
 .. math::
   :nowrap:
@@ -1497,7 +1501,7 @@ correctly  (in our units:math:`c=1`) [Lasenby,pp229-231].
   \end{equation*}
 
 
-:math:`B` Magnetic Field Bi-Vector 
+:math:`B` Magnetic Field Bi-Vector
 
 .. math::
   :nowrap:
@@ -1507,7 +1511,7 @@ correctly  (in our units:math:`c=1`) [Lasenby,pp229-231].
   \end{equation*}
 
 
-:math:`F` Electric Field Bi-Vector 
+:math:`F` Electric Field Bi-Vector
 
 .. math::
   :nowrap:
@@ -1517,7 +1521,7 @@ correctly  (in our units:math:`c=1`) [Lasenby,pp229-231].
   \end{equation*}
 
 
-:math:`E+IB` Electo-Magnetic Field Bi-Vector 
+:math:`E+IB` Electo-Magnetic Field Bi-Vector
 
 .. math::
   :nowrap:
@@ -1527,7 +1531,7 @@ correctly  (in our units:math:`c=1`) [Lasenby,pp229-231].
   \end{equation*}
 
 
-:math:`J` Four Current 
+:math:`J` Four Current
 
 .. math::
   :nowrap:
@@ -1537,7 +1541,7 @@ correctly  (in our units:math:`c=1`) [Lasenby,pp229-231].
   \end{equation*}
 
 
-Geometric Derivative of Electo-Magnetic Field Bi-Vector  
+Geometric Derivative of Electo-Magnetic Field Bi-Vector
 
 .. math::
   :nowrap:
@@ -1546,7 +1550,7 @@ Geometric Derivative of Electo-Magnetic Field Bi-Vector
   \nabla F & =   \left(\partial_{z} {E^{z}} + \partial_{y} {E^{y}} + \partial_{x} {E^{x}}\right){\gamma}_{t} \\ & + \left(-\partial_{t} {E^{x}} + \partial_{y} {B^{z}} -\partial_{z} {B^{y}}\right){\gamma}_{x} \\ & + \left(\partial_{z} {B^{x}} -\partial_{t} {E^{y}} -\partial_{x} {B^{z}}\right){\gamma}_{y} \\ & + \left(-\partial_{y} {B^{x}} -\partial_{t} {E^{z}} + \partial_{x} {B^{y}}\right){\gamma}_{z} \\ & + \left(-\partial_{x} {E^{y}} -\partial_{t} {B^{z}} + \partial_{y} {E^{x}}\right){\gamma}_{t}{\gamma}_{x}{\gamma}_{y} \\ & + \left(-\partial_{x} {E^{z}} + \partial_{t} {B^{y}} + \partial_{z} {E^{x}}\right){\gamma}_{t}{\gamma}_{x}{\gamma}_{z} \\ & + \left(-\partial_{t} {B^{x}} -\partial_{y} {E^{z}} + \partial_{z} {E^{y}}\right){\gamma}_{t}{\gamma}_{y}{\gamma}_{z} \\ & + \left(\partial_{y} {B^{y}} + \partial_{z} {B^{z}} + \partial_{x} {B^{x}}\right){\gamma}_{x}{\gamma}_{y}{\gamma}_{z}\end{align*}
 
 
-All Maxwell Equations are 
+All Maxwell Equations are
 
 .. math::
   :nowrap:
@@ -1556,7 +1560,7 @@ All Maxwell Equations are
   \end{equation*}
 
 
-Div :math:`E` and Curl :math:`H` Equations 
+Div :math:`E` and Curl :math:`H` Equations
 
 .. math::
   :nowrap:
@@ -1575,7 +1579,7 @@ Div :math:`E` and Curl :math:`H` Equations
   \end{equation*}
 
 
-Curl :math:`E` and Div :math:`B` equations  
+Curl :math:`E` and Div :math:`B` equations
 
 .. math::
   :nowrap:
@@ -1617,7 +1621,7 @@ real equation are explined  in Doran and Lasenby [Lasenby,pp281-283].
 
 ``Begin Program Output``
 
-:math:`A` is 4-vector potential  
+:math:`A` is 4-vector potential
 
 .. math::
   :nowrap:
@@ -1627,7 +1631,7 @@ real equation are explined  in Doran and Lasenby [Lasenby,pp281-283].
   \end{equation*}
 
 
-:math:`\bm{\psi}` is 8-component real spinor (even multi-vector)  
+:math:`\bm{\psi}` is 8-component real spinor (even multi-vector)
 
 .. math::
   :nowrap:
@@ -1639,7 +1643,7 @@ real equation are explined  in Doran and Lasenby [Lasenby,pp281-283].
 
 Dirac equation in terms of real geometric algebra/calculus
 :math:`\lp\nabla \bm{\psi} I \sigma_{z}-eA\bm{\psi} = m\bm{\psi}\gamma_{t}\rp`
-Spin measured with respect to :math:`z` axis  
+Spin measured with respect to :math:`z` axis
 
 .. math::
   :nowrap:
@@ -1679,7 +1683,7 @@ geometric algebra) to demonstrate the formulas derived in section :ref:`deriv`.
 
 ``Begin Program Output``
 
-Gradient of Scalar Function :math:`\psi`  
+Gradient of Scalar Function :math:`\psi`
 
 .. math::
   :nowrap:
@@ -1689,7 +1693,7 @@ Gradient of Scalar Function :math:`\psi`
   \end{equation*}
 
 
-Div and Curl of Vector Function :math:`A`  
+Div and Curl of Vector Function :math:`A`
 
 .. math::
   :nowrap:
diff --git a/sympy/galgebra/GA.py b/sympy/galgebra/GA.py
index c77ad97..5f22374 100644
--- a/sympy/galgebra/GA.py
+++ b/sympy/galgebra/GA.py
@@ -1780,8 +1780,8 @@ class MV(object):
                         else:
                             self.mv[0] = numpy.array([sympy.Symbol(value)],dtype=numpy.object)
                 self.name = value+'bm'
-        if value != '' and mvtype == '': #Most general multivector
-            if isinstance(value,types.StringType):
+        if isinstance(value,types.StringType) and mvtype == '': #Most general multivector
+            if value != '':
                 for grade in MV.n1rg:
                     symbol_str = ''
                     if grade != 0:
@@ -2156,18 +2156,34 @@ class MV(object):
     def project(self,r):
         """
         Grade projection operator. For multivector X, X.project(r)
-        returns multivector of grade r components of X.
-        """
-        grade_r = MV()
-        if r > MV.n:
-            return(grade_r)
-        self.convert_to_blades()
-        if not isinstance(self.mv[r],numpy.ndarray):
+        returns multivector of grade r components of X if r is an
+        integer. If r is a multivector X.project(r) returns a
+        mutivector consisting of the grade of X for which r has non-
+        zero grades. For example if X is a general multvector and
+        r is a general spinor then X.project(r) will return the even
+        grades of X.
+        """
+        if isinstance(r,types.IntType):
+            grade_r = MV()
+            if r > MV.n:
+                return(grade_r)
+            self.convert_to_blades()
+            if not isinstance(self.mv[r],numpy.ndarray):
+                return(grade_r)
+            grade_r.bladeflg = 1
+            grade_r.puregrade = 1
+            grade_r.mv[r] = +self.mv[r]
             return(grade_r)
-        grade_r.bladeflg = 1
-        grade_r.puregrade = 1
-        grade_r.mv[r] = +self.mv[r]
-        return(grade_r)
+        if isinstance(r,MV):
+            self.convert_to_blades()
+            r.convert_to_blades()
+            proj = MV()
+            for i in MV.n1rg:
+                if not isinstance(r.mv[i],types.IntType):
+                    proj.mv[i] = self.mv[i]
+            proj.bladeflg = self.bladeflg
+            return(proj)
+        return(None)
 
     def even(self):
         """
diff --git a/sympy/galgebra/tests/test_GA.py b/sympy/galgebra/tests/test_GA.py
index 4f16c90..c0540ca 100644
--- a/sympy/galgebra/tests/test_GA.py
+++ b/sympy/galgebra/tests/test_GA.py
@@ -40,6 +40,34 @@ def make_vector(a,n = 3):
         a = MV(sym_lst,'vector')
     return(F(a))
 
+def test_constructor():
+    """
+    Test various multivector constructor options
+    """
+    MV.setup('e1 e2 e3','1 0 0,0 1 0,0 0 1')
+
+    a = MV('a','scalar')
+    assert str(a) == 'a'
+    v = MV('v','vector')
+    assert str(v) == 'v__0*e1+v__1*e2+v__2*e3'
+    S = MV('S','spinor')
+    assert str(S) == 'S+S__01*e1e2+S__02*e1e3+S__12*e2e3'
+    A = MV('A')
+    assert str(A) == 'A+A__0*e1+A__1*e2+A__2*e3+A__01*e1e2+A__02*e1e3+A__12*e2e3+A__012*e1e2e3'
+
+def test_project():
+    """
+    Test project() function options
+    """
+    MV.setup('e1 e2 e3','1 0 0,0 1 0,0 0 1')
+
+    S = MV('S','spinor')
+    A = MV('A')
+    W_2 = A.project(2)
+    assert str(W_2) == 'A__01*e1^e2+A__02*e1^e3+A__12*e2^e3'
+    W_S = A.project(S)
+    assert str(W_S) == 'A+A__01*e1^e2+A__02*e1^e3+A__12*e2^e3'
+
 def test_rmul():
     """
     Test for communitive scalar multiplication.  Leftover from when sympy and
@@ -75,7 +103,6 @@ def test_substitution():
     Y = X.subs([(x,2),(y,3),(z,4)])
     assert Y == 2*e_x+3*e_y+4*e_z
 
-
 def test_vector_extraction():
     """
     Show that conformal bivector encodes two points. See D&L Section 10.4.1
-- 
1.6.0.4

Reply via email to